Skip to content

Commit 64ccb22

Browse files
authored
Do not delete previous annotation and support delete annotation via CLI (#4940)
* Do not delete previous annotation Currently, if passing another annotations, original previous annotation will be removed and the passed new annotations will be added. It may give users some confused that why my previous annotation gone. So it is better to not delete user's previous annotation when adding new annotation, but at the same time, need to provide a feature that support to delete annotation by user via ClI, e.g. wsk action update hello --del-annotation key1 --del-annotation key2 CLI side needs to support as well * Add test cases * Fix some review comments Co-authored-by: ning.yougang <[email protected]>
1 parent df2c499 commit 64ccb22

File tree

8 files changed

+94
-3
lines changed

8 files changed

+94
-3
lines changed

common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ case class WhiskActionPut(exec: Option[Exec] = None,
5656
limits: Option[ActionLimitsOption] = None,
5757
version: Option[SemVer] = None,
5858
publish: Option[Boolean] = None,
59-
annotations: Option[Parameters] = None) {
59+
annotations: Option[Parameters] = None,
60+
delAnnotations: Option[Array[String]] = None) {
6061

6162
protected[core] def replace(exec: Exec) = {
6263
WhiskActionPut(Some(exec), parameters, limits, version, publish, annotations)
@@ -643,5 +644,5 @@ object ActionLimitsOption extends DefaultJsonProtocol {
643644
}
644645

645646
object WhiskActionPut extends DefaultJsonProtocol {
646-
implicit val serdes = jsonFormat6(WhiskActionPut.apply)
647+
implicit val serdes = jsonFormat7(WhiskActionPut.apply)
647648
}

core/controller/src/main/resources/apiv1swagger.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,13 @@
19101910
},
19111911
"description": "annotations on the item"
19121912
},
1913+
"delAnnotations": {
1914+
"type": "array",
1915+
"items": {
1916+
"type": "string"
1917+
},
1918+
"description": "The list of annotations to be deleted from the item"
1919+
},
19131920
"parameters": {
19141921
"type": "array",
19151922
"items": {

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,13 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
537537

538538
val exec = content.exec getOrElse action.exec
539539

540+
val newAnnotations = content.delAnnotations
541+
.map { annotationArray =>
542+
annotationArray.foldRight(action.annotations)((a: String, b: Parameters) => b - a)
543+
}
544+
.map(_ ++ content.annotations)
545+
.getOrElse(action.annotations ++ content.annotations)
546+
540547
WhiskAction(
541548
action.namespace,
542549
action.name,
@@ -545,7 +552,7 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
545552
limits,
546553
content.version getOrElse action.version.upPatch,
547554
content.publish getOrElse action.publish,
548-
WhiskActionsApi.amendAnnotations(content.annotations getOrElse action.annotations, exec, create = false))
555+
WhiskActionsApi.amendAnnotations(newAnnotations, exec, create = false))
549556
.revision[WhiskAction](action.docinfo.rev)
550557
}
551558

tests/src/test/scala/common/WskCliOperations.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ class CliActionOperations(override val wsk: RunCliCmd)
195195
docker: Option[String] = None,
196196
parameters: Map[String, JsValue] = Map.empty,
197197
annotations: Map[String, JsValue] = Map.empty,
198+
delAnnotations: Array[String] = Array(),
198199
parameterFile: Option[String] = None,
199200
annotationFile: Option[String] = None,
200201
timeout: Option[Duration] = None,
@@ -229,6 +230,10 @@ class CliActionOperations(override val wsk: RunCliCmd)
229230
annotations flatMap { p =>
230231
Seq("-a", p._1, p._2.compactPrint)
231232
}
233+
} ++ {
234+
delAnnotations flatMap { p =>
235+
Seq("--del-annotation", p)
236+
}
232237
} ++ {
233238
parameterFile map { pf =>
234239
Seq("-P", pf)

tests/src/test/scala/common/WskOperations.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ trait ActionOperations extends DeleteFromCollectionOperations with ListOrGetFrom
234234
docker: Option[String] = None,
235235
parameters: Map[String, JsValue] = Map.empty,
236236
annotations: Map[String, JsValue] = Map.empty,
237+
delAnnotations: Array[String] = Array(),
237238
parameterFile: Option[String] = None,
238239
annotationFile: Option[String] = None,
239240
timeout: Option[Duration] = None,

tests/src/test/scala/common/rest/WskRestOperations.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ class RestActionOperations(implicit val actorSystem: ActorSystem)
264264
docker: Option[String] = None,
265265
parameters: Map[String, JsValue] = Map.empty,
266266
annotations: Map[String, JsValue] = Map.empty,
267+
delAnnotations: Array[String] = Array(),
267268
parameterFile: Option[String] = None,
268269
annotationFile: Option[String] = None,
269270
timeout: Option[Duration] = None,
@@ -364,6 +365,8 @@ class RestActionOperations(implicit val actorSystem: ActorSystem)
364365
content = content + ("annotations" -> annos.toJson)
365366
if (limits.nonEmpty)
366367
content = content + ("limits" -> limits.toJson)
368+
if (delAnnotations.nonEmpty)
369+
content = content + ("delAnnotations" -> delAnnotations.toJson)
367370
content
368371
}
369372

tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskRestBasicUsageTests.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,38 @@ class WskRestBasicUsageTests extends TestHelpers with WskTestHelpers with WskAct
131131
}
132132
}
133133

