Skip to content

Commit

Permalink
feat: webhook patch (#4272)
Browse files Browse the repository at this point in the history
* feat: webhook patch method

* fix: update webhook cli

* fix: update doc

* fix: golint
  • Loading branch information
vsukhin authored Aug 16, 2023
1 parent 74501d9 commit 9d26103
Show file tree
Hide file tree
Showing 16 changed files with 493 additions and 27 deletions.
61 changes: 59 additions & 2 deletions api/v1/testkube.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2309,7 +2309,7 @@ paths:
description: "Create new webhook based on variables passed in request"
operationId: createWebhook
requestBody:
description: executor request body data
description: webhook request body data
required: true
content:
application/json:
Expand All @@ -2332,7 +2332,7 @@ paths:
schema:
$ref: "#/components/schemas/Webhook"
400:
description: "problem with executor definition - probably some bad input occurs (invalid JSON body or similar)"
description: "problem with webhook definition - probably some bad input occurs (invalid JSON body or similar)"
content:
application/problem+json:
schema:
Expand Down Expand Up @@ -2449,6 +2449,56 @@ paths:
type: array
items:
$ref: "#/components/schemas/Problem"
patch:
parameters:
- $ref: "#/components/parameters/ID"
tags:
- webhook
- api
summary: "Update new webhook"
description: "Update new webhook based on variables passed in request"
operationId: updateWebhook
requestBody:
description: webhook request body data
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/WebhookUpdateRequest"
text/yaml:
schema:
type: string
responses:
200:
description: "successful operation"
content:
application/json:
schema:
$ref: "#/components/schemas/Webhook"
400:
description: "problem with webhook definition - probably some bad input occurs (invalid JSON body or similar)"
content:
application/problem+json:
schema:
type: array
items:
$ref: "#/components/schemas/Problem"
404:
description: "webhook not found"
content:
application/problem+json:
schema:
type: array
items:
$ref: "#/components/schemas/Problem"
502:
description: "problem with communicating with kubernetes cluster"
content:
application/problem+json:
schema:
type: array
items:
$ref: "#/components/schemas/Problem"

/config:
patch:
Expand Down Expand Up @@ -4618,6 +4668,13 @@ components:
allOf:
- $ref: "#/components/schemas/Webhook"

WebhookUpdateRequest:
description: webhook update request body
type: object
nullable: true
allOf:
- $ref: "#/components/schemas/Webhook"

# Copied from CRD spec
# https://github.com/kubeshop/testkube-operator/blob/main/config/crd/bases/executor.testkube.io_executors.yaml
# TODO we need to sync those in some nice way
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubectl-testkube/commands/executors/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/kubeshop/testkube/pkg/ui"
)

// NewUpsertExecutorOptionsFromFlags creates upsert executor options fom command flags
// NewUpsertExecutorOptionsFromFlags creates upsert executor options from command flags
func NewUpsertExecutorOptionsFromFlags(cmd *cobra.Command) (options apiClient.UpsertExecutorOptions, err error) {
name := cmd.Flag("name").Value.String()
types, err := cmd.Flags().GetStringArray("types")
Expand Down
2 changes: 2 additions & 0 deletions cmd/kubectl-testkube/commands/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests"
"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsources"
"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites"
"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/webhooks"
"github.com/kubeshop/testkube/cmd/kubectl-testkube/config"
"github.com/kubeshop/testkube/pkg/ui"
)
Expand All @@ -35,6 +36,7 @@ func NewUpdateCmd() *cobra.Command {
cmd.AddCommand(testsuites.UpdateTestSuitesCmd())
cmd.AddCommand(testsources.UpdateTestSourceCmd())
cmd.AddCommand(executors.UpdateExecutorCmd())
cmd.AddCommand(webhooks.UpdateWebhookCmd())

return cmd
}
135 changes: 135 additions & 0 deletions cmd/kubectl-testkube/commands/webhooks/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package webhooks

import (
"fmt"
"os"

"github.com/spf13/cobra"

apiv1 "github.com/kubeshop/testkube/pkg/api/v1/client"
"github.com/kubeshop/testkube/pkg/api/v1/testkube"
webhooksmapper "github.com/kubeshop/testkube/pkg/mapper/webhooks"
"github.com/kubeshop/testkube/pkg/ui"
)

