diff --git a/api/v1alpha1/kclrun_types.go b/api/v1alpha1/kclrun_types.go index 567c1e8..6824e51 100644 --- a/api/v1alpha1/kclrun_types.go +++ b/api/v1alpha1/kclrun_types.go @@ -22,6 +22,7 @@ import ( kc "github.com/fluxcd/kustomize-controller/api/v1" "github.com/fluxcd/pkg/apis/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" ) const ( @@ -97,7 +98,7 @@ type KCLRunSpec struct { // +optional Force bool `json:"force,omitempty"` - // The interval at which to reconcile the Kustomization. + // The interval at which to reconcile the KCL Module. // This interval is approximate and may be subject to jitter to ensure // efficient use of resources. // +kubebuilder:validation:Type=string @@ -106,7 +107,7 @@ type KCLRunSpec struct { Interval metav1.Duration `json:"interval"` // The interval at which to retry a previously failed reconciliation. - // When not specified, the controller uses the KustomizationSpec.Interval + // When not specified, the controller uses the KCLRunSpec.Interval // value to retry failures. // +kubebuilder:validation:Type=string // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" @@ -118,10 +119,13 @@ type KCLRunSpec struct { // +optional Path string `json:"path,omitempty"` - // PostBuild describes which actions to perform on the YAML manifest - // generated by building the KCL module. + // Params are the parameters in key-value pairs format. // +optional - PostBuild *PostBuild `json:"postBuild,omitempty"` + Params map[string]runtime.RawExtension `json:"params,omitempty" yaml:"params,omitempty"` + + // Config is the KCL compile config. + // +optional + Config *ConfigSpec `json:"config,omitempty" yaml:"config,omitempty"` // Prune enables garbage collection. // +required @@ -157,47 +161,32 @@ type CommonMetadata struct { Labels map[string]string `json:"labels,omitempty"` } -// PostBuild describes which actions to perform on the YAML manifest -// generated by building the kustomize overlay. -type PostBuild struct { - // Substitute holds a map of key/value pairs. - // The variables defined in your YAML manifests that match any of the keys - // defined in the map will be substituted with the set value. - // Includes support for bash string replacement functions - // e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. +// ConfigSpec defines the compile config. +type ConfigSpec struct { + // Arguments is the list of top level dynamic arguments for the kcl option function, e.g., env="prod" // +optional - Substitute map[string]string `json:"substitute,omitempty"` - - // SubstituteFrom holds references to ConfigMaps and Secrets containing - // the variables and their values to be substituted in the YAML manifests. - // The ConfigMap and the Secret data keys represent the var names, and they - // must match the vars declared in the manifests for the substitution to - // happen. + Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty"` + // Settings is the list of kcl setting files including all of the CLI config. // +optional - SubstituteFrom []SubstituteReference `json:"substituteFrom,omitempty"` -} - -// SubstituteReference contains a reference to a resource containing -// the variables name and value. -type SubstituteReference struct { - // Kind of the values referent, valid values are ('Secret', 'ConfigMap'). - // +kubebuilder:validation:Enum=Secret;ConfigMap - // +required - Kind string `json:"kind"` - - // Name of the values referent. Should reside in the same namespace as the - // referring resource. - // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:MaxLength=253 - // +required - Name string `json:"name"` - - // Optional indicates whether the referenced resource must exist, or whether to - // tolerate its absence. If true and the referenced resource is absent, proceed - // as if the resource was present but empty, without any variables defined. - // +kubebuilder:default:=false + Settings []string `json:"settings,omitempty" yaml:"settings,omitempty"` + // Overrides is the list of override paths and values, e.g., app.image="v2" + // +optional + Overrides []string `json:"overrides,omitempty" yaml:"overrides,omitempty"` + // PathSelectors is the list of path selectors to select output result, e.g., a.b.c + // +optional + PathSelectors []string `json:"pathSelectors,omitempty" yaml:"pathSelectors,omitempty"` + // Vendor denotes running kcl in the vendor mode. + // +optional + Vendor bool `json:"vendor,omitempty" yaml:"vendor,omitempty"` + // SortKeys denotes sorting the output result keys, e.g., `{b = 1, a = 2} => {a = 2, b = 1}`. + // +optional + SortKeys bool `json:"sortKeys,omitempty" yaml:"sortKeys,omitempty"` + // ShowHidden denotes output the hidden attribute in the result. + // +optional + ShowHidden bool `json:"showHidden,omitempty" yaml:"showHidden,omitempty"` + // DisableNone denotes running kcl and disable dumping None values. // +optional - Optional bool `json:"optional,omitempty"` + DisableNone bool `json:"disableNone,omitempty" yaml:"disableNone,omitempty"` } // KCLRunStatus defines the observed state of KCLRun diff --git a/config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml b/config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml index 442a774..da4059d 100644 --- a/config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml +++ b/config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml @@ -56,6 +56,49 @@ spec: description: Labels to be added to the object's metadata. type: object type: object + config: + description: Config is the KCL compile config. + properties: + arguments: + description: Arguments is the list of top level dynamic arguments + for the kcl option function, e.g., env="prod" + items: + type: string + type: array + disableNone: + description: DisableNone denotes running kcl and disable dumping + None values. + type: boolean + overrides: + description: Overrides is the list of override paths and values, + e.g., app.image="v2" + items: + type: string + type: array + pathSelectors: + description: PathSelectors is the list of path selectors to select + output result, e.g., a.b.c + items: + type: string + type: array + settings: + description: Settings is the list of kcl setting files including + all of the CLI config. + items: + type: string + type: array + showHidden: + description: ShowHidden denotes output the hidden attribute in + the result. + type: boolean + sortKeys: + description: SortKeys denotes sorting the output result keys, + e.g., `{b = 1, a = 2} => {a = 2, b = 1}`. + type: boolean + vendor: + description: Vendor denotes running kcl in the vendor mode. + type: boolean + type: object dependsOn: description: |- DependsOn may contain a meta.NamespacedObjectReference slice @@ -111,7 +154,7 @@ spec: type: array interval: description: |- - The interval at which to reconcile the Kustomization. + The interval at which to reconcile the KCL Module. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ @@ -150,6 +193,12 @@ spec: required: - secretRef type: object + params: + additionalProperties: + type: object + x-kubernetes-preserve-unknown-fields: true + description: Params are the parameters in key-value pairs format. + type: object path: description: |- Path to the directory containing the kcl.mod file. @@ -164,67 +213,13 @@ spec: If not set, it defaults to true. type: boolean - postBuild: - description: |- - PostBuild describes which actions to perform on the YAML manifest - generated by building the kustomize overlay. - properties: - substitute: - additionalProperties: - type: string - description: |- - Substitute holds a map of key/value pairs. - The variables defined in your YAML manifests that match any of the keys - defined in the map will be substituted with the set value. - Includes support for bash string replacement functions - e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. - type: object - substituteFrom: - description: |- - SubstituteFrom holds references to ConfigMaps and Secrets containing - the variables and their values to be substituted in the YAML manifests. - The ConfigMap and the Secret data keys represent the var names, and they - must match the vars declared in the manifests for the substitution to - happen. - items: - description: |- - SubstituteReference contains a reference to a resource containing - the variables name and value. - properties: - kind: - description: Kind of the values referent, valid values are - ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: |- - Name of the values referent. Should reside in the same namespace as the - referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - default: false - description: |- - Optional indicates whether the referenced resource must exist, or whether to - tolerate its absence. If true and the referenced resource is absent, proceed - as if the resource was present but empty, without any variables defined. - type: boolean - required: - - kind - - name - type: object - type: array - type: object prune: description: Prune enables garbage collection. type: boolean retryInterval: description: |- The interval at which to retry a previously failed reconciliation. - When not specified, the controller uses the KustomizationSpec.Interval + When not specified, the controller uses the KCLRunSpec.Interval value to retry failures. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string diff --git a/internal/controller/kclrun_controller.go b/internal/controller/kclrun_controller.go index a21146e..baa9f69 100644 --- a/internal/controller/kclrun_controller.go +++ b/internal/controller/kclrun_controller.go @@ -210,7 +210,7 @@ func (r *KCLRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr return ctrl.Result{}, err } // Compile the KCL source code into the Kubernetes manifests - res, err := kcl.CompileKclPackage(dirPath) + res, err := kcl.CompileKclPackage(&obj, dirPath) if err != nil { conditions.MarkFalse(&obj, meta.ReadyCondition, "FetchFailed", err.Error()) log.Error(err, "failed to compile the KCL source code") diff --git a/internal/kcl/kcl.go b/internal/kcl/kcl.go index e477645..3b3519c 100644 --- a/internal/kcl/kcl.go +++ b/internal/kcl/kcl.go @@ -1,16 +1,19 @@ package kcl import ( + "encoding/json" + "fmt" "os" "path/filepath" + "github.com/kcl-lang/flux-kcl-controller/api/v1alpha1" "kcl-lang.io/kcl-go/pkg/kcl" "kcl-lang.io/kpm/pkg/client" "kcl-lang.io/kpm/pkg/opt" ) // Compile the KCL source code into kubernetes manifests. -func CompileKclPackage(pkgPath string) (*kcl.KCLResultList, error) { +func CompileKclPackage(obj *v1alpha1.KCLRun, pkgPath string) (*kcl.KCLResultList, error) { cli, _ := client.NewKpmClient() opts := opt.DefaultCompileOptions() @@ -23,9 +26,34 @@ func CompileKclPackage(pkgPath string) (*kcl.KCLResultList, error) { settings := filepath.Join(pkgPath, "kcl.yaml") _, err = os.Stat(settings) if err == nil { - opts.Option.Merge(kcl.WithSettings(settings)) + opts.Merge(kcl.WithSettings(settings)) opts.SetHasSettingsYaml(true) } + if obj != nil { + if obj.Spec.Config != nil { + for _, s := range obj.Spec.Config.Settings { + opts.Merge(kcl.WithSettings(s)) + opts.SetHasSettingsYaml(true) + } + opts.SetVendor(obj.Spec.Config.Vendor) + opts.Merge( + kcl.WithOptions(obj.Spec.Config.Arguments...), + kcl.WithOverrides(obj.Spec.Config.Overrides...), + kcl.WithSelectors(obj.Spec.Config.PathSelectors...), + kcl.WithSortKeys(obj.Spec.Config.SortKeys), + kcl.WithShowHidden(obj.Spec.Config.ShowHidden), + kcl.WithDisableNone(obj.Spec.Config.DisableNone), + ) + } + if obj.Spec.Params != nil { + paramsBytes, err := json.Marshal(obj.Spec.Params) + if err != nil { + return nil, err + } + opts.Merge(kcl.WithOptions(fmt.Sprintf("params=%s", string(paramsBytes)))) + } + } + opts.Merge() return cli.CompileWithOpts(opts) }