134+
it should "delete the given annotations using delAnnotations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
135+
val name = "hello"
136+
137+
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
138+
val annotations = Map("key1" -> "value1".toJson, "key2" -> "value2".toJson)
139+
action.create(name, Some(TestUtils.getTestActionFilename("hello.js")), annotations = annotations)
140+
val annotationString = wsk.parseJsonString(wsk.action.get(name).stdout).fields("annotations").toString
141+
142+
annotationString should include(""""key":"key1"""")
143+
annotationString should include(""""value":"value1"""")
144+
annotationString should include(""""key":"key2"""")
145+
annotationString should include(""""value":"value2"""")
146+
147+
//Delete key1 only
148+
val delAnnotations = Array("key1")
149+
150+
action.create(
151+
name,
152+
Some(TestUtils.getTestActionFilename("hello.js")),
153+
delAnnotations = delAnnotations,
154+
update = true)
155+
val newAnnotationString = wsk.parseJsonString(wsk.action.get(name).stdout).fields("annotations").toString
156+
157+
newAnnotationString should not include (""""key":"key1"""")
158+
newAnnotationString should not include (""""value":"value1"""")
159+
newAnnotationString should include(""""key":"key2"""")
160+
newAnnotationString should include(""""value":"value2"""")
161+
162+
action.create(name, Some(TestUtils.getTestActionFilename("hello.js")), update = true)
163+
}
164+
}
165+
134166
it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
135167
(wp, assetHelper) =>
136168
val name = "actionAnnotAndParamParsing"

tests/src/test/scala/system/basic/WskActionTests.scala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,4 +357,39 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers with
357357
}
358358
}
359359

360+
it should "not delete existing annotations when updating action with new annotation" in withAssetCleaner(wskprops) {
361+
(wp, assetHelper) =>
362+
val name = "hello"
363+
364+
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
365+
val annotations = Map("key1" -> "value1".toJson, "key2" -> "value2".toJson)
366+
action.create(name, Some(TestUtils.getTestActionFilename("hello.js")), annotations = annotations)
367+
val annotationString = wsk.parseJsonString(wsk.action.get(name).stdout).fields("annotations").toString
368+
369+
annotationString should include(""""key":"key1"""")
370+
annotationString should include(""""value":"value1"""")
371+
annotationString should include(""""key":"key2"""")
372+
annotationString should include(""""value":"value2"""")
373+
374+
val newAnnotations = Map("key3" -> "value3".toJson, "key4" -> "value4".toJson)
375+
action.create(
376+
name,
377+
Some(TestUtils.getTestActionFilename("hello.js")),
378+
annotations = newAnnotations,
379+
update = true)
380+
val newAnnotationString = wsk.parseJsonString(wsk.action.get(name).stdout).fields("annotations").toString
381+
382+
newAnnotationString should include(""""key":"key1"""")
383+
newAnnotationString should include(""""value":"value1"""")
384+
newAnnotationString should include(""""key":"key2"""")
385+
newAnnotationString should include(""""value":"value2"""")
386+
newAnnotationString should include(""""key":"key3"""")
387+
newAnnotationString should include(""""value":"value3"""")
388+
newAnnotationString should include(""""key":"key4"""")
389+
newAnnotationString should include(""""value":"value4"""")
390+
391+
action.create(name, Some(TestUtils.getTestActionFilename("hello.js")), update = true)
392+
}
393+
}
394+
360395
}

0 commit comments

Comments
 (0)