// NewCreateWebhookOptionsFromFlags creates create webhook options from command flags
func NewCreateWebhookOptionsFromFlags(cmd *cobra.Command) (options apiv1.CreateWebhookOptions, err error) {
name := cmd.Flag("name").Value.String()
namespace := cmd.Flag("namespace").Value.String()
events, err := cmd.Flags().GetStringArray("events")
if err != nil {
return options, err
}

payloadObjectField := cmd.Flag("payload-field").Value.String()
payloadTemplate := cmd.Flag("payload-template").Value.String()
payloadTemplateContent := ""
if payloadTemplate != "" {
b, err := os.ReadFile(payloadTemplate)
ui.ExitOnError("reading payload template", err)
payloadTemplateContent = string(b)
}

uri := cmd.Flag("uri").Value.String()
selector := cmd.Flag("selector").Value.String()
labels, err := cmd.Flags().GetStringToString("label")
if err != nil {
return options, err
}

headers, err := cmd.Flags().GetStringToString("header")
if err != nil {
return options, err
}

options = apiv1.CreateWebhookOptions{
Name: name,
Namespace: namespace,
Events: webhooksmapper.MapStringArrayToCRDEvents(events),
Uri: uri,
Selector: selector,
Labels: labels,
PayloadObjectField: payloadObjectField,
PayloadTemplate: payloadTemplateContent,
Headers: headers,
}

return options, nil
}

// NewUpdateWebhookOptionsFromFlags creates update webhook options from command flags
func NewUpdateWebhookOptionsFromFlags(cmd *cobra.Command) (options apiv1.UpdateWebhookOptions, err error) {
var fields = []struct {
name string
destination **string
}{
{
"name",
&options.Name,
},
{
"uri",
&options.Uri,
},
{
"selector",
&options.Selector,
},
{
"payload-field",
&options.PayloadObjectField,
},
}

for _, field := range fields {
if cmd.Flag(field.name).Changed {
value := cmd.Flag(field.name).Value.String()
*field.destination = &value
}
}

if cmd.Flag("payload-template").Changed {
payloadTemplate := cmd.Flag("payload-template").Value.String()
b, err := os.ReadFile(payloadTemplate)
if err != nil {
return options, fmt.Errorf("reading payload template %w", err)
}

value := string(b)
options.PayloadTemplate = &value
}

if cmd.Flag("events").Changed {
events, err := cmd.Flags().GetStringArray("events")
if err != nil {
return options, err
}

var eventTypes []testkube.EventType
for _, event := range events {
eventTypes = append(eventTypes, testkube.EventType(event))
}

options.Events = &eventTypes
}

if cmd.Flag("label").Changed {
labels, err := cmd.Flags().GetStringToString("label")
if err != nil {
return options, err
}

options.Labels = &labels
}

if cmd.Flag("header").Changed {
headers, err := cmd.Flags().GetStringToString("header")
if err != nil {
return options, err
}

options.Headers = &headers
}

return options, nil
}
25 changes: 3 additions & 22 deletions cmd/kubectl-testkube/commands/webhooks/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ package webhooks

import (
"fmt"
"os"
"strconv"

"github.com/spf13/cobra"

"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common"
apiv1 "github.com/kubeshop/testkube/pkg/api/v1/client"
"github.com/kubeshop/testkube/pkg/crd"
webhooksmapper "github.com/kubeshop/testkube/pkg/mapper/webhooks"
"github.com/kubeshop/testkube/pkg/ui"
)

Expand Down Expand Up @@ -39,14 +37,6 @@ func NewCreateWebhookCmd() *cobra.Command {
}

namespace := cmd.Flag("namespace").Value.String()
payloadTemplate = cmd.Flag("payload-template").Value.String()
payloadTemplateContent := ""
if payloadTemplate != "" {
b, err := os.ReadFile(payloadTemplate)
ui.ExitOnError("reading job template", err)
payloadTemplateContent = string(b)
}

var client apiv1.Client
if !crdOnly {
client, namespace, err = common.GetClient(cmd)
Expand All @@ -58,17 +48,8 @@ func NewCreateWebhookCmd() *cobra.Command {
}
}

options := apiv1.CreateWebhookOptions{
Name: name,
Namespace: namespace,
Events: webhooksmapper.MapStringArrayToCRDEvents(events),
Uri: uri,
Selector: selector,
Labels: labels,
PayloadObjectField: payloadObjectField,
PayloadTemplate: payloadTemplateContent,
Headers: headers,
}
options, err := NewCreateWebhookOptionsFromFlags(cmd)
ui.ExitOnError("getting webhook options", err)

