github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/deploy/util/util_test.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "testing" 21 22 v1 "k8s.io/api/core/v1" 23 "k8s.io/apimachinery/pkg/runtime/schema" 24 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/yaml" 31 "github.com/GoogleContainerTools/skaffold/testutil" 32 ) 33 34 func TestConsolidateNamespaces(t *testing.T) { 35 tests := []struct { 36 description string 37 oldNamespaces []string 38 newNamespaces []string 39 expected []string 40 }{ 41 { 42 description: "update namespace when not present in runContext", 43 oldNamespaces: []string{"test"}, 44 newNamespaces: []string{"another"}, 45 expected: []string{"another", "test"}, 46 }, 47 { 48 description: "update namespace with duplicates should not return duplicate", 49 oldNamespaces: []string{"test", "foo"}, 50 newNamespaces: []string{"another", "foo", "another"}, 51 expected: []string{"another", "foo", "test"}, 52 }, 53 { 54 description: "update namespaces when namespaces is empty", 55 oldNamespaces: []string{"test", "foo"}, 56 newNamespaces: []string{}, 57 expected: []string{"test", "foo"}, 58 }, 59 { 60 description: "update namespaces when runcontext namespaces is empty", 61 oldNamespaces: []string{}, 62 newNamespaces: []string{"test", "another"}, 63 expected: []string{"another", "test"}, 64 }, 65 { 66 description: "update namespaces when both namespaces and runcontext namespaces is empty", 67 oldNamespaces: []string{}, 68 newNamespaces: []string{}, 69 expected: []string{}, 70 }, 71 { 72 description: "update namespace when runcontext namespace has an empty string", 73 oldNamespaces: []string{""}, 74 newNamespaces: []string{"another"}, 75 expected: []string{"another"}, 76 }, 77 { 78 description: "update namespace when namespace is empty string", 79 oldNamespaces: []string{"test"}, 80 newNamespaces: []string{""}, 81 expected: []string{"test"}, 82 }, 83 { 84 description: "update namespace when namespace is empty string and runContext is empty", 85 oldNamespaces: []string{}, 86 newNamespaces: []string{""}, 87 }, 88 } 89 for _, test := range tests { 90 testutil.Run(t, test.description, func(t *testutil.T) { 91 ns := ConsolidateNamespaces(test.oldNamespaces, test.newNamespaces) 92 93 t.CheckDeepEqual(test.expected, ns) 94 }) 95 } 96 } 97 98 func TestAddTagsToPodSelector(t *testing.T) { 99 tests := []struct { 100 description string 101 artifacts []graph.Artifact 102 deployerArtifacts []graph.Artifact 103 expectedImages []string 104 }{ 105 { 106 description: "empty image list", 107 }, 108 { 109 description: "non-matching image results in empty list", 110 artifacts: []graph.Artifact{ 111 { 112 ImageName: "my-image", 113 Tag: "my-image-tag", 114 }, 115 }, 116 deployerArtifacts: []graph.Artifact{ 117 { 118 ImageName: "not-my-image", 119 }, 120 }, 121 }, 122 { 123 description: "matching images appear in list", 124 artifacts: []graph.Artifact{ 125 { 126 ImageName: "my-image1", 127 Tag: "registry.example.com/repo/my-image1:tag1", 128 }, 129 { 130 ImageName: "my-image2", 131 Tag: "registry.example.com/repo/my-image2:tag2", 132 }, 133 { 134 ImageName: "image-not-in-deployer", 135 Tag: "registry.example.com/repo/my-image3:tag3", 136 }, 137 }, 138 deployerArtifacts: []graph.Artifact{ 139 { 140 ImageName: "my-image1", 141 }, 142 { 143 ImageName: "my-image2", 144 }, 145 }, 146 expectedImages: []string{ 147 "registry.example.com/repo/my-image1:tag1", 148 "registry.example.com/repo/my-image2:tag2", 149 }, 150 }, 151 { 152 description: "images from manifest files with ko:// scheme prefix are sanitized before matching", 153 artifacts: []graph.Artifact{ 154 { 155 ImageName: "ko://git.example.com/Foo/bar", 156 Tag: "registry.example.com/repo/git.example.com/foo/bar:tag", 157 }, 158 }, 159 deployerArtifacts: []graph.Artifact{ 160 { 161 ImageName: "git.example.com/foo/bar", 162 Tag: "ko://git.example.com/Foo/bar", 163 }, 164 }, 165 expectedImages: []string{ 166 "registry.example.com/repo/git.example.com/foo/bar:tag", 167 }, 168 }, 169 } 170 for _, test := range tests { 171 testutil.Run(t, test.description, func(t *testutil.T) { 172 podSelector := kubernetes.NewImageList() 173 AddTagsToPodSelector(test.artifacts, test.deployerArtifacts, podSelector) 174 for _, expectedImage := range test.expectedImages { 175 if exists := podSelector.Select(&v1.Pod{ 176 Spec: v1.PodSpec{ 177 Containers: []v1.Container{ 178 {Image: expectedImage}, 179 }, 180 }, 181 }); !exists { 182 t.Errorf("expected image list to contain %s", expectedImage) 183 } 184 } 185 }) 186 } 187 } 188 189 func TestConsolidateTransformConfiguration(t *testing.T) { 190 tests := []struct { 191 description string 192 shouldErr bool 193 allowSchemaTransforms []latest.ResourceFilter 194 denySchemaTransforms []latest.ResourceFilter 195 flagTransforms latest.ResourceSelectorConfig 196 expected func(map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter) (map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter) 197 }{ 198 { 199 description: "verify schema transform configuration outprioritizes default hardcoded transform configuration", 200 denySchemaTransforms: []latest.ResourceFilter{ 201 { 202 GroupKind: "Deployment.apps", 203 }, 204 }, 205 expected: func(allow map[schema.GroupKind]latest.ResourceFilter, deny map[schema.GroupKind]latest.ResourceFilter) (map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter) { 206 // Deployment.apps removed from hardcoded allowlist 207 delete(allow, schema.GroupKind{Group: "apps", Kind: "Deployment"}) 208 // Deployment.apps added to denylist 209 deny[schema.GroupKind{Group: "apps", Kind: "Deployment"}] = latest.ResourceFilter{GroupKind: "Deployment.apps"} 210 return allow, deny 211 }, 212 }, 213 { 214 description: "verify flag transform configuration outprioritizes schema transform configuration", 215 flagTransforms: latest.ResourceSelectorConfig{ 216 Allow: []latest.ResourceFilter{ 217 { 218 GroupKind: "Test.skaffold.dev", 219 }, 220 }, 221 }, 222 denySchemaTransforms: []latest.ResourceFilter{ 223 { 224 GroupKind: "Test.skaffold.dev", 225 }, 226 }, 227 expected: func(allow map[schema.GroupKind]latest.ResourceFilter, deny map[schema.GroupKind]latest.ResourceFilter) (map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter) { 228 // Test.skaffold.dev added to allowlist as flag config outprioritizes schema config 229 allow[schema.GroupKind{Group: "skaffold.dev", Kind: "Test"}] = latest.ResourceFilter{GroupKind: "Test.skaffold.dev"} 230 return allow, deny 231 }, 232 }, 233 { 234 description: "verify denylist outprioritizes allowlist transform configuration (for same config input source)", 235 flagTransforms: latest.ResourceSelectorConfig{ 236 Allow: []latest.ResourceFilter{ 237 { 238 GroupKind: "Test.skaffold.dev", 239 }, 240 }, 241 Deny: []latest.ResourceFilter{ 242 { 243 GroupKind: "Test.skaffold.dev", 244 }, 245 }, 246 }, 247 expected: func(allow map[schema.GroupKind]latest.ResourceFilter, deny map[schema.GroupKind]latest.ResourceFilter) (map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter) { 248 // Test.skaffold.dev added to denylist as deny config outprioritizes allow config for same priority config source (both flag config) 249 deny[schema.GroupKind{Group: "skaffold.dev", Kind: "Test"}] = latest.ResourceFilter{GroupKind: "Test.skaffold.dev"} 250 return allow, deny 251 }, 252 }, 253 } 254 for _, test := range tests { 255 testutil.Run(t, test.description, func(t *testutil.T) { 256 // convert flagTransform struct to yaml 257 buf, err := yaml.Marshal(test.flagTransforms) 258 if err != nil { 259 t.Fatalf("error marshalling flagTransforms test inputs: %v", err) 260 } 261 262 // denybuf, err := yaml.Marshal(test.denyFlagTransforms) 263 // if err != nil { 264 // t.Fatalf("error marshalling denyFlagTransforms test inputs: %v", err) 265 // } 266 267 flagTransformYAMLFile := t.TempFile("TestConsolidateTransformConfiguration", buf) 268 269 cfg := &mockDeployConfig{ 270 transformAllowList: test.allowSchemaTransforms, 271 transformDenyList: test.denySchemaTransforms, 272 transformRulesFile: flagTransformYAMLFile, 273 } 274 allowlist, denylist, err := ConsolidateTransformConfiguration(cfg) 275 t.CheckError(test.shouldErr, err) 276 277 copyAllow := map[schema.GroupKind]latest.ResourceFilter{} 278 for k, v := range manifest.TransformAllowlist { 279 copyAllow[k] = v 280 } 281 282 copyDeny := map[schema.GroupKind]latest.ResourceFilter{} 283 for k, v := range manifest.TransformDenylist { 284 copyDeny[k] = v 285 } 286 expectedAllowlist, expectedDenyList := test.expected(copyAllow, copyDeny) 287 t.CheckDeepEqual(expectedAllowlist, allowlist) 288 t.CheckDeepEqual(expectedDenyList, denylist) 289 }) 290 } 291 } 292 293 type mockDeployConfig struct { 294 runcontext.RunContext // Embedded to provide the default values. 295 transformAllowList []latest.ResourceFilter 296 transformDenyList []latest.ResourceFilter 297 transformRulesFile string 298 } 299 300 func (c *mockDeployConfig) ForceDeploy() bool { return false } 301 func (c *mockDeployConfig) GetKubeConfig() string { return "" } 302 func (c *mockDeployConfig) GetKubeContext() string { return "" } 303 func (c *mockDeployConfig) GetKubeNamespace() string { return "" } 304 func (c *mockDeployConfig) ConfigurationFile() string { return "" } 305 func (c *mockDeployConfig) PortForwardResources() []*latest.PortForwardResource { return nil } 306 func (c *mockDeployConfig) TransformAllowList() []latest.ResourceFilter { 307 return c.transformAllowList 308 } 309 func (c *mockDeployConfig) TransformDenyList() []latest.ResourceFilter { 310 return c.transformDenyList 311 } 312 func (c *mockDeployConfig) TransformRulesFile() string { return c.transformRulesFile }