github.com/argoproj/argo-cd/v3@v3.2.1/cmd/util/app_test.go (about)

     1  package util
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/spf13/cobra"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    13  
    14  	"k8s.io/apimachinery/pkg/util/intstr"
    15  )
    16  
    17  func Test_setHelmOpt(t *testing.T) {
    18  	t.Run("Zero", func(t *testing.T) {
    19  		src := v1alpha1.ApplicationSource{}
    20  		setHelmOpt(&src, helmOpts{})
    21  		assert.Nil(t, src.Helm)
    22  	})
    23  	t.Run("ValueFiles", func(t *testing.T) {
    24  		src := v1alpha1.ApplicationSource{}
    25  		setHelmOpt(&src, helmOpts{valueFiles: []string{"foo"}})
    26  		assert.Equal(t, []string{"foo"}, src.Helm.ValueFiles)
    27  	})
    28  	t.Run("IgnoreMissingValueFiles", func(t *testing.T) {
    29  		src := v1alpha1.ApplicationSource{}
    30  		setHelmOpt(&src, helmOpts{ignoreMissingValueFiles: true})
    31  		assert.True(t, src.Helm.IgnoreMissingValueFiles)
    32  	})
    33  	t.Run("ReleaseName", func(t *testing.T) {
    34  		src := v1alpha1.ApplicationSource{}
    35  		setHelmOpt(&src, helmOpts{releaseName: "foo"})
    36  		assert.Equal(t, "foo", src.Helm.ReleaseName)
    37  	})
    38  	t.Run("HelmSets", func(t *testing.T) {
    39  		src := v1alpha1.ApplicationSource{}
    40  		setHelmOpt(&src, helmOpts{helmSets: []string{"foo=bar"}})
    41  		assert.Equal(t, []v1alpha1.HelmParameter{{Name: "foo", Value: "bar"}}, src.Helm.Parameters)
    42  	})
    43  	t.Run("HelmSetStrings", func(t *testing.T) {
    44  		src := v1alpha1.ApplicationSource{}
    45  		setHelmOpt(&src, helmOpts{helmSetStrings: []string{"foo=bar"}})
    46  		assert.Equal(t, []v1alpha1.HelmParameter{{Name: "foo", Value: "bar", ForceString: true}}, src.Helm.Parameters)
    47  	})
    48  	t.Run("HelmSetFiles", func(t *testing.T) {
    49  		src := v1alpha1.ApplicationSource{}
    50  		setHelmOpt(&src, helmOpts{helmSetFiles: []string{"foo=bar"}})
    51  		assert.Equal(t, []v1alpha1.HelmFileParameter{{Name: "foo", Path: "bar"}}, src.Helm.FileParameters)
    52  	})
    53  	t.Run("Version", func(t *testing.T) {
    54  		src := v1alpha1.ApplicationSource{}
    55  		setHelmOpt(&src, helmOpts{version: "v3"})
    56  		assert.Equal(t, "v3", src.Helm.Version)
    57  	})
    58  	t.Run("HelmPassCredentials", func(t *testing.T) {
    59  		src := v1alpha1.ApplicationSource{}
    60  		setHelmOpt(&src, helmOpts{passCredentials: true})
    61  		assert.True(t, src.Helm.PassCredentials)
    62  	})
    63  	t.Run("HelmSkipCrds", func(t *testing.T) {
    64  		src := v1alpha1.ApplicationSource{}
    65  		setHelmOpt(&src, helmOpts{skipCrds: true})
    66  		assert.True(t, src.Helm.SkipCrds)
    67  	})
    68  	t.Run("HelmSkipSchemaValidation", func(t *testing.T) {
    69  		src := v1alpha1.ApplicationSource{}
    70  		setHelmOpt(&src, helmOpts{skipSchemaValidation: true})
    71  		assert.True(t, src.Helm.SkipSchemaValidation)
    72  	})
    73  	t.Run("HelmSkipTests", func(t *testing.T) {
    74  		src := v1alpha1.ApplicationSource{}
    75  		setHelmOpt(&src, helmOpts{skipTests: true})
    76  		assert.True(t, src.Helm.SkipTests)
    77  	})
    78  	t.Run("HelmNamespace", func(t *testing.T) {
    79  		src := v1alpha1.ApplicationSource{}
    80  		setHelmOpt(&src, helmOpts{namespace: "custom-namespace"})
    81  		assert.Equal(t, "custom-namespace", src.Helm.Namespace)
    82  	})
    83  	t.Run("HelmKubeVersion", func(t *testing.T) {
    84  		src := v1alpha1.ApplicationSource{}
    85  		setHelmOpt(&src, helmOpts{kubeVersion: "v1.16.0"})
    86  		assert.Equal(t, "v1.16.0", src.Helm.KubeVersion)
    87  	})
    88  	t.Run("HelmApiVersions", func(t *testing.T) {
    89  		src := v1alpha1.ApplicationSource{}
    90  		setHelmOpt(&src, helmOpts{apiVersions: []string{"v1", "v2"}})
    91  		assert.Equal(t, []string{"v1", "v2"}, src.Helm.APIVersions)
    92  	})
    93  }
    94  
    95  func Test_setKustomizeOpt(t *testing.T) {
    96  	t.Run("No kustomize", func(t *testing.T) {
    97  		src := v1alpha1.ApplicationSource{}
    98  		setKustomizeOpt(&src, kustomizeOpts{})
    99  		assert.Nil(t, src.Kustomize)
   100  	})
   101  	t.Run("Name prefix", func(t *testing.T) {
   102  		src := v1alpha1.ApplicationSource{}
   103  		setKustomizeOpt(&src, kustomizeOpts{namePrefix: "test-"})
   104  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{NamePrefix: "test-"}, src.Kustomize)
   105  	})
   106  	t.Run("Name suffix", func(t *testing.T) {
   107  		src := v1alpha1.ApplicationSource{}
   108  		setKustomizeOpt(&src, kustomizeOpts{nameSuffix: "-test"})
   109  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{NameSuffix: "-test"}, src.Kustomize)
   110  	})
   111  	t.Run("Images", func(t *testing.T) {
   112  		src := v1alpha1.ApplicationSource{}
   113  		setKustomizeOpt(&src, kustomizeOpts{images: []string{"org/image:v1", "org/image:v2"}})
   114  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{Images: v1alpha1.KustomizeImages{v1alpha1.KustomizeImage("org/image:v2")}}, src.Kustomize)
   115  	})
   116  	t.Run("Replicas", func(t *testing.T) {
   117  		src := v1alpha1.ApplicationSource{}
   118  		testReplicasString := []string{"my-deployment=2", "my-statefulset=4"}
   119  		testReplicas := v1alpha1.KustomizeReplicas{
   120  			{
   121  				Name:  "my-deployment",
   122  				Count: intstr.FromInt(2),
   123  			},
   124  			{
   125  				Name:  "my-statefulset",
   126  				Count: intstr.FromInt(4),
   127  			},
   128  		}
   129  		setKustomizeOpt(&src, kustomizeOpts{replicas: testReplicasString})
   130  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{Replicas: testReplicas}, src.Kustomize)
   131  	})
   132  	t.Run("Version", func(t *testing.T) {
   133  		src := v1alpha1.ApplicationSource{}
   134  		setKustomizeOpt(&src, kustomizeOpts{version: "v0.1"})
   135  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{Version: "v0.1"}, src.Kustomize)
   136  	})
   137  	t.Run("Namespace", func(t *testing.T) {
   138  		src := v1alpha1.ApplicationSource{}
   139  		setKustomizeOpt(&src, kustomizeOpts{namespace: "custom-namespace"})
   140  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{Namespace: "custom-namespace"}, src.Kustomize)
   141  	})
   142  	t.Run("KubeVersion", func(t *testing.T) {
   143  		src := v1alpha1.ApplicationSource{}
   144  		setKustomizeOpt(&src, kustomizeOpts{kubeVersion: "999.999.999"})
   145  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{KubeVersion: "999.999.999"}, src.Kustomize)
   146  	})
   147  	t.Run("ApiVersions", func(t *testing.T) {
   148  		src := v1alpha1.ApplicationSource{}
   149  		setKustomizeOpt(&src, kustomizeOpts{apiVersions: []string{"v1", "v2"}})
   150  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{APIVersions: []string{"v1", "v2"}}, src.Kustomize)
   151  	})
   152  	t.Run("Common labels", func(t *testing.T) {
   153  		src := v1alpha1.ApplicationSource{}
   154  		setKustomizeOpt(&src, kustomizeOpts{commonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}})
   155  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{CommonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}}, src.Kustomize)
   156  	})
   157  	t.Run("Common annotations", func(t *testing.T) {
   158  		src := v1alpha1.ApplicationSource{}
   159  		setKustomizeOpt(&src, kustomizeOpts{commonAnnotations: map[string]string{"foo1": "bar1", "foo2": "bar2"}})
   160  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{CommonAnnotations: map[string]string{"foo1": "bar1", "foo2": "bar2"}}, src.Kustomize)
   161  	})
   162  	t.Run("Label Without Selector", func(t *testing.T) {
   163  		src := v1alpha1.ApplicationSource{}
   164  		setKustomizeOpt(&src, kustomizeOpts{commonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}, labelWithoutSelector: true})
   165  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{CommonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}, LabelWithoutSelector: true}, src.Kustomize)
   166  	})
   167  	t.Run("Label include templates", func(t *testing.T) {
   168  		src := v1alpha1.ApplicationSource{}
   169  		setKustomizeOpt(&src, kustomizeOpts{commonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}, labelIncludeTemplates: true})
   170  		assert.Equal(t, &v1alpha1.ApplicationSourceKustomize{CommonLabels: map[string]string{"foo1": "bar1", "foo2": "bar2"}, LabelIncludeTemplates: true}, src.Kustomize)
   171  	})
   172  	t.Run("IgnoreMissingComponents", func(t *testing.T) {
   173  		src := v1alpha1.ApplicationSource{}
   174  		setKustomizeOpt(&src, kustomizeOpts{ignoreMissingComponents: true})
   175  		t.Logf("HERE IS THE SOURCE\n %+v\n", src)
   176  		assert.True(t, src.Kustomize.IgnoreMissingComponents)
   177  	})
   178  }
   179  
   180  func Test_setJsonnetOpt(t *testing.T) {
   181  	t.Run("TlaSets", func(t *testing.T) {
   182  		src := v1alpha1.ApplicationSource{}
   183  		setJsonnetOpt(&src, []string{"foo=bar"}, false)
   184  		assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}}, src.Directory.Jsonnet.TLAs)
   185  		setJsonnetOpt(&src, []string{"bar=baz"}, false)
   186  		assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}, {Name: "bar", Value: "baz"}}, src.Directory.Jsonnet.TLAs)
   187  	})
   188  	t.Run("ExtSets", func(t *testing.T) {
   189  		src := v1alpha1.ApplicationSource{}
   190  		setJsonnetOptExtVar(&src, []string{"foo=bar"}, false)
   191  		assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}}, src.Directory.Jsonnet.ExtVars)
   192  		setJsonnetOptExtVar(&src, []string{"bar=baz"}, false)
   193  		assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}, {Name: "bar", Value: "baz"}}, src.Directory.Jsonnet.ExtVars)
   194  	})
   195  }
   196  
   197  func Test_setPluginOptEnvs(t *testing.T) {
   198  	t.Run("PluginEnvs", func(t *testing.T) {
   199  		src := v1alpha1.ApplicationSource{}
   200  		setPluginOptEnvs(&src, []string{"FOO=bar"})
   201  		assert.Equal(t, v1alpha1.EnvEntry{Name: "FOO", Value: "bar"}, *src.Plugin.Env[0])
   202  		setPluginOptEnvs(&src, []string{"BAR=baz"})
   203  		assert.Equal(t, v1alpha1.EnvEntry{Name: "BAR", Value: "baz"}, *src.Plugin.Env[1])
   204  		setPluginOptEnvs(&src, []string{"FOO=baz"})
   205  		assert.Equal(t, v1alpha1.EnvEntry{Name: "FOO", Value: "baz"}, *src.Plugin.Env[0])
   206  	})
   207  }
   208  
   209  type appOptionsFixture struct {
   210  	spec    *v1alpha1.ApplicationSpec
   211  	command *cobra.Command
   212  	options *AppOptions
   213  }
   214  
   215  func (f *appOptionsFixture) SetFlag(key, value string) error {
   216  	err := f.command.Flags().Set(key, value)
   217  	if err != nil {
   218  		return err
   219  	}
   220  	_ = SetAppSpecOptions(f.command.Flags(), f.spec, f.options, 0)
   221  	return err
   222  }
   223  
   224  func (f *appOptionsFixture) SetFlagWithSourcePosition(key, value string, sourcePosition int) error {
   225  	err := f.command.Flags().Set(key, value)
   226  	if err != nil {
   227  		return err
   228  	}
   229  	_ = SetAppSpecOptions(f.command.Flags(), f.spec, f.options, sourcePosition)
   230  	return err
   231  }
   232  
   233  func newAppOptionsFixture() *appOptionsFixture {
   234  	fixture := &appOptionsFixture{
   235  		spec: &v1alpha1.ApplicationSpec{
   236  			Source: &v1alpha1.ApplicationSource{},
   237  		},
   238  		command: &cobra.Command{},
   239  		options: &AppOptions{},
   240  	}
   241  	AddAppFlags(fixture.command, fixture.options)
   242  	return fixture
   243  }
   244  
   245  func Test_setAppSpecOptions(t *testing.T) {
   246  	f := newAppOptionsFixture()
   247  	t.Run("SyncPolicy", func(t *testing.T) {
   248  		require.NoError(t, f.SetFlag("sync-policy", "automated"))
   249  		assert.NotNil(t, f.spec.SyncPolicy.Automated)
   250  
   251  		f.spec.SyncPolicy = nil
   252  		require.NoError(t, f.SetFlag("sync-policy", "automatic"))
   253  		assert.NotNil(t, f.spec.SyncPolicy.Automated)
   254  
   255  		f.spec.SyncPolicy = nil
   256  		require.NoError(t, f.SetFlag("sync-policy", "auto"))
   257  		assert.NotNil(t, f.spec.SyncPolicy.Automated)
   258  
   259  		require.NoError(t, f.SetFlag("sync-policy", "none"))
   260  		assert.Nil(t, f.spec.SyncPolicy)
   261  	})
   262  	t.Run("SyncOptions", func(t *testing.T) {
   263  		require.NoError(t, f.SetFlag("sync-option", "a=1"))
   264  		assert.True(t, f.spec.SyncPolicy.SyncOptions.HasOption("a=1"))
   265  
   266  		// remove the options using !
   267  		require.NoError(t, f.SetFlag("sync-option", "!a=1"))
   268  		assert.Nil(t, f.spec.SyncPolicy)
   269  	})
   270  	t.Run("RetryLimit", func(t *testing.T) {
   271  		require.NoError(t, f.SetFlag("sync-retry-limit", "5"))
   272  		assert.Equal(t, int64(5), f.spec.SyncPolicy.Retry.Limit)
   273  
   274  		require.NoError(t, f.SetFlag("sync-retry-limit", "0"))
   275  		assert.Nil(t, f.spec.SyncPolicy.Retry)
   276  	})
   277  	t.Run("RetryRefresh", func(t *testing.T) {
   278  		require.NoError(t, f.SetFlag("sync-retry-refresh", "true"))
   279  		assert.True(t, f.spec.SyncPolicy.Retry.Refresh)
   280  
   281  		require.NoError(t, f.SetFlag("sync-retry-refresh", "false"))
   282  		assert.False(t, f.spec.SyncPolicy.Retry.Refresh)
   283  	})
   284  	t.Run("Kustomize", func(t *testing.T) {
   285  		require.NoError(t, f.SetFlag("kustomize-replica", "my-deployment=2"))
   286  		require.NoError(t, f.SetFlag("kustomize-replica", "my-statefulset=4"))
   287  		assert.Equal(t, v1alpha1.KustomizeReplicas{{Name: "my-deployment", Count: intstr.FromInt(2)}, {Name: "my-statefulset", Count: intstr.FromInt(4)}}, f.spec.Source.Kustomize.Replicas)
   288  	})
   289  	t.Run("Kustomize Namespace", func(t *testing.T) {
   290  		require.NoError(t, f.SetFlag("kustomize-namespace", "override-namespace"))
   291  		assert.Equal(t, "override-namespace", f.spec.Source.Kustomize.Namespace)
   292  	})
   293  	t.Run("Kustomize Kube Version", func(t *testing.T) {
   294  		require.NoError(t, f.SetFlag("kustomize-kube-version", "999.999.999"))
   295  		assert.Equal(t, "999.999.999", f.spec.Source.Kustomize.KubeVersion)
   296  	})
   297  	t.Run("Kustomize API Versions", func(t *testing.T) {
   298  		require.NoError(t, f.SetFlag("kustomize-api-versions", "v1"))
   299  		require.NoError(t, f.SetFlag("kustomize-api-versions", "v2"))
   300  		assert.Equal(t, []string{"v1", "v2"}, f.spec.Source.Kustomize.APIVersions)
   301  	})
   302  	t.Run("Helm Namespace", func(t *testing.T) {
   303  		require.NoError(t, f.SetFlag("helm-namespace", "override-namespace"))
   304  		assert.Equal(t, "override-namespace", f.spec.Source.Helm.Namespace)
   305  	})
   306  	t.Run("Helm Kube Version", func(t *testing.T) {
   307  		require.NoError(t, f.SetFlag("kustomize-kube-version", "999.999.999"))
   308  		assert.Equal(t, "999.999.999", f.spec.Source.Kustomize.KubeVersion)
   309  	})
   310  	t.Run("Helm API Versions", func(t *testing.T) {
   311  		require.NoError(t, f.SetFlag("helm-api-versions", "v1"))
   312  		require.NoError(t, f.SetFlag("helm-api-versions", "v2"))
   313  		assert.Equal(t, []string{"v1", "v2"}, f.spec.Source.Helm.APIVersions)
   314  	})
   315  	t.Run("source hydrator", func(t *testing.T) {
   316  		require.NoError(t, f.SetFlag("dry-source-repo", "https://github.com/argoproj/argocd-example-apps"))
   317  		assert.Equal(t, "https://github.com/argoproj/argocd-example-apps", f.spec.SourceHydrator.DrySource.RepoURL)
   318  
   319  		require.NoError(t, f.SetFlag("dry-source-path", "apps"))
   320  		assert.Equal(t, "apps", f.spec.SourceHydrator.DrySource.Path)
   321  
   322  		require.NoError(t, f.SetFlag("dry-source-revision", "HEAD"))
   323  		assert.Equal(t, "HEAD", f.spec.SourceHydrator.DrySource.TargetRevision)
   324  
   325  		require.NoError(t, f.SetFlag("sync-source-branch", "env/test"))
   326  		assert.Equal(t, "env/test", f.spec.SourceHydrator.SyncSource.TargetBranch)
   327  
   328  		require.NoError(t, f.SetFlag("sync-source-path", "apps"))
   329  		assert.Equal(t, "apps", f.spec.SourceHydrator.SyncSource.Path)
   330  
   331  		require.NoError(t, f.SetFlag("hydrate-to-branch", "env/test-next"))
   332  		assert.Equal(t, "env/test-next", f.spec.SourceHydrator.HydrateTo.TargetBranch)
   333  
   334  		require.NoError(t, f.SetFlag("hydrate-to-branch", ""))
   335  		assert.Nil(t, f.spec.SourceHydrator.HydrateTo)
   336  	})
   337  }
   338  
   339  func newMultiSourceAppOptionsFixture() *appOptionsFixture {
   340  	fixture := &appOptionsFixture{
   341  		spec: &v1alpha1.ApplicationSpec{
   342  			Sources: v1alpha1.ApplicationSources{
   343  				v1alpha1.ApplicationSource{},
   344  				v1alpha1.ApplicationSource{},
   345  			},
   346  		},
   347  		command: &cobra.Command{},
   348  		options: &AppOptions{},
   349  	}
   350  	AddAppFlags(fixture.command, fixture.options)
   351  	return fixture
   352  }
   353  
   354  func Test_setAppSpecOptionsMultiSourceApp(t *testing.T) {
   355  	f := newMultiSourceAppOptionsFixture()
   356  	sourcePosition := 0
   357  	sourcePosition1 := 1
   358  	sourcePosition2 := 2
   359  	t.Run("SyncPolicy", func(t *testing.T) {
   360  		require.NoError(t, f.SetFlagWithSourcePosition("sync-policy", "automated", sourcePosition1))
   361  		assert.NotNil(t, f.spec.SyncPolicy.Automated)
   362  
   363  		f.spec.SyncPolicy = nil
   364  		require.NoError(t, f.SetFlagWithSourcePosition("sync-policy", "automatic", sourcePosition1))
   365  		assert.NotNil(t, f.spec.SyncPolicy.Automated)
   366  	})
   367  	t.Run("Helm - SourcePosition 0", func(t *testing.T) {
   368  		require.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v2", sourcePosition))
   369  		assert.Len(t, f.spec.GetSources(), 2)
   370  		assert.Equal(t, "v2", f.spec.GetSources()[sourcePosition].Helm.Version)
   371  	})
   372  	t.Run("Kustomize", func(t *testing.T) {
   373  		require.NoError(t, f.SetFlagWithSourcePosition("kustomize-replica", "my-deployment=2", sourcePosition1))
   374  		assert.Equal(t, v1alpha1.KustomizeReplicas{{Name: "my-deployment", Count: intstr.FromInt(2)}}, f.spec.Sources[sourcePosition1-1].Kustomize.Replicas)
   375  		require.NoError(t, f.SetFlagWithSourcePosition("kustomize-replica", "my-deployment=4", sourcePosition2))
   376  		assert.Equal(t, v1alpha1.KustomizeReplicas{{Name: "my-deployment", Count: intstr.FromInt(4)}}, f.spec.Sources[sourcePosition2-1].Kustomize.Replicas)
   377  	})
   378  	t.Run("Helm", func(t *testing.T) {
   379  		require.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v2", sourcePosition1))
   380  		require.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v3", sourcePosition2))
   381  		assert.Len(t, f.spec.GetSources(), 2)
   382  		assert.Equal(t, "v2", f.spec.GetSources()[sourcePosition1-1].Helm.Version)
   383  		assert.Equal(t, "v3", f.spec.GetSources()[sourcePosition2-1].Helm.Version)
   384  	})
   385  }
   386  
   387  func Test_setAnnotations(t *testing.T) {
   388  	t.Run("Annotations", func(t *testing.T) {
   389  		app := v1alpha1.Application{}
   390  		setAnnotations(&app, []string{"hoge=foo", "huga=bar"})
   391  		assert.Equal(t, map[string]string{"hoge": "foo", "huga": "bar"}, app.Annotations)
   392  	})
   393  	t.Run("Annotations value contains equal", func(t *testing.T) {
   394  		app := v1alpha1.Application{}
   395  		setAnnotations(&app, []string{"hoge=foo=bar"})
   396  		assert.Equal(t, map[string]string{"hoge": "foo=bar"}, app.Annotations)
   397  	})
   398  	t.Run("Annotations empty value", func(t *testing.T) {
   399  		app := v1alpha1.Application{}
   400  		setAnnotations(&app, []string{"hoge"})
   401  		assert.Equal(t, map[string]string{"hoge": ""}, app.Annotations)
   402  	})
   403  }
   404  
   405  const appsYaml = `---
   406  # Source: apps/templates/helm.yaml
   407  apiVersion: argoproj.io/v1alpha1
   408  kind: Application
   409  metadata:
   410    name: sth1
   411    namespace: argocd
   412    finalizers:
   413      - resources-finalizer.argocd.argoproj.io
   414  spec:
   415    destination:
   416      namespace: sth
   417      server: 'https://kubernetes.default.svc'
   418    project: default
   419    source:
   420      repoURL: 'https://github.com/pasha-codefresh/argocd-example-apps'
   421      targetRevision: HEAD
   422      path: apps
   423      helm:
   424        valueFiles:
   425          - values.yaml
   426  ---
   427  # Source: apps/templates/helm.yaml
   428  apiVersion: argoproj.io/v1alpha1
   429  kind: Application
   430  metadata:
   431    name: sth2
   432    namespace: argocd
   433    finalizers:
   434      - resources-finalizer.argocd.argoproj.io
   435  spec:
   436    destination:
   437      namespace: sth
   438      server: 'https://kubernetes.default.svc'
   439    project: default
   440    source:
   441      repoURL: 'https://github.com/pasha-codefresh/argocd-example-apps'
   442      targetRevision: HEAD
   443      path: apps
   444      helm:
   445        valueFiles:
   446          - values.yaml`
   447  
   448  func TestReadAppsFromURI(t *testing.T) {
   449  	file, err := os.CreateTemp(os.TempDir(), "")
   450  	if err != nil {
   451  		panic(err)
   452  	}
   453  	defer func() {
   454  		_ = os.Remove(file.Name())
   455  	}()
   456  
   457  	_, _ = file.WriteString(appsYaml)
   458  	_ = file.Sync()
   459  
   460  	apps := make([]*v1alpha1.Application, 0)
   461  	err = readAppsFromURI(file.Name(), &apps)
   462  	require.NoError(t, err)
   463  	assert.Len(t, apps, 2)
   464  
   465  	assert.Equal(t, "sth1", apps[0].Name)
   466  	assert.Equal(t, "sth2", apps[1].Name)
   467  }
   468  
   469  func TestConstructAppFromStdin(t *testing.T) {
   470  	file, err := os.CreateTemp(os.TempDir(), "")
   471  	if err != nil {
   472  		panic(err)
   473  	}
   474  	defer func() {
   475  		_ = os.Remove(file.Name())
   476  	}()
   477  
   478  	_, _ = file.WriteString(appsYaml)
   479  	_ = file.Sync()
   480  
   481  	if _, err := file.Seek(0, 0); err != nil {
   482  		log.Fatal(err)
   483  	}
   484  
   485  	os.Stdin = file
   486  
   487  	apps, err := ConstructApps("-", "test", []string{}, []string{}, []string{}, AppOptions{}, nil)
   488  
   489  	if err := file.Close(); err != nil {
   490  		log.Fatal(err)
   491  	}
   492  	require.NoError(t, err)
   493  	assert.Len(t, apps, 2)
   494  	assert.Equal(t, "sth1", apps[0].Name)
   495  	assert.Equal(t, "sth2", apps[1].Name)
   496  }
   497  
   498  func TestConstructBasedOnName(t *testing.T) {
   499  	apps, err := ConstructApps("", "test", []string{}, []string{}, []string{}, AppOptions{}, nil)
   500  
   501  	require.NoError(t, err)
   502  	assert.Len(t, apps, 1)
   503  	assert.Equal(t, "test", apps[0].Name)
   504  }
   505  
   506  func TestFilterResources(t *testing.T) {
   507  	t.Run("Filter by ns", func(t *testing.T) {
   508  		resources := []*v1alpha1.ResourceDiff{
   509  			{
   510  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   511  			},
   512  			{
   513  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"ns\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   514  			},
   515  		}
   516  
   517  		filteredResources, err := FilterResources(false, resources, "g", "Service", "ns", "test-helm-guestbook", true)
   518  		require.NoError(t, err)
   519  		assert.Len(t, filteredResources, 1)
   520  	})
   521  
   522  	t.Run("Filter by kind", func(t *testing.T) {
   523  		resources := []*v1alpha1.ResourceDiff{
   524  			{
   525  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   526  			},
   527  			{
   528  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Deployment\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   529  			},
   530  		}
   531  
   532  		filteredResources, err := FilterResources(false, resources, "g", "Deployment", "argocd", "test-helm-guestbook", true)
   533  		require.NoError(t, err)
   534  		assert.Len(t, filteredResources, 1)
   535  	})
   536  
   537  	t.Run("Filter by name", func(t *testing.T) {
   538  		resources := []*v1alpha1.ResourceDiff{
   539  			{
   540  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   541  			},
   542  			{
   543  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   544  			},
   545  		}
   546  
   547  		filteredResources, err := FilterResources(false, resources, "g", "Service", "argocd", "test-helm", true)
   548  		require.NoError(t, err)
   549  		assert.Len(t, filteredResources, 1)
   550  	})
   551  
   552  	t.Run("Filter no result", func(t *testing.T) {
   553  		resources := []*v1alpha1.ResourceDiff{
   554  			{
   555  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm-guestbook\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   556  			},
   557  			{
   558  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   559  			},
   560  		}
   561  
   562  		filteredResources, err := FilterResources(false, resources, "g", "Service", "argocd-unknown", "test-helm", true)
   563  		require.ErrorContains(t, err, "no matching resource found")
   564  		assert.Nil(t, filteredResources)
   565  	})
   566  
   567  	t.Run("Filter multiple results", func(t *testing.T) {
   568  		resources := []*v1alpha1.ResourceDiff{
   569  			{
   570  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   571  			},
   572  			{
   573  				LiveState: "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"test-helm\",\"namespace\":\"argocd\"},\"spec\":{\"selector\":{\"app\":\"helm-guestbook\",\"release\":\"test\"},\"sessionAffinity\":\"None\",\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}",
   574  			},
   575  		}
   576  
   577  		filteredResources, err := FilterResources(false, resources, "g", "Service", "argocd", "test-helm", false)
   578  		require.ErrorContains(t, err, "use the --all flag")
   579  		assert.Nil(t, filteredResources)
   580  	})
   581  }