Skip to content

Commit

Permalink
feat: implement 'argocd admin appset generate' to troubeshoot appsets (
Browse files Browse the repository at this point in the history
…#19518)

* feat: implement 'argocd appset generate' to troubeshoot appsets

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>

* remove unnecessary ErrorLog field

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>

* apply reviewer suggestions

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>

---------

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
  • Loading branch information
alexmt authored Aug 28, 2024
1 parent ef57349 commit 3a5b653
Show file tree
Hide file tree
Showing 9 changed files with 761 additions and 44 deletions.
21 changes: 21 additions & 0 deletions assets/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion cmd/argocd-server/commands/argocd_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"time"

"github.com/redis/go-redis/v9"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"

"github.com/argoproj/pkg/stats"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -142,7 +144,11 @@ func NewCommand() *cobra.Command {

dynamicClient := dynamic.NewForConfigOrDie(config)

controllerClient, err := client.New(config, client.Options{})
scheme := runtime.NewScheme()
_ = clientgoscheme.AddToScheme(scheme)
_ = v1alpha1.AddToScheme(scheme)

controllerClient, err := client.New(config, client.Options{Scheme: scheme})
errors.CheckError(err)
controllerClient = client.NewDryRunClient(controllerClient)

Expand Down
71 changes: 71 additions & 0 deletions cmd/argocd/commands/applicationset.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"

"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/admin"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
Expand Down Expand Up @@ -53,6 +54,7 @@ func NewAppSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
command.AddCommand(NewApplicationSetCreateCommand(clientOpts))
command.AddCommand(NewApplicationSetListCommand(clientOpts))
command.AddCommand(NewApplicationSetDeleteCommand(clientOpts))
command.AddCommand(NewApplicationSetGenerateCommand(clientOpts))
return command
}

Expand Down Expand Up @@ -208,6 +210,75 @@ func NewApplicationSetCreateCommand(clientOpts *argocdclient.ClientOptions) *cob
return command
}

// NewApplicationSetGenerateCommand returns a new instance of an `argocd appset generate` command
func NewApplicationSetGenerateCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var output string
command := &cobra.Command{
Use: "generate",
Short: "Generate apps of ApplicationSet rendered templates",
Example: templates.Examples(`
# Generate apps of ApplicationSet rendered templates
argocd appset generate <filename or URL> (<filename or URL>...)
`),
Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

if len(args) == 0 {
c.HelpFunc()(c, args)
os.Exit(1)
}
argocdClient := headless.NewClientOrDie(clientOpts, c)
fileUrl := args[0]
appsets, err := cmdutil.ConstructApplicationSet(fileUrl)
errors.CheckError(err)

if len(appsets) != 1 {
fmt.Printf("Input file must contain one ApplicationSet")
os.Exit(1)
}
appset := appsets[0]
if appset.Name == "" {
err := fmt.Errorf("Error generating apps for ApplicationSet %s. ApplicationSet does not have Name field set", appset)
errors.CheckError(err)
}

conn, appIf := argocdClient.NewApplicationSetClientOrDie()
defer argoio.Close(conn)

req := applicationset.ApplicationSetGenerateRequest{
ApplicationSet: appset,
}
resp, err := appIf.Generate(ctx, &req)
errors.CheckError(err)

var appsList []arogappsetv1.Application
for i := range resp.Applications {
appsList = append(appsList, *resp.Applications[i])
}

switch output {
case "yaml", "json":
var resources []interface{}
for i := range appsList {
app := appsList[i]
// backfill api version and kind because k8s client always return empty values for these fields
app.APIVersion = arogappsetv1.ApplicationSchemaGroupVersionKind.GroupVersion().String()
app.Kind = arogappsetv1.ApplicationSchemaGroupVersionKind.Kind
resources = append(resources, app)
}

cobra.CheckErr(admin.PrintResources(output, os.Stdout, resources...))
case "wide", "":
printApplicationTable(appsList, &output)
default:
errors.CheckError(fmt.Errorf("unknown output format: %s", output))
}
},
}
command.Flags().StringVarP(&output, "output", "o", "wide", "Output format. One of: json|yaml|wide")
return command
}

// NewApplicationSetListCommand returns a new instance of an `argocd appset list` command
func NewApplicationSetListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
Expand Down
1 change: 1 addition & 0 deletions docs/user-guide/commands/argocd_appset.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions docs/user-guide/commands/argocd_appset_generate.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3a5b653

Please # to comment.