Commit d1ed6f59 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #30614 from AdoHe/run_pull_policy

Automatic merge from submit-queue kubectl run add pull-policy flag to control image pull policy ```release-note Add support for --image-pull-policy to 'kubectl run' ``` Fix #30493 @pwittrock @thockin ptal
parents 069929bb ca315e31
......@@ -107,6 +107,7 @@ func addRunFlags(cmd *cobra.Command) {
cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'deployment/v1beta1' if --restart=Always, 'job/v1' for OnFailure and 'run-pod/v1' for Never. This will happen only for cluster version at least 1.3, for 1.2 we will fallback to 'deployment/v1beta1' for --restart=Always, 'job/v1' for others, for olders we will fallback to 'run/v1' for --restart=Always, 'run-pod/v1' for others.")
cmd.Flags().String("image", "", "The image for the container to run.")
cmd.MarkFlagRequired("image")
cmd.Flags().String("image-pull-policy", "", "The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server")
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.")
cmd.Flags().String("overrides", "", "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.")
......@@ -168,6 +169,10 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas))
}
if err := verifyImagePullPolicy(cmd); err != nil {
return err
}
generatorName := cmdutil.GetFlagString(cmd, "generator")
schedule := cmdutil.GetFlagString(cmd, "schedule")
if len(schedule) != 0 && len(generatorName) == 0 {
......@@ -511,6 +516,18 @@ func getRestartPolicy(cmd *cobra.Command, interactive bool) (api.RestartPolicy,
}
}
func verifyImagePullPolicy(cmd *cobra.Command) error {
pullPolicy := cmdutil.GetFlagString(cmd, "image-pull-policy")
switch api.PullPolicy(pullPolicy) {
case api.PullAlways, api.PullIfNotPresent, api.PullNever:
return nil
case "":
return nil
default:
return cmdutil.UsageError(cmd, fmt.Sprintf("invalid image pull policy: %s", pullPolicy))
}
}
func generateService(f *cmdutil.Factory, cmd *cobra.Command, args []string, serviceGenerator string, paramsIn map[string]interface{}, namespace string, out io.Writer) error {
generators := f.Generators("expose")
generator, found := generators[serviceGenerator]
......
......@@ -42,6 +42,7 @@ func (DeploymentV1Beta1) ParamNames() []GeneratorParam {
{"name", true},
{"replicas", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -90,7 +91,8 @@ func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime
return nil, err
}
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
imagePullPolicy := api.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
return nil, err
}
......@@ -217,6 +219,7 @@ func (JobV1Beta1) ParamNames() []GeneratorParam {
{"default-name", false},
{"name", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -262,7 +265,8 @@ func (JobV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object
return nil, err
}
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
imagePullPolicy := api.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
return nil, err
}
......@@ -312,6 +316,7 @@ func (JobV1) ParamNames() []GeneratorParam {
{"default-name", false},
{"name", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -357,7 +362,8 @@ func (JobV1) Generate(genericParams map[string]interface{}) (runtime.Object, err
return nil, err
}
if err = updateV1PodContainers(params, args, envs, podSpec); err != nil {
imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updateV1PodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
return nil, err
}
......@@ -403,6 +409,7 @@ func (ScheduledJobV2Alpha1) ParamNames() []GeneratorParam {
{"default-name", false},
{"name", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -449,7 +456,8 @@ func (ScheduledJobV2Alpha1) Generate(genericParams map[string]interface{}) (runt
return nil, err
}
if err = updateV1PodContainers(params, args, envs, podSpec); err != nil {
imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updateV1PodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
return nil, err
}
......@@ -502,6 +510,7 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
{"name", true},
{"replicas", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -690,7 +699,8 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
return nil, err
}
if err = updatePodContainers(params, args, envs, podSpec); err != nil {
imagePullPolicy := api.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
return nil, err
}
......@@ -717,7 +727,7 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
return &controller, nil
}
func updatePodContainers(params map[string]string, args []string, envs []api.EnvVar, podSpec *api.PodSpec) error {
func updatePodContainers(params map[string]string, args []string, envs []api.EnvVar, imagePullPolicy api.PullPolicy, podSpec *api.PodSpec) error {
if len(args) > 0 {
command, err := GetBool(params, "command", false)
if err != nil {
......@@ -733,10 +743,15 @@ func updatePodContainers(params map[string]string, args []string, envs []api.Env
if len(envs) > 0 {
podSpec.Containers[0].Env = envs
}
if len(imagePullPolicy) > 0 {
// imagePullPolicy should be valid here since we have verified it before.
podSpec.Containers[0].ImagePullPolicy = imagePullPolicy
}
return nil
}
func updateV1PodContainers(params map[string]string, args []string, envs []v1.EnvVar, podSpec *v1.PodSpec) error {
func updateV1PodContainers(params map[string]string, args []string, envs []v1.EnvVar, imagePullPolicy v1.PullPolicy, podSpec *v1.PodSpec) error {
if len(args) > 0 {
command, err := GetBool(params, "command", false)
if err != nil {
......@@ -752,6 +767,11 @@ func updateV1PodContainers(params map[string]string, args []string, envs []v1.En
if len(envs) > 0 {
podSpec.Containers[0].Env = envs
}
if len(imagePullPolicy) > 0 {
// imagePullPolicy should be valid here since we have verified it before.
podSpec.Containers[0].ImagePullPolicy = imagePullPolicy
}
return nil
}
......@@ -831,6 +851,7 @@ func (BasicPod) ParamNames() []GeneratorParam {
{"default-name", false},
{"name", true},
{"image", true},
{"image-pull-policy", false},
{"port", false},
{"hostport", false},
{"stdin", false},
......@@ -894,6 +915,8 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
if len(restartPolicy) == 0 {
restartPolicy = api.RestartPolicyAlways
}
// TODO: Figure out why we set ImagePullPolicy here, whether we can make it
// consistent with the other places imagePullPolicy is set using flag.
pod := api.Pod{
ObjectMeta: api.ObjectMeta{
Name: name,
......@@ -915,7 +938,8 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
RestartPolicy: restartPolicy,
},
}
if err = updatePodContainers(params, args, envs, &pod.Spec); err != nil {
imagePullPolicy := api.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, &pod.Spec); err != nil {
return nil, err
}
......
......@@ -35,10 +35,11 @@ func TestGenerate(t *testing.T) {
}{
{
params: map[string]interface{}{
"name": "foo",
"image": "someimage",
"replicas": "1",
"port": "-1",
"name": "foo",
"image": "someimage",
"image-pull-policy": "Always",
"replicas": "1",
"port": "-1",
},
expected: &api.ReplicationController{
ObjectMeta: api.ObjectMeta{
......@@ -55,8 +56,9 @@ func TestGenerate(t *testing.T) {
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "foo",
Image: "someimage",
Name: "foo",
Image: "someimage",
ImagePullPolicy: api.PullAlways,
},
},
},
......@@ -110,11 +112,12 @@ func TestGenerate(t *testing.T) {
{
params: map[string]interface{}{
"name": "foo",
"image": "someimage",
"replicas": "1",
"port": "-1",
"args": []string{"bar", "baz", "blah"},
"name": "foo",
"image": "someimage",
"image-pull-policy": "Never",
"replicas": "1",
"port": "-1",
"args": []string{"bar", "baz", "blah"},
},
expected: &api.ReplicationController{
ObjectMeta: api.ObjectMeta{
......@@ -131,9 +134,10 @@ func TestGenerate(t *testing.T) {
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "foo",
Image: "someimage",
Args: []string{"bar", "baz", "blah"},
Name: "foo",
Image: "someimage",
ImagePullPolicy: api.PullNever,
Args: []string{"bar", "baz", "blah"},
},
},
},
......@@ -213,11 +217,12 @@ func TestGenerate(t *testing.T) {
},
{
params: map[string]interface{}{
"name": "foo",
"image": "someimage",
"replicas": "1",
"port": "80",
"hostport": "80",
"name": "foo",
"image": "someimage",
"image-pull-policy": "IfNotPresent",
"replicas": "1",
"port": "80",
"hostport": "80",
},
expected: &api.ReplicationController{
ObjectMeta: api.ObjectMeta{
......@@ -234,8 +239,9 @@ func TestGenerate(t *testing.T) {
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "foo",
Image: "someimage",
Name: "foo",
Image: "someimage",
ImagePullPolicy: api.PullIfNotPresent,
Ports: []api.ContainerPort{
{
ContainerPort: 80,
......@@ -435,9 +441,10 @@ func TestGeneratePod(t *testing.T) {
},
{
params: map[string]interface{}{
"name": "foo",
"image": "someimage",
"env": []string{"a=b", "c=d"},
"name": "foo",
"image": "someimage",
"image-pull-policy": "Always",
"env": []string{"a=b", "c=d"},
},
expected: &api.Pod{
ObjectMeta: api.ObjectMeta{
......@@ -448,7 +455,7 @@ func TestGeneratePod(t *testing.T) {
{
Name: "foo",
Image: "someimage",
ImagePullPolicy: api.PullIfNotPresent,
ImagePullPolicy: api.PullAlways,
Env: []api.EnvVar{
{
Name: "a",
......@@ -639,18 +646,19 @@ func TestGenerateDeployment(t *testing.T) {
}{
{
params: map[string]interface{}{
"labels": "foo=bar,baz=blah",
"name": "foo",
"replicas": "3",
"image": "someimage",
"port": "80",
"hostport": "80",
"stdin": "true",
"command": "true",
"args": []string{"bar", "baz", "blah"},
"env": []string{"a=b", "c=d"},
"requests": "cpu=100m,memory=100Mi",
"limits": "cpu=400m,memory=200Mi",
"labels": "foo=bar,baz=blah",
"name": "foo",
"replicas": "3",
"image": "someimage",
"image-pull-policy": "Always",
"port": "80",
"hostport": "80",
"stdin": "true",
"command": "true",
"args": []string{"bar", "baz", "blah"},
"env": []string{"a=b", "c=d"},
"requests": "cpu=100m,memory=100Mi",
"limits": "cpu=400m,memory=200Mi",
},
expected: &extensions.Deployment{
ObjectMeta: api.ObjectMeta{
......@@ -667,9 +675,10 @@ func TestGenerateDeployment(t *testing.T) {
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "foo",
Image: "someimage",
Stdin: true,
Name: "foo",
Image: "someimage",
ImagePullPolicy: api.PullAlways,
Stdin: true,
Ports: []api.ContainerPort{
{
ContainerPort: 80,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment