Skip to content

Commit 5f68d61

Browse files
authored
update: Change default to server-side generated revision names (extended) (#1240)
* update: Change default to server-side generated revision names Fixes #1144 * update: Fix wait loop for synthetic events for which the generations are already in sync * fix assertion as a service label change does not create a new revision * fix: --cluster-local does not create a new revision but just changes a service's label * chore: Fixed formatting * update: Check generation in update already before doing a watch * fixed lint issue * fix test assertions
1 parent 09c5129 commit 5f68d61

21 files changed

+136
-88
lines changed

CHANGELOG.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
| 🐣
3838
| Do not print `serviceUID` and `configUID` labels in service export results
3939
| https://github.com/knative/client/pull/1194[#1194]
40+
41+
| ✨
42+
| Use server-side generated revision names by default now. For BYO revision names use `--revision-name` for service commands
43+
| https://github.com/knative/client/issues/1240[#1240]
4044
|===
4145

4246
## v0.20.0 (2021-01-14)

docs/cmd/kn_service_apply.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ kn service apply s0 --filename my-svc.yml
5858
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
5959
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
6060
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
61-
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
61+
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants (e.g. {{.Service}}-{{.Random 5}}-{{.Generation}})
6262
--scale string Set the Minimum and Maximum number of replicas. You can use this flag to set both to a single value, or set a range with min/max values, or set either min or max values without specifying the other. Example: --scale 5 (scale-min = 5, scale-max = 5) or --scale 1..5 (scale-min = 1, scale-max = 5) or --scale 1.. (scale-min = 1, scale-max = unchanged) or --scale ..5 (scale-min = unchanged, scale-max = 5)
6363
--scale-init int Initial number of replicas with which a service starts. Can be 0 or a positive integer.
6464
--scale-max int Maximum number of replicas.

docs/cmd/kn_service_create.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ kn service create NAME --image IMAGE
8383
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
8484
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
8585
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
86-
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
86+
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants (e.g. {{.Service}}-{{.Random 5}}-{{.Generation}})
8787
--scale string Set the Minimum and Maximum number of replicas. You can use this flag to set both to a single value, or set a range with min/max values, or set either min or max values without specifying the other. Example: --scale 5 (scale-min = 5, scale-max = 5) or --scale 1..5 (scale-min = 1, scale-max = 5) or --scale 1.. (scale-min = 1, scale-max = unchanged) or --scale ..5 (scale-min = unchanged, scale-max = 5)
8888
--scale-init int Initial number of replicas with which a service starts. Can be 0 or a positive integer.
8989
--scale-max int Maximum number of replicas.

docs/cmd/kn_service_update.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ kn service update NAME
6666
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
6767
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
6868
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
69-
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
69+
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants (e.g. {{.Service}}-{{.Random 5}}-{{.Generation}})
7070
--scale string Set the Minimum and Maximum number of replicas. You can use this flag to set both to a single value, or set a range with min/max values, or set either min or max values without specifying the other. Example: --scale 5 (scale-min = 5, scale-max = 5) or --scale 1..5 (scale-min = 1, scale-max = 5) or --scale 1.. (scale-min = 1, scale-max = unchanged) or --scale ..5 (scale-min = unchanged, scale-max = 5)
7171
--scale-init int Initial number of replicas with which a service starts. Can be 0 or a positive integer.
7272
--scale-max int Maximum number of replicas.

pkg/kn/commands/service/configuration_edit_flags.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ func (p *ConfigurationEditFlags) addSharedFlags(command *cobra.Command) {
104104

105105
knflags.AddBothBoolFlagsUnhidden(command.Flags(), &p.ClusterLocal, "cluster-local", "", false,
106106
"Specify that the service be private. (--no-cluster-local will make the service publicly available)")
107-
//TODO: Need to also not change revision when already set (solution to issue #646)
108-
p.markFlagMakesRevision("cluster-local")
109-
p.markFlagMakesRevision("no-cluster-local")
110107

111108
command.Flags().IntVar(&p.ConcurrencyTarget, "concurrency-target", 0,
112109
"Recommendation for when to scale up based on the concurrent number of incoming request. "+
@@ -140,11 +137,12 @@ func (p *ConfigurationEditFlags) addSharedFlags(command *cobra.Command) {
140137
"precedence over the \"label\" flag.")
141138
p.markFlagMakesRevision("label-revision")
142139

143-
command.Flags().StringVar(&p.RevisionName, "revision-name", "{{.Service}}-{{.Random 5}}-{{.Generation}}",
140+
command.Flags().StringVar(&p.RevisionName, "revision-name", "",
144141
"The revision name to set. Must start with the service name and a dash as a prefix. "+
145142
"Empty revision name will result in the server generating a name for the revision. "+
146143
"Accepts golang templates, allowing {{.Service}} for the service name, "+
147-
"{{.Generation}} for the generation, and {{.Random [n]}} for n random consonants.")
144+
"{{.Generation}} for the generation, and {{.Random [n]}} for n random consonants "+
145+
"(e.g. {{.Service}}-{{.Random 5}}-{{.Generation}})")
148146
p.markFlagMakesRevision("revision-name")
149147

150148
knflags.AddBothBoolFlagsUnhidden(command.Flags(), &p.LockToDigest, "lock-to-digest", "", true,
@@ -206,30 +204,31 @@ func (p *ConfigurationEditFlags) Apply(
206204
return err
207205
}
208206

209-
name, err := servinglib.GenerateRevisionName(p.RevisionName, service)
210-
if err != nil {
211-
return err
212-
}
207+
name := ""
208+
if p.RevisionName != "" {
209+
name, err = servinglib.GenerateRevisionName(p.RevisionName, service)
210+
if err != nil {
211+
return err
212+
}
213213

214-
if p.AnyMutation(cmd) {
215-
template.Name = name
214+
if p.AnyMutation(cmd) {
215+
template.Name = name
216+
}
216217
}
217218

218-
imageSet := false
219-
if cmd.Flags().Changed("image") {
220-
imageSet = true
221-
}
222219
_, userImagePresent := template.Annotations[servinglib.UserImageAnnotationKey]
223220
freezeMode := userImagePresent || cmd.Flags().Changed("lock-to-digest")
224221
if p.LockToDigest && p.AnyMutation(cmd) && freezeMode {
225222
servinglib.SetUserImageAnnot(template)
226-
if !imageSet {
223+
if !cmd.Flags().Changed("image") {
227224
err = servinglib.FreezeImageToDigest(template, baseRevision)
228225
if err != nil {
229226
return err
230227
}
231228
}
232-
} else if !p.LockToDigest {
229+
}
230+
231+
if !p.LockToDigest {
233232
servinglib.UnsetUserImageAnnot(template)
234233
}
235234

pkg/kn/commands/service/create.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,14 @@ func createService(client clientservingv1.KnServingClient, service *servingv1.Se
155155
}
156156

157157
func replaceService(client clientservingv1.KnServingClient, service *servingv1.Service, waitFlags commands.WaitFlags, out io.Writer, targetFlag string) error {
158-
err := prepareAndUpdateService(client, service)
158+
changed, err := prepareAndUpdateService(client, service)
159159
if err != nil {
160160
return err
161161
}
162+
if !changed {
163+
fmt.Fprintf(out, "Service '%s' replaced in namespace '%s' (unchanged).\n", service.Name, client.Namespace())
164+
return nil
165+
}
162166
return waitIfRequested(client, waitFlags, service.Name, "Replacing", "replaced", targetFlag, out)
163167
}
164168

@@ -171,12 +175,12 @@ func waitIfRequested(client clientservingv1.KnServingClient, waitFlags commands.
171175
return waitForServiceToGetReady(client, serviceName, waitFlags.TimeoutInSeconds, verbDone, out)
172176
}
173177

174-
func prepareAndUpdateService(client clientservingv1.KnServingClient, service *servingv1.Service) error {
178+
func prepareAndUpdateService(client clientservingv1.KnServingClient, service *servingv1.Service) (bool, error) {
175179
var retries = 0
176180
for {
177181
existingService, err := client.GetService(service.Name)
178182
if err != nil {
179-
return err
183+
return false, err
180184
}
181185

182186
// Copy over some annotations that we want to keep around. Erase others
@@ -200,16 +204,16 @@ func prepareAndUpdateService(client clientservingv1.KnServingClient, service *se
200204
}
201205

202206
service.ResourceVersion = existingService.ResourceVersion
203-
err = client.UpdateService(service)
207+
changed, err := client.UpdateService(service)
204208
if err != nil {
205209
// Retry to update when a resource version conflict exists
206210
if apierrors.IsConflict(err) && retries < MaxUpdateRetries {
207211
retries++
208212
continue
209213
}
210-
return err
214+
return changed, err
211215
}
212-
return nil
216+
return changed, nil
213217
}
214218
}
215219

pkg/kn/commands/service/create_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ func TestServiceCreateImage(t *testing.T) {
137137
!strings.Contains(output, commands.FakeNamespace) {
138138
t.Fatalf("wrong stdout message: %v", output)
139139
}
140+
141+
// No revision name set by default
142+
assert.Assert(t, template.Name == "")
140143
}
141144

142145
func TestServiceCreateWithMultipleImages(t *testing.T) {

pkg/kn/commands/service/service_update_mock_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func recordServiceUpdateWithSuccess(r *clientservingv1.ServingRecorder, svcName
131131
r.GetService(svcName, nil, errors.NewNotFound(servingv1.Resource("service"), svcName))
132132
r.CreateService(newService, nil)
133133
r.GetService(svcName, newService, nil)
134-
r.UpdateService(updatedService, nil)
134+
r.UpdateService(updatedService, true, nil)
135135
}
136136

137137
func TestServiceUpdateEnvFromAddingWithConfigMap(t *testing.T) {
@@ -283,7 +283,7 @@ func TestServiceUpdateEnvFromRemovalWithConfigMap(t *testing.T) {
283283
r.GetService(svcName, updatedService1, nil)
284284
//r.UpdateService(updatedService2, nil) // since an error happens, update is not triggered here
285285
r.GetService(svcName, updatedService2, nil)
286-
r.UpdateService(updatedService3, nil)
286+
r.UpdateService(updatedService3, true, nil)
287287

288288
output, err := executeServiceCommand(client,
289289
"create", svcName, "--image", "gcr.io/foo/bar:baz",
@@ -372,7 +372,7 @@ func TestServiceUpdateEnvFromRemovalWithEmptyName(t *testing.T) {
372372
r.CreateService(newService, nil)
373373
r.GetService(svcName, newService, nil)
374374
r.GetService(svcName, newService, nil)
375-
r.UpdateService(updatedService1, nil)
375+
r.UpdateService(updatedService1, true, nil)
376376

377377
output, err := executeServiceCommand(client,
378378
"create", svcName, "--image", "gcr.io/foo/bar:baz",
@@ -625,11 +625,11 @@ func TestServiceUpdateEnvFromRemovalWithSecret(t *testing.T) {
625625
r.GetService(svcName, nil, errors.NewNotFound(servingv1.Resource("service"), svcName))
626626
r.CreateService(newService, nil)
627627
r.GetService(svcName, newService, nil)
628-
r.UpdateService(updatedService1, nil)
628+
r.UpdateService(updatedService1, true, nil)
629629
r.GetService(svcName, updatedService1, nil)
630630
//r.UpdateService(updatedService2, nil) // since an error happens, update is not triggered here
631631
r.GetService(svcName, updatedService2, nil)
632-
r.UpdateService(updatedService3, nil)
632+
r.UpdateService(updatedService3, true, nil)
633633

634634
output, err := executeServiceCommand(client,
635635
"create", svcName, "--image", "gcr.io/foo/bar:baz",
@@ -1383,9 +1383,9 @@ func TestServiceUpdateWithRemovingMount(t *testing.T) {
13831383
r.GetService(svcName, nil, errors.NewNotFound(servingv1.Resource("service"), svcName))
13841384
r.CreateService(newService, nil)
13851385
r.GetService(svcName, newService, nil)
1386-
r.UpdateService(updatedService1, nil)
1386+
r.UpdateService(updatedService1, true, nil)
13871387
r.GetService(svcName, updatedService1, nil)
1388-
r.UpdateService(updatedService2, nil)
1388+
r.UpdateService(updatedService2, true, nil)
13891389

13901390
output, err := executeServiceCommand(client,
13911391
"create", svcName, "--image", "gcr.io/foo/bar:baz",

pkg/kn/commands/service/update.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,19 @@ func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command {
109109
}
110110

111111
// Do the actual update with retry in case of conflicts
112-
err = client.UpdateServiceWithRetry(name, updateFunc, MaxUpdateRetries)
112+
changed, err := client.UpdateServiceWithRetry(name, updateFunc, MaxUpdateRetries)
113113
if err != nil {
114114
return err
115115
}
116-
117116
out := cmd.OutOrStdout()
117+
118+
// No need to wait if not changed
119+
if !changed {
120+
fmt.Fprintf(out, "Service '%s' updated in namespace '%s'.\n", args[0], namespace)
121+
fmt.Fprintln(out, "No new revision has been created.")
122+
return nil
123+
}
124+
118125
if waitFlags.Wait && targetFlag == "" {
119126
fmt.Fprintf(out, "Updating Service '%s' in namespace '%s':\n", args[0], namespace)
120127
fmt.Fprintln(out, "")

pkg/kn/commands/service/update_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ func fakeServiceUpdate(original *servingv1.Service, args []string) (
6262
if !ok {
6363
return true, nil, fmt.Errorf("wrong kind of action %v", action)
6464
}
65-
updated, ok = updateAction.GetObject().(*servingv1.Service)
65+
given, ok := updateAction.GetObject().(*servingv1.Service)
6666
if !ok {
6767
return true, nil, errors.New("was passed the wrong object")
6868
}
69+
updated = given.DeepCopy()
70+
updated.Generation = given.Generation + 1
6971
return true, updated, nil
7072
})
7173
fakeServing.AddReactor("get", "services",
@@ -271,7 +273,7 @@ func TestServiceUpdateRevisionNameGenerated(t *testing.T) {
271273

272274
// Test prefix added by command
273275
action, updated, _, err := fakeServiceUpdate(orig, []string{
274-
"service", "update", "foo", "--image", "gcr.io/foo/quux:xyzzy", "--namespace", "bar", "--no-wait"})
276+
"service", "update", "foo", "--image", "gcr.io/foo/quux:xyzzy", "--namespace", "bar", "--no-wait", "--revision-name", "{{.Service}}-{{.Random 5}}-{{.Generation}}"})
275277
assert.NilError(t, err)
276278
if !action.Matches("update", "services") {
277279
t.Fatalf("Bad action %v", action)
@@ -282,6 +284,24 @@ func TestServiceUpdateRevisionNameGenerated(t *testing.T) {
282284
assert.Assert(t, !(template.Name == "foo-asdf"))
283285
}
284286

287+
func TestServiceUpdateRevisionNameDefault(t *testing.T) {
288+
orig := newEmptyService()
289+
290+
template := orig.Spec.Template
291+
template.Name = "foo-asdf"
292+
293+
// Test prefix added by command
294+
action, updated, _, err := fakeServiceUpdate(orig, []string{
295+
"service", "update", "foo", "--image", "gcr.io/foo/quux:xyzzy"})
296+
assert.NilError(t, err)
297+
if !action.Matches("update", "services") {
298+
t.Fatalf("Bad action %v", action)
299+
}
300+
301+
template = updated.Spec.Template
302+
assert.Assert(t, cmp.Equal(template.Name, ""))
303+
}
304+
285305
func TestServiceUpdateRevisionNameCleared(t *testing.T) {
286306
orig := newEmptyService()
287307

0 commit comments

Comments
 (0)