Skip to content

Commit 68eff8c

Browse files
committed
add --env-secret and --env-config-map flags to deploy
1 parent 906e34a commit 68eff8c

File tree

5 files changed

+184
-20
lines changed

5 files changed

+184
-20
lines changed

docs/cmd/knctl_deploy.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ knctl deploy [flags]
3939
```
4040
--build-timeout duration Set timeout for building stage (Knative Build has a 10m default)
4141
-d, --directory string Set source code directory
42-
-e, --env strings Set environment variable (format: key=value) (can be specified multiple times)
42+
-e, --env strings Set environment variable (format: ENV_KEY=value) (can be specified multiple times)
43+
--env-config-map strings Set environment variable from a config map (format: ENV_KEY=config-map-name/key) (can be specified multiple times)
44+
--env-secret strings Set environment variable from a secret (format: ENV_KEY=secret-name/key) (can be specified multiple times)
4345
--generate-name Set to generate name
4446
--git-revision string Set Git revision (examples: https://git-scm.com/docs/gitrevisions#_specifying_revisions)
4547
--git-url string Set Git URL

pkg/knctl/cmd/service/deploy_flags.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ type DeployFlags struct {
2828
GenerateNameFlags cmdcore.GenerateNameFlags
2929
BuildCreateArgsFlags cmdbld.CreateArgsFlags
3030

31-
Image string
32-
Env []string
31+
Image string
32+
EnvVars []string
33+
EnvSecrets []string
34+
EnvConfigMaps []string
3335

3436
WatchRevisionReady bool
3537
WatchRevisionReadyTimeout time.Duration
@@ -57,5 +59,7 @@ func (s *DeployFlags) Set(cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory)
5759
cmd.Flags().BoolVarP(&s.WatchPodLogsIndefinitely, "watch-pod-logs-indefinitely", "l",
5860
false, "Watch pod logs for new revision indefinitely")
5961

60-
cmd.Flags().StringSliceVarP(&s.Env, "env", "e", nil, "Set environment variable (format: key=value) (can be specified multiple times)")
62+
cmd.Flags().StringSliceVarP(&s.EnvVars, "env", "e", nil, "Set environment variable (format: ENV_KEY=value) (can be specified multiple times)")
63+
cmd.Flags().StringSliceVar(&s.EnvSecrets, "env-secret", nil, "Set environment variable from a secret (format: ENV_KEY=secret-name/key) (can be specified multiple times)")
64+
cmd.Flags().StringSliceVar(&s.EnvConfigMaps, "env-config-map", nil, "Set environment variable from a config map (format: ENV_KEY=config-map-name/key) (can be specified multiple times)")
6165
}

pkg/knctl/cmd/service/deploy_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ func TestNewDeployCmd_Ok(t *testing.T) {
5858
Timeout: 1 * time.Second,
5959
},
6060
},
61-
Image: "test-image",
62-
Env: []string{"key1=val1", "key2=val2"},
61+
Image: "test-image",
62+
EnvVars: []string{"key1=val1", "key2=val2"},
6363

6464
WatchRevisionReady: true,
6565
WatchRevisionReadyTimeout: 5 * time.Minute,
@@ -98,8 +98,8 @@ func TestNewDeployCmd_OkLongFlagNames(t *testing.T) {
9898
Timeout: 1 * time.Second,
9999
},
100100
},
101-
Image: "test-image",
102-
Env: []string{"key1=val1", "key2=val2"},
101+
Image: "test-image",
102+
EnvVars: []string{"key1=val1", "key2=val2"},
103103

104104
WatchRevisionReady: true,
105105
WatchRevisionReadyTimeout: 5 * time.Minute,

pkg/knctl/cmd/service/service_spec.go

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131

3232
type ServiceSpec struct{}
3333

34-
func (ServiceSpec) Build(serviceFlags cmdflags.ServiceFlags, deployFlags DeployFlags) (v1alpha1.Service, error) {
34+
func (s ServiceSpec) Build(serviceFlags cmdflags.ServiceFlags, deployFlags DeployFlags) (v1alpha1.Service, error) {
3535
var buildSpec *buildv1alpha1.BuildSpec
3636

3737
if deployFlags.BuildCreateArgsFlags.IsProvided() {
@@ -50,14 +50,28 @@ func (ServiceSpec) Build(serviceFlags cmdflags.ServiceFlags, deployFlags DeployF
5050
Image: deployFlags.Image,
5151
}
5252

53-
for _, kv := range deployFlags.Env {
53+
for _, kv := range deployFlags.EnvVars {
5454
pieces := strings.SplitN(kv, "=", 2)
5555
if len(pieces) != 2 {
56-
return v1alpha1.Service{}, fmt.Errorf("Expected environment variable to be in format 'KEY=VALUE'")
56+
return v1alpha1.Service{}, fmt.Errorf("Expected environment variable to be in format 'ENV_KEY=value'")
5757
}
5858
serviceCont.Env = append(serviceCont.Env, corev1.EnvVar{Name: pieces[0], Value: pieces[1]})
5959
}
6060

61+
envVars, err := s.buildEnvFromSecrets(deployFlags)
62+
if err != nil {
63+
return v1alpha1.Service{}, err
64+
}
65+
66+
serviceCont.Env = append(serviceCont.Env, envVars...)
67+
68+
envVars, err = s.buildEnvFromConfigMaps(deployFlags)
69+
if err != nil {
70+
return v1alpha1.Service{}, err
71+
}
72+
73+
serviceCont.Env = append(serviceCont.Env, envVars...)
74+
6175
// TODO it's convenient to force redeploy anytime deploy is issued
6276
if !deployFlags.RemoveKnctlDeployEnvVar {
6377
serviceCont.Env = append(serviceCont.Env, corev1.EnvVar{
@@ -89,3 +103,63 @@ func (ServiceSpec) Build(serviceFlags cmdflags.ServiceFlags, deployFlags DeployF
89103

90104
return service, nil
91105
}
106+
107+
func (ServiceSpec) buildEnvFromSecrets(deployFlags DeployFlags) ([]corev1.EnvVar, error) {
108+
var result []corev1.EnvVar
109+
110+
for _, kv := range deployFlags.EnvSecrets {
111+
pieces := strings.SplitN(kv, "=", 2)
112+
if len(pieces) != 2 {
113+
return nil, fmt.Errorf("Expected environment variable from secret to be in format 'ENV_KEY=secret-name/key'")
114+
}
115+
116+
secretPieces := strings.SplitN(pieces[1], "/", 2)
117+
if len(secretPieces) != 2 {
118+
return nil, fmt.Errorf("Expected environment variable secret ref to be in format 'secret-name/key'")
119+
}
120+
121+
result = append(result, corev1.EnvVar{
122+
Name: pieces[0],
123+
ValueFrom: &corev1.EnvVarSource{
124+
SecretKeyRef: &corev1.SecretKeySelector{
125+
LocalObjectReference: corev1.LocalObjectReference{
126+
Name: secretPieces[0],
127+
},
128+
Key: secretPieces[1],
129+
},
130+
},
131+
})
132+
}
133+
134+
return result, nil
135+
}
136+
137+
func (ServiceSpec) buildEnvFromConfigMaps(deployFlags DeployFlags) ([]corev1.EnvVar, error) {
138+
var result []corev1.EnvVar
139+
140+
for _, kv := range deployFlags.EnvConfigMaps {
141+
pieces := strings.SplitN(kv, "=", 2)
142+
if len(pieces) != 2 {
143+
return nil, fmt.Errorf("Expected environment variable from config map to be in format 'ENV_KEY=config-map-name/key'")
144+
}
145+
146+
mapPieces := strings.SplitN(pieces[1], "/", 2)
147+
if len(mapPieces) != 2 {
148+
return nil, fmt.Errorf("Expected environment variable config map ref to be in format 'config-map-name/key'")
149+
}
150+
151+
result = append(result, corev1.EnvVar{
152+
Name: pieces[0],
153+
ValueFrom: &corev1.EnvVarSource{
154+
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
155+
LocalObjectReference: corev1.LocalObjectReference{
156+
Name: mapPieces[0],
157+
},
158+
Key: mapPieces[1],
159+
},
160+
},
161+
})
162+
}
163+
164+
return result, nil
165+
}

pkg/knctl/cmd/service/service_spec_test.go

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ func TestServiceSpecWithBuildConfiguration(t *testing.T) {
4747
ServiceAccountName: "test-service-account",
4848
},
4949
},
50-
Image: "test-image",
51-
Env: []string{"test-env-key1=test-env-val1"},
50+
Image: "test-image",
51+
EnvVars: []string{"test-env-key1=test-env-val1"},
5252

5353
RemoveKnctlDeployEnvVar: true,
5454
}
@@ -113,8 +113,8 @@ func TestServiceSpecWithoutBuildConfiguration(t *testing.T) {
113113
}
114114

115115
deployFlags := DeployFlags{
116-
Image: "test-image",
117-
Env: []string{"test-env-key1=test-env-val1"},
116+
Image: "test-image",
117+
EnvVars: []string{"test-env-key1=test-env-val1"},
118118

119119
RemoveKnctlDeployEnvVar: true,
120120
}
@@ -160,8 +160,8 @@ func TestServiceSpecWithInvalidEnv(t *testing.T) {
160160
}
161161

162162
deployFlags := DeployFlags{
163-
Image: "test-image",
164-
Env: []string{"test-env-key1"},
163+
Image: "test-image",
164+
EnvVars: []string{"test-env-key1"},
165165

166166
RemoveKnctlDeployEnvVar: true,
167167
}
@@ -171,7 +171,7 @@ func TestServiceSpecWithInvalidEnv(t *testing.T) {
171171
t.Fatalf("Expected error to happen")
172172
}
173173

174-
if err.Error() != "Expected environment variable to be in format 'KEY=VALUE'" {
174+
if err.Error() != "Expected environment variable to be in format 'ENV_KEY=value'" {
175175
t.Fatalf("Expected error to happen, but was '%s'", err)
176176
}
177177
}
@@ -185,8 +185,10 @@ func TestServiceSpecWithMultipleEnv(t *testing.T) {
185185
}
186186

187187
deployFlags := DeployFlags{
188-
Image: "test-image",
189-
Env: []string{"test-env-key1=test-env-val1", "test-env-key2=test-env-val2"},
188+
Image: "test-image",
189+
EnvVars: []string{"test-env-key1=test-env-val1", "test-env-key2=test-env-val2"},
190+
EnvSecrets: []string{"test-env-key3=test-secret1/key", "test-env-key4=test-secret2/key"},
191+
EnvConfigMaps: []string{"test-env-key5=test-config-map1/key", "test-env-key6=test-config-map2/key"},
190192

191193
RemoveKnctlDeployEnvVar: true,
192194
}
@@ -212,6 +214,38 @@ func TestServiceSpecWithMultipleEnv(t *testing.T) {
212214
Env: []corev1.EnvVar{
213215
{Name: "test-env-key1", Value: "test-env-val1"},
214216
{Name: "test-env-key2", Value: "test-env-val2"},
217+
{Name: "test-env-key3", ValueFrom: &corev1.EnvVarSource{
218+
SecretKeyRef: &corev1.SecretKeySelector{
219+
LocalObjectReference: corev1.LocalObjectReference{
220+
Name: "test-secret1",
221+
},
222+
Key: "key",
223+
},
224+
}},
225+
{Name: "test-env-key4", ValueFrom: &corev1.EnvVarSource{
226+
SecretKeyRef: &corev1.SecretKeySelector{
227+
LocalObjectReference: corev1.LocalObjectReference{
228+
Name: "test-secret2",
229+
},
230+
Key: "key",
231+
},
232+
}},
233+
{Name: "test-env-key5", ValueFrom: &corev1.EnvVarSource{
234+
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
235+
LocalObjectReference: corev1.LocalObjectReference{
236+
Name: "test-config-map1",
237+
},
238+
Key: "key",
239+
},
240+
}},
241+
{Name: "test-env-key6", ValueFrom: &corev1.EnvVarSource{
242+
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
243+
LocalObjectReference: corev1.LocalObjectReference{
244+
Name: "test-config-map2",
245+
},
246+
Key: "key",
247+
},
248+
}},
215249
},
216250
},
217251
},
@@ -225,3 +259,53 @@ func TestServiceSpecWithMultipleEnv(t *testing.T) {
225259
t.Fatalf("Expected spec '%#v' to equal '%#v'", spec, expectedSpec)
226260
}
227261
}
262+
263+
func TestServiceSpecWithInvalidEnvSecret(t *testing.T) {
264+
serviceFlags := cmdflags.ServiceFlags{
265+
NamespaceFlags: cmdcore.NamespaceFlags{
266+
Name: "test-namespace",
267+
},
268+
Name: "test-service",
269+
}
270+
271+
deployFlags := DeployFlags{
272+
Image: "test-image",
273+
EnvSecrets: []string{"test-env-secret-key1"},
274+
275+
RemoveKnctlDeployEnvVar: true,
276+
}
277+
278+
_, err := ServiceSpec{}.Build(serviceFlags, deployFlags)
279+
if err == nil {
280+
t.Fatalf("Expected error to happen")
281+
}
282+
283+
if err.Error() != "Expected environment variable from secret to be in format 'ENV_KEY=secret-name/key'" {
284+
t.Fatalf("Expected error to happen, but was '%s'", err)
285+
}
286+
}
287+
288+
func TestServiceSpecWithInvalidEnvConfigMap(t *testing.T) {
289+
serviceFlags := cmdflags.ServiceFlags{
290+
NamespaceFlags: cmdcore.NamespaceFlags{
291+
Name: "test-namespace",
292+
},
293+
Name: "test-service",
294+
}
295+
296+
deployFlags := DeployFlags{
297+
Image: "test-image",
298+
EnvConfigMaps: []string{"test-env-config-map-key1"},
299+
300+
RemoveKnctlDeployEnvVar: true,
301+
}
302+
303+
_, err := ServiceSpec{}.Build(serviceFlags, deployFlags)
304+
if err == nil {
305+
t.Fatalf("Expected error to happen")
306+
}
307+
308+
if err.Error() != "Expected environment variable from config map to be in format 'ENV_KEY=config-map-name/key'" {
309+
t.Fatalf("Expected error to happen, but was '%s'", err)
310+
}
311+
}

0 commit comments

Comments
 (0)