All Products
Search
Document Center

Container Service for Kubernetes:Publish Argo CD applications using the Go SDK

Last Updated:Nov 21, 2025

ACK One GitOps provides continuous delivery for multi-cluster applications in hybrid cloud, multicloud, and multi-cluster scenarios. It is built on a managed open source Argo CD and is fully compatible with Argo CD APIs, such as the Application API. Compared with open source Argo CD, ACK One GitOps offers advantages such as multi-cluster distribution, multi-user permission management, and out-of-the-box, O&M-free use. To integrate ACK One GitOps into your application release system, you can use the Go SDK to create, delete, or sync Argo CD Applications. This topic uses Argo CD v2.9.3 as an example to demonstrate how to create an Application using the Go SDK.

Demo code configuration

Step 1: Get the Server or Name of the target cluster

You must specify the Server or Name of the target cluster in the Argo CD Application.

  1. Obtain the KubeConfig file of the fleet instance from the ACK One console and use kubectl to connect to the fleet instance.

    For more information, see Obtain the KubeConfig of a cluster and use kubectl to connect to the cluster.

  2. Run one of the following commands to retrieve the list of Name or Server values for all associated clusters. You only need to select one. The Name is more readable and uses the format <cluster id>-<cluster name> by default.

    • Retrieve the list of Name values

      kubectl get secret -nargocd -l argocd.argoproj.io/secret-type=cluster |awk 'NR>1 {print $1}'|xargs -I {} sh -c 'kubectl get secret -nargocd {} -ojsonpath="{.data.name}"|base64 -d; echo'
    • Retrieve the list of Server values

      kubectl get secret -nargocd -l argocd.argoproj.io/secret-type=cluster |awk 'NR>1 {print $1}'|xargs -I {} sh -c 'kubectl get secret -nargocd {} -ojsonpath="{.data.server}"|base64 -d; echo'

Step 2: Get a token

Create a local user in the fleet instance and generate a token for the user to manage Application operations.

  1. Create a local user.

    1. Run the following command to edit the argocd-cm ConfigMap of Argo CD.

      kubectl edit cm argocd-cm -n argocd
    2. In the argocd-cm ConfigMap, add a local user named localuser1 as shown in the following code.

      data:
        accounts.localuser1: login,apiKey    # Allow the local user to log on to the Argo CD UI and the Argo CD CLI, and generate an apiKey token. 
        accounts.localuser1.enabled: "true"  # Create local user localuser1.
    3. Run the following command to query the local user:

      argocd account list

      Expected output:

      NAME        ENABLED  CAPABILITIES
      admin       true     login
      localuser1  true     login,apiKey   # The local user localuser1.
  2. In argocd-rbac-cm, grant Role-Based Access Control (RBAC) permissions for the Kubernetes resources of Argo CD to the local user that you created. For example, you can grant the admin role, which has read and write permissions on resources such as applications, clusters, and projects.

    For more information about Argo CD RBAC permissions, see Configure Argo CD RBAC for a user.

    1. Run the following command to edit the argocd-rbac-cm ConfigMap of Argo CD.

      kubectl edit cm argocd-rbac-cm -n argocd
    2. In the argocd-rbac-cm ConfigMap file, grant permissions to the local user as shown in the following example.

      Important

      Do not modify the existing configurations in this ConfigMap file.

        data:
        policy.csv: |
          g, "14***01", role:admin          # Existing configuration. Do not modify.
          g, localuser1, role:admin         # New configuration. Maps localuser1 to the admin role.
        scopes: '[uid]'  
  3. Generate a token for the local user.

    Generate a token using the Argo CD CLI

    Run the following command to set a password and generate a token:

    # Set a password. 
    argocd account update-password \
      --account localuser1 \
      --current-password <admin password> \
      --new-password <localuser1-password>
    
    # Generate a token for localuser1. 
    argocd account generate-token --account localuser1
    eyJhb......

    Generate a token using the Argo CD UI

    1. Log on to the ACK One console. In the left-side navigation pane, choose Fleet > Multi-cluster Applications.

    2. On the Multi-cluster GitOps page, click the Dingtalk_20231226104633.jpg icon next to the fleet name in the upper-left corner. From the drop-down list, select the target fleet. Then, click GitOps Console. On the logon page that appears, enter the username and password to log on.

    3. In the navigation pane on the left of the Argo CD console, choose Settings, and then choose Accounts. Find the local user that you added and click the username. This topic uses localuser1 as an example.

    4. On the user page for localuser1, click Generate New in the Tokens section and save the token.

