Skip to content
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: Make spec.source.helm.values field accepts either a string or a rawExtension #8794

Closed
1 change: 1 addition & 0 deletions USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,4 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Yubo](https://www.yubo.live/)
1. [Zimpler](https://www.zimpler.com/)
1. [ZOZO](https://corp.zozo.com/)
1. [Renault Group](https://www.renaultgroup.com/)
27 changes: 25 additions & 2 deletions assets/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -4130,6 +4130,17 @@
}
}
},
"runtimeRawExtension": {
"description": "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned\nstruct, and Object in your internal struct. You also need to register your\nvarious plugin types.\n\n// Internal package:\ntype MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.Object `json:\"myPlugin\"`\n}\ntype PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// External package:\ntype MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n}\ntype PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// On the wire, the JSON will look something like this:\n{\n\t\"kind\":\"MyAPIObject\",\n\t\"apiVersion\":\"v1\",\n\t\"myPlugin\": {\n\t\t\"kind\":\"PluginA\",\n\t\t\"aOption\":\"foo\",\n\t},\n}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into\nyour external MyAPIObject. That causes the raw JSON to be stored, but not unpacked.\nThe next step is to copy (using pkg/conversion) into the internal struct. The runtime\npackage's DefaultScheme has conversion functions installed which will unpack the\nJSON stored in RawExtension, turning it into the correct object type, and storing it\nin the Object. (TODO: In the case where the object is of an unknown type, a\nruntime.Unknown object will be created and stored.)\n\n+k8s:deepcopy-gen=true\n+protobuf=true\n+k8s:openapi-gen=true",
"type": "object",
"properties": {
"raw": {
"description": "Raw is the underlying serialization of this object.\n\nTODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.",
"type": "string",
"format": "byte"
}
}
},
"runtimeStreamError": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -4946,8 +4957,7 @@
}
},
"values": {
"type": "string",
"title": "Values specifies Helm values to be passed to helm template, typically defined as a block"
"$ref": "#/definitions/v1alpha1StringOrObject"
},
"version": {
"type": "string",
Expand Down Expand Up @@ -6459,6 +6469,19 @@
}
}
},
"v1alpha1StringOrObject": {
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
"type": "object",
"title": "+patchStrategy=replace\n+protobuf.options.(gogoproto.goproto_stringer)=false\n+kubebuilder:validation:Type=\"\"",
"properties": {
"raw": {
"$ref": "#/definitions/runtimeRawExtension"
},
"values": {
"type": "string",
"title": "Values as string if Raw == nil"
}
}
},
"v1alpha1SyncOperation": {
"description": "SyncOperation contains details about a sync operation.",
"type": "object",
Expand Down
12 changes: 10 additions & 2 deletions cmd/argocd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
kustomizeImages []string
pluginEnvs []string
appOpts cmdutil.AppOptions
valuesRawLiteral bool
)
var command = &cobra.Command{
Use: "unset APPNAME parameters",
Expand Down Expand Up @@ -632,7 +633,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
}
}
if app.Spec.Source.Helm != nil {
if len(parameters) == 0 && len(valuesFiles) == 0 && !valuesLiteral && !ignoreMissingValueFiles {
if len(parameters) == 0 && len(valuesFiles) == 0 && !valuesLiteral && !valuesRawLiteral && !ignoreMissingValueFiles {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see a CLI unit test for this param. Recently merged tests like #8918 and #8901 might be helpful.

c.HelpFunc()(c, args)
os.Exit(1)
}
Expand All @@ -647,7 +648,13 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
}
}
if valuesLiteral {
app.Spec.Source.Helm.Values = ""
app.Spec.Source.Helm.Values.Values = ""
updated = true
}
if valuesRawLiteral {
app.Spec.Source.Helm.Values = argoappv1.StringOrObject{
Raw: nil,
}
updated = true
}
for _, valuesFile := range valuesFiles {
Expand Down Expand Up @@ -705,6 +712,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
command.Flags().BoolVar(&kustomizeVersion, "kustomize-version", false, "Kustomize version")
command.Flags().StringArrayVar(&kustomizeImages, "kustomize-image", []string{}, "Kustomize images name (e.g. --kustomize-image node --kustomize-image mysql)")
command.Flags().StringArrayVar(&pluginEnvs, "plugin-env", []string{}, "Unset plugin env variables (e.g --plugin-env name)")
command.Flags().BoolVar(&valuesRawLiteral, "values-raw-literal", false, "Unset literal Helm values raw")
return command
}

