mirror of https://github.com/k3s-io/k3s
kubectl run add pull-policy flag to control image pull policy
parent
85c91eb332
commit
ca315e317b
|
@ -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("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.Flags().String("image", "", "The image for the container to run.")
|
||||||
cmd.MarkFlagRequired("image")
|
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().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().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.")
|
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))
|
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")
|
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||||
schedule := cmdutil.GetFlagString(cmd, "schedule")
|
schedule := cmdutil.GetFlagString(cmd, "schedule")
|
||||||
if len(schedule) != 0 && len(generatorName) == 0 {
|
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 {
|
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")
|
generators := f.Generators("expose")
|
||||||
generator, found := generators[serviceGenerator]
|
generator, found := generators[serviceGenerator]
|
||||||
|
|
|
@ -42,6 +42,7 @@ func (DeploymentV1Beta1) ParamNames() []GeneratorParam {
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"replicas", true},
|
{"replicas", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -90,7 +91,8 @@ func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime
|
||||||
return nil, err
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +219,7 @@ func (JobV1Beta1) ParamNames() []GeneratorParam {
|
||||||
{"default-name", false},
|
{"default-name", false},
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -262,7 +265,8 @@ func (JobV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object
|
||||||
return nil, err
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +316,7 @@ func (JobV1) ParamNames() []GeneratorParam {
|
||||||
{"default-name", false},
|
{"default-name", false},
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -357,7 +362,8 @@ func (JobV1) Generate(genericParams map[string]interface{}) (runtime.Object, err
|
||||||
return nil, 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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +409,7 @@ func (ScheduledJobV2Alpha1) ParamNames() []GeneratorParam {
|
||||||
{"default-name", false},
|
{"default-name", false},
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -449,7 +456,8 @@ func (ScheduledJobV2Alpha1) Generate(genericParams map[string]interface{}) (runt
|
||||||
return nil, 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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,6 +510,7 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"replicas", true},
|
{"replicas", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -690,7 +699,8 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
|
||||||
return nil, err
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +727,7 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
|
||||||
return &controller, nil
|
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 {
|
if len(args) > 0 {
|
||||||
command, err := GetBool(params, "command", false)
|
command, err := GetBool(params, "command", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -733,10 +743,15 @@ func updatePodContainers(params map[string]string, args []string, envs []api.Env
|
||||||
if len(envs) > 0 {
|
if len(envs) > 0 {
|
||||||
podSpec.Containers[0].Env = envs
|
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
|
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 {
|
if len(args) > 0 {
|
||||||
command, err := GetBool(params, "command", false)
|
command, err := GetBool(params, "command", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -752,6 +767,11 @@ func updateV1PodContainers(params map[string]string, args []string, envs []v1.En
|
||||||
if len(envs) > 0 {
|
if len(envs) > 0 {
|
||||||
podSpec.Containers[0].Env = envs
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,6 +851,7 @@ func (BasicPod) ParamNames() []GeneratorParam {
|
||||||
{"default-name", false},
|
{"default-name", false},
|
||||||
{"name", true},
|
{"name", true},
|
||||||
{"image", true},
|
{"image", true},
|
||||||
|
{"image-pull-policy", false},
|
||||||
{"port", false},
|
{"port", false},
|
||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
|
@ -894,6 +915,8 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
|
||||||
if len(restartPolicy) == 0 {
|
if len(restartPolicy) == 0 {
|
||||||
restartPolicy = api.RestartPolicyAlways
|
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{
|
pod := api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -915,7 +938,8 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
|
||||||
RestartPolicy: restartPolicy,
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,11 @@ func TestGenerate(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
params: map[string]interface{}{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"image-pull-policy": "Always",
|
||||||
"port": "-1",
|
"replicas": "1",
|
||||||
|
"port": "-1",
|
||||||
},
|
},
|
||||||
expected: &api.ReplicationController{
|
expected: &api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -55,8 +56,9 @@ func TestGenerate(t *testing.T) {
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Image: "someimage",
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullAlways,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -110,11 +112,12 @@ func TestGenerate(t *testing.T) {
|
||||||
|
|
||||||
{
|
{
|
||||||
params: map[string]interface{}{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"image-pull-policy": "Never",
|
||||||
"port": "-1",
|
"replicas": "1",
|
||||||
"args": []string{"bar", "baz", "blah"},
|
"port": "-1",
|
||||||
|
"args": []string{"bar", "baz", "blah"},
|
||||||
},
|
},
|
||||||
expected: &api.ReplicationController{
|
expected: &api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -131,9 +134,10 @@ func TestGenerate(t *testing.T) {
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Image: "someimage",
|
Image: "someimage",
|
||||||
Args: []string{"bar", "baz", "blah"},
|
ImagePullPolicy: api.PullNever,
|
||||||
|
Args: []string{"bar", "baz", "blah"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -213,11 +217,12 @@ func TestGenerate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]interface{}{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"image-pull-policy": "IfNotPresent",
|
||||||
"port": "80",
|
"replicas": "1",
|
||||||
"hostport": "80",
|
"port": "80",
|
||||||
|
"hostport": "80",
|
||||||
},
|
},
|
||||||
expected: &api.ReplicationController{
|
expected: &api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -234,8 +239,9 @@ func TestGenerate(t *testing.T) {
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Image: "someimage",
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
Ports: []api.ContainerPort{
|
Ports: []api.ContainerPort{
|
||||||
{
|
{
|
||||||
ContainerPort: 80,
|
ContainerPort: 80,
|
||||||
|
@ -435,9 +441,10 @@ func TestGeneratePod(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]interface{}{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"env": []string{"a=b", "c=d"},
|
"image-pull-policy": "Always",
|
||||||
|
"env": []string{"a=b", "c=d"},
|
||||||
},
|
},
|
||||||
expected: &api.Pod{
|
expected: &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -448,7 +455,7 @@ func TestGeneratePod(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Image: "someimage",
|
Image: "someimage",
|
||||||
ImagePullPolicy: api.PullIfNotPresent,
|
ImagePullPolicy: api.PullAlways,
|
||||||
Env: []api.EnvVar{
|
Env: []api.EnvVar{
|
||||||
{
|
{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
|
@ -639,18 +646,19 @@ func TestGenerateDeployment(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
params: map[string]interface{}{
|
params: map[string]interface{}{
|
||||||
"labels": "foo=bar,baz=blah",
|
"labels": "foo=bar,baz=blah",
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"replicas": "3",
|
"replicas": "3",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"port": "80",
|
"image-pull-policy": "Always",
|
||||||
"hostport": "80",
|
"port": "80",
|
||||||
"stdin": "true",
|
"hostport": "80",
|
||||||
"command": "true",
|
"stdin": "true",
|
||||||
"args": []string{"bar", "baz", "blah"},
|
"command": "true",
|
||||||
"env": []string{"a=b", "c=d"},
|
"args": []string{"bar", "baz", "blah"},
|
||||||
"requests": "cpu=100m,memory=100Mi",
|
"env": []string{"a=b", "c=d"},
|
||||||
"limits": "cpu=400m,memory=200Mi",
|
"requests": "cpu=100m,memory=100Mi",
|
||||||
|
"limits": "cpu=400m,memory=200Mi",
|
||||||
},
|
},
|
||||||
expected: &extensions.Deployment{
|
expected: &extensions.Deployment{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -667,9 +675,10 @@ func TestGenerateDeployment(t *testing.T) {
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Image: "someimage",
|
Image: "someimage",
|
||||||
Stdin: true,
|
ImagePullPolicy: api.PullAlways,
|
||||||
|
Stdin: true,
|
||||||
Ports: []api.ContainerPort{
|
Ports: []api.ContainerPort{
|
||||||
{
|
{
|
||||||
ContainerPort: 80,
|
ContainerPort: 80,
|
||||||
|
|
Loading…
Reference in New Issue