kubectl run add pull-policy flag to control image pull policy

pull/6/head
AdoHe 2016-08-17 11:26:27 +08:00
parent 85c91eb332
commit ca315e317b
3 changed files with 98 additions and 48 deletions

View File

@ -105,6 +105,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.")
@ -167,6 +168,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 {
@ -417,6 +422,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]

View File

@ -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
}

View File

@ -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,