mirror of https://github.com/knative/client.git
Adds --force flag to service create command (service replace) (#79)
* Adds --force flag to service create command / service replace Fixes #13 * Keeps the resourceVersion of service with --force flag * Updates the tests * Removes unnecessary comments
This commit is contained in:
parent
08a12e112f
commit
cab512c969
|
|
@ -29,6 +29,7 @@ type ConfigurationEditFlags struct {
|
||||||
Image string
|
Image string
|
||||||
Env []string
|
Env []string
|
||||||
RequestsFlags, LimitsFlags ResourceFlags
|
RequestsFlags, LimitsFlags ResourceFlags
|
||||||
|
ForceCreate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceFlags struct {
|
type ResourceFlags struct {
|
||||||
|
|
@ -49,6 +50,7 @@ func (p *ConfigurationEditFlags) AddUpdateFlags(command *cobra.Command) {
|
||||||
|
|
||||||
func (p *ConfigurationEditFlags) AddCreateFlags(command *cobra.Command) {
|
func (p *ConfigurationEditFlags) AddCreateFlags(command *cobra.Command) {
|
||||||
p.AddUpdateFlags(command)
|
p.AddUpdateFlags(command)
|
||||||
|
command.Flags().BoolVar(&p.ForceCreate, "force", false, "Create service forcefully, replaces existing service if any.")
|
||||||
command.MarkFlagRequired("image")
|
command.MarkFlagRequired("image")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
servingv1alpha1 "github.com/knative/serving/pkg/apis/serving/v1alpha1"
|
servingv1alpha1 "github.com/knative/serving/pkg/apis/serving/v1alpha1"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewServiceCreateCommand(p *KnParams) *cobra.Command {
|
func NewServiceCreateCommand(p *KnParams) *cobra.Command {
|
||||||
|
|
@ -35,7 +36,19 @@ func NewServiceCreateCommand(p *KnParams) *cobra.Command {
|
||||||
kn service create mysvc --image dev.local/ns/image:latest
|
kn service create mysvc --image dev.local/ns/image:latest
|
||||||
|
|
||||||
# Create a service with multiple environment variables
|
# Create a service with multiple environment variables
|
||||||
kn service create mysvc --env KEY1=VALUE1 --env KEY2=VALUE2 --image dev.local/ns/image:latest`,
|
kn service create mysvc --env KEY1=VALUE1 --env KEY2=VALUE2 --image dev.local/ns/image:latest
|
||||||
|
|
||||||
|
# Create or replace a service 's1' with image dev.local/ns/image:v2 using --force flag
|
||||||
|
# if service 's1' doesn't exist, it's just a normal create operation
|
||||||
|
kn service create --force s1 --image dev.local/ns/image:v2
|
||||||
|
|
||||||
|
# Create or replace environment variables of service 's1' using --force flag
|
||||||
|
kn service create --force s1 --env KEY1=NEW_VALUE1 --env NEW_KEY2=NEW_VALUE2 --image dev.local/ns/image:v1
|
||||||
|
|
||||||
|
# Create or replace default resources of a service 's1' using --force flag
|
||||||
|
# (earlier configured resource requests and limits will be replaced with default)
|
||||||
|
# (earlier configured environment variables will be cleared too if any)
|
||||||
|
kn service create --force s1 --image dev.local/ns/image:v1`,
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
|
|
@ -70,11 +83,26 @@ func NewServiceCreateCommand(p *KnParams) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = client.Services(namespace).Create(&service)
|
var serviceExists bool = false
|
||||||
if err != nil {
|
if editFlags.ForceCreate {
|
||||||
return err
|
existingService, err := client.Services(namespace).Get(args[0], v1.GetOptions{})
|
||||||
|
if err == nil {
|
||||||
|
serviceExists = true
|
||||||
|
service.ResourceVersion = existingService.ResourceVersion
|
||||||
|
_, err = client.Services(namespace).Update(&service)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' successfully replaced in namespace '%s'.\n", args[0], namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !serviceExists {
|
||||||
|
_, err = client.Services(namespace).Create(&service)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' successfully created in namespace '%s'.\n", args[0], namespace)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' successfully created in namespace '%s'.\n", args[0], namespace)
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,3 +290,63 @@ func parseQuantity(t *testing.T, quantityString string) resource.Quantity {
|
||||||
}
|
}
|
||||||
return quantity
|
return quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServiceCreateImageForce(t *testing.T) {
|
||||||
|
_, _, _, err := fakeServiceCreate([]string{
|
||||||
|
"service", "create", "foo", "--image", "gcr.io/foo/bar:v1"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
action, created, output, err := fakeServiceCreate([]string{
|
||||||
|
"service", "create", "foo", "--force", "--image", "gcr.io/foo/bar:v2"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if !action.Matches("create", "services") {
|
||||||
|
t.Fatalf("Bad action %v", action)
|
||||||
|
}
|
||||||
|
conf, err := servinglib.GetConfiguration(created)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if conf.RevisionTemplate.Spec.Container.Image != "gcr.io/foo/bar:v2" {
|
||||||
|
t.Fatalf("wrong image set: %v", conf.RevisionTemplate.Spec.Container.Image)
|
||||||
|
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "default") {
|
||||||
|
t.Fatalf("wrong output: %s", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceCreateEnvForce(t *testing.T) {
|
||||||
|
_, _, _, err := fakeServiceCreate([]string{
|
||||||
|
"service", "create", "foo", "--image", "gcr.io/foo/bar:v1", "-e", "A=DOGS", "--env", "B=WOLVES"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
action, created, output, err := fakeServiceCreate([]string{
|
||||||
|
"service", "create", "foo", "--force", "--image", "gcr.io/foo/bar:v2", "-e", "A=CATS", "--env", "B=LIONS"})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if !action.Matches("create", "services") {
|
||||||
|
t.Fatalf("Bad action %v", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedEnvVars := map[string]string{
|
||||||
|
"A": "CATS",
|
||||||
|
"B": "LIONS"}
|
||||||
|
|
||||||
|
conf, err := servinglib.GetConfiguration(created)
|
||||||
|
actualEnvVars, err := servinglib.EnvToMap(conf.RevisionTemplate.Spec.Container.Env)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if conf.RevisionTemplate.Spec.Container.Image != "gcr.io/foo/bar:v2" {
|
||||||
|
t.Fatalf("wrong image set: %v", conf.RevisionTemplate.Spec.Container.Image)
|
||||||
|
} else if !reflect.DeepEqual(
|
||||||
|
actualEnvVars,
|
||||||
|
expectedEnvVars) {
|
||||||
|
t.Fatalf("wrong env vars:%v", conf.RevisionTemplate.Spec.Container.Env)
|
||||||
|
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "default") {
|
||||||
|
t.Fatalf("wrong output: %s", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue