Skip to content

Commit ed1a0e9

Browse files
committed
Refactor create deployment and add --port flag
1 parent 9e7ca87 commit ed1a0e9

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

staging/src/k8s.io/kubectl/pkg/cmd/create/create_deployment.go

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import (
2222
"strings"
2323

2424
"github.com/spf13/cobra"
25+
2526
appsv1 "k8s.io/api/apps/v1"
26-
v1 "k8s.io/api/core/v1"
27+
corev1 "k8s.io/api/core/v1"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
"k8s.io/apimachinery/pkg/runtime"
2930
utilrand "k8s.io/apimachinery/pkg/util/rand"
@@ -41,17 +42,26 @@ var (
4142
Create a deployment with the specified name.`))
4243

4344
deploymentExample = templates.Examples(i18n.T(`
44-
# Create a new deployment named my-dep that runs the busybox image.
45-
kubectl create deployment my-dep --image=busybox`))
45+
# Create a deployment named my-dep that runs the busybox image.
46+
kubectl create deployment my-dep --image=busybox
47+
48+
# Create a deployment with command
49+
kubectl create deployment my-dep --image=busybox -- date
50+
51+
# Create a deployment named my-dep that runs the busybox image and expose port 5701.
52+
kubectl create deployment my-dep --image=busybox --port=5701`))
4653
)
4754

