From ba2011482e8f81405381ca83511d9e4782fc0249 Mon Sep 17 00:00:00 2001 From: Jessica Yuen <im.jessicayuen@gmail.com> Date: Tue, 31 Oct 2017 16:49:53 -0700 Subject: [PATCH] Implement logic for retrieving component params This commit will add an interface `GetComponentParams` to metadata.Manager that returns a map of parameters for the passed in component. Also implements the logic for parsing the jsonnet snippet to retrieve the parameters. This functionality will later support new commands to list parameters. --- metadata/interface.go | 2 +- metadata/manager.go | 9 ++++ metadata/snippet/interface.go | 13 +++++ metadata/snippet/params.go | 23 ++++----- metadata/snippet/params_test.go | 91 +++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 13 deletions(-) diff --git a/metadata/interface.go b/metadata/interface.go index 4f860e91..d4f5495b 100644 --- a/metadata/interface.go +++ b/metadata/interface.go @@ -45,6 +45,7 @@ type Manager interface { CreateComponent(name string, text string, params map[string]string, templateType prototype.TemplateType) error LibPaths(envName string) (libPath, envLibPath, envComponentPath, envParamsPath AbsPath) SetComponentParams(component string, params map[string]string) error + GetComponentParams(name string) (map[string]string, error) CreateEnvironment(name, uri, namespace string, spec ClusterSpec) error DeleteEnvironment(name string) error GetEnvironments() ([]*Environment, error) @@ -57,7 +58,6 @@ type Manager interface { // GetPrototype(id string) Protoype // SearchPrototypes(query string) []Protoype // VendorLibrary(uri, version string) error - // GetComponentParams(name string) map[string]string // SetEnvironmentParams(component, env string, params map[string]string) error // GetEnvironmentParams(env string) (map[string]map[string]string, error) } diff --git a/metadata/manager.go b/metadata/manager.go index 10e63b8a..fdcbd706 100644 --- a/metadata/manager.go +++ b/metadata/manager.go @@ -194,6 +194,15 @@ func (m *manager) LibPaths(envName string) (libPath, envLibPath, envComponentPat appendToAbsPath(envPath, path.Base(envName)+".jsonnet"), appendToAbsPath(envPath, componentParamsFile) } +func (m *manager) GetComponentParams(component string) (map[string]string, error) { + text, err := afero.ReadFile(m.appFS, string(m.componentParamsPath)) + if err != nil { + return nil, err + } + + return snippet.GetComponentParams(component, string(text)) +} + func (m *manager) SetComponentParams(component string, params map[string]string) error { text, err := afero.ReadFile(m.appFS, string(m.componentParamsPath)) if err != nil { diff --git a/metadata/snippet/interface.go b/metadata/snippet/interface.go index e5461e86..7d6175cc 100644 --- a/metadata/snippet/interface.go +++ b/metadata/snippet/interface.go @@ -26,6 +26,19 @@ func AppendComponent(component, snippet string, params map[string]string) (strin return appendComponent(component, snippet, params) } +// GetComponentParams takes +// +// component: the name of the component to retrieve params for. +// snippet: the jsonnet snippet containing the component parameters. +// +// and returns a map of key-value param pairs corresponding to that component. +// +// An error will be returned if the component is not found in the snippet. +func GetComponentParams(component, snippet string) (map[string]string, error) { + params, _, err := getComponentParams(component, snippet) + return params, err +} + // SetComponentParams takes // // component: the name of the new component to be modified. diff --git a/metadata/snippet/params.go b/metadata/snippet/params.go index a02a4d6f..c63917eb 100644 --- a/metadata/snippet/params.go +++ b/metadata/snippet/params.go @@ -148,31 +148,30 @@ func appendComponent(component, snippet string, params map[string]string) (strin return strings.Join(lines, "\n"), nil } -func setComponentParams(component, snippet string, params map[string]string) (string, error) { +func getComponentParams(component, snippet string) (map[string]string, *ast.LocationRange, error) { componentsNode, err := visitComponentsObj(component, snippet) if err != nil { - return "", err + return nil, nil, err } - var loc *ast.LocationRange - var currentParams map[string]string - switch n := (*componentsNode).(type) { case *ast.Object: for _, field := range n.Fields { if field.Id != nil && string(*field.Id) == component { - currentParams, loc, err = visitComponentParams(field.Expr2) - if err != nil { - return "", err - } + return visitComponentParams(field.Expr2) } } default: - return "", fmt.Errorf("Expected component node type to be object") + return nil, nil, fmt.Errorf("Expected component node type to be object") } - if loc == nil { - return "", fmt.Errorf("Could not find component identifier '%s' when attempting to set params", component) + return nil, nil, fmt.Errorf("Could not find component identifier '%s' when attempting to set params", component) +} + +func setComponentParams(component, snippet string, params map[string]string) (string, error) { + currentParams, loc, err := getComponentParams(component, snippet) + if err != nil { + return "", err } for k, v := range currentParams { diff --git a/metadata/snippet/params_test.go b/metadata/snippet/params_test.go index 9249a6f4..88765d70 100644 --- a/metadata/snippet/params_test.go +++ b/metadata/snippet/params_test.go @@ -16,6 +16,7 @@ package snippet import ( + "reflect" "testing" ) @@ -175,6 +176,96 @@ func TestAppendComponentParams(t *testing.T) { } } +func TestGetComponentParams(t *testing.T) { + tests := []struct { + componentName string + jsonnet string + expected map[string]string + }{ + // Test getting the parameters where there is a single component + { + "foo", + ` +{ + global: {}, + components: { + foo: { + name: "foo", + replicas: 1, + }, + }, +}`, + map[string]string{"name": `"foo"`, "replicas": "1"}, + }, + // Test getting the parameters where there are multiple components + { + "foo", + ` +{ + global: {}, + components: { + bar: { + replicas: 5 + }, + foo: { + name: "foo", + replicas: 1, + }, + }, +}`, + map[string]string{"name": `"foo"`, "replicas": "1"}, + }, + } + + errors := []struct { + componentName string + jsonnet string + }{ + // Test case where component doesn't exist + { + "baz", + ` +{ + components: { + foo: { + name: "foo", + }, + }, +}`, + }, + // Test case where components isn't a top level object + { + "baz", + ` +{ + global: { + // User-defined global parameters; accessible to all component and environments, Ex: + // replicas: 4, + components: {}, + }, +}`, + }, + } + + for _, s := range tests { + params, err := GetComponentParams(s.componentName, s.jsonnet) + if err != nil { + t.Errorf("Unexpected error\n input: %v\n error: %v", s.jsonnet, err) + } + + if !reflect.DeepEqual(params, s.expected) { + t.Errorf("Wrong conversion\n expected:%v\n got:%v", s.expected, params) + } + } + + for _, e := range errors { + params, err := GetComponentParams(e.componentName, e.jsonnet) + if err == nil { + t.Errorf("Expected error but not found\n input: %v got: %v", e, params) + } + } +} + func TestSetComponentParams(t *testing.T) { tests := []struct { componentName string -- GitLab