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  }