diff --git a/pkg/appfile/appfile.go b/pkg/appfile/appfile.go index 991e6a305..181c07cd2 100644 --- a/pkg/appfile/appfile.go +++ b/pkg/appfile/appfile.go @@ -26,12 +26,15 @@ type AppFile struct { UpdateTime time.Time `json:"updateTime,omitempty"` Services map[string]Service `json:"services"` Secrets map[string]string `json:"secrets"` + + configGetter configGetter } func NewAppFile() *AppFile { return &AppFile{ - Services: make(map[string]Service), - Secrets: make(map[string]string), + Services: make(map[string]Service), + Secrets: make(map[string]string), + configGetter: defaultConfigGetter{}, } } @@ -96,7 +99,7 @@ func (app *AppFile) buildOAM(ns string, io cmdutil.IOStreams, buildImage bool, t } io.Infof("\nRendering configs for service (%s)...\n", sname) - acComp, comp, err := svc.RenderService(tm, sname, ns) + acComp, comp, err := svc.RenderService(tm, sname, ns, app.configGetter) if err != nil { return nil, nil, err } diff --git a/pkg/appfile/appfile_test.go b/pkg/appfile/appfile_test.go index 4f7560ed2..1ff8faa83 100644 --- a/pkg/appfile/appfile_test.go +++ b/pkg/appfile/appfile_test.go @@ -42,6 +42,19 @@ services: cmd: ["node", "server.js"] ` + yamlWithConfig := `name: myapp +services: + express-server: + type: withconfig + image: oamdev/testapp:v1 + cmd: ["node", "server.js"] + route: + domain: example.com + http: + "/": 8080 + config: test +` + templateWebservice := `parameter: #webservice #webservice: { cmd: [...string] @@ -77,6 +90,25 @@ output: { command: parameter.cmd } }` + templateWithConfig := `parameter: #withconfig +#withconfig: { + cmd: [...string] + image: string +} + +output: { + apiVersion: "test.oam.dev/v1" + kind: "WebService" + metadata: { + name: context.name + } + spec: { + image: parameter.image + command: parameter.cmd + env: context.config + } +} +` templateRoute := `parameter: #route #route: { domain: string @@ -234,6 +266,22 @@ outputs: ingress: { }, } + compWithConfig := comp1.DeepCopy() + fakeConfigData2 := []map[string]string{{ + "name": "test", + "value": "test-value", + }} + // for deepCopy. Otherwise deepcopy will panic in SetNestedField. + fakeConfigData := []interface{}{map[string]interface{}{ + "name": "test", + "value": "test-value", + }} + if err := unstructured.SetNestedField( + compWithConfig.Spec.Workload.Object.(*unstructured.Unstructured).UnstructuredContent(), + fakeConfigData, "spec", "env"); err != nil { + t.Fatal(err) + } + type args struct { appfileData string workloadTemplates map[string]string @@ -287,12 +335,30 @@ outputs: ingress: { err: ErrImageNotDefined, }, }, + "config data should be set": { + args: args{ + appfileData: yamlWithConfig, + workloadTemplates: map[string]string{ + "withconfig": templateWithConfig, + }, + traitTemplates: map[string]string{ + "route": templateRoute, + }, + }, + want: want{ + appConfig: ac1, + components: []*v1alpha2.Component{compWithConfig}, + }, + }, } io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr} for caseName, c := range cases { t.Run(caseName, func(t *testing.T) { app := NewAppFile() + app.configGetter = &fakeConfigGetter{ + Data: fakeConfigData2, + } err := yaml.Unmarshal([]byte(c.args.appfileData), app) if err != nil { t.Fatal(err) @@ -339,7 +405,7 @@ outputs: ingress: { if cp1.Name != cp2.Name { continue } - assert.Equal(t, cp1, cp2) + assert.Equal(t, cp1.Spec.Workload.Object, cp2.Spec.Workload.Object) found = true break } diff --git a/pkg/appfile/config_getter.go b/pkg/appfile/config_getter.go new file mode 100644 index 000000000..413662d83 --- /dev/null +++ b/pkg/appfile/config_getter.go @@ -0,0 +1,47 @@ +package appfile + +import ( + "bufio" + "bytes" + + "github.com/oam-dev/kubevela/pkg/utils/config" + "github.com/oam-dev/kubevela/pkg/utils/env" +) + +type configGetter interface { + GetConfigData(configName string) ([]map[string]string, error) +} + +type defaultConfigGetter struct{} + +func (defaultConfigGetter) GetConfigData(configName string) ([]map[string]string, error) { + envName, err := env.GetCurrentEnvName() + if err != nil { + return nil, err + } + cfgData, err := config.ReadConfig(envName, configName) + if err != nil { + return nil, err + } + scanner := bufio.NewScanner(bytes.NewReader(cfgData)) + data := []map[string]string{} + for scanner.Scan() { + k, v, err := config.ReadConfigLine(scanner.Text()) + if err != nil { + return nil, err + } + data = append(data, map[string]string{ + "name": k, + "value": v, + }) + } + return data, nil +} + +type fakeConfigGetter struct { + Data []map[string]string +} + +func (f *fakeConfigGetter) GetConfigData(_ string) ([]map[string]string, error) { + return f.Data, nil +} diff --git a/pkg/appfile/service.go b/pkg/appfile/service.go index c62ccbfa6..411738e70 100644 --- a/pkg/appfile/service.go +++ b/pkg/appfile/service.go @@ -1,8 +1,6 @@ package appfile import ( - "bufio" - "bytes" "encoding/json" "errors" "fmt" @@ -18,8 +16,6 @@ import ( "github.com/oam-dev/kubevela/pkg/appfile/template" mycue "github.com/oam-dev/kubevela/pkg/cue" - "github.com/oam-dev/kubevela/pkg/utils/config" - "github.com/oam-dev/kubevela/pkg/utils/env" ) type Service map[string]interface{} @@ -74,8 +70,7 @@ func (s Service) GetBuild() *Build { // RenderService render all capabilities of a service to CUE values of a Component. // It outputs a Component which will be marshaled as standalone Component and also returned AppConfig Component section. -func (s Service) RenderService(tm template.Manager, name, ns string) ( - *v1alpha2.ApplicationConfigurationComponent, *v1alpha2.Component, error) { +func (s Service) RenderService(tm template.Manager, name, ns string, cg configGetter) (*v1alpha2.ApplicationConfigurationComponent, *v1alpha2.Component, error) { // sort out configs by workload/trait workloadKeys := map[string]interface{}{} @@ -103,7 +98,7 @@ func (s Service) RenderService(tm template.Manager, name, ns string) ( "name": name, } if cn := s.GetUserConfigName(); cn != "" { - data, err := getConfigData(cn) + data, err := cg.GetConfigData(cn) if err != nil { return nil, nil, err } @@ -143,30 +138,6 @@ func (s Service) RenderService(tm template.Manager, name, ns string) ( return acComp, component, nil } -func getConfigData(configName string) ([]map[string]string, error) { - envName, err := env.GetCurrentEnvName() - if err != nil { - return nil, err - } - cfgData, err := config.ReadConfig(envName, configName) - if err != nil { - return nil, err - } - scanner := bufio.NewScanner(bytes.NewReader(cfgData)) - data := []map[string]string{} - for scanner.Scan() { - k, v, err := config.ReadConfigLine(scanner.Text()) - if err != nil { - return nil, err - } - data = append(data, map[string]string{ - "name": k, - "value": v, - }) - } - return data, nil -} - func (af *AppFile) GetServices() map[string]Service { return af.Services }