Repository: fission/fission (language: go)

Issue:
fission environment create should allow adding environment variables to builder
**Is your feature request related to a problem? Please describe.**

The fission node builder allows pass through of the NODE_ENV variable, but there is no simple way of setting this variable.

**Describe the solution you'd like**

`fission environment create --builder-env` cli option to allow setting static environment variables


Discussion / hints:
Thank you for your first issue! ✨😊
@sanketsudake I am willing to work on this. Please assign me this issue.

Fix patch:
diff --git a/pkg/fission-cli/cmd/environment/command.go b/pkg/fission-cli/cmd/environment/command.go
index f4849418d1..feea1f0b0b 100644
--- a/pkg/fission-cli/cmd/environment/command.go
+++ b/pkg/fission-cli/cmd/environment/command.go
@@ -35,9 +35,8 @@ func Commands() *cobra.Command {
 			flag.EnvPoolsize, flag.EnvBuilderImage, flag.EnvBuildCmd,
 			flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory, flag.RunTimeMaxMemory,
 			flag.EnvTerminationGracePeriod, flag.EnvVersion, flag.EnvImagePullSecret, flag.EnvKeepArchive,
-			flag.NamespaceEnvironment, flag.EnvExternalNetwork,
-			flag.Labels, flag.Annotation,
-			flag.SpecSave, flag.SpecDry},
+			flag.NamespaceEnvironment, flag.EnvExternalNetwork, flag.Labels, flag.Annotation,
+			flag.SpecSave, flag.SpecDry, flag.EnvBuilder, flag.EnvRuntime},
 	})
 
 	getCmd := &cobra.Command{
diff --git a/pkg/fission-cli/cmd/environment/create.go b/pkg/fission-cli/cmd/environment/create.go
index 56bca9c592..0acf532332 100644
--- a/pkg/fission-cli/cmd/environment/create.go
+++ b/pkg/fission-cli/cmd/environment/create.go
@@ -21,6 +21,7 @@ import (
 
 	"github.com/hashicorp/go-multierror"
 	"github.com/pkg/errors"
+	apiv1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	fv1 "github.com/fission/fission/pkg/apis/core/v1"
@@ -143,6 +144,12 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
 		}
 	}
 
+	builderEnvParams := input.StringSlice(flagkey.EnvBuilder)
+	builderEnvList := util.GetEnvVarFromStringSlice(builderEnvParams)
+
+	runtimeEnvParams := input.StringSlice(flagkey.EnvRuntime)
+	runtimeEnvList := util.GetEnvVarFromStringSlice(runtimeEnvParams)
+
 	resourceReq, err := util.GetResourceReqs(input, nil)
 	if err != nil {
 		e = multierror.Append(e, err)
@@ -165,10 +172,16 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
 			Version: envVersion,
 			Runtime: fv1.Runtime{
 				Image: envImg,
+				Container: &apiv1.Container{
+					Env: runtimeEnvList,
+				},
 			},
 			Builder: fv1.Builder{
 				Image:   envBuilderImg,
 				Command: envBuildCmd,
+				Container: &apiv1.Container{
+					Env: builderEnvList,
+				},
 			},
 			Poolsize:                     poolsize,
 			Resources:                    *resourceReq,
diff --git a/pkg/fission-cli/flag/flag.go b/pkg/fission-cli/flag/flag.go
index 61fc23e745..05a813bc2f 100644
--- a/pkg/fission-cli/flag/flag.go
+++ b/pkg/fission-cli/flag/flag.go
@@ -181,6 +181,8 @@ var (
 	EnvImagePullSecret        = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
 	EnvExecutorType           = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"}
 	EnvForce                  = Flag{Type: Bool, Name: flagkey.EnvForce, Short: "f", Usage: "Force delete env even if one or more functions exist", DefaultValue: false}
+	EnvBuilder                = Flag{Type: StringSlice, Name: flagkey.EnvBuilder, Usage: "Environment variable to be set in the builder container"}
+	EnvRuntime                = Flag{Type: StringSlice, Name: flagkey.EnvRuntime, Usage: "Environment variable to be set in the runtime container"}
 
 	KwName      = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
 	KwFnName    = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
diff --git a/pkg/fission-cli/flag/key/key.go b/pkg/fission-cli/flag/key/key.go
index 4030706655..97607eec16 100644
--- a/pkg/fission-cli/flag/key/key.go
+++ b/pkg/fission-cli/flag/key/key.go
@@ -131,6 +131,8 @@ const (
 	EnvImagePullSecret = "imagepullsecret"
 	EnvExecutorType    = "executortype"
 	EnvForce           = force
+	EnvBuilder         = "builder-env"
+	EnvRuntime         = "runtime-env"
 
 	KwName      = resourceName
 	KwFnName    = "function"
diff --git a/pkg/fission-cli/util/util.go b/pkg/fission-cli/util/util.go
index b9877bbdce..0d55793fb2 100644
--- a/pkg/fission-cli/util/util.go
+++ b/pkg/fission-cli/util/util.go
@@ -372,6 +372,21 @@ func UpdateMapFromStringSlice(dataMap *map[string]string, params []string) bool
 	return updated
 }
 
+// GetEnvVarFromStringSlice parses key, val from "key=val" string array and updates passed []v1.EnvVar
+func GetEnvVarFromStringSlice(params []string) []v1.EnvVar {
+	envVarList := []v1.EnvVar{}
+	for _, m := range params {
+		keyValue := strings.SplitN(m, "=", 2)
+		if len(keyValue) == 2 && keyValue[1] != "" {
+			envVarList = append(envVarList, v1.EnvVar{
+				Name:  keyValue[0],
+				Value: keyValue[1],
+			})
+		}
+	}
+	return envVarList
+}
+
 func UrlForFunction(name, namespace string) string {
 	prefix := "/fission-function"
 	if namespace != metav1.NamespaceDefault {


Test patch:
diff --git a/pkg/fission-cli/util/util_test.go b/pkg/fission-cli/util/util_test.go
new file mode 100644
index 0000000000..fd64262b0f
--- /dev/null
+++ b/pkg/fission-cli/util/util_test.go
@@ -0,0 +1,66 @@
+/*
+Copyright 2022 The Fission 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 (
+	"reflect"
+	"testing"
+
+	v1 "k8s.io/api/core/v1"
+)
+
+func TestGetEnvVarFromStringSlice(t *testing.T) {
+
+	tests := []struct {
+		name string
+		args []string
+		want []v1.EnvVar
+	}{
+		{
+			name: "params-with-key-value",
+			args: []string{"serverless=fission", "container=docker"},
+			want: []v1.EnvVar{
+				{
+					Name:  "serverless",
+					Value: "fission",
+				},
+				{
+					Name:  "container",
+					Value: "docker",
+				},
+			},
+		},
+		{
+			name: "params-with-nil-value",
+			args: []string{"serverless=", "container="},
+			want: []v1.EnvVar{},
+		},
+		{
+			name: "params-with-only-key",
+			args: []string{"serverless", "container"},
+			want: []v1.EnvVar{},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := GetEnvVarFromStringSlice(tt.args); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetEnvVarFromStringSlice() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}