Step 3: Sample code for Application operations

The following sample code shows how to perform application operations, including creating, syncing, retrieving the details of, updating, and deleting an application.

  • Main entry point.

    Note
    • Replace <argocd server lb ip> with the IP address of the Argo CD server load balancer, which you can obtain by running the kubectl get svc -nargocd argocd-server -ojsonpath='{.status.loadBalancer.ingress[0].ip}' command.

    • Replace local user token with the token that you obtained in Step 2: Obtain a token.

    Click to view the sample code

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	conn := &Connection{
    		Address: "<argocd server lb ip>",
    		Token:   "local user token",
    	}
    	argoCDClient, err := NewArgoCDClient(conn)
    	if err != nil {
    		panic(fmt.Sprintf("Failed to create argocd client: %v\n", err))
    	}
    
    	//if err := argoCDClient.CreateApplication(false, true); err != nil {
    	//	panic(fmt.Sprintf("Failed to create application: %v\n", err))
    	//}
    
    	if err := argoCDClient.SyncApplication("argocd", "demo-argocd-app-manual", "default"); err != nil {
    		panic(fmt.Sprintf("Failed to sync application: %v\n", err))
    	}
    }
  • Sample code for application management.

    This code is based on the Argo CD apiclient. You must replace ClusterName, ClusterServer, and GitRepoURL.

    Click to view the sample code

    package main
    
    import (
    	"context"
    	"fmt"
    	"github.com/argoproj/argo-cd/v2/pkg/apiclient"
    	"github.com/argoproj/argo-cd/v2/pkg/apiclient/application"
    	"github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster"
    	"github.com/argoproj/argo-cd/v2/pkg/apiclient/project"
    	argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    )
    
    const (
    	GitRepoURL = "https://github.com/AliyunContainerService/gitops-demo.git"
    
    	ClusterServer = "https://172.16.xx.xx:6443"
    	ClusterName   = "cc0e3a41fe49c4a7bbcd5a1f0xxxxx-test"
    )
    
    type ArgoCDClient struct {
    	projectClient project.ProjectServiceClient
    	clusterClient cluster.ClusterServiceClient
    	appClient     application.ApplicationServiceClient
    }
    
    type Connection struct {
    	Address string
    	Token   string
    }
    
    func NewArgoCDClient(conn *Connection) (*ArgoCDClient, error) {
    	argocdApiClient, err := apiclient.NewClient(&apiclient.ClientOptions{
    		ServerAddr: fmt.Sprintf(conn.Address),
    		Insecure:   true,
    		AuthToken:  conn.Token,
    	})
    	if err != nil {
    		return nil, err
    	}
    
    	_, appClient, err := argocdApiClient.NewApplicationClient()
    	if err != nil {
    		return nil, err
    	}
    
    	_, projectClient, err := argocdApiClient.NewProjectClient()
    	if err != nil {
    		return nil, err
    	}
    
    	_, clusterClient, err := argocdApiClient.NewClusterClient()
    	if err != nil {
    		return nil, err
    	}
    
    	return &ArgoCDClient{
    		projectClient: projectClient,
    		clusterClient: clusterClient,
    		appClient:     appClient,
    	}, nil
    }
    
    // CreateApplication creates an application.
    /**
     * Create an application.
     * upsert: Allows you to override an application with the same name even if the supplied application spec is different from the existing spec.
     * validate: Validates the repository and cluster.
     */
    func (c *ArgoCDClient) CreateApplication(upsert, validate bool) error {
    	app := &argoappv1.Application{
    		ObjectMeta: v1.ObjectMeta{
    			Name:      "demo-argocd-app-manual",
    			Namespace: "argocd",
    		},
    		Spec: argoappv1.ApplicationSpec{
    			Project: "default",
    			Source: &argoappv1.ApplicationSource{
    				RepoURL:        GitRepoURL,
    				Path:           "manifests/helm/echo-server",
    				TargetRevision: "HEAD",
    			},
    			Destination: argoappv1.ApplicationDestination{
    				//Server:    ClusterServer,
    				Name:      ClusterName,
    				Namespace: "echo-server-demo2",
    			},
    			SyncPolicy: &argoappv1.SyncPolicy{
    				SyncOptions: argoappv1.SyncOptions{
    					"CreateNamespace=true",
    				},
    			},
    		},
    	}
    
    	if _, err := c.appClient.Create(context.Background(), &application.ApplicationCreateRequest{
    		Application: app,
    		Upsert:      &upsert,
    		Validate:    &validate,
    	}); err != nil {
    		return err
    	}
    
    	return nil
    }
    
    // SyncApplication syncs an application.
    // For information about the parameters in ApplicationSyncRequest, run `argocd app sync --help`.
    func (c *ArgoCDClient) SyncApplication(namespace, name, project string) error {
    	if _, err := c.appClient.Sync(context.Background(), &application.ApplicationSyncRequest{
    		Name:         &name,
    		AppNamespace: &namespace,
    		Revision:     nil,
    		//DryRun:        nil,
    		//Prune:         nil,
    		//Strategy:      nil,
    		//Resources:     nil,
    		//Manifests:     nil,
    		//Infos:         nil,
    		//RetryStrategy: nil,
    		//SyncOptions: syncOptionsFactory,
    		Project: &project,
    	}); err != nil {
    		return err
    	}
    
    	return nil
    }
    
    // GetApplication gets the details of an application.
    func (c *ArgoCDClient) GetApplication(namespace, name string) (*argoappv1.Application, error) {
    	if app, err := c.appClient.Get(context.Background(), &application.ApplicationQuery{
    		Name:         &name,
    		AppNamespace: &namespace,
    	}); err != nil {
    		return nil, err
    	} else {
    		return app, nil
    	}
    }
    
    // DeleteApplication deletes an application.
    func (c *ArgoCDClient) DeleteApplication(namespace, name string) error {
    	if _, err := c.appClient.Delete(context.Background(), &application.ApplicationDeleteRequest{
    		Name:         &name,
    		AppNamespace: &namespace,
    	}); err != nil {
    		return err
    	}
    	return nil
    }
    
    // UpdateApplication updates an application.
    func (c *ArgoCDClient) UpdateApplication(newApp *argoappv1.Application, validate bool, project string) error {
    	if _, err := c.appClient.Update(context.Background(), &application.ApplicationUpdateRequest{
    		Application: newApp,
    		Validate:    &validate,
    		Project:     &project,
    	}); err != nil {
    		return err
    	}
    	return nil
    }
    

