kubelet_pods_test.go 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package kubelet
  14. import (
  15. "errors"
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "path/filepath"
  20. "sort"
  21. "testing"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/stretchr/testify/require"
  24. v1 "k8s.io/api/core/v1"
  25. apierrors "k8s.io/apimachinery/pkg/api/errors"
  26. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. "k8s.io/apimachinery/pkg/labels"
  28. "k8s.io/apimachinery/pkg/runtime"
  29. "k8s.io/apimachinery/pkg/types"
  30. utilfeature "k8s.io/apiserver/pkg/util/feature"
  31. core "k8s.io/client-go/testing"
  32. "k8s.io/client-go/tools/record"
  33. featuregatetesting "k8s.io/component-base/featuregate/testing"
  34. // TODO: remove this import if
  35. // api.Registry.GroupOrDie(v1.GroupName).GroupVersions[0].String() is changed
  36. // to "v1"?
  37. _ "k8s.io/kubernetes/pkg/apis/core/install"
  38. "k8s.io/kubernetes/pkg/features"
  39. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  40. containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
  41. "k8s.io/kubernetes/pkg/kubelet/server/portforward"
  42. "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
  43. "k8s.io/kubernetes/pkg/volume/util/hostutil"
  44. "k8s.io/kubernetes/pkg/volume/util/subpath"
  45. )
  46. func TestDisabledSubpath(t *testing.T) {
  47. fhu := hostutil.NewFakeHostUtil(nil)
  48. fsp := &subpath.FakeSubpath{}
  49. pod := v1.Pod{
  50. Spec: v1.PodSpec{
  51. HostNetwork: true,
  52. },
  53. }
  54. podVolumes := kubecontainer.VolumeMap{
  55. "disk": kubecontainer.VolumeInfo{Mounter: &stubVolume{path: "/mnt/disk"}},
  56. }
  57. cases := map[string]struct {
  58. container v1.Container
  59. expectError bool
  60. }{
  61. "subpath not specified": {
  62. v1.Container{
  63. VolumeMounts: []v1.VolumeMount{
  64. {
  65. MountPath: "/mnt/path3",
  66. Name: "disk",
  67. ReadOnly: true,
  68. },
  69. },
  70. },
  71. false,
  72. },
  73. "subpath specified": {
  74. v1.Container{
  75. VolumeMounts: []v1.VolumeMount{
  76. {
  77. MountPath: "/mnt/path3",
  78. SubPath: "/must/not/be/absolute",
  79. Name: "disk",
  80. ReadOnly: true,
  81. },
  82. },
  83. },
  84. true,
  85. },
  86. }
  87. defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, false)()
  88. for name, test := range cases {
  89. _, _, err := makeMounts(&pod, "/pod", &test.container, "fakepodname", "", []string{}, podVolumes, fhu, fsp, nil)
  90. if err != nil && !test.expectError {
  91. t.Errorf("test %v failed: %v", name, err)
  92. }
  93. if err == nil && test.expectError {
  94. t.Errorf("test %v failed: expected error", name)
  95. }
  96. }
  97. }
  98. func TestNodeHostsFileContent(t *testing.T) {
  99. testCases := []struct {
  100. hostsFileName string
  101. hostAliases []v1.HostAlias
  102. rawHostsFileContent string
  103. expectedHostsFileContent string
  104. }{
  105. {
  106. "hosts_test_file1",
  107. []v1.HostAlias{},
  108. `# hosts file for testing.
  109. 127.0.0.1 localhost
  110. ::1 localhost ip6-localhost ip6-loopback
  111. fe00::0 ip6-localnet
  112. fe00::0 ip6-mcastprefix
  113. fe00::1 ip6-allnodes
  114. fe00::2 ip6-allrouters
  115. 123.45.67.89 some.domain
  116. `,
  117. `# Kubernetes-managed hosts file (host network).
  118. # hosts file for testing.
  119. 127.0.0.1 localhost
  120. ::1 localhost ip6-localhost ip6-loopback
  121. fe00::0 ip6-localnet
  122. fe00::0 ip6-mcastprefix
  123. fe00::1 ip6-allnodes
  124. fe00::2 ip6-allrouters
  125. 123.45.67.89 some.domain
  126. `,
  127. },
  128. {
  129. "hosts_test_file2",
  130. []v1.HostAlias{},
  131. `# another hosts file for testing.
  132. 127.0.0.1 localhost
  133. ::1 localhost ip6-localhost ip6-loopback
  134. fe00::0 ip6-localnet
  135. fe00::0 ip6-mcastprefix
  136. fe00::1 ip6-allnodes
  137. fe00::2 ip6-allrouters
  138. 12.34.56.78 another.domain
  139. `,
  140. `# Kubernetes-managed hosts file (host network).
  141. # another hosts file for testing.
  142. 127.0.0.1 localhost
  143. ::1 localhost ip6-localhost ip6-loopback
  144. fe00::0 ip6-localnet
  145. fe00::0 ip6-mcastprefix
  146. fe00::1 ip6-allnodes
  147. fe00::2 ip6-allrouters
  148. 12.34.56.78 another.domain
  149. `,
  150. },
  151. {
  152. "hosts_test_file1_with_host_aliases",
  153. []v1.HostAlias{
  154. {IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
  155. },
  156. `# hosts file for testing.
  157. 127.0.0.1 localhost
  158. ::1 localhost ip6-localhost ip6-loopback
  159. fe00::0 ip6-localnet
  160. fe00::0 ip6-mcastprefix
  161. fe00::1 ip6-allnodes
  162. fe00::2 ip6-allrouters
  163. 123.45.67.89 some.domain
  164. `,
  165. `# Kubernetes-managed hosts file (host network).
  166. # hosts file for testing.
  167. 127.0.0.1 localhost
  168. ::1 localhost ip6-localhost ip6-loopback
  169. fe00::0 ip6-localnet
  170. fe00::0 ip6-mcastprefix
  171. fe00::1 ip6-allnodes
  172. fe00::2 ip6-allrouters
  173. 123.45.67.89 some.domain
  174. # Entries added by HostAliases.
  175. 123.45.67.89 foo bar baz
  176. `,
  177. },
  178. {
  179. "hosts_test_file2_with_host_aliases",
  180. []v1.HostAlias{
  181. {IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
  182. {IP: "456.78.90.123", Hostnames: []string{"park", "doo", "boo"}},
  183. },
  184. `# another hosts file for testing.
  185. 127.0.0.1 localhost
  186. ::1 localhost ip6-localhost ip6-loopback
  187. fe00::0 ip6-localnet
  188. fe00::0 ip6-mcastprefix
  189. fe00::1 ip6-allnodes
  190. fe00::2 ip6-allrouters
  191. 12.34.56.78 another.domain
  192. `,
  193. `# Kubernetes-managed hosts file (host network).
  194. # another hosts file for testing.
  195. 127.0.0.1 localhost
  196. ::1 localhost ip6-localhost ip6-loopback
  197. fe00::0 ip6-localnet
  198. fe00::0 ip6-mcastprefix
  199. fe00::1 ip6-allnodes
  200. fe00::2 ip6-allrouters
  201. 12.34.56.78 another.domain
  202. # Entries added by HostAliases.
  203. 123.45.67.89 foo bar baz
  204. 456.78.90.123 park doo boo
  205. `,
  206. },
  207. }
  208. for _, testCase := range testCases {
  209. tmpdir, err := writeHostsFile(testCase.hostsFileName, testCase.rawHostsFileContent)
  210. require.NoError(t, err, "could not create a temp hosts file")
  211. defer os.RemoveAll(tmpdir)
  212. actualContent, fileReadErr := nodeHostsFileContent(filepath.Join(tmpdir, testCase.hostsFileName), testCase.hostAliases)
  213. require.NoError(t, fileReadErr, "could not create read hosts file")
  214. assert.Equal(t, testCase.expectedHostsFileContent, string(actualContent), "hosts file content not expected")
  215. }
  216. }
  217. // writeHostsFile will write a hosts file into a temporary dir, and return that dir.
  218. // Caller is responsible for deleting the dir and its contents.
  219. func writeHostsFile(filename string, cfg string) (string, error) {
  220. tmpdir, err := ioutil.TempDir("", "kubelet=kubelet_pods_test.go=")
  221. if err != nil {
  222. return "", err
  223. }
  224. return tmpdir, ioutil.WriteFile(filepath.Join(tmpdir, filename), []byte(cfg), 0644)
  225. }
  226. func TestManagedHostsFileContent(t *testing.T) {
  227. testCases := []struct {
  228. hostIPs []string
  229. hostName string
  230. hostDomainName string
  231. hostAliases []v1.HostAlias
  232. expectedContent string
  233. }{
  234. {
  235. []string{"123.45.67.89"},
  236. "podFoo",
  237. "",
  238. []v1.HostAlias{},
  239. `# Kubernetes-managed hosts file.
  240. 127.0.0.1 localhost
  241. ::1 localhost ip6-localhost ip6-loopback
  242. fe00::0 ip6-localnet
  243. fe00::0 ip6-mcastprefix
  244. fe00::1 ip6-allnodes
  245. fe00::2 ip6-allrouters
  246. 123.45.67.89 podFoo
  247. `,
  248. },
  249. {
  250. []string{"203.0.113.1"},
  251. "podFoo",
  252. "domainFoo",
  253. []v1.HostAlias{},
  254. `# Kubernetes-managed hosts file.
  255. 127.0.0.1 localhost
  256. ::1 localhost ip6-localhost ip6-loopback
  257. fe00::0 ip6-localnet
  258. fe00::0 ip6-mcastprefix
  259. fe00::1 ip6-allnodes
  260. fe00::2 ip6-allrouters
  261. 203.0.113.1 podFoo.domainFoo podFoo
  262. `,
  263. },
  264. {
  265. []string{"203.0.113.1"},
  266. "podFoo",
  267. "domainFoo",
  268. []v1.HostAlias{
  269. {IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
  270. },
  271. `# Kubernetes-managed hosts file.
  272. 127.0.0.1 localhost
  273. ::1 localhost ip6-localhost ip6-loopback
  274. fe00::0 ip6-localnet
  275. fe00::0 ip6-mcastprefix
  276. fe00::1 ip6-allnodes
  277. fe00::2 ip6-allrouters
  278. 203.0.113.1 podFoo.domainFoo podFoo
  279. # Entries added by HostAliases.
  280. 123.45.67.89 foo bar baz
  281. `,
  282. },
  283. {
  284. []string{"203.0.113.1"},
  285. "podFoo",
  286. "domainFoo",
  287. []v1.HostAlias{
  288. {IP: "123.45.67.89", Hostnames: []string{"foo", "bar", "baz"}},
  289. {IP: "456.78.90.123", Hostnames: []string{"park", "doo", "boo"}},
  290. },
  291. `# Kubernetes-managed hosts file.
  292. 127.0.0.1 localhost
  293. ::1 localhost ip6-localhost ip6-loopback
  294. fe00::0 ip6-localnet
  295. fe00::0 ip6-mcastprefix
  296. fe00::1 ip6-allnodes
  297. fe00::2 ip6-allrouters
  298. 203.0.113.1 podFoo.domainFoo podFoo
  299. # Entries added by HostAliases.
  300. 123.45.67.89 foo bar baz
  301. 456.78.90.123 park doo boo
  302. `,
  303. },
  304. {
  305. []string{"203.0.113.1", "fd00::6"},
  306. "podFoo",
  307. "domainFoo",
  308. []v1.HostAlias{},
  309. `# Kubernetes-managed hosts file.
  310. 127.0.0.1 localhost
  311. ::1 localhost ip6-localhost ip6-loopback
  312. fe00::0 ip6-localnet
  313. fe00::0 ip6-mcastprefix
  314. fe00::1 ip6-allnodes
  315. fe00::2 ip6-allrouters
  316. 203.0.113.1 podFoo.domainFoo podFoo
  317. fd00::6 podFoo.domainFoo podFoo
  318. `,
  319. },
  320. }
  321. for _, testCase := range testCases {
  322. actualContent := managedHostsFileContent(testCase.hostIPs, testCase.hostName, testCase.hostDomainName, testCase.hostAliases)
  323. assert.Equal(t, testCase.expectedContent, string(actualContent), "hosts file content not expected")
  324. }
  325. }
  326. func TestRunInContainerNoSuchPod(t *testing.T) {
  327. testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
  328. defer testKubelet.Cleanup()
  329. kubelet := testKubelet.kubelet
  330. fakeRuntime := testKubelet.fakeRuntime
  331. fakeRuntime.PodList = []*containertest.FakePod{}
  332. podName := "podFoo"
  333. podNamespace := "nsFoo"
  334. containerName := "containerFoo"
  335. output, err := kubelet.RunInContainer(
  336. kubecontainer.GetPodFullName(&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: podNamespace}}),
  337. "",
  338. containerName,
  339. []string{"ls"})
  340. assert.Error(t, err)
  341. assert.Nil(t, output, "output should be nil")
  342. }
  343. func TestRunInContainer(t *testing.T) {
  344. for _, testError := range []error{nil, errors.New("bar")} {
  345. testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
  346. defer testKubelet.Cleanup()
  347. kubelet := testKubelet.kubelet
  348. fakeRuntime := testKubelet.fakeRuntime
  349. fakeCommandRunner := containertest.FakeContainerCommandRunner{
  350. Err: testError,
  351. Stdout: "foo",
  352. }
  353. kubelet.runner = &fakeCommandRunner
  354. containerID := kubecontainer.ContainerID{Type: "test", ID: "abc1234"}
  355. fakeRuntime.PodList = []*containertest.FakePod{
  356. {Pod: &kubecontainer.Pod{
  357. ID: "12345678",
  358. Name: "podFoo",
  359. Namespace: "nsFoo",
  360. Containers: []*kubecontainer.Container{
  361. {Name: "containerFoo",
  362. ID: containerID,
  363. },
  364. },
  365. }},
  366. }
  367. cmd := []string{"ls"}
  368. actualOutput, err := kubelet.RunInContainer("podFoo_nsFoo", "", "containerFoo", cmd)
  369. assert.Equal(t, containerID, fakeCommandRunner.ContainerID, "(testError=%v) ID", testError)
  370. assert.Equal(t, cmd, fakeCommandRunner.Cmd, "(testError=%v) command", testError)
  371. // this isn't 100% foolproof as a bug in a real ContainerCommandRunner where it fails to copy to stdout/stderr wouldn't be caught by this test
  372. assert.Equal(t, "foo", string(actualOutput), "(testError=%v) output", testError)
  373. assert.Equal(t, err, testError, "(testError=%v) err", testError)
  374. }
  375. }
  376. type testServiceLister struct {
  377. services []*v1.Service
  378. }
  379. func (ls testServiceLister) List(labels.Selector) ([]*v1.Service, error) {
  380. return ls.services, nil
  381. }
  382. type envs []kubecontainer.EnvVar
  383. func (e envs) Len() int {
  384. return len(e)
  385. }
  386. func (e envs) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
  387. func (e envs) Less(i, j int) bool { return e[i].Name < e[j].Name }
  388. func buildService(name, namespace, clusterIP, protocol string, port int) *v1.Service {
  389. return &v1.Service{
  390. ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
  391. Spec: v1.ServiceSpec{
  392. Ports: []v1.ServicePort{{
  393. Protocol: v1.Protocol(protocol),
  394. Port: int32(port),
  395. }},
  396. ClusterIP: clusterIP,
  397. },
  398. }
  399. }
  400. func TestMakeEnvironmentVariables(t *testing.T) {
  401. trueVal := true
  402. services := []*v1.Service{
  403. buildService("kubernetes", metav1.NamespaceDefault, "1.2.3.1", "TCP", 8081),
  404. buildService("test", "test1", "1.2.3.3", "TCP", 8083),
  405. buildService("kubernetes", "test2", "1.2.3.4", "TCP", 8084),
  406. buildService("test", "test2", "1.2.3.5", "TCP", 8085),
  407. buildService("test", "test2", "None", "TCP", 8085),
  408. buildService("test", "test2", "", "TCP", 8085),
  409. buildService("kubernetes", "kubernetes", "1.2.3.6", "TCP", 8086),
  410. buildService("not-special", "kubernetes", "1.2.3.8", "TCP", 8088),
  411. buildService("not-special", "kubernetes", "None", "TCP", 8088),
  412. buildService("not-special", "kubernetes", "", "TCP", 8088),
  413. }
  414. trueValue := true
  415. falseValue := false
  416. testCases := []struct {
  417. name string // the name of the test case
  418. ns string // the namespace to generate environment for
  419. enableServiceLinks *bool // enabling service links
  420. container *v1.Container // the container to use
  421. masterServiceNs string // the namespace to read master service info from
  422. nilLister bool // whether the lister should be nil
  423. configMap *v1.ConfigMap // an optional ConfigMap to pull from
  424. secret *v1.Secret // an optional Secret to pull from
  425. expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars
  426. expectedError bool // does the test fail
  427. expectedEvent string // does the test emit an event
  428. }{
  429. {
  430. name: "api server = Y, kubelet = Y",
  431. ns: "test1",
  432. enableServiceLinks: &falseValue,
  433. container: &v1.Container{
  434. Env: []v1.EnvVar{
  435. {Name: "FOO", Value: "BAR"},
  436. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
  437. {Name: "TEST_SERVICE_PORT", Value: "8083"},
  438. {Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
  439. {Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
  440. {Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
  441. {Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
  442. {Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
  443. },
  444. },
  445. masterServiceNs: metav1.NamespaceDefault,
  446. nilLister: false,
  447. expectedEnvs: []kubecontainer.EnvVar{
  448. {Name: "FOO", Value: "BAR"},
  449. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
  450. {Name: "TEST_SERVICE_PORT", Value: "8083"},
  451. {Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
  452. {Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
  453. {Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
  454. {Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
  455. {Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
  456. {Name: "KUBERNETES_SERVICE_PORT", Value: "8081"},
  457. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.1"},
  458. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.1:8081"},
  459. {Name: "KUBERNETES_PORT_8081_TCP", Value: "tcp://1.2.3.1:8081"},
  460. {Name: "KUBERNETES_PORT_8081_TCP_PROTO", Value: "tcp"},
  461. {Name: "KUBERNETES_PORT_8081_TCP_PORT", Value: "8081"},
  462. {Name: "KUBERNETES_PORT_8081_TCP_ADDR", Value: "1.2.3.1"},
  463. },
  464. },
  465. {
  466. name: "api server = Y, kubelet = N",
  467. ns: "test1",
  468. enableServiceLinks: &falseValue,
  469. container: &v1.Container{
  470. Env: []v1.EnvVar{
  471. {Name: "FOO", Value: "BAR"},
  472. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
  473. {Name: "TEST_SERVICE_PORT", Value: "8083"},
  474. {Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
  475. {Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
  476. {Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
  477. {Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
  478. {Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
  479. },
  480. },
  481. masterServiceNs: metav1.NamespaceDefault,
  482. nilLister: true,
  483. expectedEnvs: []kubecontainer.EnvVar{
  484. {Name: "FOO", Value: "BAR"},
  485. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
  486. {Name: "TEST_SERVICE_PORT", Value: "8083"},
  487. {Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
  488. {Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
  489. {Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
  490. {Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
  491. {Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
  492. },
  493. },
  494. {
  495. name: "api server = N; kubelet = Y",
  496. ns: "test1",
  497. enableServiceLinks: &falseValue,
  498. container: &v1.Container{
  499. Env: []v1.EnvVar{
  500. {Name: "FOO", Value: "BAZ"},
  501. },
  502. },
  503. masterServiceNs: metav1.NamespaceDefault,
  504. nilLister: false,
  505. expectedEnvs: []kubecontainer.EnvVar{
  506. {Name: "FOO", Value: "BAZ"},
  507. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.1"},
  508. {Name: "KUBERNETES_SERVICE_PORT", Value: "8081"},
  509. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.1:8081"},
  510. {Name: "KUBERNETES_PORT_8081_TCP", Value: "tcp://1.2.3.1:8081"},
  511. {Name: "KUBERNETES_PORT_8081_TCP_PROTO", Value: "tcp"},
  512. {Name: "KUBERNETES_PORT_8081_TCP_PORT", Value: "8081"},
  513. {Name: "KUBERNETES_PORT_8081_TCP_ADDR", Value: "1.2.3.1"},
  514. },
  515. },
  516. {
  517. name: "api server = N; kubelet = Y; service env vars",
  518. ns: "test1",
  519. enableServiceLinks: &trueValue,
  520. container: &v1.Container{
  521. Env: []v1.EnvVar{
  522. {Name: "FOO", Value: "BAZ"},
  523. },
  524. },
  525. masterServiceNs: metav1.NamespaceDefault,
  526. nilLister: false,
  527. expectedEnvs: []kubecontainer.EnvVar{
  528. {Name: "FOO", Value: "BAZ"},
  529. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
  530. {Name: "TEST_SERVICE_PORT", Value: "8083"},
  531. {Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
  532. {Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
  533. {Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
  534. {Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
  535. {Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
  536. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.1"},
  537. {Name: "KUBERNETES_SERVICE_PORT", Value: "8081"},
  538. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.1:8081"},
  539. {Name: "KUBERNETES_PORT_8081_TCP", Value: "tcp://1.2.3.1:8081"},
  540. {Name: "KUBERNETES_PORT_8081_TCP_PROTO", Value: "tcp"},
  541. {Name: "KUBERNETES_PORT_8081_TCP_PORT", Value: "8081"},
  542. {Name: "KUBERNETES_PORT_8081_TCP_ADDR", Value: "1.2.3.1"},
  543. },
  544. },
  545. {
  546. name: "master service in pod ns",
  547. ns: "test2",
  548. enableServiceLinks: &falseValue,
  549. container: &v1.Container{
  550. Env: []v1.EnvVar{
  551. {Name: "FOO", Value: "ZAP"},
  552. },
  553. },
  554. masterServiceNs: "kubernetes",
  555. nilLister: false,
  556. expectedEnvs: []kubecontainer.EnvVar{
  557. {Name: "FOO", Value: "ZAP"},
  558. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.6"},
  559. {Name: "KUBERNETES_SERVICE_PORT", Value: "8086"},
  560. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.6:8086"},
  561. {Name: "KUBERNETES_PORT_8086_TCP", Value: "tcp://1.2.3.6:8086"},
  562. {Name: "KUBERNETES_PORT_8086_TCP_PROTO", Value: "tcp"},
  563. {Name: "KUBERNETES_PORT_8086_TCP_PORT", Value: "8086"},
  564. {Name: "KUBERNETES_PORT_8086_TCP_ADDR", Value: "1.2.3.6"},
  565. },
  566. },
  567. {
  568. name: "master service in pod ns, service env vars",
  569. ns: "test2",
  570. enableServiceLinks: &trueValue,
  571. container: &v1.Container{
  572. Env: []v1.EnvVar{
  573. {Name: "FOO", Value: "ZAP"},
  574. },
  575. },
  576. masterServiceNs: "kubernetes",
  577. nilLister: false,
  578. expectedEnvs: []kubecontainer.EnvVar{
  579. {Name: "FOO", Value: "ZAP"},
  580. {Name: "TEST_SERVICE_HOST", Value: "1.2.3.5"},
  581. {Name: "TEST_SERVICE_PORT", Value: "8085"},
  582. {Name: "TEST_PORT", Value: "tcp://1.2.3.5:8085"},
  583. {Name: "TEST_PORT_8085_TCP", Value: "tcp://1.2.3.5:8085"},
  584. {Name: "TEST_PORT_8085_TCP_PROTO", Value: "tcp"},
  585. {Name: "TEST_PORT_8085_TCP_PORT", Value: "8085"},
  586. {Name: "TEST_PORT_8085_TCP_ADDR", Value: "1.2.3.5"},
  587. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.4"},
  588. {Name: "KUBERNETES_SERVICE_PORT", Value: "8084"},
  589. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.4:8084"},
  590. {Name: "KUBERNETES_PORT_8084_TCP", Value: "tcp://1.2.3.4:8084"},
  591. {Name: "KUBERNETES_PORT_8084_TCP_PROTO", Value: "tcp"},
  592. {Name: "KUBERNETES_PORT_8084_TCP_PORT", Value: "8084"},
  593. {Name: "KUBERNETES_PORT_8084_TCP_ADDR", Value: "1.2.3.4"},
  594. },
  595. },
  596. {
  597. name: "pod in master service ns",
  598. ns: "kubernetes",
  599. enableServiceLinks: &falseValue,
  600. container: &v1.Container{},
  601. masterServiceNs: "kubernetes",
  602. nilLister: false,
  603. expectedEnvs: []kubecontainer.EnvVar{
  604. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.6"},
  605. {Name: "KUBERNETES_SERVICE_PORT", Value: "8086"},
  606. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.6:8086"},
  607. {Name: "KUBERNETES_PORT_8086_TCP", Value: "tcp://1.2.3.6:8086"},
  608. {Name: "KUBERNETES_PORT_8086_TCP_PROTO", Value: "tcp"},
  609. {Name: "KUBERNETES_PORT_8086_TCP_PORT", Value: "8086"},
  610. {Name: "KUBERNETES_PORT_8086_TCP_ADDR", Value: "1.2.3.6"},
  611. },
  612. },
  613. {
  614. name: "pod in master service ns, service env vars",
  615. ns: "kubernetes",
  616. enableServiceLinks: &trueValue,
  617. container: &v1.Container{},
  618. masterServiceNs: "kubernetes",
  619. nilLister: false,
  620. expectedEnvs: []kubecontainer.EnvVar{
  621. {Name: "NOT_SPECIAL_SERVICE_HOST", Value: "1.2.3.8"},
  622. {Name: "NOT_SPECIAL_SERVICE_PORT", Value: "8088"},
  623. {Name: "NOT_SPECIAL_PORT", Value: "tcp://1.2.3.8:8088"},
  624. {Name: "NOT_SPECIAL_PORT_8088_TCP", Value: "tcp://1.2.3.8:8088"},
  625. {Name: "NOT_SPECIAL_PORT_8088_TCP_PROTO", Value: "tcp"},
  626. {Name: "NOT_SPECIAL_PORT_8088_TCP_PORT", Value: "8088"},
  627. {Name: "NOT_SPECIAL_PORT_8088_TCP_ADDR", Value: "1.2.3.8"},
  628. {Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.6"},
  629. {Name: "KUBERNETES_SERVICE_PORT", Value: "8086"},
  630. {Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.6:8086"},
  631. {Name: "KUBERNETES_PORT_8086_TCP", Value: "tcp://1.2.3.6:8086"},
  632. {Name: "KUBERNETES_PORT_8086_TCP_PROTO", Value: "tcp"},
  633. {Name: "KUBERNETES_PORT_8086_TCP_PORT", Value: "8086"},
  634. {Name: "KUBERNETES_PORT_8086_TCP_ADDR", Value: "1.2.3.6"},
  635. },
  636. },
  637. {
  638. name: "downward api pod",
  639. ns: "downward-api",
  640. enableServiceLinks: &falseValue,
  641. container: &v1.Container{
  642. Env: []v1.EnvVar{
  643. {
  644. Name: "POD_NAME",
  645. ValueFrom: &v1.EnvVarSource{
  646. FieldRef: &v1.ObjectFieldSelector{
  647. APIVersion: "v1",
  648. FieldPath: "metadata.name",
  649. },
  650. },
  651. },
  652. {
  653. Name: "POD_NAMESPACE",
  654. ValueFrom: &v1.EnvVarSource{
  655. FieldRef: &v1.ObjectFieldSelector{
  656. APIVersion: "v1",
  657. FieldPath: "metadata.namespace",
  658. },
  659. },
  660. },
  661. {
  662. Name: "POD_NODE_NAME",
  663. ValueFrom: &v1.EnvVarSource{
  664. FieldRef: &v1.ObjectFieldSelector{
  665. APIVersion: "v1",
  666. FieldPath: "spec.nodeName",
  667. },
  668. },
  669. },
  670. {
  671. Name: "POD_SERVICE_ACCOUNT_NAME",
  672. ValueFrom: &v1.EnvVarSource{
  673. FieldRef: &v1.ObjectFieldSelector{
  674. APIVersion: "v1",
  675. FieldPath: "spec.serviceAccountName",
  676. },
  677. },
  678. },
  679. {
  680. Name: "POD_IP",
  681. ValueFrom: &v1.EnvVarSource{
  682. FieldRef: &v1.ObjectFieldSelector{
  683. APIVersion: "v1",
  684. FieldPath: "status.podIP",
  685. },
  686. },
  687. },
  688. {
  689. Name: "POD_IPS",
  690. ValueFrom: &v1.EnvVarSource{
  691. FieldRef: &v1.ObjectFieldSelector{
  692. APIVersion: "v1",
  693. FieldPath: "status.podIPs",
  694. },
  695. },
  696. },
  697. {
  698. Name: "HOST_IP",
  699. ValueFrom: &v1.EnvVarSource{
  700. FieldRef: &v1.ObjectFieldSelector{
  701. APIVersion: "v1",
  702. FieldPath: "status.hostIP",
  703. },
  704. },
  705. },
  706. },
  707. },
  708. masterServiceNs: "nothing",
  709. nilLister: true,
  710. expectedEnvs: []kubecontainer.EnvVar{
  711. {Name: "POD_NAME", Value: "dapi-test-pod-name"},
  712. {Name: "POD_NAMESPACE", Value: "downward-api"},
  713. {Name: "POD_NODE_NAME", Value: "node-name"},
  714. {Name: "POD_SERVICE_ACCOUNT_NAME", Value: "special"},
  715. {Name: "POD_IP", Value: "1.2.3.4"},
  716. {Name: "POD_IPS", Value: "1.2.3.4,fd00::6"},
  717. {Name: "HOST_IP", Value: testKubeletHostIP},
  718. },
  719. },
  720. {
  721. name: "env expansion",
  722. ns: "test1",
  723. enableServiceLinks: &falseValue,
  724. container: &v1.Container{
  725. Env: []v1.EnvVar{
  726. {
  727. Name: "TEST_LITERAL",
  728. Value: "test-test-test",
  729. },
  730. {
  731. Name: "POD_NAME",
  732. ValueFrom: &v1.EnvVarSource{
  733. FieldRef: &v1.ObjectFieldSelector{
  734. APIVersion: "v1", //legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
  735. FieldPath: "metadata.name",
  736. },
  737. },
  738. },
  739. {
  740. Name: "OUT_OF_ORDER_TEST",
  741. Value: "$(OUT_OF_ORDER_TARGET)",
  742. },
  743. {
  744. Name: "OUT_OF_ORDER_TARGET",
  745. Value: "FOO",
  746. },
  747. {
  748. Name: "EMPTY_VAR",
  749. },
  750. {
  751. Name: "EMPTY_TEST",
  752. Value: "foo-$(EMPTY_VAR)",
  753. },
  754. {
  755. Name: "POD_NAME_TEST2",
  756. Value: "test2-$(POD_NAME)",
  757. },
  758. {
  759. Name: "POD_NAME_TEST3",
  760. Value: "$(POD_NAME_TEST2)-3",
  761. },
  762. {
  763. Name: "LITERAL_TEST",
  764. Value: "literal-$(TEST_LITERAL)",
  765. },
  766. {
  767. Name: "TEST_UNDEFINED",
  768. Value: "$(UNDEFINED_VAR)",
  769. },
  770. },
  771. },
  772. masterServiceNs: "nothing",
  773. nilLister: false,
  774. expectedEnvs: []kubecontainer.EnvVar{
  775. {
  776. Name: "TEST_LITERAL",
  777. Value: "test-test-test",
  778. },
  779. {
  780. Name: "POD_NAME",
  781. Value: "dapi-test-pod-name",
  782. },
  783. {
  784. Name: "POD_NAME_TEST2",
  785. Value: "test2-dapi-test-pod-name",
  786. },
  787. {
  788. Name: "POD_NAME_TEST3",
  789. Value: "test2-dapi-test-pod-name-3",
  790. },
  791. {
  792. Name: "LITERAL_TEST",
  793. Value: "literal-test-test-test",
  794. },
  795. {
  796. Name: "OUT_OF_ORDER_TEST",
  797. Value: "$(OUT_OF_ORDER_TARGET)",
  798. },
  799. {
  800. Name: "OUT_OF_ORDER_TARGET",
  801. Value: "FOO",
  802. },
  803. {
  804. Name: "TEST_UNDEFINED",
  805. Value: "$(UNDEFINED_VAR)",
  806. },
  807. {
  808. Name: "EMPTY_VAR",
  809. },
  810. {
  811. Name: "EMPTY_TEST",
  812. Value: "foo-",
  813. },
  814. },
  815. },
  816. {
  817. name: "env expansion, service env vars",
  818. ns: "test1",
  819. enableServiceLinks: &trueValue,
  820. container: &v1.Container{
  821. Env: []v1.EnvVar{
  822. {
  823. Name: "TEST_LITERAL",
  824. Value: "test-test-test",
  825. },
  826. {
  827. Name: "POD_NAME",
  828. ValueFrom: &v1.EnvVarSource{
  829. FieldRef: &v1.ObjectFieldSelector{
  830. APIVersion: "v1",
  831. FieldPath: "metadata.name",
  832. },
  833. },
  834. },
  835. {
  836. Name: "OUT_OF_ORDER_TEST",
  837. Value: "$(OUT_OF_ORDER_TARGET)",
  838. },
  839. {
  840. Name: "OUT_OF_ORDER_TARGET",
  841. Value: "FOO",
  842. },
  843. {
  844. Name: "EMPTY_VAR",
  845. },
  846. {
  847. Name: "EMPTY_TEST",
  848. Value: "foo-$(EMPTY_VAR)",
  849. },
  850. {
  851. Name: "POD_NAME_TEST2",
  852. Value: "test2-$(POD_NAME)",
  853. },
  854. {
  855. Name: "POD_NAME_TEST3",
  856. Value: "$(POD_NAME_TEST2)-3",
  857. },
  858. {
  859. Name: "LITERAL_TEST",
  860. Value: "literal-$(TEST_LITERAL)",
  861. },
  862. {
  863. Name: "SERVICE_VAR_TEST",
  864. Value: "$(TEST_SERVICE_HOST):$(TEST_SERVICE_PORT)",
  865. },
  866. {
  867. Name: "TEST_UNDEFINED",
  868. Value: "$(UNDEFINED_VAR)",
  869. },
  870. },
  871. },
  872. masterServiceNs: "nothing",
  873. nilLister: false,
  874. expectedEnvs: []kubecontainer.EnvVar{
  875. {
  876. Name: "TEST_LITERAL",
  877. Value: "test-test-test",
  878. },
  879. {
  880. Name: "POD_NAME",
  881. Value: "dapi-test-pod-name",
  882. },
  883. {
  884. Name: "POD_NAME_TEST2",
  885. Value: "test2-dapi-test-pod-name",
  886. },
  887. {
  888. Name: "POD_NAME_TEST3",
  889. Value: "test2-dapi-test-pod-name-3",
  890. },
  891. {
  892. Name: "LITERAL_TEST",
  893. Value: "literal-test-test-test",
  894. },
  895. {
  896. Name: "TEST_SERVICE_HOST",
  897. Value: "1.2.3.3",
  898. },
  899. {
  900. Name: "TEST_SERVICE_PORT",
  901. Value: "8083",
  902. },
  903. {
  904. Name: "TEST_PORT",
  905. Value: "tcp://1.2.3.3:8083",
  906. },
  907. {
  908. Name: "TEST_PORT_8083_TCP",
  909. Value: "tcp://1.2.3.3:8083",
  910. },
  911. {
  912. Name: "TEST_PORT_8083_TCP_PROTO",
  913. Value: "tcp",
  914. },
  915. {
  916. Name: "TEST_PORT_8083_TCP_PORT",
  917. Value: "8083",
  918. },
  919. {
  920. Name: "TEST_PORT_8083_TCP_ADDR",
  921. Value: "1.2.3.3",
  922. },
  923. {
  924. Name: "SERVICE_VAR_TEST",
  925. Value: "1.2.3.3:8083",
  926. },
  927. {
  928. Name: "OUT_OF_ORDER_TEST",
  929. Value: "$(OUT_OF_ORDER_TARGET)",
  930. },
  931. {
  932. Name: "OUT_OF_ORDER_TARGET",
  933. Value: "FOO",
  934. },
  935. {
  936. Name: "TEST_UNDEFINED",
  937. Value: "$(UNDEFINED_VAR)",
  938. },
  939. {
  940. Name: "EMPTY_VAR",
  941. },
  942. {
  943. Name: "EMPTY_TEST",
  944. Value: "foo-",
  945. },
  946. },
  947. },
  948. {
  949. name: "configmapkeyref_missing_optional",
  950. ns: "test",
  951. enableServiceLinks: &falseValue,
  952. container: &v1.Container{
  953. Env: []v1.EnvVar{
  954. {
  955. Name: "POD_NAME",
  956. ValueFrom: &v1.EnvVarSource{
  957. ConfigMapKeyRef: &v1.ConfigMapKeySelector{
  958. LocalObjectReference: v1.LocalObjectReference{Name: "missing-config-map"},
  959. Key: "key",
  960. Optional: &trueVal,
  961. },
  962. },
  963. },
  964. },
  965. },
  966. masterServiceNs: "nothing",
  967. expectedEnvs: nil,
  968. },
  969. {
  970. name: "configmapkeyref_missing_key_optional",
  971. ns: "test",
  972. enableServiceLinks: &falseValue,
  973. container: &v1.Container{
  974. Env: []v1.EnvVar{
  975. {
  976. Name: "POD_NAME",
  977. ValueFrom: &v1.EnvVarSource{
  978. ConfigMapKeyRef: &v1.ConfigMapKeySelector{
  979. LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"},
  980. Key: "key",
  981. Optional: &trueVal,
  982. },
  983. },
  984. },
  985. },
  986. },
  987. masterServiceNs: "nothing",
  988. nilLister: true,
  989. configMap: &v1.ConfigMap{
  990. ObjectMeta: metav1.ObjectMeta{
  991. Namespace: "test1",
  992. Name: "test-configmap",
  993. },
  994. Data: map[string]string{
  995. "a": "b",
  996. },
  997. },
  998. expectedEnvs: nil,
  999. },
  1000. {
  1001. name: "secretkeyref_missing_optional",
  1002. ns: "test",
  1003. enableServiceLinks: &falseValue,
  1004. container: &v1.Container{
  1005. Env: []v1.EnvVar{
  1006. {
  1007. Name: "POD_NAME",
  1008. ValueFrom: &v1.EnvVarSource{
  1009. SecretKeyRef: &v1.SecretKeySelector{
  1010. LocalObjectReference: v1.LocalObjectReference{Name: "missing-secret"},
  1011. Key: "key",
  1012. Optional: &trueVal,
  1013. },
  1014. },
  1015. },
  1016. },
  1017. },
  1018. masterServiceNs: "nothing",
  1019. expectedEnvs: nil,
  1020. },
  1021. {
  1022. name: "secretkeyref_missing_key_optional",
  1023. ns: "test",
  1024. enableServiceLinks: &falseValue,
  1025. container: &v1.Container{
  1026. Env: []v1.EnvVar{
  1027. {
  1028. Name: "POD_NAME",
  1029. ValueFrom: &v1.EnvVarSource{
  1030. SecretKeyRef: &v1.SecretKeySelector{
  1031. LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"},
  1032. Key: "key",
  1033. Optional: &trueVal,
  1034. },
  1035. },
  1036. },
  1037. },
  1038. },
  1039. masterServiceNs: "nothing",
  1040. nilLister: true,
  1041. secret: &v1.Secret{
  1042. ObjectMeta: metav1.ObjectMeta{
  1043. Namespace: "test1",
  1044. Name: "test-secret",
  1045. },
  1046. Data: map[string][]byte{
  1047. "a": []byte("b"),
  1048. },
  1049. },
  1050. expectedEnvs: nil,
  1051. },
  1052. {
  1053. name: "configmap",
  1054. ns: "test1",
  1055. enableServiceLinks: &falseValue,
  1056. container: &v1.Container{
  1057. EnvFrom: []v1.EnvFromSource{
  1058. {
  1059. ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
  1060. },
  1061. {
  1062. Prefix: "p_",
  1063. ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
  1064. },
  1065. },
  1066. Env: []v1.EnvVar{
  1067. {
  1068. Name: "TEST_LITERAL",
  1069. Value: "test-test-test",
  1070. },
  1071. {
  1072. Name: "EXPANSION_TEST",
  1073. Value: "$(REPLACE_ME)",
  1074. },
  1075. {
  1076. Name: "DUPE_TEST",
  1077. Value: "ENV_VAR",
  1078. },
  1079. },
  1080. },
  1081. masterServiceNs: "nothing",
  1082. nilLister: false,
  1083. configMap: &v1.ConfigMap{
  1084. ObjectMeta: metav1.ObjectMeta{
  1085. Namespace: "test1",
  1086. Name: "test-configmap",
  1087. },
  1088. Data: map[string]string{
  1089. "REPLACE_ME": "FROM_CONFIG_MAP",
  1090. "DUPE_TEST": "CONFIG_MAP",
  1091. },
  1092. },
  1093. expectedEnvs: []kubecontainer.EnvVar{
  1094. {
  1095. Name: "TEST_LITERAL",
  1096. Value: "test-test-test",
  1097. },
  1098. {
  1099. Name: "REPLACE_ME",
  1100. Value: "FROM_CONFIG_MAP",
  1101. },
  1102. {
  1103. Name: "EXPANSION_TEST",
  1104. Value: "FROM_CONFIG_MAP",
  1105. },
  1106. {
  1107. Name: "DUPE_TEST",
  1108. Value: "ENV_VAR",
  1109. },
  1110. {
  1111. Name: "p_REPLACE_ME",
  1112. Value: "FROM_CONFIG_MAP",
  1113. },
  1114. {
  1115. Name: "p_DUPE_TEST",
  1116. Value: "CONFIG_MAP",
  1117. },
  1118. },
  1119. },
  1120. {
  1121. name: "configmap, service env vars",
  1122. ns: "test1",
  1123. enableServiceLinks: &trueValue,
  1124. container: &v1.Container{
  1125. EnvFrom: []v1.EnvFromSource{
  1126. {
  1127. ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
  1128. },
  1129. {
  1130. Prefix: "p_",
  1131. ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
  1132. },
  1133. },
  1134. Env: []v1.EnvVar{
  1135. {
  1136. Name: "TEST_LITERAL",
  1137. Value: "test-test-test",
  1138. },
  1139. {
  1140. Name: "EXPANSION_TEST",
  1141. Value: "$(REPLACE_ME)",
  1142. },
  1143. {
  1144. Name: "DUPE_TEST",
  1145. Value: "ENV_VAR",
  1146. },
  1147. },
  1148. },
  1149. masterServiceNs: "nothing",
  1150. nilLister: false,
  1151. configMap: &v1.ConfigMap{
  1152. ObjectMeta: metav1.ObjectMeta{
  1153. Namespace: "test1",
  1154. Name: "test-configmap",
  1155. },
  1156. Data: map[string]string{
  1157. "REPLACE_ME": "FROM_CONFIG_MAP",
  1158. "DUPE_TEST": "CONFIG_MAP",
  1159. },
  1160. },
  1161. expectedEnvs: []kubecontainer.EnvVar{
  1162. {
  1163. Name: "TEST_LITERAL",
  1164. Value: "test-test-test",
  1165. },
  1166. {
  1167. Name: "TEST_SERVICE_HOST",
  1168. Value: "1.2.3.3",
  1169. },
  1170. {
  1171. Name: "TEST_SERVICE_PORT",
  1172. Value: "8083",
  1173. },
  1174. {
  1175. Name: "TEST_PORT",
  1176. Value: "tcp://1.2.3.3:8083",
  1177. },
  1178. {
  1179. Name: "TEST_PORT_8083_TCP",
  1180. Value: "tcp://1.2.3.3:8083",
  1181. },
  1182. {
  1183. Name: "TEST_PORT_8083_TCP_PROTO",
  1184. Value: "tcp",
  1185. },
  1186. {
  1187. Name: "TEST_PORT_8083_TCP_PORT",
  1188. Value: "8083",
  1189. },
  1190. {
  1191. Name: "TEST_PORT_8083_TCP_ADDR",
  1192. Value: "1.2.3.3",
  1193. },
  1194. {
  1195. Name: "REPLACE_ME",
  1196. Value: "FROM_CONFIG_MAP",
  1197. },
  1198. {
  1199. Name: "EXPANSION_TEST",
  1200. Value: "FROM_CONFIG_MAP",
  1201. },
  1202. {
  1203. Name: "DUPE_TEST",
  1204. Value: "ENV_VAR",
  1205. },
  1206. {
  1207. Name: "p_REPLACE_ME",
  1208. Value: "FROM_CONFIG_MAP",
  1209. },
  1210. {
  1211. Name: "p_DUPE_TEST",
  1212. Value: "CONFIG_MAP",
  1213. },
  1214. },
  1215. },
  1216. {
  1217. name: "configmap_missing",
  1218. ns: "test1",
  1219. enableServiceLinks: &falseValue,
  1220. container: &v1.Container{
  1221. EnvFrom: []v1.EnvFromSource{
  1222. {ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}}},
  1223. },
  1224. },
  1225. masterServiceNs: "nothing",
  1226. expectedError: true,
  1227. },
  1228. {
  1229. name: "configmap_missing_optional",
  1230. ns: "test",
  1231. enableServiceLinks: &falseValue,
  1232. container: &v1.Container{
  1233. EnvFrom: []v1.EnvFromSource{
  1234. {ConfigMapRef: &v1.ConfigMapEnvSource{
  1235. Optional: &trueVal,
  1236. LocalObjectReference: v1.LocalObjectReference{Name: "missing-config-map"}}},
  1237. },
  1238. },
  1239. masterServiceNs: "nothing",
  1240. expectedEnvs: nil,
  1241. },
  1242. {
  1243. name: "configmap_invalid_keys",
  1244. ns: "test",
  1245. enableServiceLinks: &falseValue,
  1246. container: &v1.Container{
  1247. EnvFrom: []v1.EnvFromSource{
  1248. {ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}}},
  1249. },
  1250. },
  1251. masterServiceNs: "nothing",
  1252. configMap: &v1.ConfigMap{
  1253. ObjectMeta: metav1.ObjectMeta{
  1254. Namespace: "test1",
  1255. Name: "test-configmap",
  1256. },
  1257. Data: map[string]string{
  1258. "1234": "abc",
  1259. "1z": "abc",
  1260. "key": "value",
  1261. },
  1262. },
  1263. expectedEnvs: []kubecontainer.EnvVar{
  1264. {
  1265. Name: "key",
  1266. Value: "value",
  1267. },
  1268. },
  1269. expectedEvent: "Warning InvalidEnvironmentVariableNames Keys [1234, 1z] from the EnvFrom configMap test/test-config-map were skipped since they are considered invalid environment variable names.",
  1270. },
  1271. {
  1272. name: "configmap_invalid_keys_valid",
  1273. ns: "test",
  1274. enableServiceLinks: &falseValue,
  1275. container: &v1.Container{
  1276. EnvFrom: []v1.EnvFromSource{
  1277. {
  1278. Prefix: "p_",
  1279. ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
  1280. },
  1281. },
  1282. },
  1283. masterServiceNs: "",
  1284. configMap: &v1.ConfigMap{
  1285. ObjectMeta: metav1.ObjectMeta{
  1286. Namespace: "test1",
  1287. Name: "test-configmap",
  1288. },
  1289. Data: map[string]string{
  1290. "1234": "abc",
  1291. },
  1292. },
  1293. expectedEnvs: []kubecontainer.EnvVar{
  1294. {
  1295. Name: "p_1234",
  1296. Value: "abc",
  1297. },
  1298. },
  1299. },
  1300. {
  1301. name: "secret",
  1302. ns: "test1",
  1303. enableServiceLinks: &falseValue,
  1304. container: &v1.Container{
  1305. EnvFrom: []v1.EnvFromSource{
  1306. {
  1307. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1308. },
  1309. {
  1310. Prefix: "p_",
  1311. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1312. },
  1313. },
  1314. Env: []v1.EnvVar{
  1315. {
  1316. Name: "TEST_LITERAL",
  1317. Value: "test-test-test",
  1318. },
  1319. {
  1320. Name: "EXPANSION_TEST",
  1321. Value: "$(REPLACE_ME)",
  1322. },
  1323. {
  1324. Name: "DUPE_TEST",
  1325. Value: "ENV_VAR",
  1326. },
  1327. },
  1328. },
  1329. masterServiceNs: "nothing",
  1330. nilLister: false,
  1331. secret: &v1.Secret{
  1332. ObjectMeta: metav1.ObjectMeta{
  1333. Namespace: "test1",
  1334. Name: "test-secret",
  1335. },
  1336. Data: map[string][]byte{
  1337. "REPLACE_ME": []byte("FROM_SECRET"),
  1338. "DUPE_TEST": []byte("SECRET"),
  1339. },
  1340. },
  1341. expectedEnvs: []kubecontainer.EnvVar{
  1342. {
  1343. Name: "TEST_LITERAL",
  1344. Value: "test-test-test",
  1345. },
  1346. {
  1347. Name: "REPLACE_ME",
  1348. Value: "FROM_SECRET",
  1349. },
  1350. {
  1351. Name: "EXPANSION_TEST",
  1352. Value: "FROM_SECRET",
  1353. },
  1354. {
  1355. Name: "DUPE_TEST",
  1356. Value: "ENV_VAR",
  1357. },
  1358. {
  1359. Name: "p_REPLACE_ME",
  1360. Value: "FROM_SECRET",
  1361. },
  1362. {
  1363. Name: "p_DUPE_TEST",
  1364. Value: "SECRET",
  1365. },
  1366. },
  1367. },
  1368. {
  1369. name: "secret, service env vars",
  1370. ns: "test1",
  1371. enableServiceLinks: &trueValue,
  1372. container: &v1.Container{
  1373. EnvFrom: []v1.EnvFromSource{
  1374. {
  1375. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1376. },
  1377. {
  1378. Prefix: "p_",
  1379. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1380. },
  1381. },
  1382. Env: []v1.EnvVar{
  1383. {
  1384. Name: "TEST_LITERAL",
  1385. Value: "test-test-test",
  1386. },
  1387. {
  1388. Name: "EXPANSION_TEST",
  1389. Value: "$(REPLACE_ME)",
  1390. },
  1391. {
  1392. Name: "DUPE_TEST",
  1393. Value: "ENV_VAR",
  1394. },
  1395. },
  1396. },
  1397. masterServiceNs: "nothing",
  1398. nilLister: false,
  1399. secret: &v1.Secret{
  1400. ObjectMeta: metav1.ObjectMeta{
  1401. Namespace: "test1",
  1402. Name: "test-secret",
  1403. },
  1404. Data: map[string][]byte{
  1405. "REPLACE_ME": []byte("FROM_SECRET"),
  1406. "DUPE_TEST": []byte("SECRET"),
  1407. },
  1408. },
  1409. expectedEnvs: []kubecontainer.EnvVar{
  1410. {
  1411. Name: "TEST_LITERAL",
  1412. Value: "test-test-test",
  1413. },
  1414. {
  1415. Name: "TEST_SERVICE_HOST",
  1416. Value: "1.2.3.3",
  1417. },
  1418. {
  1419. Name: "TEST_SERVICE_PORT",
  1420. Value: "8083",
  1421. },
  1422. {
  1423. Name: "TEST_PORT",
  1424. Value: "tcp://1.2.3.3:8083",
  1425. },
  1426. {
  1427. Name: "TEST_PORT_8083_TCP",
  1428. Value: "tcp://1.2.3.3:8083",
  1429. },
  1430. {
  1431. Name: "TEST_PORT_8083_TCP_PROTO",
  1432. Value: "tcp",
  1433. },
  1434. {
  1435. Name: "TEST_PORT_8083_TCP_PORT",
  1436. Value: "8083",
  1437. },
  1438. {
  1439. Name: "TEST_PORT_8083_TCP_ADDR",
  1440. Value: "1.2.3.3",
  1441. },
  1442. {
  1443. Name: "REPLACE_ME",
  1444. Value: "FROM_SECRET",
  1445. },
  1446. {
  1447. Name: "EXPANSION_TEST",
  1448. Value: "FROM_SECRET",
  1449. },
  1450. {
  1451. Name: "DUPE_TEST",
  1452. Value: "ENV_VAR",
  1453. },
  1454. {
  1455. Name: "p_REPLACE_ME",
  1456. Value: "FROM_SECRET",
  1457. },
  1458. {
  1459. Name: "p_DUPE_TEST",
  1460. Value: "SECRET",
  1461. },
  1462. },
  1463. },
  1464. {
  1465. name: "secret_missing",
  1466. ns: "test1",
  1467. enableServiceLinks: &falseValue,
  1468. container: &v1.Container{
  1469. EnvFrom: []v1.EnvFromSource{
  1470. {SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}},
  1471. },
  1472. },
  1473. masterServiceNs: "nothing",
  1474. expectedError: true,
  1475. },
  1476. {
  1477. name: "secret_missing_optional",
  1478. ns: "test",
  1479. enableServiceLinks: &falseValue,
  1480. container: &v1.Container{
  1481. EnvFrom: []v1.EnvFromSource{
  1482. {SecretRef: &v1.SecretEnvSource{
  1483. LocalObjectReference: v1.LocalObjectReference{Name: "missing-secret"},
  1484. Optional: &trueVal}},
  1485. },
  1486. },
  1487. masterServiceNs: "nothing",
  1488. expectedEnvs: nil,
  1489. },
  1490. {
  1491. name: "secret_invalid_keys",
  1492. ns: "test",
  1493. enableServiceLinks: &falseValue,
  1494. container: &v1.Container{
  1495. EnvFrom: []v1.EnvFromSource{
  1496. {SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}},
  1497. },
  1498. },
  1499. masterServiceNs: "nothing",
  1500. secret: &v1.Secret{
  1501. ObjectMeta: metav1.ObjectMeta{
  1502. Namespace: "test1",
  1503. Name: "test-secret",
  1504. },
  1505. Data: map[string][]byte{
  1506. "1234": []byte("abc"),
  1507. "1z": []byte("abc"),
  1508. "key.1": []byte("value"),
  1509. },
  1510. },
  1511. expectedEnvs: []kubecontainer.EnvVar{
  1512. {
  1513. Name: "key.1",
  1514. Value: "value",
  1515. },
  1516. },
  1517. expectedEvent: "Warning InvalidEnvironmentVariableNames Keys [1234, 1z] from the EnvFrom secret test/test-secret were skipped since they are considered invalid environment variable names.",
  1518. },
  1519. {
  1520. name: "secret_invalid_keys_valid",
  1521. ns: "test",
  1522. enableServiceLinks: &falseValue,
  1523. container: &v1.Container{
  1524. EnvFrom: []v1.EnvFromSource{
  1525. {
  1526. Prefix: "p_",
  1527. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1528. },
  1529. },
  1530. },
  1531. masterServiceNs: "",
  1532. secret: &v1.Secret{
  1533. ObjectMeta: metav1.ObjectMeta{
  1534. Namespace: "test1",
  1535. Name: "test-secret",
  1536. },
  1537. Data: map[string][]byte{
  1538. "1234.name": []byte("abc"),
  1539. },
  1540. },
  1541. expectedEnvs: []kubecontainer.EnvVar{
  1542. {
  1543. Name: "p_1234.name",
  1544. Value: "abc",
  1545. },
  1546. },
  1547. },
  1548. {
  1549. name: "nil_enableServiceLinks",
  1550. ns: "test",
  1551. enableServiceLinks: nil,
  1552. container: &v1.Container{
  1553. EnvFrom: []v1.EnvFromSource{
  1554. {
  1555. Prefix: "p_",
  1556. SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}},
  1557. },
  1558. },
  1559. },
  1560. masterServiceNs: "",
  1561. secret: &v1.Secret{
  1562. ObjectMeta: metav1.ObjectMeta{
  1563. Namespace: "test1",
  1564. Name: "test-secret",
  1565. },
  1566. Data: map[string][]byte{
  1567. "1234.name": []byte("abc"),
  1568. },
  1569. },
  1570. expectedError: true,
  1571. },
  1572. }
  1573. for _, tc := range testCases {
  1574. fakeRecorder := record.NewFakeRecorder(1)
  1575. testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
  1576. testKubelet.kubelet.recorder = fakeRecorder
  1577. defer testKubelet.Cleanup()
  1578. kl := testKubelet.kubelet
  1579. kl.masterServiceNamespace = tc.masterServiceNs
  1580. if tc.nilLister {
  1581. kl.serviceLister = nil
  1582. } else {
  1583. kl.serviceLister = testServiceLister{services}
  1584. }
  1585. testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
  1586. var err error
  1587. if tc.configMap == nil {
  1588. err = apierrors.NewNotFound(action.GetResource().GroupResource(), "configmap-name")
  1589. }
  1590. return true, tc.configMap, err
  1591. })
  1592. testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
  1593. var err error
  1594. if tc.secret == nil {
  1595. err = apierrors.NewNotFound(action.GetResource().GroupResource(), "secret-name")
  1596. }
  1597. return true, tc.secret, err
  1598. })
  1599. testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
  1600. var err error
  1601. if tc.secret == nil {
  1602. err = errors.New("no secret defined")
  1603. }
  1604. return true, tc.secret, err
  1605. })
  1606. testPod := &v1.Pod{
  1607. ObjectMeta: metav1.ObjectMeta{
  1608. Namespace: tc.ns,
  1609. Name: "dapi-test-pod-name",
  1610. },
  1611. Spec: v1.PodSpec{
  1612. ServiceAccountName: "special",
  1613. NodeName: "node-name",
  1614. EnableServiceLinks: tc.enableServiceLinks,
  1615. },
  1616. }
  1617. podIP := "1.2.3.4"
  1618. podIPs := []string{"1.2.3.4,fd00::6"}
  1619. result, err := kl.makeEnvironmentVariables(testPod, tc.container, podIP, podIPs)
  1620. select {
  1621. case e := <-fakeRecorder.Events:
  1622. assert.Equal(t, tc.expectedEvent, e)
  1623. default:
  1624. assert.Equal(t, "", tc.expectedEvent)
  1625. }
  1626. if tc.expectedError {
  1627. assert.Error(t, err, tc.name)
  1628. } else {
  1629. assert.NoError(t, err, "[%s]", tc.name)
  1630. sort.Sort(envs(result))
  1631. sort.Sort(envs(tc.expectedEnvs))
  1632. assert.Equal(t, tc.expectedEnvs, result, "[%s] env entries", tc.name)
  1633. }
  1634. }
  1635. }
  1636. func waitingState(cName string) v1.ContainerStatus {
  1637. return v1.ContainerStatus{
  1638. Name: cName,
  1639. State: v1.ContainerState{
  1640. Waiting: &v1.ContainerStateWaiting{},
  1641. },
  1642. }
  1643. }
  1644. func waitingStateWithLastTermination(cName string) v1.ContainerStatus {
  1645. return v1.ContainerStatus{
  1646. Name: cName,
  1647. State: v1.ContainerState{
  1648. Waiting: &v1.ContainerStateWaiting{},
  1649. },
  1650. LastTerminationState: v1.ContainerState{
  1651. Terminated: &v1.ContainerStateTerminated{
  1652. ExitCode: 0,
  1653. },
  1654. },
  1655. }
  1656. }
  1657. func runningState(cName string) v1.ContainerStatus {
  1658. return v1.ContainerStatus{
  1659. Name: cName,
  1660. State: v1.ContainerState{
  1661. Running: &v1.ContainerStateRunning{},
  1662. },
  1663. }
  1664. }
  1665. func stoppedState(cName string) v1.ContainerStatus {
  1666. return v1.ContainerStatus{
  1667. Name: cName,
  1668. State: v1.ContainerState{
  1669. Terminated: &v1.ContainerStateTerminated{},
  1670. },
  1671. }
  1672. }
  1673. func succeededState(cName string) v1.ContainerStatus {
  1674. return v1.ContainerStatus{
  1675. Name: cName,
  1676. State: v1.ContainerState{
  1677. Terminated: &v1.ContainerStateTerminated{
  1678. ExitCode: 0,
  1679. },
  1680. },
  1681. }
  1682. }
  1683. func failedState(cName string) v1.ContainerStatus {
  1684. return v1.ContainerStatus{
  1685. Name: cName,
  1686. State: v1.ContainerState{
  1687. Terminated: &v1.ContainerStateTerminated{
  1688. ExitCode: -1,
  1689. },
  1690. },
  1691. }
  1692. }
  1693. func TestPodPhaseWithRestartAlways(t *testing.T) {
  1694. desiredState := v1.PodSpec{
  1695. NodeName: "machine",
  1696. Containers: []v1.Container{
  1697. {Name: "containerA"},
  1698. {Name: "containerB"},
  1699. },
  1700. RestartPolicy: v1.RestartPolicyAlways,
  1701. }
  1702. tests := []struct {
  1703. pod *v1.Pod
  1704. status v1.PodPhase
  1705. test string
  1706. }{
  1707. {&v1.Pod{Spec: desiredState, Status: v1.PodStatus{}}, v1.PodPending, "waiting"},
  1708. {
  1709. &v1.Pod{
  1710. Spec: desiredState,
  1711. Status: v1.PodStatus{
  1712. ContainerStatuses: []v1.ContainerStatus{
  1713. runningState("containerA"),
  1714. runningState("containerB"),
  1715. },
  1716. },
  1717. },
  1718. v1.PodRunning,
  1719. "all running",
  1720. },
  1721. {
  1722. &v1.Pod{
  1723. Spec: desiredState,
  1724. Status: v1.PodStatus{
  1725. ContainerStatuses: []v1.ContainerStatus{
  1726. stoppedState("containerA"),
  1727. stoppedState("containerB"),
  1728. },
  1729. },
  1730. },
  1731. v1.PodRunning,
  1732. "all stopped with restart always",
  1733. },
  1734. {
  1735. &v1.Pod{
  1736. Spec: desiredState,
  1737. Status: v1.PodStatus{
  1738. ContainerStatuses: []v1.ContainerStatus{
  1739. runningState("containerA"),
  1740. stoppedState("containerB"),
  1741. },
  1742. },
  1743. },
  1744. v1.PodRunning,
  1745. "mixed state #1 with restart always",
  1746. },
  1747. {
  1748. &v1.Pod{
  1749. Spec: desiredState,
  1750. Status: v1.PodStatus{
  1751. ContainerStatuses: []v1.ContainerStatus{
  1752. runningState("containerA"),
  1753. },
  1754. },
  1755. },
  1756. v1.PodPending,
  1757. "mixed state #2 with restart always",
  1758. },
  1759. {
  1760. &v1.Pod{
  1761. Spec: desiredState,
  1762. Status: v1.PodStatus{
  1763. ContainerStatuses: []v1.ContainerStatus{
  1764. runningState("containerA"),
  1765. waitingState("containerB"),
  1766. },
  1767. },
  1768. },
  1769. v1.PodPending,
  1770. "mixed state #3 with restart always",
  1771. },
  1772. {
  1773. &v1.Pod{
  1774. Spec: desiredState,
  1775. Status: v1.PodStatus{
  1776. ContainerStatuses: []v1.ContainerStatus{
  1777. runningState("containerA"),
  1778. waitingStateWithLastTermination("containerB"),
  1779. },
  1780. },
  1781. },
  1782. v1.PodRunning,
  1783. "backoff crashloop container with restart always",
  1784. },
  1785. }
  1786. for _, test := range tests {
  1787. status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
  1788. assert.Equal(t, test.status, status, "[test %s]", test.test)
  1789. }
  1790. }
  1791. func TestPodPhaseWithRestartNever(t *testing.T) {
  1792. desiredState := v1.PodSpec{
  1793. NodeName: "machine",
  1794. Containers: []v1.Container{
  1795. {Name: "containerA"},
  1796. {Name: "containerB"},
  1797. },
  1798. RestartPolicy: v1.RestartPolicyNever,
  1799. }
  1800. tests := []struct {
  1801. pod *v1.Pod
  1802. status v1.PodPhase
  1803. test string
  1804. }{
  1805. {&v1.Pod{Spec: desiredState, Status: v1.PodStatus{}}, v1.PodPending, "waiting"},
  1806. {
  1807. &v1.Pod{
  1808. Spec: desiredState,
  1809. Status: v1.PodStatus{
  1810. ContainerStatuses: []v1.ContainerStatus{
  1811. runningState("containerA"),
  1812. runningState("containerB"),
  1813. },
  1814. },
  1815. },
  1816. v1.PodRunning,
  1817. "all running with restart never",
  1818. },
  1819. {
  1820. &v1.Pod{
  1821. Spec: desiredState,
  1822. Status: v1.PodStatus{
  1823. ContainerStatuses: []v1.ContainerStatus{
  1824. succeededState("containerA"),
  1825. succeededState("containerB"),
  1826. },
  1827. },
  1828. },
  1829. v1.PodSucceeded,
  1830. "all succeeded with restart never",
  1831. },
  1832. {
  1833. &v1.Pod{
  1834. Spec: desiredState,
  1835. Status: v1.PodStatus{
  1836. ContainerStatuses: []v1.ContainerStatus{
  1837. failedState("containerA"),
  1838. failedState("containerB"),
  1839. },
  1840. },
  1841. },
  1842. v1.PodFailed,
  1843. "all failed with restart never",
  1844. },
  1845. {
  1846. &v1.Pod{
  1847. Spec: desiredState,
  1848. Status: v1.PodStatus{
  1849. ContainerStatuses: []v1.ContainerStatus{
  1850. runningState("containerA"),
  1851. succeededState("containerB"),
  1852. },
  1853. },
  1854. },
  1855. v1.PodRunning,
  1856. "mixed state #1 with restart never",
  1857. },
  1858. {
  1859. &v1.Pod{
  1860. Spec: desiredState,
  1861. Status: v1.PodStatus{
  1862. ContainerStatuses: []v1.ContainerStatus{
  1863. runningState("containerA"),
  1864. },
  1865. },
  1866. },
  1867. v1.PodPending,
  1868. "mixed state #2 with restart never",
  1869. },
  1870. {
  1871. &v1.Pod{
  1872. Spec: desiredState,
  1873. Status: v1.PodStatus{
  1874. ContainerStatuses: []v1.ContainerStatus{
  1875. runningState("containerA"),
  1876. waitingState("containerB"),
  1877. },
  1878. },
  1879. },
  1880. v1.PodPending,
  1881. "mixed state #3 with restart never",
  1882. },
  1883. }
  1884. for _, test := range tests {
  1885. status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
  1886. assert.Equal(t, test.status, status, "[test %s]", test.test)
  1887. }
  1888. }
  1889. func TestPodPhaseWithRestartOnFailure(t *testing.T) {
  1890. desiredState := v1.PodSpec{
  1891. NodeName: "machine",
  1892. Containers: []v1.Container{
  1893. {Name: "containerA"},
  1894. {Name: "containerB"},
  1895. },
  1896. RestartPolicy: v1.RestartPolicyOnFailure,
  1897. }
  1898. tests := []struct {
  1899. pod *v1.Pod
  1900. status v1.PodPhase
  1901. test string
  1902. }{
  1903. {&v1.Pod{Spec: desiredState, Status: v1.PodStatus{}}, v1.PodPending, "waiting"},
  1904. {
  1905. &v1.Pod{
  1906. Spec: desiredState,
  1907. Status: v1.PodStatus{
  1908. ContainerStatuses: []v1.ContainerStatus{
  1909. runningState("containerA"),
  1910. runningState("containerB"),
  1911. },
  1912. },
  1913. },
  1914. v1.PodRunning,
  1915. "all running with restart onfailure",
  1916. },
  1917. {
  1918. &v1.Pod{
  1919. Spec: desiredState,
  1920. Status: v1.PodStatus{
  1921. ContainerStatuses: []v1.ContainerStatus{
  1922. succeededState("containerA"),
  1923. succeededState("containerB"),
  1924. },
  1925. },
  1926. },
  1927. v1.PodSucceeded,
  1928. "all succeeded with restart onfailure",
  1929. },
  1930. {
  1931. &v1.Pod{
  1932. Spec: desiredState,
  1933. Status: v1.PodStatus{
  1934. ContainerStatuses: []v1.ContainerStatus{
  1935. failedState("containerA"),
  1936. failedState("containerB"),
  1937. },
  1938. },
  1939. },
  1940. v1.PodRunning,
  1941. "all failed with restart never",
  1942. },
  1943. {
  1944. &v1.Pod{
  1945. Spec: desiredState,
  1946. Status: v1.PodStatus{
  1947. ContainerStatuses: []v1.ContainerStatus{
  1948. runningState("containerA"),
  1949. succeededState("containerB"),
  1950. },
  1951. },
  1952. },
  1953. v1.PodRunning,
  1954. "mixed state #1 with restart onfailure",
  1955. },
  1956. {
  1957. &v1.Pod{
  1958. Spec: desiredState,
  1959. Status: v1.PodStatus{
  1960. ContainerStatuses: []v1.ContainerStatus{
  1961. runningState("containerA"),
  1962. },
  1963. },
  1964. },
  1965. v1.PodPending,
  1966. "mixed state #2 with restart onfailure",
  1967. },
  1968. {
  1969. &v1.Pod{
  1970. Spec: desiredState,
  1971. Status: v1.PodStatus{
  1972. ContainerStatuses: []v1.ContainerStatus{
  1973. runningState("containerA"),
  1974. waitingState("containerB"),
  1975. },
  1976. },
  1977. },
  1978. v1.PodPending,
  1979. "mixed state #3 with restart onfailure",
  1980. },
  1981. {
  1982. &v1.Pod{
  1983. Spec: desiredState,
  1984. Status: v1.PodStatus{
  1985. ContainerStatuses: []v1.ContainerStatus{
  1986. runningState("containerA"),
  1987. waitingStateWithLastTermination("containerB"),
  1988. },
  1989. },
  1990. },
  1991. v1.PodRunning,
  1992. "backoff crashloop container with restart onfailure",
  1993. },
  1994. }
  1995. for _, test := range tests {
  1996. status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
  1997. assert.Equal(t, test.status, status, "[test %s]", test.test)
  1998. }
  1999. }
  2000. func TestGetExec(t *testing.T) {
  2001. const (
  2002. podName = "podFoo"
  2003. podNamespace = "nsFoo"
  2004. podUID types.UID = "12345678"
  2005. containerID = "containerFoo"
  2006. tty = true
  2007. )
  2008. var (
  2009. podFullName = kubecontainer.GetPodFullName(podWithUIDNameNs(podUID, podName, podNamespace))
  2010. command = []string{"ls"}
  2011. )
  2012. testcases := []struct {
  2013. description string
  2014. podFullName string
  2015. container string
  2016. expectError bool
  2017. }{{
  2018. description: "success case",
  2019. podFullName: podFullName,
  2020. container: containerID,
  2021. }, {
  2022. description: "no such pod",
  2023. podFullName: "bar" + podFullName,
  2024. container: containerID,
  2025. expectError: true,
  2026. }, {
  2027. description: "no such container",
  2028. podFullName: podFullName,
  2029. container: "containerBar",
  2030. expectError: true,
  2031. }}
  2032. for _, tc := range testcases {
  2033. testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
  2034. defer testKubelet.Cleanup()
  2035. kubelet := testKubelet.kubelet
  2036. testKubelet.fakeRuntime.PodList = []*containertest.FakePod{
  2037. {Pod: &kubecontainer.Pod{
  2038. ID: podUID,
  2039. Name: podName,
  2040. Namespace: podNamespace,
  2041. Containers: []*kubecontainer.Container{
  2042. {Name: containerID,
  2043. ID: kubecontainer.ContainerID{Type: "test", ID: containerID},
  2044. },
  2045. },
  2046. }},
  2047. }
  2048. description := "streaming - " + tc.description
  2049. fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime}
  2050. kubelet.containerRuntime = fakeRuntime
  2051. kubelet.streamingRuntime = fakeRuntime
  2052. redirect, err := kubelet.GetExec(tc.podFullName, podUID, tc.container, command, remotecommand.Options{})
  2053. if tc.expectError {
  2054. assert.Error(t, err, description)
  2055. } else {
  2056. assert.NoError(t, err, description)
  2057. assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect")
  2058. }
  2059. }
  2060. }
  2061. func TestGetPortForward(t *testing.T) {
  2062. const (
  2063. podName = "podFoo"
  2064. podNamespace = "nsFoo"
  2065. podUID types.UID = "12345678"
  2066. port int32 = 5000
  2067. )
  2068. testcases := []struct {
  2069. description string
  2070. podName string
  2071. expectError bool
  2072. }{{
  2073. description: "success case",
  2074. podName: podName,
  2075. }, {
  2076. description: "no such pod",
  2077. podName: "bar",
  2078. expectError: true,
  2079. }}
  2080. for _, tc := range testcases {
  2081. testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
  2082. defer testKubelet.Cleanup()
  2083. kubelet := testKubelet.kubelet
  2084. testKubelet.fakeRuntime.PodList = []*containertest.FakePod{
  2085. {Pod: &kubecontainer.Pod{
  2086. ID: podUID,
  2087. Name: podName,
  2088. Namespace: podNamespace,
  2089. Containers: []*kubecontainer.Container{
  2090. {Name: "foo",
  2091. ID: kubecontainer.ContainerID{Type: "test", ID: "foo"},
  2092. },
  2093. },
  2094. }},
  2095. }
  2096. description := "streaming - " + tc.description
  2097. fakeRuntime := &containertest.FakeStreamingRuntime{FakeRuntime: testKubelet.fakeRuntime}
  2098. kubelet.containerRuntime = fakeRuntime
  2099. kubelet.streamingRuntime = fakeRuntime
  2100. redirect, err := kubelet.GetPortForward(tc.podName, podNamespace, podUID, portforward.V4Options{})
  2101. if tc.expectError {
  2102. assert.Error(t, err, description)
  2103. } else {
  2104. assert.NoError(t, err, description)
  2105. assert.Equal(t, containertest.FakeHost, redirect.Host, description+": redirect")
  2106. }
  2107. }
  2108. }
  2109. func TestHasHostMountPVC(t *testing.T) {
  2110. tests := map[string]struct {
  2111. pvError error
  2112. pvcError error
  2113. expected bool
  2114. podHasPVC bool
  2115. pvcIsHostPath bool
  2116. }{
  2117. "no pvc": {podHasPVC: false, expected: false},
  2118. "error fetching pvc": {
  2119. podHasPVC: true,
  2120. pvcError: fmt.Errorf("foo"),
  2121. expected: false,
  2122. },
  2123. "error fetching pv": {
  2124. podHasPVC: true,
  2125. pvError: fmt.Errorf("foo"),
  2126. expected: false,
  2127. },
  2128. "host path pvc": {
  2129. podHasPVC: true,
  2130. pvcIsHostPath: true,
  2131. expected: true,
  2132. },
  2133. "non host path pvc": {
  2134. podHasPVC: true,
  2135. pvcIsHostPath: false,
  2136. expected: false,
  2137. },
  2138. }
  2139. for k, v := range tests {
  2140. testKubelet := newTestKubelet(t, false)
  2141. defer testKubelet.Cleanup()
  2142. pod := &v1.Pod{
  2143. Spec: v1.PodSpec{},
  2144. }
  2145. volumeToReturn := &v1.PersistentVolume{
  2146. Spec: v1.PersistentVolumeSpec{},
  2147. }
  2148. if v.podHasPVC {
  2149. pod.Spec.Volumes = []v1.Volume{
  2150. {
  2151. VolumeSource: v1.VolumeSource{
  2152. PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{},
  2153. },
  2154. },
  2155. }
  2156. if v.pvcIsHostPath {
  2157. volumeToReturn.Spec.PersistentVolumeSource = v1.PersistentVolumeSource{
  2158. HostPath: &v1.HostPathVolumeSource{},
  2159. }
  2160. }
  2161. }
  2162. testKubelet.fakeKubeClient.AddReactor("get", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) {
  2163. return true, &v1.PersistentVolumeClaim{
  2164. Spec: v1.PersistentVolumeClaimSpec{
  2165. VolumeName: "foo",
  2166. },
  2167. }, v.pvcError
  2168. })
  2169. testKubelet.fakeKubeClient.AddReactor("get", "persistentvolumes", func(action core.Action) (bool, runtime.Object, error) {
  2170. return true, volumeToReturn, v.pvError
  2171. })
  2172. actual := testKubelet.kubelet.hasHostMountPVC(pod)
  2173. if actual != v.expected {
  2174. t.Errorf("%s expected %t but got %t", k, v.expected, actual)
  2175. }
  2176. }
  2177. }
  2178. func TestHasNonNamespacedCapability(t *testing.T) {
  2179. createPodWithCap := func(caps []v1.Capability) *v1.Pod {
  2180. pod := &v1.Pod{
  2181. Spec: v1.PodSpec{
  2182. Containers: []v1.Container{{}},
  2183. },
  2184. }
  2185. if len(caps) > 0 {
  2186. pod.Spec.Containers[0].SecurityContext = &v1.SecurityContext{
  2187. Capabilities: &v1.Capabilities{
  2188. Add: caps,
  2189. },
  2190. }
  2191. }
  2192. return pod
  2193. }
  2194. nilCaps := createPodWithCap([]v1.Capability{v1.Capability("foo")})
  2195. nilCaps.Spec.Containers[0].SecurityContext = nil
  2196. tests := map[string]struct {
  2197. pod *v1.Pod
  2198. expected bool
  2199. }{
  2200. "nil security contxt": {createPodWithCap(nil), false},
  2201. "nil caps": {nilCaps, false},
  2202. "namespaced cap": {createPodWithCap([]v1.Capability{v1.Capability("foo")}), false},
  2203. "non-namespaced cap MKNOD": {createPodWithCap([]v1.Capability{v1.Capability("MKNOD")}), true},
  2204. "non-namespaced cap SYS_TIME": {createPodWithCap([]v1.Capability{v1.Capability("SYS_TIME")}), true},
  2205. "non-namespaced cap SYS_MODULE": {createPodWithCap([]v1.Capability{v1.Capability("SYS_MODULE")}), true},
  2206. }
  2207. for k, v := range tests {
  2208. actual := hasNonNamespacedCapability(v.pod)
  2209. if actual != v.expected {
  2210. t.Errorf("%s failed, expected %t but got %t", k, v.expected, actual)
  2211. }
  2212. }
  2213. }
  2214. func TestHasHostVolume(t *testing.T) {
  2215. pod := &v1.Pod{
  2216. Spec: v1.PodSpec{
  2217. Volumes: []v1.Volume{
  2218. {
  2219. VolumeSource: v1.VolumeSource{
  2220. HostPath: &v1.HostPathVolumeSource{},
  2221. },
  2222. },
  2223. },
  2224. },
  2225. }
  2226. result := hasHostVolume(pod)
  2227. if !result {
  2228. t.Errorf("expected host volume to enable host user namespace")
  2229. }
  2230. pod.Spec.Volumes[0].VolumeSource.HostPath = nil
  2231. result = hasHostVolume(pod)
  2232. if result {
  2233. t.Errorf("expected nil host volume to not enable host user namespace")
  2234. }
  2235. }
  2236. func TestHasHostNamespace(t *testing.T) {
  2237. tests := map[string]struct {
  2238. ps v1.PodSpec
  2239. expected bool
  2240. }{
  2241. "nil psc": {
  2242. ps: v1.PodSpec{},
  2243. expected: false},
  2244. "host pid true": {
  2245. ps: v1.PodSpec{
  2246. HostPID: true,
  2247. SecurityContext: &v1.PodSecurityContext{},
  2248. },
  2249. expected: true,
  2250. },
  2251. "host ipc true": {
  2252. ps: v1.PodSpec{
  2253. HostIPC: true,
  2254. SecurityContext: &v1.PodSecurityContext{},
  2255. },
  2256. expected: true,
  2257. },
  2258. "host net true": {
  2259. ps: v1.PodSpec{
  2260. HostNetwork: true,
  2261. SecurityContext: &v1.PodSecurityContext{},
  2262. },
  2263. expected: true,
  2264. },
  2265. "no host ns": {
  2266. ps: v1.PodSpec{
  2267. SecurityContext: &v1.PodSecurityContext{},
  2268. },
  2269. expected: false,
  2270. },
  2271. }
  2272. for k, v := range tests {
  2273. pod := &v1.Pod{
  2274. Spec: v.ps,
  2275. }
  2276. actual := hasHostNamespace(pod)
  2277. if actual != v.expected {
  2278. t.Errorf("%s failed, expected %t but got %t", k, v.expected, actual)
  2279. }
  2280. }
  2281. }
  2282. func TestTruncatePodHostname(t *testing.T) {
  2283. for c, test := range map[string]struct {
  2284. input string
  2285. output string
  2286. }{
  2287. "valid hostname": {
  2288. input: "test.pod.hostname",
  2289. output: "test.pod.hostname",
  2290. },
  2291. "too long hostname": {
  2292. input: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567.", // 8*9=72 chars
  2293. output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.1234567", //8*8-1=63 chars
  2294. },
  2295. "hostname end with .": {
  2296. input: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456.1234567.", // 8*9-1=71 chars
  2297. output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456", //8*8-2=62 chars
  2298. },
  2299. "hostname end with -": {
  2300. input: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456-1234567.", // 8*9-1=71 chars
  2301. output: "1234567.1234567.1234567.1234567.1234567.1234567.1234567.123456", //8*8-2=62 chars
  2302. },
  2303. } {
  2304. t.Logf("TestCase: %q", c)
  2305. output, err := truncatePodHostnameIfNeeded("test-pod", test.input)
  2306. assert.NoError(t, err)
  2307. assert.Equal(t, test.output, output)
  2308. }
  2309. }