Skip to content

Commit 6a17f25

Browse files
adding run-as-user flag in deploy-image plugin
1 parent 78ad658 commit 6a17f25

File tree

19 files changed

+568
-17
lines changed

19 files changed

+568
-17
lines changed

pkg/plugins/golang/deploy-image/v1alpha1/api.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ type createAPISubcommand struct {
6969

7070
// imageContainerPort indicates the port that we should use in the scaffold
7171
imageContainerPort string
72+
73+
// runAsUser indicates the user-id used for running the container
74+
runAsUser string
7275
}
7376

7477
func (p *createAPISubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
@@ -121,6 +124,7 @@ func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) {
121124
fs.StringVar(&p.imageContainerPort, "image-container-port", "", "[Optional] if informed, "+
122125
"will be used to scaffold the container port that should be used by container image in "+
123126
"the controller and its spec in the API (CRD/CR). (i.e --image-container-port=\"11211\") ")
127+
fs.StringVar(&p.runAsUser, "run-as-user", "", "User-Id for the container formed will be set to this value")
124128

125129
fs.BoolVar(&p.runMake, "make", true, "if true, run `make generate` after generating files")
126130
fs.BoolVar(&p.runManifests, "manifests", true, "if true, run `make manifests` after generating files")
@@ -195,7 +199,8 @@ func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
195199
*p.resource,
196200
p.image,
197201
p.imageContainerCommand,
198-
p.imageContainerPort)
202+
p.imageContainerPort,
203+
p.runAsUser)
199204
scaffolder.InjectFS(fs)
200205
err := scaffolder.Scaffold()
201206
if err != nil {
@@ -215,6 +220,7 @@ func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
215220
Image: p.image,
216221
ContainerCommand: p.imageContainerCommand,
217222
ContainerPort: p.imageContainerPort,
223+
RunAsUser: p.runAsUser,
218224
}
219225
cfg.Resources = append(cfg.Resources, resourceData{
220226
Group: p.resource.GVK.Group,

pkg/plugins/golang/deploy-image/v1alpha1/plugin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,5 @@ type options struct {
6767
Image string `json:"image,omitempty"`
6868
ContainerCommand string `json:"containerCommand,omitempty"`
6969
ContainerPort string `json:"containerPort,omitempty"`
70+
RunAsUser string `json:"runAsUser,omitempty"`
7071
}

pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/api.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ var _ plugins.Scaffolder = &apiScaffolder{}
4040
// apiScaffolder contains configuration for generating scaffolding for Go type
4141
// representing the API and controller that implements the behavior for the API.
4242
type apiScaffolder struct {
43-
config config.Config
44-
resource resource.Resource
45-
image string
46-
command string
47-
port string
43+
config config.Config
44+
resource resource.Resource
45+
image string
46+
command string
47+
port string
48+
runAsUser string
4849

4950
// fs is the filesystem that will be used by the scaffolder
5051
fs machinery.Filesystem
@@ -53,13 +54,14 @@ type apiScaffolder struct {
5354
// NewAPIScaffolder returns a new Scaffolder for declarative
5455
//nolint: lll
5556
func NewDeployImageScaffolder(config config.Config, res resource.Resource, image,
56-
command, port string) plugins.Scaffolder {
57+
command, port, runAsUser string) plugins.Scaffolder {
5758
return &apiScaffolder{
58-
config: config,
59-
resource: res,
60-
image: image,
61-
command: command,
62-
port: port,
59+
config: config,
60+
resource: res,
61+
image: image,
62+
command: command,
63+
port: port,
64+
runAsUser: runAsUser,
6365
}
6466
}
6567

@@ -143,7 +145,6 @@ func (s *apiScaffolder) scafffoldControllerWithImage(scaffold *machinery.Scaffol
143145
res = res[:len(res)-1]
144146
err := util.InsertCode(controllerPath, `SecurityContext: &corev1.SecurityContext{
145147
RunAsNonRoot: &[]bool{true}[0],
146-
RunAsUser: &[]int64{1000}[0],
147148
AllowPrivilegeEscalation: &[]bool{false}[0],
148149
Capabilities: &corev1.Capabilities{
149150
Drop: []corev1.Capability{
@@ -160,7 +161,6 @@ func (s *apiScaffolder) scafffoldControllerWithImage(scaffold *machinery.Scaffol
160161
if len(s.port) > 0 {
161162
err := util.InsertCode(controllerPath, `SecurityContext: &corev1.SecurityContext{
162163
RunAsNonRoot: &[]bool{true}[0],
163-
RunAsUser: &[]int64{1000}[0],
164164
AllowPrivilegeEscalation: &[]bool{false}[0],
165165
Capabilities: &corev1.Capabilities{
166166
Drop: []corev1.Capability{
@@ -172,6 +172,14 @@ func (s *apiScaffolder) scafffoldControllerWithImage(scaffold *machinery.Scaffol
172172
return fmt.Errorf("error scaffolding container port in the controller: %v", err)
173173
}
174174
}
175+
176+
if len(s.runAsUser) > 0 {
177+
if err := util.InsertCode(controllerPath, `RunAsNonRoot: &[]bool{true}[0],`,
178+
fmt.Sprintf(runAsUserTemplate, s.runAsUser),
179+
); err != nil {
180+
return fmt.Errorf("error scaffolding user-id in the controller: %v", err)
181+
}
182+
}
175183
return nil
176184
}
177185

@@ -207,7 +215,6 @@ const containerTemplate = `Containers: []corev1.Container{{
207215
// More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
208216
SecurityContext: &corev1.SecurityContext{
209217
RunAsNonRoot: &[]bool{true}[0],
210-
RunAsUser: &[]int64{1000}[0],
211218
AllowPrivilegeEscalation: &[]bool{false}[0],
212219
Capabilities: &corev1.Capabilities{
213220
Drop: []corev1.Capability{
@@ -217,6 +224,9 @@ const containerTemplate = `Containers: []corev1.Container{{
217224
},
218225
}}`
219226

227+
const runAsUserTemplate = `
228+
RunAsUser: &[]int64{%s}[0],`
229+
220230
const commandTemplate = `
221231
Command: []string{%s},`
222232

test/e2e/deployimage/plugin_cluster_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ var _ = Describe("kubebuilder", func() {
106106
"--image", "memcached:1.4.36-alpine",
107107
"--image-container-port", "11211",
108108
"--image-container-command", "memcached,-m=64,-o,modern,-v",
109+
"--run-as-user", "1001",
109110
"--make=false",
110111
"--manifests=false",
111112
)

test/testdata/generate.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ function scaffold_test_project {
109109
$kb create api --group crew --version v1 --kind Admiral --controller=true --resource=true --namespaced=false --make=false
110110
elif [[ $project == "project-v3-with-deploy-image" ]]; then
111111
header_text 'Creating Memcached API with deploy-image plugin ...'
112-
$kb create api --group example.com --version v1alpha1 --kind Memcached --image=memcached:1.4.36-alpine --image-container-command="memcached,-m=64,-o,modern,-v" --image-container-port="11211" --plugins="deploy-image/v1-alpha" --make=false --namespaced=false
112+
$kb create api --group example.com --version v1alpha1 --kind Memcached --image=memcached:1.4.36-alpine --image-container-command="memcached,-m=64,-o,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha" --make=false --namespaced=false
113+
$kb create api --group example.com --version v1alpha1 --kind Busybox --image=busybox:1.28 --plugins="deploy-image/v1-alpha" --make=false --namespaced=false
113114
header_text 'Creating Memcached webhook ...'
114115
$kb create webhook --group example.com --version v1alpha1 --kind Memcached --programmatic-validation
115116
fi

testdata/project-v3-with-deploy-image/PROJECT

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ plugins:
1111
containerCommand: memcached,-m=64,-o,modern,-v
1212
containerPort: "11211"
1313
image: memcached:1.4.36-alpine
14+
runAsUser: "1001"
15+
version: v1alpha1
16+
- domain: testproject.org
17+
group: example.com
18+
kind: Busybox
19+
options:
20+
image: busybox:1.28
1421
version: v1alpha1
1522
projectName: project-v3-with-deploy-image
1623
repo: sigs.k8s.io/kubebuilder/testdata/project-v3-with-deploy-image
@@ -26,4 +33,12 @@ resources:
2633
webhooks:
2734
validation: true
2835
webhookVersion: v1
36+
- api:
37+
crdVersion: v1
38+
controller: true
39+
domain: testproject.org
40+
group: example.com
41+
kind: Busybox
42+
path: sigs.k8s.io/kubebuilder/testdata/project-v3-with-deploy-image/api/v1alpha1
43+
version: v1alpha1
2944
version: "3"
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Copyright 2022 The Kubernetes authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24+
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25+
26+
// BusyboxSpec defines the desired state of Busybox
27+
type BusyboxSpec struct {
28+
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29+
// Important: Run "make" to regenerate code after modifying this file
30+
31+
// Size defines the number of Busybox instances
32+
Size int32 `json:"size,omitempty"`
33+
}
34+
35+
// BusyboxStatus defines the observed state of Busybox
36+
type BusyboxStatus struct {
37+
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
38+
// Important: Run "make" to regenerate code after modifying this file
39+
}
40+
41+
//+kubebuilder:object:root=true
42+
//+kubebuilder:subresource:status
43+
//+kubebuilder:resource:scope=Cluster
44+
45+
// Busybox is the Schema for the busyboxes API
46+
type Busybox struct {
47+
metav1.TypeMeta `json:",inline"`
48+
metav1.ObjectMeta `json:"metadata,omitempty"`
49+
50+
Spec BusyboxSpec `json:"spec,omitempty"`
51+
Status BusyboxStatus `json:"status,omitempty"`
52+
}
53+
54+
//+kubebuilder:object:root=true
55+
56+
// BusyboxList contains a list of Busybox
57+
type BusyboxList struct {
58+
metav1.TypeMeta `json:",inline"`
59+
metav1.ListMeta `json:"metadata,omitempty"`
60+
Items []Busybox `json:"items"`
61+
}
62+
63+
func init() {
64+
SchemeBuilder.Register(&Busybox{}, &BusyboxList{})
65+
}

testdata/project-v3-with-deploy-image/api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 89 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.9.0
7+
creationTimestamp: null
8+
name: busyboxes.example.com.testproject.org
9+
spec:
10+
group: example.com.testproject.org
11+
names:
12+
kind: Busybox
13+
listKind: BusyboxList
14+
plural: busyboxes
15+
singular: busybox
16+
scope: Cluster
17+
versions:
18+
- name: v1alpha1
19+
schema:
20+
openAPIV3Schema:
21+
description: Busybox is the Schema for the busyboxes API
22+
properties:
23+
apiVersion:
24+
description: 'APIVersion defines the versioned schema of this representation
25+
of an object. Servers should convert recognized schemas to the latest
26+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
27+
type: string
28+
kind:
29+
description: 'Kind is a string value representing the REST resource this
30+
object represents. Servers may infer this from the endpoint the client
31+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
32+
type: string
33+
metadata:
34+
type: object
35+
spec:
36+
description: BusyboxSpec defines the desired state of Busybox
37+
properties:
38+
size:
39+
description: Size defines the number of Busybox instances
40+
format: int32
41+
type: integer
42+
type: object
43+
status:
44+
description: BusyboxStatus defines the observed state of Busybox
45+
type: object
46+
type: object
47+
served: true
48+
storage: true
49+
subresources:
50+
status: {}

0 commit comments

Comments
 (0)