go.mod configuration

When you import Argo CD Go packages into your Go project, you may encounter an "unknown revision v0.0.0" error when you download dependencies. This error occurs because Argo CD directly depends on Kubernetes packages whose go.mod files contain this v0.0.0 version.

You can resolve this issue by adding a `replace` directive. For more information, see the community documentation Importing Argo CD go packages. However, the required dependency versions in the `replace` directive vary based on the Argo CD version. You must set the versions of the Kubernetes packages in the `replace` directive to match the Argo CD version.

The demo in this topic uses the Go packages for Argo CD v2.9.3. Therefore, you must set all Kubernetes packages in the `replace` directive to v0.24.17, which corresponds to Argo CD v2.9.3. The following code provides a complete go.mod example:

Click to view the sample code

module awesomeProject1

go 1.19

require (
	github.com/argoproj/argo-cd/v2 v2.9.3
	k8s.io/apimachinery v0.24.17
	sigs.k8s.io/controller-runtime v0.11.0
)

require (
	cloud.google.com/go/compute v1.20.1 // indirect
	cloud.google.com/go/compute/metadata v0.2.3 // indirect
	dario.cat/mergo v1.0.0 // indirect
	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
	github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
	github.com/Masterminds/semver/v3 v3.2.1 // indirect
	github.com/Microsoft/go-winio v0.6.1 // indirect
	github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
	github.com/argoproj/gitops-engine v0.7.1-0.20230906152414-b0fffe419a0f // indirect
	github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 // indirect
	github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
	github.com/bombsimon/logrusr/v2 v2.0.1 // indirect
	github.com/bradleyfalzon/ghinstallation/v2 v2.6.0 // indirect
	github.com/cespare/xxhash/v2 v2.2.0 // indirect
	github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
	github.com/cloudflare/circl v1.3.3 // indirect
	github.com/coreos/go-oidc/v3 v3.6.0 // indirect
	github.com/cyphar/filepath-securejoin v0.2.4 // indirect
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
	github.com/docker/distribution v2.8.2+incompatible // indirect
	github.com/emicklei/go-restful/v3 v3.8.0 // indirect
	github.com/emirpasic/gods v1.18.1 // indirect
	github.com/evanphx/json-patch v5.6.0+incompatible // indirect
	github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
	github.com/fatih/camelcase v1.0.0 // indirect
	github.com/felixge/httpsnoop v1.0.3 // indirect
	github.com/fvbommel/sortorder v1.0.1 // indirect
	github.com/go-errors/errors v1.4.2 // indirect
	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
	github.com/go-git/go-billy/v5 v5.5.0 // indirect
	github.com/go-git/go-git/v5 v5.11.0 // indirect
	github.com/go-jose/go-jose/v3 v3.0.0 // indirect
	github.com/go-logr/logr v1.2.4 // indirect
	github.com/go-logr/stdr v1.2.2 // indirect
	github.com/go-openapi/jsonpointer v0.19.5 // indirect
	github.com/go-openapi/jsonreference v0.20.0 // indirect
	github.com/go-openapi/swag v0.22.3 // indirect
	github.com/go-redis/cache/v9 v9.0.0 // indirect
	github.com/gobwas/glob v0.2.3 // indirect
	github.com/gogo/protobuf v1.3.2 // indirect
	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
	github.com/golang/protobuf v1.5.3 // indirect
	github.com/google/btree v1.1.2 // indirect
	github.com/google/gnostic v0.6.9 // indirect
	github.com/google/go-cmp v0.6.0 // indirect
	github.com/google/go-github/v53 v53.2.0 // indirect
	github.com/google/go-querystring v1.1.0 // indirect
	github.com/google/gofuzz v1.2.0 // indirect
	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
	github.com/google/uuid v1.3.0 // indirect
	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
	github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
	github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
	github.com/imdario/mergo v0.3.16 // indirect
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
	github.com/jonboulle/clockwork v0.2.2 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
	github.com/kevinburke/ssh_config v1.2.0 // indirect
	github.com/klauspost/compress v1.16.5 // indirect
	github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/mitchellh/go-wordwrap v1.0.0 // indirect
	github.com/moby/spdystream v0.2.0 // indirect
	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
	github.com/opencontainers/go-digest v1.0.0 // indirect
	github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
	github.com/pjbgf/sha1cd v0.3.0 // indirect
	github.com/pkg/errors v0.9.1 // indirect
	github.com/r3labs/diff v1.1.0 // indirect
	github.com/redis/go-redis/v9 v9.0.5 // indirect
	github.com/robfig/cron/v3 v3.0.1 // indirect
	github.com/russross/blackfriday v1.6.0 // indirect
	github.com/sergi/go-diff v1.1.0 // indirect
	github.com/sirupsen/logrus v1.9.3 // indirect
	github.com/skeema/knownhosts v1.2.1 // indirect
	github.com/spf13/cobra v1.7.0 // indirect
	github.com/spf13/pflag v1.0.5 // indirect
	github.com/vmihailenco/go-tinylfu v0.2.2 // indirect
	github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
	github.com/xanzy/ssh-agent v0.3.3 // indirect
	github.com/xlab/treeprint v1.1.0 // indirect
	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 // indirect
	go.opentelemetry.io/otel v1.16.0 // indirect
	go.opentelemetry.io/otel/metric v1.16.0 // indirect
	go.opentelemetry.io/otel/trace v1.16.0 // indirect
	go.starlark.net v0.0.0-20220328144851-d1966c6b9fcd // indirect
	golang.org/x/crypto v0.16.0 // indirect
	golang.org/x/mod v0.12.0 // indirect
	golang.org/x/net v0.19.0 // indirect
	golang.org/x/oauth2 v0.11.0 // indirect
	golang.org/x/sync v0.3.0 // indirect
	golang.org/x/sys v0.15.0 // indirect
	golang.org/x/term v0.15.0 // indirect
	golang.org/x/text v0.14.0 // indirect
	golang.org/x/time v0.3.0 // indirect
	golang.org/x/tools v0.13.0 // indirect
	google.golang.org/appengine v1.6.7 // indirect
	google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
	google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
	google.golang.org/grpc v1.56.2 // indirect
	google.golang.org/protobuf v1.31.0 // indirect
	gopkg.in/inf.v0 v0.9.1 // indirect
	gopkg.in/warnings.v0 v0.1.2 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
	k8s.io/api v0.24.17 // indirect
	k8s.io/apiextensions-apiserver v0.24.2 // indirect
	k8s.io/apiserver v0.24.17 // indirect
	k8s.io/cli-runtime v0.24.17 // indirect
	k8s.io/client-go v0.24.17 // indirect
	k8s.io/component-base v0.24.17 // indirect
	k8s.io/component-helpers v0.24.17 // indirect
	k8s.io/klog/v2 v2.70.1 // indirect
	k8s.io/kube-aggregator v0.24.2 // indirect
	k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect
	k8s.io/kubectl v0.24.2 // indirect
	k8s.io/kubernetes v1.24.17 // indirect
	k8s.io/utils v0.0.0-20220706174534-f6158b442e7c // indirect
	oras.land/oras-go/v2 v2.3.0 // indirect
	sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect
	sigs.k8s.io/kustomize/api v0.11.5 // indirect
	sigs.k8s.io/kustomize/kyaml v0.13.7 // indirect
	sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
	sigs.k8s.io/yaml v1.3.0 // indirect
)

