github.com/argoproj/argo-cd/v3@v3.2.1/util/kube/kube_test.go (about) 1 package kube 2 3 import ( 4 "encoding/json" 5 "log" 6 "os" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 corev1 "k8s.io/api/core/v1" 12 extv1beta1 "k8s.io/api/extensions/v1beta1" 13 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 14 "sigs.k8s.io/yaml" 15 16 "github.com/argoproj/argo-cd/v3/common" 17 ) 18 19 const depWithoutSelector = ` 20 apiVersion: extensions/v1beta1 21 kind: Deployment 22 metadata: 23 name: nginx-deployment 24 spec: 25 template: 26 metadata: 27 labels: 28 app: nginx 29 spec: 30 containers: 31 - image: nginx:1.7.9 32 name: nginx 33 ports: 34 - containerPort: 80 35 ` 36 37 const depWithSelector = ` 38 apiVersion: extensions/v1beta1 39 kind: Deployment 40 metadata: 41 name: nginx-deployment 42 spec: 43 selector: 44 matchLabels: 45 app: nginx 46 template: 47 metadata: 48 labels: 49 app: nginx 50 spec: 51 containers: 52 - image: nginx:1.7.9 53 name: nginx 54 ports: 55 - containerPort: 80 56 ` 57 58 func TestSetLabels(t *testing.T) { 59 for _, yamlStr := range []string{depWithoutSelector, depWithSelector} { 60 var obj unstructured.Unstructured 61 err := yaml.Unmarshal([]byte(yamlStr), &obj) 62 require.NoError(t, err) 63 64 err = SetAppInstanceLabel(&obj, common.LabelKeyAppInstance, "my-app") 65 require.NoError(t, err) 66 67 manifestBytes, err := json.MarshalIndent(obj.Object, "", " ") 68 require.NoError(t, err) 69 log.Println(string(manifestBytes)) 70 71 var depV1Beta1 extv1beta1.Deployment 72 err = json.Unmarshal(manifestBytes, &depV1Beta1) 73 require.NoError(t, err) 74 75 // the following makes sure we are not falling into legacy code which injects labels 76 switch yamlStr { 77 case depWithoutSelector: 78 assert.Nil(t, depV1Beta1.Spec.Selector) 79 case depWithSelector: 80 assert.Len(t, depV1Beta1.Spec.Selector.MatchLabels, 1) 81 assert.Equal(t, "nginx", depV1Beta1.Spec.Selector.MatchLabels["app"]) 82 } 83 assert.Len(t, depV1Beta1.Spec.Template.Labels, 1) 84 assert.Equal(t, "nginx", depV1Beta1.Spec.Template.Labels["app"]) 85 } 86 } 87 88 func TestSetLegacyLabels(t *testing.T) { 89 for _, yamlStr := range []string{depWithoutSelector, depWithSelector} { 90 var obj unstructured.Unstructured 91 err := yaml.Unmarshal([]byte(yamlStr), &obj) 92 require.NoError(t, err) 93 94 err = SetAppInstanceLabel(&obj, common.LabelKeyLegacyApplicationName, "my-app") 95 require.NoError(t, err) 96 97 manifestBytes, err := json.MarshalIndent(obj.Object, "", " ") 98 require.NoError(t, err) 99 log.Println(string(manifestBytes)) 100 101 var depV1Beta1 extv1beta1.Deployment 102 err = json.Unmarshal(manifestBytes, &depV1Beta1) 103 require.NoError(t, err) 104 assert.Len(t, depV1Beta1.Spec.Selector.MatchLabels, 1) 105 assert.Equal(t, "nginx", depV1Beta1.Spec.Selector.MatchLabels["app"]) 106 assert.Len(t, depV1Beta1.Spec.Template.Labels, 2) 107 assert.Equal(t, "nginx", depV1Beta1.Spec.Template.Labels["app"]) 108 assert.Equal(t, "my-app", depV1Beta1.Spec.Template.Labels[common.LabelKeyLegacyApplicationName]) 109 } 110 } 111 112 func TestSetLegacyJobLabel(t *testing.T) { 113 yamlBytes, err := os.ReadFile("testdata/job.yaml") 114 require.NoError(t, err) 115 var obj unstructured.Unstructured 116 err = yaml.Unmarshal(yamlBytes, &obj) 117 require.NoError(t, err) 118 err = SetAppInstanceLabel(&obj, common.LabelKeyLegacyApplicationName, "my-app") 119 require.NoError(t, err) 120 121 manifestBytes, err := json.MarshalIndent(obj.Object, "", " ") 122 require.NoError(t, err) 123 log.Println(string(manifestBytes)) 124 125 job := unstructured.Unstructured{} 126 err = json.Unmarshal(manifestBytes, &job) 127 require.NoError(t, err) 128 129 labels := job.GetLabels() 130 assert.Equal(t, "my-app", labels[common.LabelKeyLegacyApplicationName]) 131 132 templateLabels, ok, err := unstructured.NestedMap(job.UnstructuredContent(), "spec", "template", "metadata", "labels") 133 assert.True(t, ok) 134 require.NoError(t, err) 135 assert.Equal(t, "my-app", templateLabels[common.LabelKeyLegacyApplicationName]) 136 } 137 138 func TestSetSvcLabel(t *testing.T) { 139 yamlBytes, err := os.ReadFile("testdata/svc.yaml") 140 require.NoError(t, err) 141 var obj unstructured.Unstructured 142 err = yaml.Unmarshal(yamlBytes, &obj) 143 require.NoError(t, err) 144 err = SetAppInstanceLabel(&obj, common.LabelKeyAppInstance, "my-app") 145 require.NoError(t, err) 146 147 manifestBytes, err := json.MarshalIndent(obj.Object, "", " ") 148 require.NoError(t, err) 149 log.Println(string(manifestBytes)) 150 151 var s corev1.Service 152 err = json.Unmarshal(manifestBytes, &s) 153 require.NoError(t, err) 154 155 log.Println(s.Name) 156 log.Println(s.ObjectMeta) 157 assert.Equal(t, "my-app", s.Labels[common.LabelKeyAppInstance]) 158 } 159 160 func TestIsValidResourceName(t *testing.T) { 161 assert.True(t, IsValidResourceName("guestbook-ui")) 162 assert.True(t, IsValidResourceName("guestbook-ui1")) 163 assert.False(t, IsValidResourceName("Guestbook-ui")) 164 assert.False(t, IsValidResourceName("-guestbook-ui")) 165 } 166 167 func TestSetAppInstanceAnnotation(t *testing.T) { 168 yamlBytes, err := os.ReadFile("testdata/svc.yaml") 169 require.NoError(t, err) 170 var obj unstructured.Unstructured 171 err = yaml.Unmarshal(yamlBytes, &obj) 172 require.NoError(t, err) 173 err = SetAppInstanceAnnotation(&obj, common.LabelKeyAppInstance, "my-app") 174 require.NoError(t, err) 175 176 manifestBytes, err := json.MarshalIndent(obj.Object, "", " ") 177 require.NoError(t, err) 178 log.Println(string(manifestBytes)) 179 180 var s corev1.Service 181 err = json.Unmarshal(manifestBytes, &s) 182 require.NoError(t, err) 183 184 log.Println(s.Name) 185 log.Println(s.ObjectMeta) 186 assert.Equal(t, "my-app", s.Annotations[common.LabelKeyAppInstance]) 187 } 188 189 func TestSetAppInstanceAnnotationWithInvalidData(t *testing.T) { 190 yamlBytes, err := os.ReadFile("testdata/svc-with-invalid-data.yaml") 191 require.NoError(t, err) 192 var obj unstructured.Unstructured 193 err = yaml.Unmarshal(yamlBytes, &obj) 194 require.NoError(t, err) 195 err = SetAppInstanceAnnotation(&obj, common.LabelKeyAppInstance, "my-app") 196 assert.EqualError(t, err, "failed to get annotations from target object /v1, Kind=Service /my-service: .metadata.annotations accessor error: contains non-string value in the map under key \"invalid-annotation\": <nil> is of the type <nil>, expected string") 197 } 198 199 func TestGetAppInstanceAnnotation(t *testing.T) { 200 yamlBytes, err := os.ReadFile("testdata/svc.yaml") 201 require.NoError(t, err) 202 var obj unstructured.Unstructured 203 err = yaml.Unmarshal(yamlBytes, &obj) 204 require.NoError(t, err) 205 err = SetAppInstanceAnnotation(&obj, common.LabelKeyAppInstance, "my-app") 206 require.NoError(t, err) 207 208 annotation, err := GetAppInstanceAnnotation(&obj, common.LabelKeyAppInstance) 209 require.NoError(t, err) 210 assert.Equal(t, "my-app", annotation) 211 } 212 213 func TestGetAppInstanceAnnotationWithInvalidData(t *testing.T) { 214 yamlBytes, err := os.ReadFile("testdata/svc-with-invalid-data.yaml") 215 require.NoError(t, err) 216 var obj unstructured.Unstructured 217 err = yaml.Unmarshal(yamlBytes, &obj) 218 require.NoError(t, err) 219 220 _, err = GetAppInstanceAnnotation(&obj, "valid-annotation") 221 assert.EqualError(t, err, "failed to get annotations from target object /v1, Kind=Service /my-service: .metadata.annotations accessor error: contains non-string value in the map under key \"invalid-annotation\": <nil> is of the type <nil>, expected string") 222 } 223 224 func TestGetAppInstanceLabel(t *testing.T) { 225 yamlBytes, err := os.ReadFile("testdata/svc.yaml") 226 require.NoError(t, err) 227 var obj unstructured.Unstructured 228 err = yaml.Unmarshal(yamlBytes, &obj) 229 require.NoError(t, err) 230 err = SetAppInstanceLabel(&obj, common.LabelKeyAppInstance, "my-app") 231 require.NoError(t, err) 232 label, err := GetAppInstanceLabel(&obj, common.LabelKeyAppInstance) 233 require.NoError(t, err) 234 assert.Equal(t, "my-app", label) 235 } 236 237 func TestGetAppInstanceLabelWithInvalidData(t *testing.T) { 238 yamlBytes, err := os.ReadFile("testdata/svc-with-invalid-data.yaml") 239 require.NoError(t, err) 240 var obj unstructured.Unstructured 241 err = yaml.Unmarshal(yamlBytes, &obj) 242 require.NoError(t, err) 243 _, err = GetAppInstanceLabel(&obj, "valid-label") 244 assert.EqualError(t, err, "failed to get labels for /v1, Kind=Service /my-service: .metadata.labels accessor error: contains non-string value in the map under key \"invalid-label\": <nil> is of the type <nil>, expected string") 245 } 246 247 func TestRemoveLabel(t *testing.T) { 248 yamlBytes, err := os.ReadFile("testdata/svc.yaml") 249 require.NoError(t, err) 250 var obj unstructured.Unstructured 251 err = yaml.Unmarshal(yamlBytes, &obj) 252 require.NoError(t, err) 253 obj.SetLabels(map[string]string{"test": "value"}) 254 255 err = RemoveLabel(&obj, "test") 256 require.NoError(t, err) 257 258 assert.Nil(t, obj.GetLabels()) 259 } 260 261 func TestRemoveLabelWithInvalidData(t *testing.T) { 262 yamlBytes, err := os.ReadFile("testdata/svc-with-invalid-data.yaml") 263 require.NoError(t, err) 264 var obj unstructured.Unstructured 265 err = yaml.Unmarshal(yamlBytes, &obj) 266 require.NoError(t, err) 267 268 err = RemoveLabel(&obj, "valid-label") 269 assert.EqualError(t, err, "failed to get labels for /v1, Kind=Service /my-service: .metadata.labels accessor error: contains non-string value in the map under key \"invalid-label\": <nil> is of the type <nil>, expected string") 270 }