diff --git a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go index 23a7db2fd9..c40185c243 100644 --- a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go +++ b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go @@ -318,26 +318,6 @@ type FreeStyleServiceInfo struct { KeyVals []*KeyVal `bson:"key_vals" yaml:"key_vals" json:"key_vals"` } -func (j *FreeStyleServiceInfo) DeepCopyKeyVals() []*KeyVal { - envs := make([]*KeyVal, 0) - - for _, env := range j.KeyVals { - choiceOption := make([]string, 0) - for _, choice := range env.ChoiceOption { - choiceOption = append(choiceOption, choice) - } - envs = append(envs, &KeyVal{ - Key: env.Key, - Value: env.Value, - Type: env.Type, - RegistryID: env.RegistryID, - ChoiceOption: choiceOption, - IsCredential: env.IsCredential, - }) - } - return envs -} - func (i *FreeStyleServiceInfo) GetKey() string { if i == nil { return "" diff --git a/pkg/microservice/aslan/core/service.go b/pkg/microservice/aslan/core/service.go index f690472b12..3b9dde6ae7 100644 --- a/pkg/microservice/aslan/core/service.go +++ b/pkg/microservice/aslan/core/service.go @@ -33,12 +33,12 @@ import ( client2 "sigs.k8s.io/controller-runtime/pkg/client" commonconfig "github.com/koderover/zadig/v2/pkg/config" - commonutil "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/util" configbase "github.com/koderover/zadig/v2/pkg/config" "github.com/koderover/zadig/v2/pkg/microservice/aslan/config" "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/service/kube" "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/service/webhook" "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/service/workflowcontroller" + commonutil "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/util" environmentservice "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/environment/service" multiclusterservice "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/multicluster/service" releaseplanservice "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/release_plan/service" diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job.go index a36a7371cb..73d59079b0 100644 --- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job.go +++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/koderover/zadig/v2/pkg/util" "github.com/mozillazg/go-pinyin" "github.com/pkg/errors" "go.uber.org/zap" @@ -922,23 +923,31 @@ func findMatchedRepoFromParams(params []*commonmodels.Param, paramName string) ( return nil, fmt.Errorf("not found repo from params") } -func renderServiceVariables(workflow *commonmodels.WorkflowV4, envs []*commonmodels.KeyVal, serviceName string, serviceModule string) error { +func renderServiceVariables(workflow *commonmodels.WorkflowV4, envs []*commonmodels.KeyVal, serviceName string, serviceModule string) ([]*commonmodels.KeyVal, error) { + duplicatedEnvs := make([]*commonmodels.KeyVal, 0) + + err := util.DeepCopy(&duplicatedEnvs, &envs) + if err != nil { + return nil, err + } + if serviceName == "" || serviceModule == "" { - return nil + return duplicatedEnvs, nil } params, err := getWorkflowStageParams(workflow) if err != nil { err = fmt.Errorf("failed to get workflow stage parameters, error: %s", err) - return err + return nil, err } - for _, env := range envs { + + for _, env := range duplicatedEnvs { if strings.HasPrefix(env.Value, "{{.") && strings.HasSuffix(env.Value, "}}") { env.Value = strings.ReplaceAll(env.Value, "", serviceName) env.Value = strings.ReplaceAll(env.Value, "", serviceModule) env.Value = renderString(env.Value, setting.RenderValueTemplate, params) } } - return nil + return duplicatedEnvs, nil } diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_freestyle.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_freestyle.go index d61025a98a..183647bac8 100644 --- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_freestyle.go +++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_freestyle.go @@ -428,10 +428,12 @@ func (j *FreeStyleJob) toJob(taskID int64, jobSubTaskID int, registries []*commo } if service != nil { - err = renderServiceVariables(j.workflow, jobTaskSpec.Properties.Envs, service.ServiceName, service.ServiceModule) + renderedEnvs, err := renderServiceVariables(j.workflow, jobTaskSpec.Properties.Envs, service.ServiceName, service.ServiceModule) if err != nil { return nil, fmt.Errorf("failed to render service variables, error: %v", err) } + + jobTaskSpec.Properties.Envs = renderedEnvs } jobTaskSpec.Properties.CustomEnvs = jobTaskSpec.Properties.Envs diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_scanning.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_scanning.go index f34768988b..39cb27bccf 100644 --- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_scanning.go +++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_scanning.go @@ -558,10 +558,12 @@ func (j *ScanningJob) toJobTask(jobSubTaskID int, scanning *commonmodels.Scannin } if scanningType == string(config.ServiceScanningType) { - err = renderServiceVariables(j.workflow, jobTaskSpec.Properties.Envs, serviceName, serviceModule) + renderedEnv, err := renderServiceVariables(j.workflow, jobTaskSpec.Properties.Envs, serviceName, serviceModule) if err != nil { return nil, fmt.Errorf("failed to render service variables, error: %v", err) } + + jobTaskSpec.Properties.Envs = renderedEnv } cacheS3 := &commonmodels.S3Storage{} diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_testing.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_testing.go index 09bc811000..b7eebe1cf1 100644 --- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_testing.go +++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_testing.go @@ -450,7 +450,7 @@ func (j *TestingJob) toJobtask(jobSubTaskID int, testing *commonmodels.TestModul "service_module": serviceModule, } - err = renderServiceVariables(j.workflow, customEnvs, serviceName, serviceModule) + customEnvs, err = renderServiceVariables(j.workflow, customEnvs, serviceName, serviceModule) if err != nil { return nil, fmt.Errorf("failed to render service variables, error: %v", err) } diff --git a/pkg/util/deep_copy.go b/pkg/util/deep_copy.go new file mode 100644 index 0000000000..39e6c8b3c7 --- /dev/null +++ b/pkg/util/deep_copy.go @@ -0,0 +1,40 @@ +/* +Copyright 2024 The KodeRover 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 util + +import ( + "encoding/json" + "fmt" +) + +func DeepCopy(dst interface{}, src interface{}) error { + if dst == nil { + return fmt.Errorf("dst cannot be nil") + } + if src == nil { + return fmt.Errorf("src cannot be nil") + } + bytes, err := json.Marshal(src) + if err != nil { + return fmt.Errorf("unable to marshal src: %w", err) + } + err = json.Unmarshal(bytes, dst) + if err != nil { + return fmt.Errorf("unable to unmarshal into dst: %w", err) + } + return nil +} diff --git a/pkg/util/deepcopy/deepcopy.go b/pkg/util/deepcopy/deepcopy.go deleted file mode 100644 index f39b381fec..0000000000 --- a/pkg/util/deepcopy/deepcopy.go +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2022 The KodeRover 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 deepcopy - -import ( - "fmt" - "reflect" - "unsafe" - - afastjson "github.com/segmentio/encoding/json" -) - -func JsonFromTo(original, copy interface{}) error { - copyBytes, err := afastjson.Marshal(original) - if err != nil { - return fmt.Errorf("fast marshal from original failed, error: %v", err) - } - - err = afastjson.Unmarshal(copyBytes, copy) - if err != nil { - return fmt.Errorf("fast unmarshal to copy failed, error: %v", err) - } - - return nil -} - -// FromTo deep copies original and assigns the copy to the copy argument (pointer). -func FromTo(original, copy interface{}) error { - if original == nil { - copy = nil - return nil - } else if copy == nil { // TODO try to initialize it here - return fmt.Errorf("FromTo: copy target is nil, it should be a valid pointer") - // copyValue := reflect.New(value.Type().Elem()).Elem() - // copy = copyValue.Interface() - } - copyValue := reflect.ValueOf(copy) - if copyValue.Kind() != reflect.Ptr { - return fmt.Errorf("FromTo: copy target type %T and not a pointer", copy) - } - value := reflect.ValueOf(original) - if value.Kind() == reflect.Ptr { - if value.IsNil() { - copy = nil // TODO return typed nil - return nil - } - value = value.Elem() - } - copyValue.Elem().Set(deepCopy(value)) - return nil -} - -func deepCopy(original reflect.Value) reflect.Value { - switch original.Kind() { - case reflect.Slice: - return deepCopySlice(original) - case reflect.Map: - return deepCopyMap(original) - case reflect.Ptr: - return deepCopyPointer(original) - case reflect.Struct: - return deepCopyStruct(original) - case reflect.Chan: - return deepCopyChan(original) - case reflect.Array: - return deepCopyArray(original) - default: - return forceCopyValue(original) - } -} - -func deepCopySlice(original reflect.Value) reflect.Value { - if original.IsNil() { - return original - } - copy := reflect.MakeSlice(original.Type(), 0, 0) - for i := 0; i < original.Len(); i++ { - elementCopy := deepCopy(original.Index(i)) - copy = reflect.Append(copy, elementCopy) - } - return copy -} - -func deepCopyArray(original reflect.Value) reflect.Value { - if original.Len() == 0 { - // it cannot be changed anyway, so we can return the original - return original - } - elementType := original.Index(0).Type() - arrayType := reflect.ArrayOf(original.Len(), elementType) - newPointer := reflect.New(arrayType) - copy := newPointer.Elem() - for i := 0; i < original.Len(); i++ { - subCopy := deepCopy(original.Index(i)) - copy.Index(i).Set(subCopy) - } - return copy -} - -func deepCopyMap(original reflect.Value) reflect.Value { - if original.IsNil() { - return original - } - keyType := original.Type().Key() - valueType := original.Type().Elem() - mapType := reflect.MapOf(keyType, valueType) - copy := reflect.MakeMap(mapType) - for _, key := range original.MapKeys() { - value := deepCopy(original.MapIndex(key)) - copy.SetMapIndex(key, value) - } - return copy -} - -func deepCopyPointer(original reflect.Value) reflect.Value { - if original.IsNil() { - return original - } - element := original.Elem() - copy := reflect.New(element.Type()) - copyElement := deepCopy(element) - copy.Elem().Set(copyElement) - return copy -} - -func deepCopyStruct(original reflect.Value) reflect.Value { - copy := reflect.New(original.Type()).Elem() - copy.Set(original) - for i := 0; i < original.NumField(); i++ { - fieldValue := copy.Field(i) - fieldValue = reflect.NewAt(fieldValue.Type(), unsafe.Pointer(fieldValue.UnsafeAddr())).Elem() - fieldValue.Set(deepCopy(fieldValue)) - } - return copy -} - -func deepCopyChan(original reflect.Value) reflect.Value { - return reflect.MakeChan(original.Type(), original.Cap()) -} - -// forceCopyValue simply creates a new pointer and sets its value to the original. -func forceCopyValue(original reflect.Value) reflect.Value { - originalType := original.Type() - newPointer := reflect.New(originalType) - newPointer.Elem().Set(original) - return newPointer.Elem() -}