replace (
	// https://github.com/golang/go/issues/33546#issuecomment-519656923
	github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127

	github.com/golang/protobuf => github.com/golang/protobuf v1.4.2
	github.com/gorilla/websocket => github.com/gorilla/websocket v1.4.2
	github.com/grpc-ecosystem/grpc-gateway => github.com/grpc-ecosystem/grpc-gateway v1.16.0
	github.com/improbable-eng/grpc-web => github.com/improbable-eng/grpc-web v0.0.0-20181111100011-16092bd1d58a

	// Avoid CVE-2022-28948
	gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1

	// https://github.com/kubernetes/kubernetes/issues/79384#issuecomment-505627280
	k8s.io/api => k8s.io/api v0.24.17
	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.24.17
	k8s.io/apimachinery => k8s.io/apimachinery v0.24.1
	k8s.io/apiserver => k8s.io/apiserver v0.24.17
	k8s.io/cli-runtime => k8s.io/cli-runtime v0.24.17
	k8s.io/client-go => k8s.io/client-go v0.24.17
	k8s.io/cloud-provider => k8s.io/cloud-provider v0.24.17
	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.24.17
	k8s.io/code-generator => k8s.io/code-generator v0.24.17
	k8s.io/component-base => k8s.io/component-base v0.24.17
	k8s.io/component-helpers => k8s.io/component-helpers v0.24.17
	k8s.io/controller-manager => k8s.io/controller-manager v0.24.17
	k8s.io/cri-api => k8s.io/cri-api v0.24.17
	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.24.17
	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.24.17
	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.24.17
	k8s.io/kube-proxy => k8s.io/kube-proxy v0.24.17
	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.24.17
	k8s.io/kubectl => k8s.io/kubectl v0.24.17
	k8s.io/kubelet => k8s.io/kubelet v0.24.17
	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.24.17
	k8s.io/metrics => k8s.io/metrics v0.24.17
	k8s.io/mount-utils => k8s.io/mount-utils v0.24.17
	k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.24.17
	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.24.17
)

References

  • For more information about the features of ACK One GitOps, see GitOps overview.

  • For a tutorial on how to use GitOps to publish multi-cluster applications, see GitOps Quick Start.