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: add more kclrun type tag and unit tests #125

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ fmt:
vet:
go vet ./...

# Run go build
build:
go build ./...

# Generate code
generate: controller-gen
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
Expand Down
75 changes: 50 additions & 25 deletions api/v1alpha1/kclrun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,20 @@ type KCLRunSpec struct {
// applied to all resources. Any existing label or annotation will be
// overridden if its key matches a common one.
// +optional
CommonMetadata *CommonMetadata `json:"commonMetadata,omitempty"`
CommonMetadata *CommonMetadata `json:"commonMetadata,omitempty" yaml:"commonMetadata,omitempty"`

// DependsOn may contain a meta.NamespacedObjectReference slice
// with references to Kustomization resources that must be ready before this
// Kustomization can be reconciled.
// +optional
DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty"`
DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty" yaml:"dependsOn,omitempty"`

// Timeout is the time to wait for any individual Kubernetes operation (like Jobs
// for hooks) during the performance. Defaults to '5m0s'.
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
// +optional
Timeout *metav1.Duration `json:"timeout,omitempty"`
Timeout *metav1.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"`

// PersistentClient tells the controller to use a persistent Kubernetes
// client for this release. When enabled, the client will be reused for the
Expand All @@ -65,7 +65,7 @@ type KCLRunSpec struct {
// If not set, it defaults to true.
//
// +optional
PersistentClient *bool `json:"persistentClient,omitempty"`
PersistentClient *bool `json:"persistentClient,omitempty" yaml:"persistentClient,omitempty"`

// The KubeConfig for reconciling the controller on a remote cluster.
// When used in combination with `KCLRunSpec.ServiceAccountName`,
Expand All @@ -75,49 +75,49 @@ type KCLRunSpec struct {
// a controller level fallback for when `KCLRunSpec.ServiceAccountName`
// is empty.
// +optional
KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty"`
KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty" yaml:"kubeConfig,omitempty"`

// The name of the Kubernetes service account to impersonate
// when reconciling this KCL source.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty" yaml:"serviceAccountName,omitempty"`

// TargetNamespace to target when performing operations for the KCL.
// Defaults to the namespace of the KCL source.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Optional
// +optional
TargetNamespace string `json:"targetNamespace,omitempty"`
TargetNamespace string `json:"targetNamespace,omitempty" yaml:"targetNamespace,omitempty"`

// Force instructs the controller to recreate resources
// when patching fails due to an immutable field change.
// +kubebuilder:default:=false
// +optional
Force bool `json:"force,omitempty"`
Force bool `json:"force,omitempty" yaml:"force,omitempty"`

// 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
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
// +required
Interval metav1.Duration `json:"interval"`
Interval metav1.Duration `json:"interval" yaml:"interval"`

// The interval at which to retry a previously failed reconciliation.
// 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))+$"
// +optional
RetryInterval *metav1.Duration `json:"retryInterval,omitempty"`
RetryInterval *metav1.Duration `json:"retryInterval,omitempty" yaml:"retryInterval,omitempty"`

// Path to the directory containing the kcl.mod file.
// Defaults to 'None', which translates to the root path of the SourceRef.
// +optional
Path string `json:"path,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`

// Params are the parameters in key-value pairs format.
// +optional
Expand All @@ -127,6 +127,11 @@ type KCLRunSpec struct {
// +optional
Config *ConfigSpec `json:"config,omitempty" yaml:"config,omitempty"`

// ConfigReference holds references to ConfigMaps and Secrets containing
// the KCL compile config. The ConfigMap and the Secret data keys represent the config names.
// +optional
ConfigReference *ConfigReference `json:"configReference,omitempty" yaml:"configReference,omitempty"`

// Prune enables garbage collection.
// +required
Prune bool `json:"prune"`
Expand Down Expand Up @@ -189,59 +194,79 @@ type ConfigSpec struct {
DisableNone bool `json:"disableNone,omitempty" yaml:"disableNone,omitempty"`
}

// ConfigReference contains a reference to a resource containing the KCL compile config.
type ConfigReference struct {
// Kind of the values referent, valid values are ('Secret', 'ConfigMap').
// +kubebuilder:validation:Enum=Secret;ConfigMap
// +required
Kind string `json:"kind" yaml:"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" yaml:"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
// +optional
Optional bool `json:"optional,omitempty" yaml:"optional,omitempty"`
}

// KCLRunStatus defines the observed state of KCLRun
type KCLRunStatus struct {
meta.ReconcileRequestStatus `json:",inline"`
meta.ReconcileRequestStatus `json:",inline" yaml:",inline"`

// ObservedGeneration is the last reconciled generation.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
ObservedGeneration int64 `json:"observedGeneration,omitempty" yaml:"observedGeneration,omitempty"`

// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
Conditions []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`

// The last successfully applied revision.
// Equals the Revision of the applied Artifact from the referenced Source.
// +optional
LastAppliedRevision string `json:"lastAppliedRevision,omitempty"`
LastAppliedRevision string `json:"lastAppliedRevision,omitempty" yaml:"lastAppliedRevision,omitempty"`

// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

// LastAttemptedRevision is the revision of the last reconciliation attempt.
// +optional
LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty"`
LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty" yaml:"lastAttemptedRevision,omitempty"`

// LastAttemptedRevisionDigest is the digest of the last reconciliation attempt.
// This is only set for OCIRepository sources.
// +optional
LastAttemptedRevisionDigest string `json:"lastAttemptedRevisionDigest,omitempty"`
LastAttemptedRevisionDigest string `json:"lastAttemptedRevisionDigest,omitempty" yaml:"lastAttemptedRevisionDigest,omitempty"`

// Inventory contains the list of Kubernetes resource object references that
// have been successfully applied.
// +optional
Inventory *ResourceInventory `json:"inventory,omitempty"`
Inventory *ResourceInventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// KCLRun is the Schema for the kclruns API
type KCLRun struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`

Spec KCLRunSpec `json:"spec,omitempty"`
Status KCLRunStatus `json:"status,omitempty"`
Spec KCLRunSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
Status KCLRunStatus `json:"status,omitempty" yaml:"status,omitempty"`
}

//+kubebuilder:object:root=true

// KCLRunList contains a list of KCLRun
type KCLRunList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KCLRun `json:"items"`
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Items []KCLRun `json:"items" yaml:"items"`
}

func init() {
Expand Down
41 changes: 41 additions & 0 deletions api/v1alpha1/kclrun_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package v1alpha1

import (
"bytes"
"os"
"testing"

"github.com/stretchr/testify/assert"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
)

func TestKCLRunDeserialize(t *testing.T) {
yamlContent, err := os.ReadFile("testdata/kclrun.yaml")
assert.NoError(t, err)
kclRun := &KCLRun{}
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlContent), 100)
err = decoder.Decode(kclRun)
assert.NoError(t, err)
assert.Equal(t, "example-kclrun", kclRun.ObjectMeta.Name)
assert.Equal(t, "default", kclRun.ObjectMeta.Namespace)
assert.Equal(t, &v1.Duration{Duration: 600000000000}, kclRun.Spec.Timeout)
assert.True(t, kclRun.Spec.Prune)
assert.Equal(t, true, kclRun.Spec.Prune)
assert.NotNil(t, kclRun.Spec.CommonMetadata)
assert.Equal(t, "example_value", kclRun.Spec.CommonMetadata.Annotations["some_annotation"])
assert.Equal(t, "my-app", kclRun.Spec.CommonMetadata.Labels["app"])
assert.Contains(t, kclRun.Spec.DependsOn[0].Name, "my-kustomization")
assert.NotNil(t, kclRun.Spec.KubeConfig)
assert.Equal(t, "my-kubeconfig", kclRun.Spec.KubeConfig.SecretRef.Name)
assert.Equal(t, "my-service-account", kclRun.Spec.ServiceAccountName)
assert.Equal(t, "my-target-namespace", kclRun.Spec.TargetNamespace)
assert.False(t, kclRun.Spec.Force)
assert.NotNil(t, kclRun.Spec.RetryInterval)
assert.Equal(t, "/path/to/kcl_mod_file_path", kclRun.Spec.Path)
assert.NotNil(t, kclRun.Spec.Config)
assert.Contains(t, kclRun.Spec.Config.Arguments, "env=\"prod\"")
assert.NotNil(t, kclRun.Spec.ConfigReference)
assert.Equal(t, "ConfigMap", kclRun.Spec.ConfigReference.Kind)
assert.Equal(t, "config-map-reference", kclRun.Spec.ConfigReference.Name)
}
55 changes: 55 additions & 0 deletions api/v1alpha1/testdata/kclrun.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
apiVersion: kclrun.example.com/v1
kind: KCLRun
metadata:
name: example-kclrun
namespace: default
spec:
commonMetadata:
annotations:
some_annotation: "example_value"
labels:
app: my-app
dependsOn:
- name: my-kustomization
namespace: default
kind: Kustomization
timeout: "10m"
persistentClient: true
kubeConfig:
secretRef:
name: my-kubeconfig
serviceAccountName: my-service-account
targetNamespace: my-target-namespace
force: false
interval: "5m"
retryInterval: "1m"
path: /path/to/kcl_mod_file_path
config:
arguments:
- env="prod"
- debug="true"
settings:
- setting1.yaml
- setting2.yaml
overrides:
- app.image="v2"
pathSelectors:
- path.to.output
vendor: false
sortKeys: true
showHidden: false
disableNone: true
configReference:
kind: ConfigMap
name: config-map-reference
optional: false
prune: true
healthChecks:
- kind: Pod
name: my-pod
namespace: default
wait: false
sourceRef:
kind: OCIRepository
name: podinfo
suspend: false
30 changes: 30 additions & 0 deletions config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,36 @@ spec:
description: Vendor denotes running kcl in the vendor mode.
type: boolean
type: object
configReference:
description: |-
ConfigReference holds references to ConfigMaps and Secrets containing
the KCL compile config. The ConfigMap and the Secret data keys represent the config names.
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
dependsOn:
description: |-
DependsOn may contain a meta.NamespacedObjectReference slice
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/onsi/ginkgo/v2 v2.20.1
github.com/onsi/gomega v1.34.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
k8s.io/apimachinery v0.31.0
k8s.io/client-go v0.31.0
kcl-lang.io/kcl-go v0.9.3
Expand Down Expand Up @@ -121,13 +122,13 @@ require (
github.com/otiai10/copy v1.14.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/powerman/rpc-codec v1.2.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
Expand Down