diff --git a/charts/workflows/charts/escalation/templates/01-configmap_01-ticketescalation-resources.yaml b/charts/workflows/charts/escalation/templates/01-configmap_01-ticketescalation-resources.yaml new file mode 100755 index 00000000..18887141 --- /dev/null +++ b/charts/workflows/charts/escalation/templates/01-configmap_01-ticketescalation-resources.yaml @@ -0,0 +1,509 @@ +apiVersion: v1 +data: + jiraSwf.sw.yaml: "specVersion: \"0.8\"\nid: ticketingService\nname: Jira Ticketing + Service\nannotations:\n - \"workflow-type/infrastructure\"\nversion: 0.0.1\ntimeouts:\n + \ workflowExecTimeout:\n duration: PT24H\nstart: Setup\ndataInputSchema:\n + \ failOnValidationErrors: true\n schema: schemas/ticketing-service-schema.json\nerrors:\n + \ - name: authError\n code: '401'\nfunctions:\n - name: createJiraIssue\n + \ operation: specs/jira.yaml#createIssue\n - name: getJiraIssue\n operation: + specs/jira.yaml#getIssue\n - name: logInfo\n type: custom\n operation: + \"sysout:INFO\"\nstates:\n - name: Setup\n type: operation\n actions:\n + \ - name: \"logInfo\"\n functionRef:\n refName: \"logInfo\"\n + \ arguments:\n message: \"\\\"Invoking Jira SWF with: \\\\(.)\\\"\"\n + \ transition: OnRequest\n - name: OnRequest\n type: switch\n dataConditions:\n + \ - condition: '.request.type ==\"create\"'\n transition: CreateJiraIssue + \ \n - condition: '.request.type ==\"get\"'\n transition: GetJiraIssue + \ \n defaultCondition: \n transition: Unmanaged\n - name: CreateJiraIssue\n + \ type: operation\n actions:\n - name: Create Jira Issue\n functionRef:\n + \ refName: createJiraIssue\n arguments:\n update: + {}\n fields:\n summary: '\"Request For New Namespace: + \" + .request.namespace'\n labels:\n - '$SECRET.jira_label_workflowInstanceId + + \"=\" + .request.parentId'\n - \"$SECRET.jira_label_workflowName\"\n + \ issuetype:\n id: \"$SECRET.jira_issue_type\"\n project:\n + \ key: \"$SECRET.jira_project\"\n actionDataFilter:\n toStateData: + .jiraIssue\n transition: NormalizeCreateResponse\n onErrors:\n - errorRef: + authError\n transition: AuthError\n stateDataFilter:\n output: + \". += { jiraBrowser: ((.jiraIssue.self | sub(\\\"rest/.*\\\"; \\\"browse/\\\")) + + .jiraIssue.key) }\"\n - name: NormalizeCreateResponse\n type: inject\n data: + {}\n stateDataFilter:\n output: \"${ {type: \\\"create\\\", ticketId: + .jiraIssue.key, ticket: .jiraIssue, browseUrl: ((.jiraIssue.self | sub(\\\"rest/.*\\\"; + \\\"browse/\\\")) + .jiraIssue.key)} }\"\n end: true\n - name: GetJiraIssue\n + \ type: operation\n actions:\n - functionRef:\n refName: getJiraIssue\n + \ arguments:\n issueIdOrKey: .request.ticketId\n fields: + status\n actionDataFilter:\n toStateData: .jiraIssue\n transition: + NormalizeGetResponse\n - name: NormalizeGetResponse\n type: inject\n data: + {}\n stateDataFilter:\n output: \"${ { type: \\\"get\\\", ticketId: .jiraIssue.key, + ticket: .jiraIssue, status: (if .jiraIssue.fields.status.statusCategory.key == + \\\"done\\\" then \\\"Approved\\\" elif .jiraIssue.fields.status.statusCategory.key + == \\\"new\\\" then \\\"Created\\\" elif .jiraIssue.fields.status.statusCategory.key + == \\\"undefined\\\" then \\\"Unknown\\\" else \\\"Unknown\\\" end)} }\"\n end: + true\n - name: Unmanaged\n type: operation\n actions:\n - name: \"printAction\"\n + \ functionRef:\n refName: \"logInfo\"\n arguments:\n message: + \"\\\"Unmanaged request: \\\\(.)\\\"\"\n end: true\n - name: AuthError\n type: + operation\n actions:\n - name: \"printAction\"\n functionRef:\n + \ refName: \"logInfo\"\n arguments:\n message: \"\\\"AuthError: + \\\\(.)\\\"\"\n stateDataFilter:\n output: \"${ { type: \\\"get\\\", ticketId: + .jiraIssue.key, ticket: .jiraIssue, status: (if .jiraIssue.fields.status.statusCategory.key + == \\\"done\\\" then \\\"Approved\\\" elif .jiraIssue.fields.status.statusCategory.key + == \\\"new\\\" then \\\"Created\\\" elif .jiraIssue.fields.status.statusCategory.key + == \\\"undefined\\\" then \\\"Unknown\\\" else \\\"Unknown\\\" end)} }\"\n end: + true" + kube.yaml: " openapi: 3.0.0\n info:\n title: Kubernetes\n version: v1.27.3\n + \ paths:\n\n /api/v1/namespaces:\n get:\n tags:\n - core_v1\n + \ description: list or watch objects of kind Namespace\n operationId: + listCoreV1Namespace\n parameters:\n - name: allowWatchBookmarks\n + \ in: query\n description: allowWatchBookmarks requests watch + events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore + this flag and bookmarks are sent at the server's discretion. Clients should not + assume bookmarks are returned at any specific interval, nor may they assume the + server will send any BOOKMARK event during a session. If this is not a watch, + this field is ignored.\n schema:\n type: boolean\n uniqueItems: + true\n - name: continue\n in: query\n description: + |-\n The continue option should be set when retrieving more results + from the server. Since this value is server defined, clients may only use the + continue value from a previous query result with identical query parameters (except + for the value of continue) and the server may reject a continue value it does + not recognize. If the specified continue value is no longer valid whether due + to expiration (generally five to fifteen minutes) or a configuration change on + the server, the server will respond with a 410 ResourceExpired error together + with a continue token. If the client needs a consistent list, it must restart + their list without the continue field. Otherwise, the client may send another + list request with the token received with the 410 error, the server will respond + with a list starting from the next key, but from the latest snapshot, which is + inconsistent from the previous list results - objects that are created, modified, + or deleted after the first list request will be included in the response, as long + as their keys are after the \"next key\".\n \n This field is not + supported when watch is true. Clients may start a watch from the last resourceVersion + value returned by the server and not miss any modifications.\n schema:\n + \ type: string\n uniqueItems: true\n - name: + fieldSelector\n in: query\n description: A selector to restrict + the list of returned objects by their fields. Defaults to everything.\n schema:\n + \ type: string\n uniqueItems: true\n - name: + labelSelector\n in: query\n description: A selector to restrict + the list of returned objects by their labels. Defaults to everything.\n schema:\n + \ type: string\n uniqueItems: true\n - name: + limit\n in: query\n description: |-\n limit + is a maximum number of responses to return for a list call. If more items exist, + the server will set the `continue` field on the list metadata to a value that + can be used with the same initial query to retrieve the next set of results. Setting + a limit may return fewer than the requested amount of items (up to zero items) + in the event all requested objects are filtered out and clients should only use + the presence of the continue field to determine whether more results are available. + Servers may choose not to support the limit argument and will return all of the + available results. If limit is specified and the continue field is empty, clients + may assume that no more results are available. This field is not supported if + watch is true.\n \n The server guarantees that the objects returned + when using continue will be identical to issuing a single list call without a + limit - that is, no objects created, modified, or deleted after the first request + is issued will be included in any subsequent continued requests. This is sometimes + referred to as a consistent snapshot, and ensures that a client that is using + limit to receive smaller chunks of a very large result can ensure they see all + possible objects. If objects are updated during a chunked list the version of + the object that was present at the time the first list result was calculated is + returned.\n schema:\n type: integer\n uniqueItems: + true\n - name: resourceVersion\n in: query\n description: + |-\n resourceVersion sets a constraint on what resource versions + a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions + for details.\n \n Defaults to unset\n schema:\n type: + string\n uniqueItems: true\n - name: resourceVersionMatch\n + \ in: query\n description: |-\n resourceVersionMatch + determines how resourceVersion is applied to list calls. It is highly recommended + that resourceVersionMatch be set for list calls where resourceVersion is set See + https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions + for details.\n \n Defaults to unset\n schema:\n type: + string\n uniqueItems: true\n - name: sendInitialEvents\n + \ in: query\n description: |-\n `sendInitialEvents=true` + may be set together with `watch=true`. In that case, the watch stream will begin + with synthetic events to produce the current state of objects in the collection. + Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. + The bookmark will report the ResourceVersion (RV) corresponding to the set of + objects, and be marked with `\"k8s.io/initial-events-end\": \"true\"` annotation. + Afterwards, the watch stream will proceed as usual, sending watch events corresponding + to changes (subsequent to the RV) to objects watched.\n \n When + `sendInitialEvents` option is set, we require `resourceVersionMatch` option to + also be set. The semantic of the watch request is as following: - `resourceVersionMatch` + = NotOlderThan\n is interpreted as \"data at least as new as the + provided `resourceVersion`\"\n and the bookmark event is send when + the state is synced\n to a `resourceVersion` at least as fresh + as the one provided by the ListOptions.\n If `resourceVersion` + is unset, this is interpreted as \"consistent read\" and the\n bookmark + event is send when the state is synced at least to the moment\n when + request started being processed.\n - `resourceVersionMatch` set to + any other value or unset\n Invalid error is returned.\n \n Defaults + to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility + reasons) and to false otherwise.\n schema:\n type: boolean\n + \ uniqueItems: true\n - name: timeoutSeconds\n in: + query\n description: Timeout for the list/watch call. This limits the + duration of the call, regardless of any activity or inactivity.\n schema:\n + \ type: integer\n uniqueItems: true\n - name: + watch\n in: query\n description: Watch for changes to the + described resources and return them as a stream of add, update, and remove notifications. + Specify resourceVersion.\n schema:\n type: boolean\n uniqueItems: + true\n responses:\n \"200\":\n description: OK\n content:\n + \ application/json:\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.NamespaceList'\n application/json;stream=watch:\n + \ schema:\n $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceList'\n + \ application/vnd.kubernetes.protobuf:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceList'\n + \ application/vnd.kubernetes.protobuf;stream=watch:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceList'\n + \ application/yaml:\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.NamespaceList'\n \"401\":\n + \ description: Unauthorized\n x-kubernetes-action: list\n x-kubernetes-group-version-kind:\n + \ group: \"\"\n version: v1\n kind: Namespace\n security:\n + \ - BearerToken: []\n post:\n tags:\n - core_v1\n + \ description: create a Namespace\n operationId: createCoreV1Namespace\n + \ parameters:\n - name: dryRun\n in: query\n description: + 'When present, indicates that modifications should not be persisted. An invalid + or unrecognized dryRun directive will result in an error response and no further + processing of the request. Valid values are: - All: all dry run stages will be + processed'\n schema:\n type: string\n uniqueItems: + true\n - name: fieldManager\n in: query\n description: + fieldManager is a name associated with the actor or entity that is making these + changes. The value must be less than or 128 characters long, and only contain + printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.\n + \ schema:\n type: string\n uniqueItems: true\n + \ - name: fieldValidation\n in: query\n description: + 'fieldValidation instructs the server on how to handle objects in the request + (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: + This will ignore any unknown fields that are silently dropped from the object, + and will ignore all but the last duplicate field that the decoder encounters. + This is the default behavior prior to v1.23. - Warn: This will send a warning + via the standard warning response header for each unknown field that is dropped + from the object, and for each duplicate field that is encountered. The request + will still succeed if there are no other errors, and will only persist the last + of any duplicate fields. This is the default in v1.23+ - Strict: This will fail + the request with a BadRequest error if any unknown fields would be dropped from + the object, or if any duplicate fields are present. The error returned from the + server will contain all unknown and duplicate fields encountered.'\n schema:\n + \ type: string\n uniqueItems: true\n requestBody:\n + \ content:\n '*/*':\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.Namespace'\n responses:\n \"200\":\n + \ description: OK\n content:\n application/json:\n + \ schema:\n $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/vnd.kubernetes.protobuf:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/yaml:\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.Namespace'\n \"201\":\n description: + Created\n content:\n application/json:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/vnd.kubernetes.protobuf:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/yaml:\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.Namespace'\n \"202\":\n description: + Accepted\n content:\n application/json:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/vnd.kubernetes.protobuf:\n schema:\n + \ $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ application/yaml:\n schema:\n $ref: + '#/components/schemas/io.k8s.api.core.v1.Namespace'\n \"401\":\n description: + Unauthorized\n x-kubernetes-action: post\n x-kubernetes-group-version-kind:\n + \ group: \"\"\n version: v1\n kind: Namespace\n security:\n + \ - BearerToken: [ ]\n parameters:\n - name: pretty\n in: + query\n description: If 'true', then the output is pretty printed.\n + \ schema:\n type: string\n uniqueItems: true\n\n + \ components:\n schemas:\n io.k8s.apimachinery.pkg.apis.meta.v1.Time:\n + \ description: Time is a wrapper around time.Time which supports correct + marshaling to YAML and JSON. Wrappers are provided for many of the factory methods + that the time package offers.\n type: string\n format: date-time\n + \ io.k8s.api.core.v1.Namespace:\n description: Namespace provides a + scope for Names. Use of multiple namespaces is optional.\n type: object\n + \ properties:\n apiVersion:\n description: 'APIVersion + defines the versioned schema of this representation of an object. Servers should + convert recognized schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n + \ type: string\n kind:\n description: 'Kind is a + string value representing the REST resource this object represents. Servers may + infer this from the endpoint the client submits requests to. Cannot be updated. + In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n + \ type: string\n metadata:\n description: 'Standard + object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'\n + \ default:\n allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta'\n + \ spec:\n description: 'Spec defines the behavior of the Namespace. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n + \ default:\n allOf:\n - $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceSpec'\n + \ status:\n description: 'Status describes the current status + of a Namespace. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'\n + \ default:\n allOf:\n - $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceStatus'\n + \ x-kubernetes-group-version-kind:\n - group: \"\"\n kind: + Namespace\n version: v1\n io.k8s.api.core.v1.NamespaceCondition:\n + \ description: NamespaceCondition contains details about state of namespace.\n + \ type: object\n required:\n - type\n - status\n + \ properties:\n lastTransitionTime:\n default:\n allOf:\n + \ - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time'\n + \ message:\n type: string\n reason:\n type: + string\n status:\n description: Status of the condition, one + of True, False, Unknown.\n type: string\n default: \"\"\n + \ type:\n description: Type of namespace controller condition.\n + \ type: string\n default: \"\"\n io.k8s.api.core.v1.NamespaceList:\n + \ description: NamespaceList is a list of Namespaces.\n type: object\n + \ required:\n - items\n properties:\n apiVersion:\n + \ description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest internal + value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n + \ type: string\n items:\n description: 'Items is + the list of Namespace objects in the list. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'\n + \ type: array\n items:\n default:\n allOf:\n + \ - $ref: '#/components/schemas/io.k8s.api.core.v1.Namespace'\n + \ kind:\n description: 'Kind is a string value representing + the REST resource this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n + \ type: string\n metadata:\n description: 'Standard + list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n + \ default:\n allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta'\n + \ x-kubernetes-group-version-kind:\n - group: \"\"\n kind: + NamespaceList\n version: v1\n io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta:\n + \ description: ListMeta describes metadata that synthetic resources must + have, including lists and various status objects. A resource may have only one + of {ObjectMeta, ListMeta}.\n type: object\n properties:\n continue:\n + \ description: continue may be set if the user set a limit on the number + of items returned, and indicates that the server has more data available. The + value is opaque and may be used to issue another request to the endpoint that + served this list to retrieve the next set of available objects. Continuing a consistent + list may not be possible if the server configuration has changed or more than + a few minutes have passed. The resourceVersion field returned when using this + continue value will be identical to the value in the first response, unless you + have received this token from an error message.\n type: string\n remainingItemCount:\n + \ description: remainingItemCount is the number of subsequent items + in the list which are not included in this list response. If the list request + contained label or field selectors, then the number of remaining items is unknown + and the field will be left unset and omitted during serialization. If the list + is complete (either because it is not chunking or because this is the last chunk), + then there are no more remaining items and this field will be left unset and omitted + during serialization. Servers older than v1.15 do not set this field. The intended + use of the remainingItemCount is *estimating* the size of a collection. Clients + should not rely on the remainingItemCount to be set or to be exact.\n type: + integer\n format: int64\n resourceVersion:\n description: + 'String that identifies the server''s internal version of this object that can + be used by clients to determine when objects have changed. Value must be treated + as opaque by clients and passed unmodified back to the server. Populated by the + system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'\n + \ type: string\n selfLink:\n description: 'Deprecated: + selfLink is a legacy read-only field that is no longer populated by the system.'\n + \ type: string\n io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry:\n + \ description: ManagedFieldsEntry is a workflow-id, a FieldSet and the group + version of the resource that the fieldset applies to.\n type: object\n + \ properties:\n apiVersion:\n description: APIVersion + defines the version of this resource that this field set applies to. The format + is \"group/version\" just like the top-level APIVersion field. It is necessary + to track the version of a field set because it cannot be automatically converted.\n + \ type: string\n fieldsType:\n description: 'FieldsType + is the discriminator for the different fields format and version. There is currently + only one possible value: \"FieldsV1\"'\n type: string\n fieldsV1:\n + \ description: FieldsV1 holds the first JSON version format as described + in the \"FieldsV1\" type.\n allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1'\n + \ manager:\n description: Manager is an identifier of the workflow + managing these fields.\n type: string\n operation:\n description: + Operation is the type of operation which lead to this ManagedFieldsEntry being + created. The only valid values for this field are 'Apply' and 'Update'.\n type: + string\n subresource:\n description: Subresource is the name + of the subresource used to update that object, or empty string if the object was + updated through the main resource. The value of this field is used to distinguish + between managers, even if they share the same name. For example, a status update + will be distinct from a regular update using the same manager name. Note that + the APIVersion field is not related to the Subresource field and it always corresponds + to the version of the main resource.\n type: string\n time:\n + \ description: Time is the timestamp of when the ManagedFields entry + was added. The timestamp will also be updated if a field is added, the manager + changes any of the owned fields value or removes a field. The timestamp does not + update when a field is removed from the entry because another manager took it + over.\n allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time'\n + \ io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1:\n description: |-\n + \ FieldsV1 stores a set of fields in a data structure like a Trie, in + JSON format.\n\n Each key is either a '.' representing the field itself, + and will always map to an empty set, or a string representing a sub-field or item. + The string will follow one of these four formats: 'f:', where is + the name of a field in a struct, or key in a map 'v:', where is + the exact json formatted value of a list item 'i:', where is position + of a item in a list 'k:', where is a map of a list item's key fields + to their unique values If a key maps to an empty Fields value, the field that + key represents is part of the set.\n\n The exact format is defined in + sigs.k8s.io/structured-merge-diff\n type: object\n\n io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta:\n + \ description: ObjectMeta is metadata that all persisted resources must + have, which includes all objects users must create.\n type: object\n properties:\n + \ annotations:\n description: 'Annotations is an unstructured + key value map stored with a resource that may be set by external tools to store + and retrieve arbitrary metadata. They are not queryable and should be preserved + when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations'\n + \ type: object\n additionalProperties:\n type: + string\n default: \"\"\n creationTimestamp:\n description: + |-\n CreationTimestamp is a timestamp representing the server time + when this object was created. It is not guaranteed to be set in happens-before + order across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC.\n \n Populated by the system. Read-only. + Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata\n + \ default:\n allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time'\n + \ deletionGracePeriodSeconds:\n description: Number of seconds + allowed for this object to gracefully terminate before it will be removed from + the system. Only set when deletionTimestamp is also set. May only be shortened. + Read-only.\n type: integer\n format: int64\n deletionTimestamp:\n + \ description: |-\n DeletionTimestamp is RFC 3339 date + and time at which this resource will be deleted. This field is set by the server + when a graceful deletion is requested by the user, and is not directly settable + by a client. The resource is expected to be deleted (no longer visible from resource + lists, and not reachable by name) after the time in this field, once the finalizers + list is empty. As long as the finalizers list contains items, deletion is blocked. + Once the deletionTimestamp is set, this value may not be unset or be set further + into the future, although it may be shortened or the resource may be deleted prior + to this time. For example, a user may request that a pod is deleted in 30 seconds. + The Kubelet will react by sending a graceful termination signal to the containers + in the pod. After that 30 seconds, the Kubelet will send a hard termination signal + (SIGKILL) to the container and after cleanup, remove the pod from the API. In + the presence of network partitions, this object may still exist after this timestamp, + until an administrator or automated process can determine the resource is fully + terminated. If not set, graceful deletion of the object has not been requested.\n + \ \n Populated by the system when a graceful deletion is requested. + Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata\n + \ allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time'\n + \ finalizers:\n description: Must be empty before the object + is deleted from the registry. Each entry is an identifier for the responsible + component that will remove the entry from the list. If the deletionTimestamp of + the object is non-nil, entries in this list can only be removed. Finalizers may + be processed and removed in any order. Order is NOT enforced because it introduces + significant risk of stuck finalizers. finalizers is a shared field, any actor + with permission can reorder it. If the finalizer list is processed in order, then + this can lead to a situation in which the component responsible for the first + finalizer in the list is waiting for a signal (field value, external system, or + other) produced by a component responsible for a finalizer later in the list, + resulting in a deadlock. Without enforced ordering finalizers are free to order + amongst themselves and are not vulnerable to ordering changes in the list.\n type: + array\n items:\n type: string\n default: + \"\"\n x-kubernetes-patch-strategy: merge\n generateName:\n + \ description: |-\n GenerateName is an optional prefix, + used by the server, to generate a unique name ONLY IF the Name field has not been + provided. If this field is used, the name returned to the client will be different + than the name passed. This value will also be combined with a unique suffix. The + provided value has the same validation rules as the Name field, and may be truncated + by the length of the suffix required to make the value unique on the server.\n + \ \n If this field is specified and the generated name exists, the + server will return a 409.\n \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency\n + \ type: string\n generation:\n description: A sequence + number representing a specific generation of the desired state. Populated by the + system. Read-only.\n type: integer\n format: int64\n labels:\n + \ description: 'Map of string keys and values that can be used to organize + and categorize (scope and select) objects. May match selectors of replication + controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels'\n + \ type: object\n additionalProperties:\n type: + string\n default: \"\"\n managedFields:\n description: + ManagedFields maps workflow-id and version to the set of fields that are managed + by that workflow. This is mostly for internal housekeeping, and users typically + shouldn't need to set or understand this field. A workflow can be the user's name, + a controller's name, or the name of a specific apply path like \"ci-cd\". The + set of fields is always in the version that the workflow used when modifying the + object.\n type: array\n items:\n default:\n + \ allOf:\n - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry'\n + \ name:\n description: 'Name must be unique within a namespace. + Is required when creating resources, although some resources may allow a client + to request the generation of an appropriate name automatically. Name is primarily + intended for creation idempotence and configuration definition. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names'\n + \ type: string\n namespace:\n description: |-\n + \ Namespace defines the space within which each name must be unique. + An empty namespace is equivalent to the \"default\" namespace, but \"default\" + is the canonical representation. Not all objects are required to be scoped to + a namespace - the value of this field for those objects will be empty.\n \n Must + be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces\n + \ type: string\n ownerReferences:\n description: + List of objects depended by this object. If ALL objects in the list have been + deleted, this object will be garbage collected. If this object is managed by a + controller, then an entry in this list will point to this controller, with the + controller field set to true. There cannot be more than one managing controller.\n + \ type: array\n items:\n default:\n allOf:\n + \ - $ref: '#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference'\n + \ x-kubernetes-patch-merge-key: uid\n x-kubernetes-patch-strategy: + merge\n resourceVersion:\n description: |-\n An + opaque value that represents the internal version of this object that can be used + by clients to determine when objects have changed. May be used for optimistic + concurrency, change detection, and the watch operation on a resource or set of + resources. Clients must treat these values as opaque and passed unmodified back + to the server. They may only be valid for a particular resource or set of resources.\n + \ \n Populated by the system. Read-only. Value must be treated as + opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency\n + \ type: string\n selfLink:\n description: 'Deprecated: + selfLink is a legacy read-only field that is no longer populated by the system.'\n + \ type: string\n uid:\n description: |-\n UID + is the unique in time and space value for this object. It is typically generated + by the server on successful creation of a resource and is not allowed to change + on PUT operations.\n \n Populated by the system. Read-only. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids\n + \ type: string\n\n io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference:\n + \ description: OwnerReference contains enough information to let you identify + an owning object. An owning object must be in the same namespace as the dependent, + or be cluster-scoped, so there is no namespace field.\n type: object\n + \ required:\n - apiVersion\n - kind\n - name\n + \ - uid\n properties:\n apiVersion:\n description: + API version of the referent.\n type: string\n default: \"\"\n + \ blockOwnerDeletion:\n description: If true, AND if the owner + has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from + the key-value store until this reference is removed. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion + for how the garbage collector interacts with this field and enforces the foreground + deletion. Defaults to false. To set this field, a user needs \"delete\" permission + of the owner, otherwise 422 (Unprocessable Entity) will be returned.\n type: + boolean\n controller:\n description: If true, this reference + points to the managing controller.\n type: boolean\n kind:\n + \ description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n + \ type: string\n default: \"\"\n name:\n description: + 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names'\n + \ type: string\n default: \"\"\n uid:\n description: + 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids'\n + \ type: string\n default: \"\"\n x-kubernetes-map-type: + atomic\n\n io.k8s.api.core.v1.NamespaceSpec:\n description: NamespaceSpec + describes the attributes on a Namespace.\n type: object\n properties:\n + \ finalizers:\n description: 'Finalizers is an opaque list + of values that must be empty to permanently remove object from storage. More info: + https://kubernetes.io/docs/tasks/administer-cluster/namespaces/'\n type: + array\n items:\n type: string\n default: + \"\"\n io.k8s.api.core.v1.NamespaceStatus:\n description: NamespaceStatus + is information about the current status of a Namespace.\n type: object\n + \ properties:\n conditions:\n description: Represents + the latest available observations of a namespace's current state.\n type: + array\n items:\n default:\n allOf:\n - + $ref: '#/components/schemas/io.k8s.api.core.v1.NamespaceCondition'\n x-kubernetes-patch-merge-key: + type\n x-kubernetes-patch-strategy: merge\n phase:\n description: + |-\n Phase is the current lifecycle phase of the namespace. More + info: https://kubernetes.io/docs/tasks/administer-cluster/namespaces/\n \n Possible + enum values:\n - `\"Active\"` means the namespace is available for + use in the system\n - `\"Terminating\"` means the namespace is undergoing + graceful termination\n type: string\n enum:\n - + Active\n - Terminating\n\n securitySchemes:\n BearerToken:\n + \ type: http\n scheme: bearer\n description: Bearer Token + authentication\n" + ticket-escalation-schema.json: |- + { + "$id": "classpath:/schemas/ticket-escalation-schema.json", + "title": "Ticket escalation: Data Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "namespace": { + "type": "string", + "description": "Name of the requested namespace" + } + }, + "examples": [ + { + "namespace": "a-namespace" + } + ] + } + ticket-escalation_sub_schema.json: |- + { + "$id": "classpath:/schemas/ticket-escalation_sub_schema.json", + "title": "ticketEscalation: Input Section", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "namespace": { + "type": "string", + "description": "Name of the requested namespace" + } + }, + "required": [ + "namespace" + ] + } +kind: ConfigMap +metadata: + creationTimestamp: null + name: 01-ticketescalation-resources diff --git a/charts/workflows/charts/escalation/templates/01-sonataflow_ticketescalation.yaml b/charts/workflows/charts/escalation/templates/01-sonataflow_ticketescalation.yaml new file mode 100755 index 00000000..845712a3 --- /dev/null +++ b/charts/workflows/charts/escalation/templates/01-sonataflow_ticketescalation.yaml @@ -0,0 +1,167 @@ +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlow +metadata: + annotations: + sonataflow.org/description: "" + sonataflow.org/expressionLang: jq + sonataflow.org/version: 0.0.1 + creationTimestamp: null + labels: + app: ticketescalation + sonataflow.org/workflow-app: ticketescalation + name: ticketescalation +spec: + flow: + annotations: + - workflow-type/infrastructure + dataInputSchema: + failOnValidationErrors: true + schema: schemas/ticket-escalation-schema.json + errors: + - code: TimedOut + name: timeoutError + - code: "404" + name: notAvailable + events: + - dataOnly: true + kind: consumed + name: approvalEvent + source: ticket.listener + type: dev.parodos.escalation + functions: + - name: createNotification + operation: notifications#createNotification + type: rest + - name: createK8sNamespace + operation: specs/kube.yaml#createCoreV1Namespace + type: rest + - name: logInfo + operation: sysout:INFO + type: custom + start: + stateName: CreateTicket + states: + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .createResponse + useResults: true + subFlowRef: + invoke: sync + onParentComplete: terminate + workflowId: ticketingService + name: CreateTicket + stateDataFilter: + input: '. += { request: {type: "create", namespace: .namespace, parentId: $WORKFLOW.instanceId} }' + transition: + nextState: WaitForApprovalEvent + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .getResponse + useResults: true + subFlowRef: + invoke: sync + onParentComplete: terminate + workflowId: ticketingService + name: GetTicket + stateDataFilter: + input: '. += { request: { type: "get", ticketId: .createResponse.ticketId, ticket: .createResponse.ticket} }' + transition: + nextState: CheckTicketState + type: operation + - dataConditions: + - condition: (.getResponse.status == "Approved") + transition: + nextState: CreateK8sNamespace + defaultCondition: + transition: + nextState: WaitForApprovalEvent + name: CheckTicketState + type: switch + - action: + actionDataFilter: + useResults: true + functionRef: + arguments: + message: '"Waiting for approvalEvent: \(.)"' + invoke: sync + refName: logInfo + eventRef: approvalEvent + name: WaitForApprovalEvent + onErrors: + - errorRef: timeoutError + transition: + nextState: Escalate + timeouts: + eventTimeout: PT10S + transition: + nextState: CreateK8sNamespace + type: callback + - actionMode: sequential + actions: + - actionDataFilter: + useResults: true + functionRef: + arguments: + message: '"Invoking escalation: \(.)"' + invoke: sync + refName: logInfo + name: printAction + - actionDataFilter: + useResults: true + functionRef: + arguments: + actions: + - title: '"Escalation ticket " + .createResponse.ticketId' + url: .createResponse.browseUrl + message: '"Please manage escalation ticket " + .createResponse.ticketId ' + origin: Escalation Workflow + title: '"ATTN: Escalation for ticket - " + .createResponse.ticketId' + topic: Escalation Workflow + invoke: sync + refName: createNotification + name: createNotification + name: Escalate + onErrors: + - errorRef: notAvailable + transition: + nextState: GetTicket + transition: + nextState: GetTicket + type: operation + - actionMode: sequential + actions: + - actionDataFilter: + toStateData: .createdNamespace + useResults: true + functionRef: + arguments: + apiVersion: v1 + kind: Namespace + metadata: + name: .namespace + invoke: sync + refName: createK8sNamespace + end: + terminate: true + name: CreateK8sNamespace + stateDataFilter: + output: '{createdNamespace: .createdNamespace}' + type: operation + timeouts: + workflowExecTimeout: + duration: PT24H + podTemplate: + container: + resources: {} + image: quay.io/orchestrator/serverless-workflow-escalation:f6fbb19dd531f5bcb612b28862a2303dfae87bd7 + resources: + configMaps: + - configMap: + name: 01-ticketescalation-resources + workflowPath: specs +status: + address: {} + lastTimeRecoverAttempt: null diff --git a/charts/workflows/charts/escalation/templates/02-configmap_ticketescalation-props.yaml b/charts/workflows/charts/escalation/templates/02-configmap_ticketescalation-props.yaml new file mode 100755 index 00000000..84a9959a --- /dev/null +++ b/charts/workflows/charts/escalation/templates/02-configmap_ticketescalation-props.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +data: + application.properties: "# The ID of the Jira issue type to be created (mandatory)\njira_issue_type=${JIRA_ISSUE_TYPE}\n# + The key of the Jira project where the escalation issue is created (mandatory)\njira_project=${JIRA_PROJECT}\n# + The name part of the Jira ticket label that contains the ID of the related SWF + instance (e.g. `workflowInstanceId=123`)\njira_label_workflowInstanceId=${JIRA_WORKFLOW_INSTANCE_ID_LABEL:workflowInstanceId}\n# + The whole Jira ticket label that contains the name of the SWF (e.g. `workflowInstanceId=escalation`)\njira_label_workflowName=${JIRA_WORKFLOW_NAME_LABEL:workflowName=escalation}\n\n# + Jira\nquarkus.rest-client.jira_yaml.url=${JIRA_URL}\nquarkus.openapi-generator.jira_yaml.auth.basicAuth.username=${JIRA_USERNAME}\n# + See https://id.atlassian.com/manage-profile/security/api-tokens\nquarkus.openapi-generator.jira_yaml.auth.basicAuth.password=${JIRA_API_TOKEN}\n\n# + The ISO 8601 duration format to wait before triggering the escalation request, + after the issue has been created\ntimeout_seconds=${ESCALATION_TIMEOUT_SECONDS:PT60S}\n\n# + OpenShift API Server\nquarkus.rest-client.kube_yaml.url=${OCP_API_SERVER_URL}\nquarkus.openapi-generator.kube_yaml.auth.BearerToken.bearer-token=${OCP_API_SERVER_TOKEN}\nquarkus.tls.trust-all=true\nquarkus.kubernetes-client.trust-certs=true\n\n# + Notifications service\nquarkus.rest-client.notifications.url=${BACKSTAGE_NOTIFICATIONS_URL:http://orchestrator-backstage.orchestrator/api/notifications/}\n\n# + This is to enable debugging of HTTP request \nquarkus.log.category.\\\"org.apache.http\\\".level=INFO\n\n# + Knative eventing configuration\nmp.messaging.incoming.kogito_incoming_stream.connector=quarkus-http\nmp.messaging.incoming.kogito_incoming_stream.path=/\nmp.messaging.incoming.kogito_incoming_stream.method=POST" +kind: ConfigMap +metadata: + creationTimestamp: null + labels: + app: ticketescalation + sonataflow.org/workflow-app: ticketescalation + name: ticketescalation-props