-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement 'argocd admin appset generate' to troubeshoot appsets #19518
Conversation
❌ Preview Environment deleted from BunnyshellAvailable commands (reply to this comment):
|
❌ Preview Environment deleted from BunnyshellAvailable commands (reply to this comment):
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #19518 +/- ##
==========================================
- Coverage 55.87% 55.80% -0.08%
==========================================
Files 316 320 +4
Lines 43794 43980 +186
==========================================
+ Hits 24471 24541 +70
- Misses 16775 16887 +112
- Partials 2548 2552 +4 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexmt Part of the implementation here is with an embedded repo server, can you share how that works?
I wonder how this command differs from a recently merged similar PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing feature. Thank you Alex, just few small comments
cmd/argocd/commands/admin/appset.go
Outdated
"sigs.k8s.io/yaml" | ||
) | ||
|
||
func NewAppsetCommand(opts *apiclient.ClientOptions) *cobra.Command { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this does not make a lot of sense under the admin commands. Maybe argocd appset template ./appset.yaml -o yaml
would make more sense. Take a look at #16781, that has prior work to implement this feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree - moved command to argocd appset generate
. I've choosen to name it generate
, however don't have strong opinion . Please let me know what you think
@agaudreault, @daftping, Thanks for letting me know about My main goal is to enable customers to troubleshoot application sets. Pros of
Cons:
I propose to improve |
@alexmt sounds good to me! Last time I looked at it, I chose not to return the full templated app so i wouldn't change the return type of the create. By default, it won't return the template when it is not a dry run because they are generated async. I didn't want to have the create returns false results. I think it would be better to introduce a new template command that would return the appset and the templates of generated apps. And if a name is provided instead of a file, it returns the actual data. That was my state of mind as far as i can recall, but I'll let you judge what's best when you get in the code! |
@alexmt I think closing this one and adding improvement to |
b9e21b6
to
b008678
Compare
Updated the PR with new implementation (instead of closing and reopening). The PR introduces PTAL @agaudreault , @pasha-codefresh |
@@ -142,7 +144,11 @@ func NewCommand() *cobra.Command { | |||
|
|||
dynamicClient := dynamic.NewForConfigOrDie(config) | |||
|
|||
controllerClient, err := client.New(config, client.Options{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change is required if user is trying to generate
appset with non default project (or create with --dry-run=true
flag)
b008678
to
170f238
Compare
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
170f238
to
5bbcffd
Compare
|
||
apps, err := s.generateApplicationSetApps(ctx, logger.WithField("applicationset", appset.Name), *appset, namespace) | ||
if err != nil { | ||
res.ErrorLog = fmt.Sprintf("unable to generate Applications of ApplicationSet: %v\n", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not return error and build error message on cli , base on this error ? In any case you will need process error on client part, to show reasonable error when request or permissions are incorrect, i think it will be more consistent to do it also when you cant generate applications
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. ErrorLog
just duplicates error - removed it.
LGTM, just left small comment |
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! ❤️ Few small comments, nothing major :)
var output string | ||
command := &cobra.Command{ | ||
Use: "generate", | ||
Short: "Generate apps of ApplicationSet", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify that we are only generating the rendered templates and not the apps themselves
Short: "Generate apps of ApplicationSet", | |
Short: "Generate apps of ApplicationSet rendered templates", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you, applied!
} | ||
appset := appsets[0] | ||
if appset.Name == "" { | ||
err := fmt.Errorf("Error generating aps for ApplicationSet %s. ApplicationSet does not have Name field set", appset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err := fmt.Errorf("Error generating aps for ApplicationSet %s. ApplicationSet does not have Name field set", appset) | |
err := fmt.Errorf("Error generating apps for ApplicationSet %s. ApplicationSet does not have Name field set", appset) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accepted suggesion
for i := range appsList { | ||
app := appsList[i] | ||
app.APIVersion = arogappsetv1.ApplicationSchemaGroupVersionKind.GroupVersion().String() | ||
app.Kind = arogappsetv1.ApplicationSchemaGroupVersionKind.Kind | ||
resources = append(resources, app) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of a question, but why are you overriding the version and kind? This should already be provided in the response object no? The client could be outdated locally and have a different ApiVersion. I think it would be better to use the value provided by the server.
Maybe adding a comment with the explanation if necessary would help future contributors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is due to a strange behavior of go k8s client. For some reason it drops apiVersion/kind . We have to do the same workaround in other places. Example:
argo-cd/cmd/argocd/commands/app_actions.go
Line 225 in 7cf5ed0
app.Kind = application.ApplicationKind |
@@ -366,6 +365,40 @@ func (s *Server) ResourceTree(ctx context.Context, q *applicationset.Application | |||
return s.buildApplicationSetTree(a) | |||
} | |||
|
|||
func (s *Server) Generate(ctx context.Context, q *applicationset.ApplicationSetGenerateRequest) (*applicationset.ApplicationSetGenerateResponse, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about RBAC for this call? It may allow to discover cluster secrets, private repos, etc. Should we restrict this to people with the "create" rbac?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree - user must have "create" RBAC to see generated apps. I've added a check here:
if err := s.checkCreatePermissions(ctx, appset, projectName); err != nil { |
355c3c0
to
dc8cad8
Compare
I've addressed your comments @agaudreault, thank you! PTAL |
@alexmt missing a run of codegen, then good to go 🚀 |
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
dc8cad8
to
49b7245
Compare
@agaudreault done! |
PR implements
argocd appset generate
that helps troubleshooting appset issues. Examples:argocd appset generate ~/go/src/github.com/argoproj/argo-cd/applicationset/examples/list-generator/list-
output
argocd appset generate ~/go/src/github.com/argoproj/argo-cd/applicationset/examples/git-generator-directory/git-directories-example.yaml
output
argocd appset generate ~/go/src/github.com/argoproj/argo-cd/applicationset/examples/pull-request-generator/pull-request-example.yaml
failed output