From 43df9633fdc1e3b2498676d5d90168c600b25c0b Mon Sep 17 00:00:00 2001 From: Lan Liang Date: Fri, 16 Aug 2024 05:05:30 +0000 Subject: [PATCH] Add field of override for duplicate args of components. Signed-off-by: Lan Liang --- .../v1alpha1/kwokctl_configuration_types.go | 2 + .../kwokctl_configuration_types.go | 2 + .../zz_generated.conversion.go | 2 + pkg/kwokctl/runtime/binary/cluster.go | 2 +- pkg/kwokctl/runtime/compose/cluster.go | 2 +- pkg/kwokctl/runtime/kind/cluster.go | 10 +- pkg/kwokctl/runtime/util.go | 32 ++++- pkg/kwokctl/runtime/util_test.go | 134 ++++++++++++++++++ site/content/en/docs/generated/apis.md | 11 ++ 9 files changed, 185 insertions(+), 12 deletions(-) create mode 100644 pkg/kwokctl/runtime/util_test.go diff --git a/pkg/apis/config/v1alpha1/kwokctl_configuration_types.go b/pkg/apis/config/v1alpha1/kwokctl_configuration_types.go index 538e64f05..29b4782d1 100644 --- a/pkg/apis/config/v1alpha1/kwokctl_configuration_types.go +++ b/pkg/apis/config/v1alpha1/kwokctl_configuration_types.go @@ -61,6 +61,8 @@ type ExtraArgs struct { Key string `json:"key"` // Value is the value of the extra args. Value string `json:"value"` + // Override is the value of is it override the arg + Override bool `json:"override"` } // ComponentPatches holds information about the component patches. diff --git a/pkg/apis/internalversion/kwokctl_configuration_types.go b/pkg/apis/internalversion/kwokctl_configuration_types.go index 43c875e25..410d799e3 100644 --- a/pkg/apis/internalversion/kwokctl_configuration_types.go +++ b/pkg/apis/internalversion/kwokctl_configuration_types.go @@ -47,6 +47,8 @@ type ExtraArgs struct { Key string // Value is the value of the extra args. Value string + // Override is the value of is it override the arg + Override bool } // ComponentPatches holds information about the component patches. diff --git a/pkg/apis/internalversion/zz_generated.conversion.go b/pkg/apis/internalversion/zz_generated.conversion.go index e0b67e51d..65008ceaa 100644 --- a/pkg/apis/internalversion/zz_generated.conversion.go +++ b/pkg/apis/internalversion/zz_generated.conversion.go @@ -1350,6 +1350,7 @@ func Convert_v1alpha1_ExpressionFromSource_To_internalversion_ExpressionFromSour func autoConvert_internalversion_ExtraArgs_To_v1alpha1_ExtraArgs(in *ExtraArgs, out *configv1alpha1.ExtraArgs, s conversion.Scope) error { out.Key = in.Key out.Value = in.Value + out.Override = in.Override return nil } @@ -1361,6 +1362,7 @@ func Convert_internalversion_ExtraArgs_To_v1alpha1_ExtraArgs(in *ExtraArgs, out func autoConvert_v1alpha1_ExtraArgs_To_internalversion_ExtraArgs(in *configv1alpha1.ExtraArgs, out *ExtraArgs, s conversion.Scope) error { out.Key = in.Key out.Value = in.Value + out.Override = in.Override return nil } diff --git a/pkg/kwokctl/runtime/binary/cluster.go b/pkg/kwokctl/runtime/binary/cluster.go index 8ec255636..d520aab32 100644 --- a/pkg/kwokctl/runtime/binary/cluster.go +++ b/pkg/kwokctl/runtime/binary/cluster.go @@ -731,7 +731,7 @@ func (c *Cluster) finishInstall(ctx context.Context, env *env) error { conf := &env.kwokctlConfig.Options for i := range env.kwokctlConfig.Components { - runtime.ApplyComponentPatches(&env.kwokctlConfig.Components[i], env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &env.kwokctlConfig.Components[i], env.kwokctlConfig.ComponentsPatches) } // Setup kubeconfig diff --git a/pkg/kwokctl/runtime/compose/cluster.go b/pkg/kwokctl/runtime/compose/cluster.go index 249983554..8ebb7d281 100644 --- a/pkg/kwokctl/runtime/compose/cluster.go +++ b/pkg/kwokctl/runtime/compose/cluster.go @@ -810,7 +810,7 @@ func (c *Cluster) finishInstall(ctx context.Context, env *env) error { conf := &env.kwokctlConfig.Options for i := range env.kwokctlConfig.Components { - runtime.ApplyComponentPatches(&env.kwokctlConfig.Components[i], env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &env.kwokctlConfig.Components[i], env.kwokctlConfig.ComponentsPatches) } // Setup kubeconfig diff --git a/pkg/kwokctl/runtime/kind/cluster.go b/pkg/kwokctl/runtime/kind/cluster.go index 484ba117f..87e1e2cc8 100644 --- a/pkg/kwokctl/runtime/kind/cluster.go +++ b/pkg/kwokctl/runtime/kind/cluster.go @@ -561,7 +561,7 @@ func (c *Cluster) addKubectlProxy(ctx context.Context, env *env) (err error) { return err } - runtime.ApplyComponentPatches(&kubectlProxyComponent, env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &kubectlProxyComponent, env.kwokctlConfig.ComponentsPatches) dashboardPod, err := yaml.Marshal(components.ConvertToPod(kubectlProxyComponent)) if err != nil { @@ -654,7 +654,7 @@ func (c *Cluster) addKwokController(ctx context.Context, env *env) (err error) { }) kwokControllerComponent.Volumes = append(kwokControllerComponent.Volumes, logVolumes...) - runtime.ApplyComponentPatches(&kwokControllerComponent, env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &kwokControllerComponent, env.kwokctlConfig.ComponentsPatches) pod := components.ConvertToPod(kwokControllerComponent) pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, corev1.EnvVar{ @@ -709,7 +709,7 @@ func (c *Cluster) addDashboard(ctx context.Context, env *env) (err error) { return fmt.Errorf("failed to build dashboard component: %w", err) } - runtime.ApplyComponentPatches(&dashboardComponent, env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &dashboardComponent, env.kwokctlConfig.ComponentsPatches) dashboardPod, err := yaml.Marshal(components.ConvertToPod(dashboardComponent)) if err != nil { @@ -859,7 +859,7 @@ func (c *Cluster) addPrometheus(ctx context.Context, env *env) (err error) { }, ) - runtime.ApplyComponentPatches(&prometheusComponent, env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &prometheusComponent, env.kwokctlConfig.ComponentsPatches) prometheusPod, err := yaml.Marshal(components.ConvertToPod(prometheusComponent)) if err != nil { @@ -901,7 +901,7 @@ func (c *Cluster) addJaeger(ctx context.Context, env *env) (err error) { return err } - runtime.ApplyComponentPatches(&jaegerComponent, env.kwokctlConfig.ComponentsPatches) + runtime.ApplyComponentPatches(ctx, &jaegerComponent, env.kwokctlConfig.ComponentsPatches) jaegerPod, err := yaml.Marshal(components.ConvertToPod(jaegerComponent)) if err != nil { diff --git a/pkg/kwokctl/runtime/util.go b/pkg/kwokctl/runtime/util.go index a9aa94aac..2ca55aa3b 100644 --- a/pkg/kwokctl/runtime/util.go +++ b/pkg/kwokctl/runtime/util.go @@ -20,12 +20,14 @@ import ( "context" "fmt" "sort" + "strings" "golang.org/x/sync/errgroup" "sigs.k8s.io/kwok/pkg/apis/internalversion" "sigs.k8s.io/kwok/pkg/config" "sigs.k8s.io/kwok/pkg/kwokctl/components" + "sigs.k8s.io/kwok/pkg/log" "sigs.k8s.io/kwok/pkg/utils/maps" "sigs.k8s.io/kwok/pkg/utils/path" "sigs.k8s.io/kwok/pkg/utils/slices" @@ -103,23 +105,43 @@ func GetComponentPatches(conf *internalversion.KwokctlConfiguration, componentNa } // ApplyComponentPatches applies patches to a component. -func ApplyComponentPatches(component *internalversion.Component, patches []internalversion.ComponentPatches) { +func ApplyComponentPatches(ctx context.Context, component *internalversion.Component, patches []internalversion.ComponentPatches) { for _, patch := range patches { - applyComponentPatch(component, patch) + applyComponentPatch(ctx, component, patch) } } -func applyComponentPatch(component *internalversion.Component, patch internalversion.ComponentPatches) { +func applyComponentPatch(ctx context.Context, component *internalversion.Component, patch internalversion.ComponentPatches) { if patch.Name != component.Name { return } component.Volumes = append(component.Volumes, patch.ExtraVolumes...) component.Envs = append(component.Envs, patch.ExtraEnvs...) - for _, a := range patch.ExtraArgs { - component.Args = append(component.Args, fmt.Sprintf("--%s=%s", a.Key, a.Value)) + if a.Override { + component.Args = applyComponentArgsOverride(ctx, component.Args, a) + } else { + component.Args = append(component.Args, fmt.Sprintf("--%s=%s", a.Key, a.Value)) + } + } +} + +func applyComponentArgsOverride(ctx context.Context, args []string, a internalversion.ExtraArgs) []string { + k := fmt.Sprintf("--%s=", a.Key) + overrided := false + for i := len(args) - 1; i >= 0; i-- { + if strings.HasPrefix(args[i], k) { + args[i] = fmt.Sprintf("--%s=%s", a.Key, a.Value) + overrided = true + break + } + } + if !overrided { + logger := log.FromContext(ctx) + logger.Warn("have not match override", "key", a.Key) } + return args } // ExpandVolumesHostPaths expands relative paths specified in volumes to absolute paths diff --git a/pkg/kwokctl/runtime/util_test.go b/pkg/kwokctl/runtime/util_test.go new file mode 100644 index 000000000..2d3ff743b --- /dev/null +++ b/pkg/kwokctl/runtime/util_test.go @@ -0,0 +1,134 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package runtime + +import ( + "context" + "reflect" + "testing" + + "sigs.k8s.io/kwok/pkg/apis/internalversion" +) + +func TestApplyComponentArgsOverride(t *testing.T) { + tests := []struct { + name string + args []string + patch internalversion.ExtraArgs + wantArgs []string + }{ + { + name: "Override the value", + args: []string{ + "--foo=1", + "--bar=2", + }, + patch: internalversion.ExtraArgs{ + Key: "foo", + Value: "10", + Override: true, + }, + wantArgs: []string{ + "--foo=10", + "--bar=2", + }, + }, + { + name: "Unmatched flag", + args: []string{ + "--foo=1", + }, + patch: internalversion.ExtraArgs{ + Key: "bar", + Value: "2", + Override: true, + }, + wantArgs: []string{ + "--foo=1", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + applyComponentArgsOverride(context.TODO(), tt.args, internalversion.ExtraArgs{ + Key: tt.patch.Key, + Value: tt.patch.Value, + Override: tt.patch.Override, + }) + + if !reflect.DeepEqual(tt.wantArgs, tt.args) { + t.Errorf("Exist is not expact! key:%s want args:%s, got args:%s", tt.patch.Key, tt.wantArgs, tt.args) + } + }) + } +} + +func TestApplyComponentPatch(t *testing.T) { + tests := []struct { + name string + component internalversion.Component + patch internalversion.ComponentPatches + wantArgs []string + }{ + { + name: "Override the value", + component: internalversion.Component{ + Name: "test", + Args: []string{"--etcd-servers=http://localhost:2379", "--etcd-prefix=/registry"}, + }, + patch: internalversion.ComponentPatches{ + Name: "test", + ExtraArgs: []internalversion.ExtraArgs{ + { + Key: "etcd-servers", + Value: "http://127.0.0.1:2379", + Override: true, + }, + }, + }, + wantArgs: []string{"--etcd-servers=http://127.0.0.1:2379", "--etcd-prefix=/registry"}, + }, + { + name: "Do not override the value", + component: internalversion.Component{ + Name: "test", + Args: []string{"--etcd-servers=http://localhost:2379", "--etcd-prefix=/registry"}, + }, + patch: internalversion.ComponentPatches{ + Name: "test", + ExtraArgs: []internalversion.ExtraArgs{ + { + Key: "etcd-servers", + Value: "http://127.0.0.1:2379", + Override: false, + }, + }, + }, + wantArgs: []string{"--etcd-servers=http://localhost:2379", "--etcd-prefix=/registry", "--etcd-servers=http://127.0.0.1:2379"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + applyComponentPatch(context.TODO(), &tt.component, tt.patch) + if !reflect.DeepEqual(tt.wantArgs, tt.component.Args) { + t.Errorf("Exist is not expact! key:%s want args:%s, got args:%s", tt.patch.ExtraArgs[0].Key, tt.wantArgs, tt.component.Args) + } + }) + } +} diff --git a/site/content/en/docs/generated/apis.md b/site/content/en/docs/generated/apis.md index 7fe24615b..526dc5a77 100644 --- a/site/content/en/docs/generated/apis.md +++ b/site/content/en/docs/generated/apis.md @@ -2264,6 +2264,17 @@ string

Value is the value of the extra args.

+ + +override + +bool + + + +

Override is the value of is it override the arg

+ +