Skip to content

Commit 7c3f706

Browse files
authored
Merge pull request kubernetes#91113 from soltysh/create_deployment
Refactor create deployment and add --port flag
2 parents 65c0a1e + ed1a0e9 commit 7c3f706

File tree

5 files changed

+70
-49
lines changed

5 files changed

+70
-49
lines changed

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

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ func NewCreateCronJobOptions(ioStreams genericclioptions.IOStreams) *CreateCronJ
8080
func NewCmdCreateCronJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
8181
o := NewCreateCronJobOptions(ioStreams)
8282
cmd := &cobra.Command{
83-
Use: "cronjob NAME --image=image --schedule='0/5 * * * ?' -- [COMMAND] [args...]",
84-
Aliases: []string{"cj"},
85-
Short: cronjobLong,
86-
Long: cronjobLong,
87-
Example: cronjobExample,
83+
Use: "cronjob NAME --image=image --schedule='0/5 * * * ?' -- [COMMAND] [args...]",
84+
DisableFlagsInUseLine: false,
85+
Aliases: []string{"cj"},
86+
Short: cronjobLong,
87+
Long: cronjobLong,
88+
Example: cronjobExample,
8889
Run: func(cmd *cobra.Command, args []string) {
8990
cmdutil.CheckErr(o.Complete(f, cmd, args))
90-
cmdutil.CheckErr(o.Validate())
9191
cmdutil.CheckErr(o.Run())
9292
},
9393
}
@@ -98,7 +98,9 @@ func NewCmdCreateCronJob(f cmdutil.Factory, ioStreams genericclioptions.IOStream
9898
cmdutil.AddValidateFlags(cmd)
9999
cmdutil.AddDryRunFlag(cmd)
100100
cmd.Flags().StringVar(&o.Image, "image", o.Image, "Image name to run.")
101+
cmd.MarkFlagRequired("image")
101102
cmd.Flags().StringVar(&o.Schedule, "schedule", o.Schedule, "A schedule in the Cron format the job should be run with.")
103+
cmd.MarkFlagRequired("schedule")
102104
cmd.Flags().StringVar(&o.Restart, "restart", o.Restart, "job's restart policy. supported values: OnFailure, Never")
103105
cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, "kubectl-create")
104106

@@ -158,20 +160,8 @@ func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
158160
return nil
159161
}
160162

161-
func (o *CreateCronJobOptions) Validate() error {
162-
if len(o.Image) == 0 {
163-
return fmt.Errorf("--image must be specified")
164-
}
165-
if len(o.Schedule) == 0 {
166-
return fmt.Errorf("--schedule must be specified")
167-
}
168-
return nil
169-
}
170-
171163
func (o *CreateCronJobOptions) Run() error {
172-
var cronjob *batchv1beta1.CronJob
173-
cronjob = o.createCronJob()
174-
164+
cronjob := o.createCronJob()
175165
if o.DryRunStrategy != cmdutil.DryRunClient {
176166
createOptions := metav1.CreateOptions{}
177167
if o.FieldManager != "" {

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,

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ func NewCreateJobOptions(ioStreams genericclioptions.IOStreams) *CreateJobOption
8585
func NewCmdCreateJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
8686
o := NewCreateJobOptions(ioStreams)
8787
cmd := &cobra.Command{
88-
Use: "job NAME --image=image [--from=cronjob/name] -- [COMMAND] [args...]",
89-
Short: jobLong,
90-
Long: jobLong,
91-
Example: jobExample,
88+
Use: "job NAME --image=image [--from=cronjob/name] -- [COMMAND] [args...]",
89+
DisableFlagsInUseLine: true,
90+
Short: jobLong,
91+
Long: jobLong,
92+
Example: jobExample,
9293
Run: func(cmd *cobra.Command, args []string) {
9394
cmdutil.CheckErr(o.Complete(f, cmd, args))
9495
cmdutil.CheckErr(o.Validate())

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)