Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [TKC-2933] add webhook config #6100

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ openapi-generate-model-testkube:
find ./pkg/api/v1/testkube -name "*update*.go" -type f -exec sed -i '' -e "s/ \*PodRequest/ \*\*PodUpdateRequest/g" {} \;
find ./pkg/api/v1/testkube -name "*update*.go" -type f -exec sed -i '' -e "s/ \*PodResourcesRequest/ \*\*PodResourcesUpdateRequest/g" {} \;
find ./pkg/api/v1/testkube -name "*update*.go" -type f -exec sed -i '' -e "s/ \*ResourceRequest/ \*ResourceUpdateRequest/g" {} \;
find ./pkg/api/v1/testkube -name "*update*.go" -type f -exec sed -i '' -e "s/ \*WebhookTemplateRef/ \*\*WebhookTemplateRef/g" {} \;
find ./pkg/api/v1/testkube -type f -exec sed -i '' -e "s/ Deprecated/ \\n\/\/ Deprecated/g" {} \;
go fmt pkg/api/v1/testkube/*.go

Expand Down
58 changes: 58 additions & 0 deletions api/v1/testkube.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7346,6 +7346,12 @@ components:
example:
- true
- false
config:
$ref: "#/components/schemas/WebhookConfig"
parameters:
$ref: "#/components/schemas/WebhookSchema"
webhookTemplateRef:
$ref: "#/components/schemas/WebhookTemplateRef"

Event:
description: Event data
Expand Down Expand Up @@ -10687,6 +10693,58 @@ components:
description: Namespace is the namespace of resource being referenced
$ref: "#/components/schemas/BoxedString"

WebhookParameterSchema:
type: object
description: parameter definition
properties:
description:
description: description for the property
type: string
required:
description: whether parameter is required
type: boolean
default: false
example:
description: example value for the parameter
type: string
default:
$ref: "#/components/schemas/BoxedString"
pattern:
type: string
description: "regular expression to match"

WebhookSchema:
type: object
description: configuration definition
additionalProperties:
$ref: "#/components/schemas/WebhookParameterSchema"

WebhookConfigValue:
type: object
description: configuration value
properties:
public:
description: public value to use in webhook template
$ref: "#/components/schemas/BoxedString"
private:
description: private value stored in secret to use in webhook template
$ref: "#/components/schemas/SecretRef"

WebhookConfig:
type: object
description: configuration values
additionalProperties:
$ref: "#/components/schemas/WebhookConfigValue"

WebhookTemplateRef:
type: object
properties:
name:
description: webhook template name to use
type: string
required:
- name

#
# Errors
#
Expand Down
3 changes: 2 additions & 1 deletion cmd/api-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ func main() {
// Initialize event handlers
websocketLoader := ws.NewWebsocketLoader()
if !cfg.DisableWebhooks {
eventsEmitter.Loader.Register(webhook.NewWebhookLoader(log.DefaultLogger, webhooksClient, deprecatedClients, deprecatedRepositories, testWorkflowResultsRepository, metrics, &proContext, envs))
eventsEmitter.Loader.Register(webhook.NewWebhookLoader(log.DefaultLogger, webhooksClient, deprecatedClients, deprecatedRepositories,
testWorkflowResultsRepository, secretClient, metrics, &proContext, envs))
}
eventsEmitter.Loader.Register(websocketLoader)
eventsEmitter.Loader.Register(commons.MustCreateSlackLoader(cfg, envs))
Expand Down
157 changes: 157 additions & 0 deletions cmd/kubectl-testkube/commands/webhooks/common.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package webhooks

import (
"encoding/csv"
"errors"
"fmt"
"os"
"strconv"
"strings"

"github.com/spf13/cobra"

"github.com/kubeshop/testkube/internal/common"
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"
Expand Down Expand Up @@ -48,6 +53,39 @@ func NewCreateWebhookOptionsFromFlags(cmd *cobra.Command) (options apiv1.CreateW
}

payloadTemplateReference := cmd.Flag("payload-template-reference").Value.String()
var config map[string]testkube.WebhookConfigValue
configs, err := cmd.Flags().GetStringToString("config")
if err != nil {
return options, err
}

if len(configs) != 0 {
config, err = getWebhookConfig(configs)
if err != nil {
return options, err
}
}

var parameter map[string]testkube.WebhookParameterSchema
parameters, err := cmd.Flags().GetStringToString("parameter")
if err != nil {
return options, err
}

if len(parameters) != 0 {
parameter, err = getWebhookParameters(parameters)
if err != nil {
return options, err
}
}

var webhookTemplateReference *testkube.WebhookTemplateRef
if cmd.Flag("webhook-template-reference").Changed {
webhookTemplateReference = &testkube.WebhookTemplateRef{
Name: cmd.Flag("webhook-template-reference").Value.String(),
}
}

options = apiv1.CreateWebhookOptions{
Name: name,
Namespace: namespace,
Expand All @@ -60,6 +98,9 @@ func NewCreateWebhookOptionsFromFlags(cmd *cobra.Command) (options apiv1.CreateW
Headers: headers,
PayloadTemplateReference: payloadTemplateReference,
Disabled: disabled,
Config: config,
Parameters: parameter,
WebhookTemplateRef: webhookTemplateReference,
}

return options, nil
Expand Down Expand Up @@ -151,5 +192,121 @@ func NewUpdateWebhookOptionsFromFlags(cmd *cobra.Command) (options apiv1.UpdateW
options.Disabled = &disabled
}

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

values, err := getWebhookConfig(configs)
if err != nil {
return options, err
}
options.Config = &values
}

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

values, err := getWebhookParameters(parameters)
if err != nil {
return options, err
}
options.Parameters = &values
}

if cmd.Flag("webhook-template-reference").Changed {
options.WebhookTemplateRef = common.Ptr(&testkube.WebhookTemplateRef{
Name: cmd.Flag("webhook-template-reference").Value.String(),
})
}

return options, nil
}

func getWebhookConfig(configs map[string]string) (map[string]testkube.WebhookConfigValue, error) {
config := map[string]testkube.WebhookConfigValue{}
for key, value := range configs {
switch {
case strings.HasPrefix(value, "public="):
config[key] = testkube.WebhookConfigValue{
Public: &testkube.BoxedString{Value: strings.TrimPrefix(value, "public=")},
}
case strings.HasPrefix(value, "private="):
data := strings.TrimPrefix(value, "private=")
r := csv.NewReader(strings.NewReader(data))
r.Comma = ','
r.LazyQuotes = true
r.TrimLeadingSpace = true

records, err := r.ReadAll()
if err != nil {
return nil, err
}

if len(records) != 1 {
return nil, errors.New("single string expected")
}

if len(records[0]) != 3 {
return nil, errors.New("3 fields expected")
}

config[key] = testkube.WebhookConfigValue{
Private: &testkube.SecretRef{
Namespace: records[0][0],
Name: records[0][1],
Key: records[0][2],
},
}
default:
continue
}
}

return config, nil
}

func getWebhookParameters(parameters map[string]string) (map[string]testkube.WebhookParameterSchema, error) {
parameter := map[string]testkube.WebhookParameterSchema{}
for key, value := range parameters {
r := csv.NewReader(strings.NewReader(value))
r.Comma = ','
r.LazyQuotes = true
r.TrimLeadingSpace = true

records, err := r.ReadAll()
if err != nil {
return nil, err
}

if len(records) != 1 {
return nil, errors.New("single string expected")
}

if len(records[0]) != 5 {
return nil, errors.New("5 fields expected")
}

var required bool
required, err = strconv.ParseBool(records[0][1])
if err != nil {
return nil, err
}

parameter[key] = testkube.WebhookParameterSchema{
Description: records[0][0],
Required: required,
Example: records[0][2],
Default_: &testkube.BoxedString{
Value: records[0][3],
},
Pattern: records[0][4],
}
}

return parameter, nil
}
6 changes: 6 additions & 0 deletions cmd/kubectl-testkube/commands/webhooks/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func NewCreateWebhookCmd() *cobra.Command {
payloadTemplateReference string
update bool
disable bool
config map[string]string
parameters map[string]string
webhookTemplateReference string
)

cmd := &cobra.Command{
Expand Down Expand Up @@ -99,6 +102,9 @@ func NewCreateWebhookCmd() *cobra.Command {
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 (golang template supported): --header Content-Type=application/xml")
cmd.Flags().StringVar(&payloadTemplateReference, "payload-template-reference", "", "reference to payload template to use for the webhook")
cmd.Flags().StringToStringVarP(&config, "config", "", nil, "webhook config variable with csv coluums (public=value or private=namespace,secret,key): --config var1=public=value1 or --config var2=private=ns1,secret1,key1")
cmd.Flags().StringToStringVarP(&parameters, "parameter", "", nil, "webhook parameter variable with csv coluums (description,required,example,default,pattern): --parameter var3=descr,true,12345,0,[0-9]*")
cmd.Flags().StringVar(&webhookTemplateReference, "webhook-template-reference", "", "reference to webhook to use as template for the webhook")
cmd.Flags().BoolVar(&update, "update", false, "update, if webhook already exists")
cmd.Flags().BoolVar(&disable, "disable", false, "disable webhook")
cmd.Flags().MarkDeprecated("enable", "enable webhook is deprecated")
Expand Down
11 changes: 2 additions & 9 deletions cmd/kubectl-testkube/commands/webhooks/get.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package webhooks

import (
"fmt"
"os"
"strings"

Expand Down Expand Up @@ -34,10 +33,7 @@ func NewGetWebhookCmd() *cobra.Command {
ui.ExitOnError("getting webhook: "+name, err)

if crdOnly {
if webhook.PayloadTemplate != "" {
webhook.PayloadTemplate = fmt.Sprintf("%q", webhook.PayloadTemplate)
}

webhook.QuoteTextFields()
common.UIPrintCRD(crd.TemplateWebhook, webhook, &firstEntry)
return
}
Expand All @@ -50,10 +46,7 @@ func NewGetWebhookCmd() *cobra.Command {

if crdOnly {
for _, webhook := range webhooks {
if webhook.PayloadTemplate != "" {
webhook.PayloadTemplate = fmt.Sprintf("%q", webhook.PayloadTemplate)
}

webhook.QuoteTextFields()
common.UIPrintCRD(crd.TemplateWebhook, webhook, &firstEntry)
}

Expand Down
6 changes: 6 additions & 0 deletions cmd/kubectl-testkube/commands/webhooks/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func UpdateWebhookCmd() *cobra.Command {
headers map[string]string
payloadTemplateReference string
disable bool
config map[string]string
parameters map[string]string
webhookTemplateReference string
)

cmd := &cobra.Command{
Expand Down Expand Up @@ -57,6 +60,9 @@ func UpdateWebhookCmd() *cobra.Command {
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 (golang template supported): --header Content-Type=application/xml")
cmd.Flags().StringVar(&payloadTemplateReference, "payload-template-reference", "", "reference to payload template to use for the webhook")
cmd.Flags().StringToStringVarP(&config, "config", "", nil, "webhook config variable with csv coluums (public=value or private=namespace,secret,key): --config var1=public=value1 or --config var2=private=ns1,secret1,key1")
cmd.Flags().StringToStringVarP(&parameters, "parameter", "", nil, "webhook parameter variable with csv coluums (description,required,example,default,pattern): --parameter var3=descr,true,12345,0,[0-9]*")
cmd.Flags().StringVar(&webhookTemplateReference, "webhook-template-reference", "", "reference to webhook to use as template for the webhook")
cmd.Flags().BoolVar(&disable, "disable", false, "disable webhook")
cmd.Flags().MarkDeprecated("enable", "enable webhook is depecated")

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ require (
github.com/keygen-sh/jsonapi-go v1.2.1
github.com/keygen-sh/keygen-go/v3 v3.2.0
github.com/kubepug/kubepug v1.7.1
github.com/kubeshop/testkube-operator v1.17.55-0.20241219143413-6a33aef7130f
github.com/kubeshop/testkube-operator v1.17.55-0.20241220172614-fb95745c73c1
github.com/minio/minio-go/v7 v7.0.66
github.com/montanaflynn/stats v0.7.1
github.com/moogar0880/problems v0.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubepug/kubepug v1.7.1 h1:LKhfSxS8Y5mXs50v+3Lpyec+cogErDLcV7CMUuiaisw=
github.com/kubepug/kubepug v1.7.1/go.mod h1:lv+HxD0oTFL7ZWjj0u6HKhMbbTIId3eG7aWIW0gyF8g=
github.com/kubeshop/testkube-operator v1.17.55-0.20241219143413-6a33aef7130f h1:7wDuGy4MohoFcgz2QPH/02JWCsgBqkWdGgefIH2YSEE=
github.com/kubeshop/testkube-operator v1.17.55-0.20241219143413-6a33aef7130f/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk=
github.com/kubeshop/testkube-operator v1.17.55-0.20241220172614-fb95745c73c1 h1:C1TIQh5zlZG25KlI8RuyaeoehcQE4FKTuw6k5oATbp0=
github.com/kubeshop/testkube-operator v1.17.55-0.20241220172614-fb95745c73c1/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
Expand Down
Loading
Loading