kubelet_pods_test.go 60 KB

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