48-
// DeploymentOpts is returned by NewCmdCreateDeployment
49-
type DeploymentOpts struct {
55+
// CreateDeploymentOptions is returned by NewCmdCreateDeployment
56+
type CreateDeploymentOptions struct {
5057
PrintFlags *genericclioptions.PrintFlags
51-
PrintObj func(obj runtime.Object) error
58+
59+
PrintObj func(obj runtime.Object) error
5260

5361
Name string
5462
Images []string
63+
Port int32
64+
Command []string
5565
Namespace string
5666
EnforceNamespace bool
5767
FieldManager string
@@ -63,46 +73,55 @@ type DeploymentOpts struct {
6373
genericclioptions.IOStreams
6474
}
6575

66-
// NewCmdCreateDeployment is a macro command to create a new deployment.
67-
// This command is better known to users as `kubectl create deployment`.
68-
func NewCmdCreateDeployment(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
69-
options := &DeploymentOpts{
76+
func NewCreateCreateDeploymentOptions(ioStreams genericclioptions.IOStreams) *CreateDeploymentOptions {
77+
return &CreateDeploymentOptions{
78+
Port: -1,
7079
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
7180
IOStreams: ioStreams,
7281
}
82+
}
7383

84+
// NewCmdCreateDeployment is a macro command to create a new deployment.
85+
// This command is better known to users as `kubectl create deployment`.
86+
func NewCmdCreateDeployment(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
87+
o := NewCreateCreateDeploymentOptions(ioStreams)
7488
cmd := &cobra.Command{
75-
Use: "deployment NAME --image=image [--dry-run=server|client|none]",
89+
Use: "deployment NAME --image=image -- [COMMAND] [args...]",
7690
DisableFlagsInUseLine: true,
7791
Aliases: []string{"deploy"},
7892
Short: deploymentLong,
7993
Long: deploymentLong,
8094
Example: deploymentExample,
8195
Run: func(cmd *cobra.Command, args []string) {
82-
cmdutil.CheckErr(options.Complete(f, cmd, args))
83-
cmdutil.CheckErr(options.Run())
96+
cmdutil.CheckErr(o.Complete(f, cmd, args))
97+
cmdutil.CheckErr(o.Validate())
98+
cmdutil.CheckErr(o.Run())
8499
},
85100
}
86101

87-
options.PrintFlags.AddFlags(cmd)
102+
o.PrintFlags.AddFlags(cmd)
88103

89104
cmdutil.AddApplyAnnotationFlags(cmd)
90105
cmdutil.AddValidateFlags(cmd)
91106
cmdutil.AddGeneratorFlags(cmd, "")
92-
cmd.Flags().StringSliceVar(&options.Images, "image", []string{}, "Image name to run.")
93-
_ = cmd.MarkFlagRequired("image")
94-
cmdutil.AddFieldManagerFlagVar(cmd, &options.FieldManager, "kubectl-create")
107+
cmd.Flags().StringSliceVar(&o.Images, "image", o.Images, "Image names to run.")
108+
cmd.MarkFlagRequired("image")
109+
cmd.Flags().Int32Var(&o.Port, "port", o.Port, "The port that this container exposes.")
110+
cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, "kubectl-create")
95111

96112
return cmd
97113
}
98114

99115
// Complete completes all the options
100-
func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
116+
func (o *CreateDeploymentOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
101117
name, err := NameFromCommandArgs(cmd, args)
102118
if err != nil {
103119
return err
104120
}
105121
o.Name = name
122+
if len(args) > 1 {
123+
o.Command = args[1:]
124+
}
106125

107126
clientConfig, err := f.ToRESTConfig()
108127
if err != nil {
@@ -144,8 +163,15 @@ func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
144163
return nil
145164
}
146165

166+
func (o *CreateDeploymentOptions) Validate() error {
167+
if len(o.Images) > 1 && len(o.Command) > 0 {
168+
return fmt.Errorf("cannot specify multiple --image options and command")
169+
}
170+
return nil
171+
}
172+
147173
// Run performs the execution of 'create deployment' sub command
148-
func (o *DeploymentOpts) Run() error {
174+
func (o *CreateDeploymentOptions) Run() error {
149175
deploy := o.createDeployment()
150176

151177
if o.DryRunStrategy != cmdutil.DryRunClient {
@@ -169,7 +195,7 @@ func (o *DeploymentOpts) Run() error {
169195
return o.PrintObj(deploy)
170196
}
171197

172-
func (o *DeploymentOpts) createDeployment() *appsv1.Deployment {
198+
func (o *CreateDeploymentOptions) createDeployment() *appsv1.Deployment {
173199
one := int32(1)
174200
labels := map[string]string{"app": o.Name}
175201
selector := metav1.LabelSelector{MatchLabels: labels}
@@ -188,7 +214,7 @@ func (o *DeploymentOpts) createDeployment() *appsv1.Deployment {
188214
Spec: appsv1.DeploymentSpec{
189215
Replicas: &one,
190216
Selector: &selector,
191-
Template: v1.PodTemplateSpec{
217+
Template: corev1.PodTemplateSpec{
192218
ObjectMeta: metav1.ObjectMeta{
193219
Labels: labels,
194220
},
@@ -200,8 +226,8 @@ func (o *DeploymentOpts) createDeployment() *appsv1.Deployment {
200226

201227
// buildPodSpec parses the image strings and assemble them into the Containers
202228
// of a PodSpec. This is all you need to create the PodSpec for a deployment.
203-
func (o *DeploymentOpts) buildPodSpec() v1.PodSpec {
204-
podSpec := v1.PodSpec{Containers: []v1.Container{}}
229+
func (o *CreateDeploymentOptions) buildPodSpec() corev1.PodSpec {
230+
podSpec := corev1.PodSpec{Containers: []corev1.Container{}}
205231
for _, imageString := range o.Images {
206232
// Retain just the image name
207233
imageSplit := strings.Split(imageString, "/")
@@ -214,7 +240,11 @@ func (o *DeploymentOpts) buildPodSpec() v1.PodSpec {
214240
name = strings.Split(name, "@")[0]
215241
}
216242
name = sanitizeAndUniquify(name)
217-
podSpec.Containers = append(podSpec.Containers, v1.Container{Name: name, Image: imageString})
243+
podSpec.Containers = append(podSpec.Containers, corev1.Container{
244+
Name: name,
245+
Image: imageString,
246+
Command: o.Command,
247+
})
218248
}
219249
return podSpec
220250
}

staging/src/k8s.io/kubectl/pkg/cmd/create/create_deployment_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func TestCreateDeploymentNoImage(t *testing.T) {
8383
ioStreams := genericclioptions.NewTestIOStreamsDiscard()
8484
cmd := NewCmdCreateDeployment(tf, ioStreams)
8585
cmd.Flags().Set("output", "name")
86-
options := &DeploymentOpts{
86+
options := &CreateDeploymentOptions{
8787
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
8888
DryRunStrategy: cmdutil.DryRunClient,
8989
IOStreams: ioStreams,

test/cmd/apps.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ run_deployment_tests() {
197197
kubectl delete deployment test-nginx-extensions "${kube_flags[@]:?}"
198198

199199
# Test kubectl create deployment
200-
kubectl create deployment test-nginx-apps --image=k8s.gcr.io/nginx:test-cmd --generator=deployment-basic/apps.v1
200+
kubectl create deployment test-nginx-apps --image=k8s.gcr.io/nginx:test-cmd
201201
# Post-Condition: Deployment "nginx" is created.
202202
kube::test::get_object_assert 'deploy test-nginx-apps' "{{${container_name_field:?}}}" 'nginx'
203203
# and new generator was used, iow. new defaults are applied

0 commit comments

Comments
 (0)