Expand Down
26 changes: 25 additions & 1 deletion cmd/util/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import (
"time"

"github.com/argoproj/gitops-engine/pkg/utils/kube"
"sigs.k8s.io/yaml"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"

"github.com/argoproj/argo-cd/v2/pkg/apis/application"
Expand Down Expand Up @@ -74,6 +76,7 @@ type AppOptions struct {
retryBackoffDuration time.Duration
retryBackoffMaxDuration time.Duration
retryBackoffFactor int64
valuesRaw string
}

func AddAppFlags(command *cobra.Command, opts *AppOptions) {
Expand Down Expand Up @@ -126,6 +129,7 @@ func AddAppFlags(command *cobra.Command, opts *AppOptions) {
command.Flags().DurationVar(&opts.retryBackoffDuration, "sync-retry-backoff-duration", argoappv1.DefaultSyncRetryDuration, "Sync retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h)")
command.Flags().DurationVar(&opts.retryBackoffMaxDuration, "sync-retry-backoff-max-duration", argoappv1.DefaultSyncRetryMaxDuration, "Max sync retry backoff duration. Input needs to be a duration (e.g. 2m, 1h)")
command.Flags().Int64Var(&opts.retryBackoffFactor, "sync-retry-backoff-factor", argoappv1.DefaultSyncRetryFactor, "Factor multiplies the base duration after each failed sync retry")
command.Flags().StringVar(&opts.valuesRaw, "values-raw-literal-file", "", "Filename or URL to import as a literal Helm values raw object")
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
}

func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, appOpts *AppOptions) int {
Expand All @@ -151,6 +155,18 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
setHelmOpt(&spec.Source, helmOpts{valueFiles: appOpts.valuesFiles})
case "ignore-missing-value-files":
setHelmOpt(&spec.Source, helmOpts{ignoreMissingValueFiles: appOpts.ignoreMissingValueFiles})
case "values-raw-literal-file":
var data []byte

// read uri
parsedURL, err := url.ParseRequestURI(appOpts.valuesRaw)
if err != nil || !(parsedURL.Scheme == "http" || parsedURL.Scheme == "https") {
data, err = ioutil.ReadFile(appOpts.valuesRaw)
} else {
data, err = config.ReadRemoteFile(appOpts.valuesRaw)
}
errors.CheckError(err)
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
setHelmOpt(&spec.Source, helmOpts{valuesRaw: data})
case "values-literal-file":
var data []byte

Expand Down Expand Up @@ -385,6 +401,7 @@ type helmOpts struct {
helmSetFiles []string
passCredentials bool
skipCrds bool
valuesRaw []byte
}

func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
Expand All @@ -398,7 +415,14 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
src.Helm.IgnoreMissingValueFiles = opts.ignoreMissingValueFiles
}
if len(opts.values) > 0 {
src.Helm.Values = opts.values
src.Helm.Values.Values = opts.values
}
if len(opts.valuesRaw) > 0 {
Comment on lines 417 to +420
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if someone specifies both? Should we throw an error if they try?

data, err := yaml.YAMLToJSON(opts.valuesRaw)
if err != nil {
log.Fatal(err)
}
src.Helm.Values.Raw = &runtime.RawExtension{Raw: data}
}
if opts.releaseName != "" {
src.Helm.ReleaseName = opts.releaseName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ argocd admin app generate-spec APPNAME [flags]
--validate Validation of repo and cluster (default true)
--values stringArray Helm values file(s) to use
--values-literal-file string Filename or URL to import as a literal Helm values block
--values-raw-literal-file string Filename or URL to import as a literal Helm values raw object
```

### Options inherited from parent commands
Expand Down
1 change: 1 addition & 0 deletions docs/user-guide/commands/argocd_app_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ argocd app create APPNAME [flags]
--validate Validation of repo and cluster (default true)
--values stringArray Helm values file(s) to use
--values-literal-file string Filename or URL to import as a literal Helm values block
--values-raw-literal-file string Filename or URL to import as a literal Helm values raw object
```

### Options inherited from parent commands
Expand Down
1 change: 1 addition & 0 deletions docs/user-guide/commands/argocd_app_set.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ argocd app set APPNAME [flags]
--validate Validation of repo and cluster (default true)
--values stringArray Helm values file(s) to use
--values-literal-file string Filename or URL to import as a literal Helm values block
--values-raw-literal-file string Filename or URL to import as a literal Helm values raw object
```

### Options inherited from parent commands
Expand Down
1 change: 1 addition & 0 deletions docs/user-guide/commands/argocd_app_unset.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ argocd app unset APPNAME parameters [flags]
--plugin-env stringArray Unset plugin env variables (e.g --plugin-env name)
--values stringArray Unset one or more Helm values files
--values-literal Unset literal Helm values block
--values-raw-literal Unset literal Helm values raw
```

### Options inherited from parent commands
Expand Down
2 changes: 1 addition & 1 deletion hack/generate-proto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ clean_swagger() {
}

echo "If additional types are added, the number of expected collisions may need to be increased"
EXPECTED_COLLISION_COUNT=62
EXPECTED_COLLISION_COUNT=64
collect_swagger server ${EXPECTED_COLLISION_COUNT}
clean_swagger server
clean_swagger reposerver
Expand Down
Loading