if !crdOnly {
_, err := client.CreateWebhook(options)
Expand All @@ -89,7 +70,7 @@ func NewCreateWebhookCmd() *cobra.Command {
}

cmd.Flags().StringVarP(&name, "name", "n", "", "unique webhook name - mandatory")
cmd.Flags().StringArrayVarP(&events, "events", "e", []string{}, "event types handled by executor e.g. start-test|end-test")
cmd.Flags().StringArrayVarP(&events, "events", "e", []string{}, "event types handled by webhook e.g. start-test|end-test")
cmd.Flags().StringVarP(&uri, "uri", "u", "", "URI which should be called when given event occurs")
cmd.Flags().StringVarP(&selector, "selector", "", "", "expression to select tests and test suites for webhook events: --selector app=backend")
cmd.Flags().StringToStringVarP(&labels, "label", "l", nil, "label key value pair: --label key1=value1")
Expand Down
59 changes: 59 additions & 0 deletions cmd/kubectl-testkube/commands/webhooks/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package webhooks

import (
"github.com/spf13/cobra"

"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common"
"github.com/kubeshop/testkube/pkg/ui"
)

func UpdateWebhookCmd() *cobra.Command {
var (
events []string
name, uri string
selector string
labels map[string]string
payloadObjectField string
payloadTemplate string
headers map[string]string
)

cmd := &cobra.Command{
Use: "webhook",
Aliases: []string{"webhooks", "wh"},
Short: "Update Webhook",
Long: `Update Webhook Custom Resource`,
Run: func(cmd *cobra.Command, args []string) {
if name == "" {
ui.Failf("pass valid name (in '--name' flag)")
}

client, namespace, err := common.GetClient(cmd)
ui.ExitOnError("getting client", err)

webhook, _ := client.GetWebhook(name)
if name != webhook.Name {
ui.Failf("Webhook with name '%s' not exists in namespace %s", name, namespace)
}

options, err := NewUpdateWebhookOptionsFromFlags(cmd)
ui.ExitOnError("getting webhook options", err)

_, err = client.UpdateWebhook(options)
ui.ExitOnError("updating webhook "+name+" in namespace "+namespace, err)

ui.Success("Webhook updated", name)
},
}

cmd.Flags().StringVarP(&name, "name", "n", "", "unique webhook name - mandatory")
cmd.Flags().StringArrayVarP(&events, "events", "e", []string{}, "event types handled by webhook e.g. start-test|end-test")
cmd.Flags().StringVarP(&uri, "uri", "u", "", "URI which should be called when given event occurs")
cmd.Flags().StringVarP(&selector, "selector", "", "", "expression to select tests and test suites for webhook events: --selector app=backend")
cmd.Flags().StringToStringVarP(&labels, "label", "l", nil, "label key value pair: --label key1=value1")
cmd.Flags().StringVarP(&payloadObjectField, "payload-field", "", "", "field to use for notification object payload")
cmd.Flags().StringVarP(&payloadTemplate, "payload-template", "", "", "if webhook needs to send a custom notification, then a path to template file should be provided")
cmd.Flags().StringToStringVarP(&headers, "header", "", nil, "webhook header value pair: --header Content-Type=application/xml")

return cmd
}
2 changes: 1 addition & 1 deletion docs/docs/cli/testkube_create_webhook.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ testkube create webhook [flags]
### Options

```
-e, --events stringArray event types handled by executor e.g. start-test|end-test
-e, --events stringArray event types handled by webhook e.g. start-test|end-test
--header stringToString webhook header value pair: --header Content-Type=application/xml (default [])
-h, --help help for webhook
-l, --label stringToString label key value pair: --label key1=value1 (default [])
Expand Down
1 change: 1 addition & 0 deletions docs/docs/cli/testkube_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ testkube update <resourceName> [flags]
* [testkube update test](testkube_update_test.md) - Update test
* [testkube update testsource](testkube_update_testsource.md) - Update TestSource
* [testkube update testsuite](testkube_update_testsuite.md) - Update Test Suite
* [testkube update webhook](testkube_update_webhook.md) - Update Webhook

Loading

0 comments on commit 9d26103

Please sign in to comment.