From cde69c6509545f373e07045a0e0fc42a3645ccd3 Mon Sep 17 00:00:00 2001 From: Iaroslav Titov Date: Fri, 13 Sep 2024 09:13:27 -0600 Subject: [PATCH] Adding environment webhook support, webhook groups (#406) ### Summary - Adding webhook group support - Adding environment webhook support - I have to build this on top on environment project support PR, so this will need to go in only after [this](https://github.com/pulumi/pulumi-pulumiservice/pull/398) ### Testing - Manual test - Updating example/integ test --------- Co-authored-by: Sean Yeh <109418+seanyeh@users.noreply.github.com> Co-authored-by: Derek --- CHANGELOG_PENDING.md | 2 + examples/examples_nodejs_test.go | 4 + examples/ts-webhooks/index.ts | 46 +++- .../pulumi-resource-pulumiservice/schema.json | 101 ++++++- provider/pkg/internal/pulumiapi/webhooks.go | 74 ++--- .../pkg/internal/pulumiapi/webhooks_test.go | 14 +- provider/pkg/provider/webhook.go | 99 ++++++- provider/pkg/provider/webhook_test.go | 6 +- sdk/dotnet/Enums.cs | 82 ++++++ sdk/dotnet/Webhook.cs | 34 ++- sdk/go/pulumiservice/pulumiEnums.go | 254 ++++++++++++++++++ sdk/go/pulumiservice/webhook.go | 30 ++- .../com/pulumi/pulumiservice/Webhook.java | 33 ++- .../com/pulumi/pulumiservice/WebhookArgs.java | 93 ++++++- .../pulumiservice/enums/WebhookFilters.java | 57 +++- .../pulumiservice/enums/WebhookGroup.java | 46 ++++ sdk/nodejs/types/enums/index.ts | 61 +++++ sdk/nodejs/webhook.ts | 24 +- sdk/python/pulumi_pulumiservice/_enums.py | 60 +++++ sdk/python/pulumi_pulumiservice/webhook.py | 66 ++++- 20 files changed, 1091 insertions(+), 95 deletions(-) create mode 100644 sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookGroup.java diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 5e78e668..96d9e0b5 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,5 +1,7 @@ ### Improvements +- Added support for ESC Webhooks and Webhook Groups [#401](https://github.com/pulumi/pulumi-pulumiservice/issues/409) + ### Bug Fixes ### Miscellaneous diff --git a/examples/examples_nodejs_test.go b/examples/examples_nodejs_test.go index 4957156f..37f8fc66 100644 --- a/examples/examples_nodejs_test.go +++ b/examples/examples_nodejs_test.go @@ -72,8 +72,12 @@ func TestTeamsExample(t *testing.T) { func TestNodejsWebhookExample(t *testing.T) { cwd := getCwd(t) + digits := generateRandomFiveDigits() integration.ProgramTest(t, &integration.ProgramTestOptions{ Dir: path.Join(cwd, ".", "ts-webhooks"), + Config: map[string]string{ + "digits": digits, + }, Dependencies: []string{ "@pulumi/pulumiservice", }, diff --git a/examples/ts-webhooks/index.ts b/examples/ts-webhooks/index.ts index 832358ac..adfc5f15 100644 --- a/examples/ts-webhooks/index.ts +++ b/examples/ts-webhooks/index.ts @@ -1,17 +1,39 @@ import * as pulumi from "@pulumi/pulumi"; -import { Webhook, WebhookFormat, WebhookFilters } from "@pulumi/pulumiservice"; +import * as service from "@pulumi/pulumiservice"; +import { WebhookGroup, WebhookFormat, WebhookFilters } from "@pulumi/pulumiservice"; const serviceOrg = "service-provider-test-org"; +let config = new pulumi.Config(); -const webhook = new Webhook("wh", { +var environment = new service.Environment("environment-to-use", { + organization: serviceOrg, + project: "test-project", + name: "testing-environment-ts-"+config.require("digits"), + yaml: new pulumi.asset.StringAsset( +`values: + myNumber: 1` + ) +}) + +// Organization webhook subscribed to all events +const webhookAllEvents = new service.Webhook("org-webhook-all", { active: true, displayName: "webhook-from-provider", organizationName: serviceOrg, payloadUrl: "https://google.com", - filters: [WebhookFilters.DeploymentStarted, WebhookFilters.DeploymentSucceeded], }); -const stackWebhook = new Webhook("stack-webhook", { +// Organization webhook only subscribed to environments and stacks groups +const webhook = new service.Webhook("org-webhook-groups", { + active: true, + displayName: "webhook-from-provider", + organizationName: serviceOrg, + payloadUrl: "https://google.com", + groups: [ WebhookGroup.Environments, WebhookGroup.Stacks ] +}); + +// Stack webhook subscribed to a group and specific filters +const stackWebhook = new service.Webhook("stack-webhook", { active: true, displayName: "stack-webhook", organizationName: serviceOrg, @@ -19,9 +41,17 @@ const stackWebhook = new Webhook("stack-webhook", { stackName: pulumi.getStack(), payloadUrl: "https://example.com", format: WebhookFormat.Slack, + groups: [ WebhookGroup.Stacks ], + filters: [WebhookFilters.DeploymentStarted, WebhookFilters.DeploymentSucceeded], }) -export const orgName = webhook.organizationName; -export const name = webhook.name; -export const stackWebhookName = stackWebhook.name; -export const stackWebhookProjectName = stackWebhook.projectName; +// Environment webhook subscribed to specific filters only +const environmentWebhook = new service.Webhook("env-webhook", { + active: true, + displayName: "env-webhook", + organizationName: serviceOrg, + projectName: environment.project, + environmentName: environment.name, + payloadUrl: "https://example.com", + filters: [WebhookFilters.EnvironmentRevisionCreated, WebhookFilters.ImportedEnvironmentChanged], +}) diff --git a/provider/cmd/pulumi-resource-pulumiservice/schema.json b/provider/cmd/pulumi-resource-pulumiservice/schema.json index 738a23fa..be85b720 100644 --- a/provider/cmd/pulumi-resource-pulumiservice/schema.json +++ b/provider/cmd/pulumi-resource-pulumiservice/schema.json @@ -73,6 +73,26 @@ } ] }, + "pulumiservice:index:WebhookGroup": { + "type": "string", + "enum": [ + { + "value": "stacks", + "description": "A group of webhooks containing all stack events.", + "name": "Stacks" + }, + { + "value": "deployments", + "description": "A group of webhooks containing all deployment events.", + "name": "Deployments" + }, + { + "value": "environments", + "description": "A group of webhooks containing all environment events.", + "name": "Environments" + } + ] + }, "pulumiservice:index:WebhookFilters": { "type": "string", "enum": [ @@ -170,6 +190,61 @@ "value": "drift_remediation_failed", "description": "Trigger a webhook when a drift remediation run fails.", "name": "DriftRemediationFailed" + }, + { + "value": "environment_created", + "description": "Trigger a webhook when a new environment is created.", + "name": "EnvironmentCreated" + }, + { + "value": "environment_deleted", + "description": "Trigger a webhook when an environment is deleted.", + "name": "EnvironmentDeleted" + }, + { + "value": "environment_revision_created", + "description": "Trigger a webhook when a new revision is created on an environment.", + "name": "EnvironmentRevisionCreated" + }, + { + "value": "environment_revision_retracted", + "description": "Trigger a webhook when a revision is retracted on an environment.", + "name": "EnvironmentRevisionRetracted" + }, + { + "value": "environment_revision_tag_created", + "description": "Trigger a webhook when a revision tag is created on an environment.", + "name": "EnvironmentRevisionTagCreated" + }, + { + "value": "environment_revision_tag_deleted", + "description": "Trigger a webhook when a revision tag is deleted on an environment.", + "name": "EnvironmentRevisionTagDeleted" + }, + { + "value": "environment_revision_tag_updated", + "description": "Trigger a webhook when a revision tag is updated on an environment.", + "name": "EnvironmentRevisionTagUpdated" + }, + { + "value": "environment_tag_created", + "description": "Trigger a webhook when an environment tag is created.", + "name": "EnvironmentTagCreated" + }, + { + "value": "environment_tag_deleted", + "description": "Trigger a webhook when an environment tag is deleted.", + "name": "EnvironmentTagDeleted" + }, + { + "value": "environment_tag_updated", + "description": "Trigger a webhook when an environment tag is updated.", + "name": "EnvironmentTagUpdated" + }, + { + "value": "imported_environment_changed", + "description": "Trigger a webhook when an imported environment has changed.", + "name": "ImportedEnvironmentChanged" } ] }, @@ -857,13 +932,17 @@ "type": "string" }, "projectName": { - "description": "Name of the project. Only specified if this is a stack webhook.", + "description": "Name of the project. Only specified if this is a stack or environment webhook.", "type": "string" }, "stackName": { "description": "Name of the stack. Only specified if this is a stack webhook.", "type": "string" }, + "environmentName": { + "description": "Name of the environment. Only specified if this is an environment webhook.", + "type": "string" + }, "format": { "description": "Format of the webhook payload. Can be either `raw`, `slack`, `ms_teams` or `pulumi_deployments`. Defaults to `raw`.", "$ref": "#/types/pulumiservice:index:WebhookFormat" @@ -874,6 +953,13 @@ "items": { "$ref": "#/types/pulumiservice:index:WebhookFilters" } + }, + "groups": { + "description": "Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information.", + "type": "array", + "items": { + "$ref": "#/types/pulumiservice:index:WebhookGroup" + } } }, "required": [ @@ -907,13 +993,17 @@ "type": "string" }, "projectName": { - "description": "Name of the project. Only needed if this is a stack webhook.", + "description": "Name of the project. Only specified if this is a stack or environment webhook.", "type": "string" }, "stackName": { "description": "Name of the stack. Only needed if this is a stack webhook.", "type": "string" }, + "environmentName": { + "description": "Name of the environment. Only specified if this is an environment webhook.", + "type": "string" + }, "format": { "description": "Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`.", "$ref": "#/types/pulumiservice:index:WebhookFormat", @@ -925,6 +1015,13 @@ "items": { "$ref": "#/types/pulumiservice:index:WebhookFilters" } + }, + "groups": { + "description": "Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information.", + "type": "array", + "items": { + "$ref": "#/types/pulumiservice:index:WebhookGroup" + } } }, "requiredInputs": [ diff --git a/provider/pkg/internal/pulumiapi/webhooks.go b/provider/pkg/internal/pulumiapi/webhooks.go index c4b09493..8813b386 100644 --- a/provider/pkg/internal/pulumiapi/webhooks.go +++ b/provider/pkg/internal/pulumiapi/webhooks.go @@ -23,10 +23,10 @@ import ( type WebhookClient interface { CreateWebhook(ctx context.Context, req WebhookRequest) (*Webhook, error) - ListWebhooks(ctx context.Context, orgName string, projectName, stackName *string) ([]Webhook, error) - GetWebhook(ctx context.Context, orgName string, projectName, stackName *string, webhookName string) (*Webhook, error) + ListWebhooks(ctx context.Context, orgName string, projectName, stackName, environmentName *string) ([]Webhook, error) + GetWebhook(ctx context.Context, orgName string, projectName, stackName, environmentName *string, webhookName string) (*Webhook, error) UpdateWebhook(ctx context.Context, req UpdateWebhookRequest) error - DeleteWebhook(ctx context.Context, orgName string, projectName, stackName *string, name string) error + DeleteWebhook(ctx context.Context, orgName string, projectName, stackName, environmentName *string, name string) error } type Webhook struct { @@ -37,18 +37,21 @@ type Webhook struct { Name string Format string Filters []string + Groups []string } type WebhookRequest struct { OrganizationName string `json:"organizationName"` ProjectName *string `json:"projectName,omitempty"` StackName *string `json:"stackName,omitempty"` + EnvironmentName *string `json:"envName,omitempty"` DisplayName string `json:"displayName"` PayloadURL string `json:"payloadUrl"` Secret *string `json:"secret,omitempty"` Active bool `json:"active"` Format *string `json:"format,omitempty"` Filters []string `json:"filters,omitempty"` + Groups []string `json:"groups,omitempty"` } type UpdateWebhookRequest struct { @@ -57,11 +60,7 @@ type UpdateWebhookRequest struct { } func (c *Client) CreateWebhook(ctx context.Context, req WebhookRequest) (*Webhook, error) { - orgName := req.OrganizationName - projectName := req.ProjectName - stackName := req.StackName - - if len(orgName) == 0 { + if len(req.OrganizationName) == 0 { return nil, errors.New("orgname must not be empty") } @@ -73,12 +72,7 @@ func (c *Client) CreateWebhook(ctx context.Context, req WebhookRequest) (*Webhoo return nil, errors.New("payloadurl must not be empty") } - var apiPath string - if projectName != nil && stackName != nil { - apiPath = path.Join("stacks", orgName, *projectName, *stackName, "hooks") - } else { - apiPath = path.Join("orgs", orgName, "hooks") - } + apiPath := constructApiPath(req.OrganizationName, req.ProjectName, req.StackName, req.EnvironmentName) var webhook Webhook _, err := c.do(ctx, http.MethodPost, apiPath, req, &webhook) @@ -88,17 +82,12 @@ func (c *Client) CreateWebhook(ctx context.Context, req WebhookRequest) (*Webhoo return &webhook, nil } -func (c *Client) ListWebhooks(ctx context.Context, orgName string, projectName, stackName *string) ([]Webhook, error) { +func (c *Client) ListWebhooks(ctx context.Context, orgName string, projectName, stackName, environmentName *string) ([]Webhook, error) { if len(orgName) == 0 { return nil, errors.New("orgName must not be empty") } - var apiPath string - if projectName != nil && stackName != nil { - path.Join("stacks", orgName, *projectName, *stackName, "hooks") - } else { - apiPath = path.Join("orgs", orgName, "hooks") - } + apiPath := constructApiPath(orgName, projectName, stackName, environmentName) var webhooks []Webhook _, err := c.do(ctx, http.MethodGet, apiPath, nil, &webhooks) @@ -110,7 +99,7 @@ func (c *Client) ListWebhooks(ctx context.Context, orgName string, projectName, } func (c *Client) GetWebhook(ctx context.Context, - orgName string, projectName, stackName *string, webhookName string) (*Webhook, error) { + orgName string, projectName, stackName, environmentName *string, webhookName string) (*Webhook, error) { if len(orgName) == 0 { return nil, errors.New("orgname must not be empty") } @@ -119,12 +108,7 @@ func (c *Client) GetWebhook(ctx context.Context, return nil, errors.New("webhookname must not be empty") } - var apiPath string - if projectName != nil && stackName != nil { - apiPath = path.Join("stacks", orgName, *projectName, *stackName, "hooks", webhookName) - } else { - apiPath = path.Join("orgs", orgName, "hooks", webhookName) - } + apiPath := constructApiPath(orgName, projectName, stackName, environmentName) + "/" + webhookName var webhook Webhook _, err := c.do(ctx, http.MethodGet, apiPath, nil, &webhook) @@ -140,15 +124,10 @@ func (c *Client) GetWebhook(ctx context.Context, } func (c *Client) UpdateWebhook(ctx context.Context, req UpdateWebhookRequest) error { - orgName := req.OrganizationName - projectName := req.ProjectName - stackName := req.StackName - name := req.Name - - if len(name) == 0 { + if len(req.Name) == 0 { return errors.New("name must not be empty") } - if len(orgName) == 0 { + if len(req.OrganizationName) == 0 { return errors.New("orgname must not be empty") } if len(req.DisplayName) == 0 { @@ -158,12 +137,7 @@ func (c *Client) UpdateWebhook(ctx context.Context, req UpdateWebhookRequest) er return errors.New("payloadurl must not be empty") } - var apiPath string - if projectName != nil && stackName != nil { - apiPath = path.Join("stacks", orgName, *projectName, *stackName, "hooks", name) - } else { - apiPath = path.Join("orgs", orgName, "hooks", name) - } + apiPath := constructApiPath(req.OrganizationName, req.ProjectName, req.StackName, req.EnvironmentName) + "/" + req.Name _, err := c.do(ctx, http.MethodPatch, apiPath, req, nil) if err != nil { @@ -172,7 +146,7 @@ func (c *Client) UpdateWebhook(ctx context.Context, req UpdateWebhookRequest) er return nil } -func (c *Client) DeleteWebhook(ctx context.Context, orgName string, projectName, stackName *string, name string) error { +func (c *Client) DeleteWebhook(ctx context.Context, orgName string, projectName, stackName, environmentName *string, name string) error { if len(name) == 0 { return errors.New("name must not be empty") } @@ -180,12 +154,7 @@ func (c *Client) DeleteWebhook(ctx context.Context, orgName string, projectName, return errors.New("orgname must not be empty") } - var apiPath string - if projectName != nil && stackName != nil { - apiPath = path.Join("stacks", orgName, *projectName, *stackName, "hooks", name) - } else { - apiPath = path.Join("orgs", orgName, "hooks", name) - } + apiPath := constructApiPath(orgName, projectName, stackName, environmentName) + "/" + name _, err := c.do(ctx, http.MethodDelete, apiPath, nil, nil) if err != nil { @@ -193,3 +162,12 @@ func (c *Client) DeleteWebhook(ctx context.Context, orgName string, projectName, } return nil } + +func constructApiPath(orgName string, projectName, stackName, environmentName *string) string { + if projectName != nil && stackName != nil { + return path.Join("stacks", orgName, *projectName, *stackName, "hooks") + } else if projectName != nil && environmentName != nil { + return path.Join("esc", "environments", orgName, *projectName, *environmentName, "hooks") + } + return path.Join("orgs", orgName, "hooks") +} diff --git a/provider/pkg/internal/pulumiapi/webhooks_test.go b/provider/pkg/internal/pulumiapi/webhooks_test.go index e342bada..cbf5278d 100644 --- a/provider/pkg/internal/pulumiapi/webhooks_test.go +++ b/provider/pkg/internal/pulumiapi/webhooks_test.go @@ -80,7 +80,7 @@ func TestListWebhooks(t *testing.T) { ResponseBody: webhooks, }) defer cleanup() - actualWebhooks, err := c.ListWebhooks(ctx, orgName, nil, nil) + actualWebhooks, err := c.ListWebhooks(ctx, orgName, nil, nil, nil) assert.NoError(t, err) assert.Equal(t, webhooks, actualWebhooks) }) @@ -95,7 +95,7 @@ func TestListWebhooks(t *testing.T) { }, }) defer cleanup() - actualWebhooks, err := c.ListWebhooks(ctx, orgName, nil, nil) + actualWebhooks, err := c.ListWebhooks(ctx, orgName, nil, nil, nil) assert.Nil(t, actualWebhooks, "webhooks should be nil since error was returned") assert.EqualError(t, err, "failed to list webhooks: 401 API error: unauthorized") }) @@ -122,7 +122,7 @@ func TestGetWebhook(t *testing.T) { ResponseBody: webhook, }) defer cleanup() - actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, webhookName) + actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, nil, webhookName) assert.NoError(t, err) assert.Equal(t, webhook, *actualWebhook) }) @@ -137,7 +137,7 @@ func TestGetWebhook(t *testing.T) { }, }) defer cleanup() - actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, webhookName) + actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, nil, webhookName) assert.Nil(t, actualWebhook, "webhooks should be nil since error was returned") assert.EqualError(t, err, "failed to get webhook: 401 API error: unauthorized") }) @@ -153,7 +153,7 @@ func TestGetWebhook(t *testing.T) { }, }) defer cleanup() - actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, webhookName) + actualWebhook, err := c.GetWebhook(ctx, orgName, nil, nil, nil, webhookName) assert.Nil(t, actualWebhook, "webhook should be nil since error was returned") assert.Nil(t, err, "err should be nil since error was returned") }) @@ -221,7 +221,7 @@ func TestDeleteWebhook(t *testing.T) { ResponseCode: 201, }) defer cleanup() - err := c.DeleteWebhook(ctx, orgName, nil, nil, webhookName) + err := c.DeleteWebhook(ctx, orgName, nil, nil, nil, webhookName) assert.NoError(t, err) }) @@ -235,7 +235,7 @@ func TestDeleteWebhook(t *testing.T) { }, }) defer cleanup() - err := c.DeleteWebhook(ctx, orgName, nil, nil, webhookName) + err := c.DeleteWebhook(ctx, orgName, nil, nil, nil, webhookName) assert.EqualError(t, err, "failed to delete webhook: 401 API error: unauthorized") }) } diff --git a/provider/pkg/provider/webhook.go b/provider/pkg/provider/webhook.go index 7f3e7b5c..d364b1ed 100644 --- a/provider/pkg/provider/webhook.go +++ b/provider/pkg/provider/webhook.go @@ -13,6 +13,13 @@ import ( pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" ) +// Not the best to create a second source of truth here, but this will likely not change for years +var defaultWebhookGroups = map[string][]string{ + "organization": {"deployments", "environments", "stacks"}, + "stack": {"deployments", "stacks"}, + "environment": {"environments"}, +} + type PulumiServiceWebhookResource struct { config PulumiServiceConfig client pulumiapi.WebhookClient @@ -26,8 +33,10 @@ type PulumiServiceWebhookInput struct { OrganizationName string ProjectName *string StackName *string + EnvironmentName *string Format *string Filters []string + Groups []string } type PulumiServiceWebhookProperties struct { @@ -52,12 +61,18 @@ func (i *PulumiServiceWebhookInput) ToPropertyMap() resource.PropertyMap { if i.StackName != nil { pm["stackName"] = resource.NewPropertyValue(*i.StackName) } + if i.EnvironmentName != nil { + pm["environmentName"] = resource.NewPropertyValue(*i.EnvironmentName) + } if i.Format != nil { pm["format"] = resource.NewPropertyValue(*i.Format) } if len(i.Filters) > 0 { pm["filters"] = resource.NewPropertyValue(i.Filters) } + if len(i.Groups) > 0 { + pm["groups"] = resource.NewPropertyValue(i.Groups) + } return pm } @@ -100,6 +115,10 @@ func (wh *PulumiServiceWebhookResource) ToPulumiServiceWebhookProperties(propMap stackNameStr := propMap["stackName"].StringValue() props.StackName = &stackNameStr } + if propMap["environmentName"].HasValue() && propMap["environmentName"].IsString() { + environmentNameStr := propMap["environmentName"].StringValue() + props.EnvironmentName = &environmentNameStr + } if propMap["format"].HasValue() && propMap["format"].IsString() { formatStr := propMap["format"].StringValue() props.Format = &formatStr @@ -114,6 +133,16 @@ func (wh *PulumiServiceWebhookResource) ToPulumiServiceWebhookProperties(propMap props.Filters = filters } + if propMap["groups"].HasValue() && propMap["groups"].IsArray() { + groupsInput := propMap["groups"].ArrayValue() + groups := make([]string, len(groupsInput)) + + for i, v := range groupsInput { + groups[i] = getSecretOrStringValue(v) + } + + props.Groups = groups + } if nameVal, ok := propMap["name"]; ok && nameVal.IsString() { props.Name = nameVal.StringValue() @@ -146,19 +175,32 @@ func (wh *PulumiServiceWebhookResource) Check(req *pulumirpc.CheckRequest) (*pul } } - stackWebhookError := "projectName and stackName must both be specified for stack webhooks, or both unspecified for org webhooks" - if !news["projectName"].HasValue() && news["stackName"].HasValue() { + if news["stackName"].HasValue() && !news["projectName"].HasValue() { failures = append(failures, &pulumirpc.CheckFailure{ - Reason: stackWebhookError, + Reason: "projectName and stackName must both be specified for stack webhooks", Property: "projectName", }) } - if news["projectName"].HasValue() && !news["stackName"].HasValue() { + if news["environmentName"].HasValue() && !news["projectName"].HasValue() { failures = append(failures, &pulumirpc.CheckFailure{ - Reason: stackWebhookError, + Reason: "projectName and environmentName must both be specified for environment webhooks", + Property: "projectName", + }) + } + if news["environmentName"].HasValue() && news["stackName"].HasValue() { + failures = append(failures, &pulumirpc.CheckFailure{ + Reason: "stackName needs to be empty if this is meant to be an environment webhook; " + + "environmentName needs to be empty if this is meant to be a stack webhook", Property: "stackName", }) } + if news["projectName"].HasValue() && !news["stackName"].HasValue() && !news["environmentName"].HasValue() { + failures = append(failures, &pulumirpc.CheckFailure{ + Reason: "projectName needs to be empty if this is meant to be an organization webhook; " + + "otherwise provide stackName for stack webhook or environmentName for environment webhook", + Property: "projectName", + }) + } // if the format is not specified, default to raw // this should work automatically because we have set the default in the schema, @@ -168,6 +210,25 @@ func (wh *PulumiServiceWebhookResource) Check(req *pulumirpc.CheckRequest) (*pul news["format"] = resource.NewPropertyValue("raw") } + // if neither filters nor groups are specified, set default groups + if !news["filters"].HasValue() && !news["groups"].HasValue() { + var groups []string + if news["stackName"].HasValue() { + groups = defaultWebhookGroups["stack"] + } else if news["environmentName"].HasValue() { + groups = defaultWebhookGroups["environment"] + } else { + groups = defaultWebhookGroups["organization"] + } + + var groupProps []resource.PropertyValue + for _, group := range groups { + groupProps = append(groupProps, resource.NewStringProperty(group)) + } + + news["groups"] = resource.NewArrayProperty(groupProps) + } + inputNews, err := plugin.MarshalProperties( news, plugin.MarshalOptions{KeepUnknowns: true, SkipNulls: true, KeepSecrets: true}, @@ -222,12 +283,14 @@ func (wh *PulumiServiceWebhookResource) createWebhook(input PulumiServiceWebhook OrganizationName: input.OrganizationName, ProjectName: input.ProjectName, StackName: input.StackName, + EnvironmentName: input.EnvironmentName, DisplayName: input.DisplayName, PayloadURL: input.PayloadUrl, Secret: input.Secret, Active: input.Active, Format: input.Format, Filters: input.Filters, + Groups: input.Groups, } webhook, err := wh.client.CreateWebhook(ctx, req) if err != nil { @@ -238,6 +301,10 @@ func (wh *PulumiServiceWebhookResource) createWebhook(input PulumiServiceWebhook if input.ProjectName != nil && input.StackName != nil { hookID = fmt.Sprintf("%s/%s/%s/%s", input.OrganizationName, *input.ProjectName, *input.StackName, webhook.Name) + } else if input.ProjectName != nil && input.EnvironmentName != nil { + // This is not ideal, but inserting "environment" string to distinguish from stack webhooks + hookID = fmt.Sprintf("%s/environment/%s/%s/%s", input.OrganizationName, *input.ProjectName, *input.EnvironmentName, + webhook.Name) } else { hookID = fmt.Sprintf("%s/%s", input.OrganizationName, webhook.Name) } @@ -279,6 +346,7 @@ func (wh *PulumiServiceWebhookResource) Diff(req *pulumirpc.DiffRequest) (*pulum "organizationName": true, "projectName": true, "stackName": true, + "environmentName": true, } for k, v := range dd { if _, ok := replaceProperties[k]; ok { @@ -322,12 +390,14 @@ func (wh *PulumiServiceWebhookResource) Update(req *pulumirpc.UpdateRequest) (*p OrganizationName: webhookNew.OrganizationName, ProjectName: webhookNew.ProjectName, StackName: webhookNew.StackName, + EnvironmentName: webhookNew.EnvironmentName, DisplayName: webhookNew.DisplayName, PayloadURL: webhookNew.PayloadUrl, Secret: webhookNew.Secret, Active: webhookNew.Active, Format: webhookNew.Format, Filters: webhookNew.Filters, + Groups: webhookNew.Groups, }, Name: webhookNew.Name, } @@ -362,7 +432,7 @@ func (wh *PulumiServiceWebhookResource) deleteWebhook(id string) error { return err } return wh.client.DeleteWebhook(context.Background(), hookID.organizationName, - hookID.projectName, hookID.stackName, hookID.webhookName) + hookID.projectName, hookID.stackName, hookID.environmentName, hookID.webhookName) } func (wh *PulumiServiceWebhookResource) Read(req *pulumirpc.ReadRequest) (*pulumirpc.ReadResponse, error) { @@ -388,9 +458,11 @@ func (wh *PulumiServiceWebhookResource) Read(req *pulumirpc.ReadRequest) (*pulum Secret: webhook.Secret, Format: &webhook.Format, Filters: webhook.Filters, + Groups: webhook.Groups, OrganizationName: hookID.organizationName, ProjectName: hookID.projectName, StackName: hookID.stackName, + EnvironmentName: hookID.environmentName, }, Name: hookID.webhookName, } @@ -424,7 +496,7 @@ func (wh *PulumiServiceWebhookResource) getWebhook(id string) (*pulumiapi.Webhoo return nil, err } webhook, err := wh.client.GetWebhook(context.Background(), - hookID.organizationName, hookID.projectName, hookID.stackName, hookID.webhookName) + hookID.organizationName, hookID.projectName, hookID.stackName, hookID.environmentName, hookID.webhookName) if err != nil { return nil, err } @@ -432,7 +504,10 @@ func (wh *PulumiServiceWebhookResource) getWebhook(id string) (*pulumiapi.Webhoo } func splitWebhookID(id string) (*webhookID, error) { - // format: organization/project/stack/webhookName (stack webhook) or organization/webhookName (org webhook) + // format: + // organization/project/stack/webhookName (stack webhook) + // organization/webhookName (org webhook) + // organization/environment/projectName/environmentName/webhookName (environment webhook) s := strings.Split(id, "/") switch len(s) { case 2: @@ -447,6 +522,13 @@ func splitWebhookID(id string) (*webhookID, error) { stackName: &s[2], webhookName: s[3], }, nil + case 5: + return &webhookID{ + organizationName: s[0], + projectName: &s[2], + environmentName: &s[3], + webhookName: s[4], + }, nil default: return nil, fmt.Errorf("%q is not a valid webhook ID", id) } @@ -456,5 +538,6 @@ type webhookID struct { organizationName string projectName *string stackName *string + environmentName *string webhookName string } diff --git a/provider/pkg/provider/webhook_test.go b/provider/pkg/provider/webhook_test.go index 2923724e..da7620f9 100644 --- a/provider/pkg/provider/webhook_test.go +++ b/provider/pkg/provider/webhook_test.go @@ -15,7 +15,7 @@ type WebhookClientMock struct { getWebhookFunc getWebhookFunc } -func (c *WebhookClientMock) GetWebhook(ctx context.Context, orgName string, projectName, stackName *string, webhookName string) (*pulumiapi.Webhook, error) { +func (c *WebhookClientMock) GetWebhook(ctx context.Context, orgName string, projectName, stackName, environmentName *string, webhookName string) (*pulumiapi.Webhook, error) { return c.getWebhookFunc() } @@ -23,7 +23,7 @@ func (c *WebhookClientMock) CreateWebhook(ctx context.Context, req pulumiapi.Web return nil, nil } -func (c *WebhookClientMock) ListWebhooks(ctx context.Context, orgName string, projectName, stackName *string) ([]pulumiapi.Webhook, error) { +func (c *WebhookClientMock) ListWebhooks(ctx context.Context, orgName string, projectName, stackName, environmentName *string) ([]pulumiapi.Webhook, error) { return nil, nil } @@ -31,7 +31,7 @@ func (c *WebhookClientMock) UpdateWebhook(ctx context.Context, req pulumiapi.Upd return nil } -func (c *WebhookClientMock) DeleteWebhook(ctx context.Context, orgName string, projectName, stackName *string, name string) error { +func (c *WebhookClientMock) DeleteWebhook(ctx context.Context, orgName string, projectName, stackName, environmentName *string, name string) error { return nil } diff --git a/sdk/dotnet/Enums.cs b/sdk/dotnet/Enums.cs index 2e3062a1..61c87775 100644 --- a/sdk/dotnet/Enums.cs +++ b/sdk/dotnet/Enums.cs @@ -219,6 +219,50 @@ private WebhookFilters(string value) /// Trigger a webhook when a drift remediation run fails. /// public static WebhookFilters DriftRemediationFailed { get; } = new WebhookFilters("drift_remediation_failed"); + /// + /// Trigger a webhook when a new environment is created. + /// + public static WebhookFilters EnvironmentCreated { get; } = new WebhookFilters("environment_created"); + /// + /// Trigger a webhook when an environment is deleted. + /// + public static WebhookFilters EnvironmentDeleted { get; } = new WebhookFilters("environment_deleted"); + /// + /// Trigger a webhook when a new revision is created on an environment. + /// + public static WebhookFilters EnvironmentRevisionCreated { get; } = new WebhookFilters("environment_revision_created"); + /// + /// Trigger a webhook when a revision is retracted on an environment. + /// + public static WebhookFilters EnvironmentRevisionRetracted { get; } = new WebhookFilters("environment_revision_retracted"); + /// + /// Trigger a webhook when a revision tag is created on an environment. + /// + public static WebhookFilters EnvironmentRevisionTagCreated { get; } = new WebhookFilters("environment_revision_tag_created"); + /// + /// Trigger a webhook when a revision tag is deleted on an environment. + /// + public static WebhookFilters EnvironmentRevisionTagDeleted { get; } = new WebhookFilters("environment_revision_tag_deleted"); + /// + /// Trigger a webhook when a revision tag is updated on an environment. + /// + public static WebhookFilters EnvironmentRevisionTagUpdated { get; } = new WebhookFilters("environment_revision_tag_updated"); + /// + /// Trigger a webhook when an environment tag is created. + /// + public static WebhookFilters EnvironmentTagCreated { get; } = new WebhookFilters("environment_tag_created"); + /// + /// Trigger a webhook when an environment tag is deleted. + /// + public static WebhookFilters EnvironmentTagDeleted { get; } = new WebhookFilters("environment_tag_deleted"); + /// + /// Trigger a webhook when an environment tag is updated. + /// + public static WebhookFilters EnvironmentTagUpdated { get; } = new WebhookFilters("environment_tag_updated"); + /// + /// Trigger a webhook when an imported environment has changed. + /// + public static WebhookFilters ImportedEnvironmentChanged { get; } = new WebhookFilters("imported_environment_changed"); public static bool operator ==(WebhookFilters left, WebhookFilters right) => left.Equals(right); public static bool operator !=(WebhookFilters left, WebhookFilters right) => !left.Equals(right); @@ -276,4 +320,42 @@ private WebhookFormat(string value) public override string ToString() => _value; } + + [EnumType] + public readonly struct WebhookGroup : IEquatable + { + private readonly string _value; + + private WebhookGroup(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + /// + /// A group of webhooks containing all stack events. + /// + public static WebhookGroup Stacks { get; } = new WebhookGroup("stacks"); + /// + /// A group of webhooks containing all deployment events. + /// + public static WebhookGroup Deployments { get; } = new WebhookGroup("deployments"); + /// + /// A group of webhooks containing all environment events. + /// + public static WebhookGroup Environments { get; } = new WebhookGroup("environments"); + + public static bool operator ==(WebhookGroup left, WebhookGroup right) => left.Equals(right); + public static bool operator !=(WebhookGroup left, WebhookGroup right) => !left.Equals(right); + + public static explicit operator string(WebhookGroup value) => value._value; + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) => obj is WebhookGroup other && Equals(other); + public bool Equals(WebhookGroup other) => string.Equals(_value, other._value, StringComparison.Ordinal); + + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + + public override string ToString() => _value; + } } diff --git a/sdk/dotnet/Webhook.cs b/sdk/dotnet/Webhook.cs index a53b164c..35ae0bbf 100644 --- a/sdk/dotnet/Webhook.cs +++ b/sdk/dotnet/Webhook.cs @@ -35,6 +35,12 @@ public partial class Webhook : global::Pulumi.CustomResource [Output("displayName")] public Output DisplayName { get; private set; } = null!; + /// + /// Name of the environment. Only specified if this is an environment webhook. + /// + [Output("environmentName")] + public Output EnvironmentName { get; private set; } = null!; + /// /// Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. /// @@ -47,6 +53,12 @@ public partial class Webhook : global::Pulumi.CustomResource [Output("format")] public Output Format { get; private set; } = null!; + /// + /// Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + /// + [Output("groups")] + public Output> Groups { get; private set; } = null!; + /// /// Webhook identifier generated by Pulumi Cloud. /// @@ -66,7 +78,7 @@ public partial class Webhook : global::Pulumi.CustomResource public Output PayloadUrl { get; private set; } = null!; /// - /// Name of the project. Only specified if this is a stack webhook. + /// Name of the project. Only specified if this is a stack or environment webhook. /// [Output("projectName")] public Output ProjectName { get; private set; } = null!; @@ -144,6 +156,12 @@ public sealed class WebhookArgs : global::Pulumi.ResourceArgs [Input("displayName", required: true)] public Input DisplayName { get; set; } = null!; + /// + /// Name of the environment. Only specified if this is an environment webhook. + /// + [Input("environmentName")] + public Input? EnvironmentName { get; set; } + [Input("filters")] private InputList? _filters; @@ -162,6 +180,18 @@ public InputList Filters [Input("format")] public Input? Format { get; set; } + [Input("groups")] + private InputList? _groups; + + /// + /// Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + /// + public InputList Groups + { + get => _groups ?? (_groups = new InputList()); + set => _groups = value; + } + /// /// Name of the organization. /// @@ -175,7 +205,7 @@ public InputList Filters public Input PayloadUrl { get; set; } = null!; /// - /// Name of the project. Only needed if this is a stack webhook. + /// Name of the project. Only specified if this is a stack or environment webhook. /// [Input("projectName")] public Input? ProjectName { get; set; } diff --git a/sdk/go/pulumiservice/pulumiEnums.go b/sdk/go/pulumiservice/pulumiEnums.go index 6a4f532f..d39a3ad8 100644 --- a/sdk/go/pulumiservice/pulumiEnums.go +++ b/sdk/go/pulumiservice/pulumiEnums.go @@ -411,6 +411,28 @@ const ( WebhookFiltersDriftRemediationSucceeded = WebhookFilters("drift_remediation_succeeded") // Trigger a webhook when a drift remediation run fails. WebhookFiltersDriftRemediationFailed = WebhookFilters("drift_remediation_failed") + // Trigger a webhook when a new environment is created. + WebhookFiltersEnvironmentCreated = WebhookFilters("environment_created") + // Trigger a webhook when an environment is deleted. + WebhookFiltersEnvironmentDeleted = WebhookFilters("environment_deleted") + // Trigger a webhook when a new revision is created on an environment. + WebhookFiltersEnvironmentRevisionCreated = WebhookFilters("environment_revision_created") + // Trigger a webhook when a revision is retracted on an environment. + WebhookFiltersEnvironmentRevisionRetracted = WebhookFilters("environment_revision_retracted") + // Trigger a webhook when a revision tag is created on an environment. + WebhookFiltersEnvironmentRevisionTagCreated = WebhookFilters("environment_revision_tag_created") + // Trigger a webhook when a revision tag is deleted on an environment. + WebhookFiltersEnvironmentRevisionTagDeleted = WebhookFilters("environment_revision_tag_deleted") + // Trigger a webhook when a revision tag is updated on an environment. + WebhookFiltersEnvironmentRevisionTagUpdated = WebhookFilters("environment_revision_tag_updated") + // Trigger a webhook when an environment tag is created. + WebhookFiltersEnvironmentTagCreated = WebhookFilters("environment_tag_created") + // Trigger a webhook when an environment tag is deleted. + WebhookFiltersEnvironmentTagDeleted = WebhookFilters("environment_tag_deleted") + // Trigger a webhook when an environment tag is updated. + WebhookFiltersEnvironmentTagUpdated = WebhookFilters("environment_tag_updated") + // Trigger a webhook when an imported environment has changed. + WebhookFiltersImportedEnvironmentChanged = WebhookFilters("imported_environment_changed") ) func (WebhookFilters) ElementType() reflect.Type { @@ -554,6 +576,17 @@ func (o WebhookFiltersPtrOutput) ToStringPtrOutputWithContext(ctx context.Contex // WebhookFiltersDriftDetectionFailed // WebhookFiltersDriftRemediationSucceeded // WebhookFiltersDriftRemediationFailed +// WebhookFiltersEnvironmentCreated +// WebhookFiltersEnvironmentDeleted +// WebhookFiltersEnvironmentRevisionCreated +// WebhookFiltersEnvironmentRevisionRetracted +// WebhookFiltersEnvironmentRevisionTagCreated +// WebhookFiltersEnvironmentRevisionTagDeleted +// WebhookFiltersEnvironmentRevisionTagUpdated +// WebhookFiltersEnvironmentTagCreated +// WebhookFiltersEnvironmentTagDeleted +// WebhookFiltersEnvironmentTagUpdated +// WebhookFiltersImportedEnvironmentChanged type WebhookFiltersInput interface { pulumi.Input @@ -806,6 +839,221 @@ func (in *webhookFormatPtr) ToWebhookFormatPtrOutputWithContext(ctx context.Cont return pulumi.ToOutputWithContext(ctx, in).(WebhookFormatPtrOutput) } +type WebhookGroup string + +const ( + // A group of webhooks containing all stack events. + WebhookGroupStacks = WebhookGroup("stacks") + // A group of webhooks containing all deployment events. + WebhookGroupDeployments = WebhookGroup("deployments") + // A group of webhooks containing all environment events. + WebhookGroupEnvironments = WebhookGroup("environments") +) + +func (WebhookGroup) ElementType() reflect.Type { + return reflect.TypeOf((*WebhookGroup)(nil)).Elem() +} + +func (e WebhookGroup) ToWebhookGroupOutput() WebhookGroupOutput { + return pulumi.ToOutput(e).(WebhookGroupOutput) +} + +func (e WebhookGroup) ToWebhookGroupOutputWithContext(ctx context.Context) WebhookGroupOutput { + return pulumi.ToOutputWithContext(ctx, e).(WebhookGroupOutput) +} + +func (e WebhookGroup) ToWebhookGroupPtrOutput() WebhookGroupPtrOutput { + return e.ToWebhookGroupPtrOutputWithContext(context.Background()) +} + +func (e WebhookGroup) ToWebhookGroupPtrOutputWithContext(ctx context.Context) WebhookGroupPtrOutput { + return WebhookGroup(e).ToWebhookGroupOutputWithContext(ctx).ToWebhookGroupPtrOutputWithContext(ctx) +} + +func (e WebhookGroup) ToStringOutput() pulumi.StringOutput { + return pulumi.ToOutput(pulumi.String(e)).(pulumi.StringOutput) +} + +func (e WebhookGroup) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput { + return pulumi.ToOutputWithContext(ctx, pulumi.String(e)).(pulumi.StringOutput) +} + +func (e WebhookGroup) ToStringPtrOutput() pulumi.StringPtrOutput { + return pulumi.String(e).ToStringPtrOutputWithContext(context.Background()) +} + +func (e WebhookGroup) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput { + return pulumi.String(e).ToStringOutputWithContext(ctx).ToStringPtrOutputWithContext(ctx) +} + +type WebhookGroupOutput struct{ *pulumi.OutputState } + +func (WebhookGroupOutput) ElementType() reflect.Type { + return reflect.TypeOf((*WebhookGroup)(nil)).Elem() +} + +func (o WebhookGroupOutput) ToWebhookGroupOutput() WebhookGroupOutput { + return o +} + +func (o WebhookGroupOutput) ToWebhookGroupOutputWithContext(ctx context.Context) WebhookGroupOutput { + return o +} + +func (o WebhookGroupOutput) ToWebhookGroupPtrOutput() WebhookGroupPtrOutput { + return o.ToWebhookGroupPtrOutputWithContext(context.Background()) +} + +func (o WebhookGroupOutput) ToWebhookGroupPtrOutputWithContext(ctx context.Context) WebhookGroupPtrOutput { + return o.ApplyTWithContext(ctx, func(_ context.Context, v WebhookGroup) *WebhookGroup { + return &v + }).(WebhookGroupPtrOutput) +} + +func (o WebhookGroupOutput) ToStringOutput() pulumi.StringOutput { + return o.ToStringOutputWithContext(context.Background()) +} + +func (o WebhookGroupOutput) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput { + return o.ApplyTWithContext(ctx, func(_ context.Context, e WebhookGroup) string { + return string(e) + }).(pulumi.StringOutput) +} + +func (o WebhookGroupOutput) ToStringPtrOutput() pulumi.StringPtrOutput { + return o.ToStringPtrOutputWithContext(context.Background()) +} + +func (o WebhookGroupOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput { + return o.ApplyTWithContext(ctx, func(_ context.Context, e WebhookGroup) *string { + v := string(e) + return &v + }).(pulumi.StringPtrOutput) +} + +type WebhookGroupPtrOutput struct{ *pulumi.OutputState } + +func (WebhookGroupPtrOutput) ElementType() reflect.Type { + return reflect.TypeOf((**WebhookGroup)(nil)).Elem() +} + +func (o WebhookGroupPtrOutput) ToWebhookGroupPtrOutput() WebhookGroupPtrOutput { + return o +} + +func (o WebhookGroupPtrOutput) ToWebhookGroupPtrOutputWithContext(ctx context.Context) WebhookGroupPtrOutput { + return o +} + +func (o WebhookGroupPtrOutput) Elem() WebhookGroupOutput { + return o.ApplyT(func(v *WebhookGroup) WebhookGroup { + if v != nil { + return *v + } + var ret WebhookGroup + return ret + }).(WebhookGroupOutput) +} + +func (o WebhookGroupPtrOutput) ToStringPtrOutput() pulumi.StringPtrOutput { + return o.ToStringPtrOutputWithContext(context.Background()) +} + +func (o WebhookGroupPtrOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput { + return o.ApplyTWithContext(ctx, func(_ context.Context, e *WebhookGroup) *string { + if e == nil { + return nil + } + v := string(*e) + return &v + }).(pulumi.StringPtrOutput) +} + +// WebhookGroupInput is an input type that accepts values of the WebhookGroup enum +// A concrete instance of `WebhookGroupInput` can be one of the following: +// +// WebhookGroupStacks +// WebhookGroupDeployments +// WebhookGroupEnvironments +type WebhookGroupInput interface { + pulumi.Input + + ToWebhookGroupOutput() WebhookGroupOutput + ToWebhookGroupOutputWithContext(context.Context) WebhookGroupOutput +} + +var webhookGroupPtrType = reflect.TypeOf((**WebhookGroup)(nil)).Elem() + +type WebhookGroupPtrInput interface { + pulumi.Input + + ToWebhookGroupPtrOutput() WebhookGroupPtrOutput + ToWebhookGroupPtrOutputWithContext(context.Context) WebhookGroupPtrOutput +} + +type webhookGroupPtr string + +func WebhookGroupPtr(v string) WebhookGroupPtrInput { + return (*webhookGroupPtr)(&v) +} + +func (*webhookGroupPtr) ElementType() reflect.Type { + return webhookGroupPtrType +} + +func (in *webhookGroupPtr) ToWebhookGroupPtrOutput() WebhookGroupPtrOutput { + return pulumi.ToOutput(in).(WebhookGroupPtrOutput) +} + +func (in *webhookGroupPtr) ToWebhookGroupPtrOutputWithContext(ctx context.Context) WebhookGroupPtrOutput { + return pulumi.ToOutputWithContext(ctx, in).(WebhookGroupPtrOutput) +} + +// WebhookGroupArrayInput is an input type that accepts WebhookGroupArray and WebhookGroupArrayOutput values. +// You can construct a concrete instance of `WebhookGroupArrayInput` via: +// +// WebhookGroupArray{ WebhookGroupArgs{...} } +type WebhookGroupArrayInput interface { + pulumi.Input + + ToWebhookGroupArrayOutput() WebhookGroupArrayOutput + ToWebhookGroupArrayOutputWithContext(context.Context) WebhookGroupArrayOutput +} + +type WebhookGroupArray []WebhookGroup + +func (WebhookGroupArray) ElementType() reflect.Type { + return reflect.TypeOf((*[]WebhookGroup)(nil)).Elem() +} + +func (i WebhookGroupArray) ToWebhookGroupArrayOutput() WebhookGroupArrayOutput { + return i.ToWebhookGroupArrayOutputWithContext(context.Background()) +} + +func (i WebhookGroupArray) ToWebhookGroupArrayOutputWithContext(ctx context.Context) WebhookGroupArrayOutput { + return pulumi.ToOutputWithContext(ctx, i).(WebhookGroupArrayOutput) +} + +type WebhookGroupArrayOutput struct{ *pulumi.OutputState } + +func (WebhookGroupArrayOutput) ElementType() reflect.Type { + return reflect.TypeOf((*[]WebhookGroup)(nil)).Elem() +} + +func (o WebhookGroupArrayOutput) ToWebhookGroupArrayOutput() WebhookGroupArrayOutput { + return o +} + +func (o WebhookGroupArrayOutput) ToWebhookGroupArrayOutputWithContext(ctx context.Context) WebhookGroupArrayOutput { + return o +} + +func (o WebhookGroupArrayOutput) Index(i pulumi.IntInput) WebhookGroupOutput { + return pulumi.All(o, i).ApplyT(func(vs []interface{}) WebhookGroup { + return vs[0].([]WebhookGroup)[vs[1].(int)] + }).(WebhookGroupOutput) +} + func init() { pulumi.RegisterInputType(reflect.TypeOf((*EnvironmentPermissionInput)(nil)).Elem(), EnvironmentPermission("none")) pulumi.RegisterInputType(reflect.TypeOf((*EnvironmentPermissionPtrInput)(nil)).Elem(), EnvironmentPermission("none")) @@ -816,6 +1064,9 @@ func init() { pulumi.RegisterInputType(reflect.TypeOf((*WebhookFiltersArrayInput)(nil)).Elem(), WebhookFiltersArray{}) pulumi.RegisterInputType(reflect.TypeOf((*WebhookFormatInput)(nil)).Elem(), WebhookFormat("raw")) pulumi.RegisterInputType(reflect.TypeOf((*WebhookFormatPtrInput)(nil)).Elem(), WebhookFormat("raw")) + pulumi.RegisterInputType(reflect.TypeOf((*WebhookGroupInput)(nil)).Elem(), WebhookGroup("stacks")) + pulumi.RegisterInputType(reflect.TypeOf((*WebhookGroupPtrInput)(nil)).Elem(), WebhookGroup("stacks")) + pulumi.RegisterInputType(reflect.TypeOf((*WebhookGroupArrayInput)(nil)).Elem(), WebhookGroupArray{}) pulumi.RegisterOutputType(EnvironmentPermissionOutput{}) pulumi.RegisterOutputType(EnvironmentPermissionPtrOutput{}) pulumi.RegisterOutputType(PulumiOperationOutput{}) @@ -825,4 +1076,7 @@ func init() { pulumi.RegisterOutputType(WebhookFiltersArrayOutput{}) pulumi.RegisterOutputType(WebhookFormatOutput{}) pulumi.RegisterOutputType(WebhookFormatPtrOutput{}) + pulumi.RegisterOutputType(WebhookGroupOutput{}) + pulumi.RegisterOutputType(WebhookGroupPtrOutput{}) + pulumi.RegisterOutputType(WebhookGroupArrayOutput{}) } diff --git a/sdk/go/pulumiservice/webhook.go b/sdk/go/pulumiservice/webhook.go index 272fce8b..cad3ed4a 100644 --- a/sdk/go/pulumiservice/webhook.go +++ b/sdk/go/pulumiservice/webhook.go @@ -30,17 +30,21 @@ type Webhook struct { Active pulumi.BoolOutput `pulumi:"active"` // The friendly name displayed in the Pulumi Cloud. DisplayName pulumi.StringOutput `pulumi:"displayName"` + // Name of the environment. Only specified if this is an environment webhook. + EnvironmentName pulumi.StringPtrOutput `pulumi:"environmentName"` // Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. Filters WebhookFiltersArrayOutput `pulumi:"filters"` // Format of the webhook payload. Can be either `raw`, `slack`, `ms_teams` or `pulumi_deployments`. Defaults to `raw`. Format WebhookFormatOutput `pulumi:"format"` + // Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + Groups WebhookGroupArrayOutput `pulumi:"groups"` // Webhook identifier generated by Pulumi Cloud. Name pulumi.StringOutput `pulumi:"name"` // Name of the organization. OrganizationName pulumi.StringOutput `pulumi:"organizationName"` // URL to send request to. PayloadUrl pulumi.StringOutput `pulumi:"payloadUrl"` - // Name of the project. Only specified if this is a stack webhook. + // Name of the project. Only specified if this is a stack or environment webhook. ProjectName pulumi.StringPtrOutput `pulumi:"projectName"` // Optional. secret used as the HMAC key. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#headers) for more information. Secret pulumi.StringPtrOutput `pulumi:"secret"` @@ -114,15 +118,19 @@ type webhookArgs struct { Active bool `pulumi:"active"` // The friendly name displayed in the Pulumi Cloud. DisplayName string `pulumi:"displayName"` + // Name of the environment. Only specified if this is an environment webhook. + EnvironmentName *string `pulumi:"environmentName"` // Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. Filters []WebhookFilters `pulumi:"filters"` // Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`. Format *WebhookFormat `pulumi:"format"` + // Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + Groups []WebhookGroup `pulumi:"groups"` // Name of the organization. OrganizationName string `pulumi:"organizationName"` // URL to send request to. PayloadUrl string `pulumi:"payloadUrl"` - // Name of the project. Only needed if this is a stack webhook. + // Name of the project. Only specified if this is a stack or environment webhook. ProjectName *string `pulumi:"projectName"` // Optional. secret used as the HMAC key. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#headers) for more information. Secret *string `pulumi:"secret"` @@ -136,15 +144,19 @@ type WebhookArgs struct { Active pulumi.BoolInput // The friendly name displayed in the Pulumi Cloud. DisplayName pulumi.StringInput + // Name of the environment. Only specified if this is an environment webhook. + EnvironmentName pulumi.StringPtrInput // Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. Filters WebhookFiltersArrayInput // Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`. Format WebhookFormatPtrInput + // Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + Groups WebhookGroupArrayInput // Name of the organization. OrganizationName pulumi.StringInput // URL to send request to. PayloadUrl pulumi.StringInput - // Name of the project. Only needed if this is a stack webhook. + // Name of the project. Only specified if this is a stack or environment webhook. ProjectName pulumi.StringPtrInput // Optional. secret used as the HMAC key. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#headers) for more information. Secret pulumi.StringPtrInput @@ -249,6 +261,11 @@ func (o WebhookOutput) DisplayName() pulumi.StringOutput { return o.ApplyT(func(v *Webhook) pulumi.StringOutput { return v.DisplayName }).(pulumi.StringOutput) } +// Name of the environment. Only specified if this is an environment webhook. +func (o WebhookOutput) EnvironmentName() pulumi.StringPtrOutput { + return o.ApplyT(func(v *Webhook) pulumi.StringPtrOutput { return v.EnvironmentName }).(pulumi.StringPtrOutput) +} + // Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. func (o WebhookOutput) Filters() WebhookFiltersArrayOutput { return o.ApplyT(func(v *Webhook) WebhookFiltersArrayOutput { return v.Filters }).(WebhookFiltersArrayOutput) @@ -259,6 +276,11 @@ func (o WebhookOutput) Format() WebhookFormatOutput { return o.ApplyT(func(v *Webhook) WebhookFormatOutput { return v.Format }).(WebhookFormatOutput) } +// Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. +func (o WebhookOutput) Groups() WebhookGroupArrayOutput { + return o.ApplyT(func(v *Webhook) WebhookGroupArrayOutput { return v.Groups }).(WebhookGroupArrayOutput) +} + // Webhook identifier generated by Pulumi Cloud. func (o WebhookOutput) Name() pulumi.StringOutput { return o.ApplyT(func(v *Webhook) pulumi.StringOutput { return v.Name }).(pulumi.StringOutput) @@ -274,7 +296,7 @@ func (o WebhookOutput) PayloadUrl() pulumi.StringOutput { return o.ApplyT(func(v *Webhook) pulumi.StringOutput { return v.PayloadUrl }).(pulumi.StringOutput) } -// Name of the project. Only specified if this is a stack webhook. +// Name of the project. Only specified if this is a stack or environment webhook. func (o WebhookOutput) ProjectName() pulumi.StringPtrOutput { return o.ApplyT(func(v *Webhook) pulumi.StringPtrOutput { return v.ProjectName }).(pulumi.StringPtrOutput) } diff --git a/sdk/java/src/main/java/com/pulumi/pulumiservice/Webhook.java b/sdk/java/src/main/java/com/pulumi/pulumiservice/Webhook.java index e0a9ad3d..c00c1527 100644 --- a/sdk/java/src/main/java/com/pulumi/pulumiservice/Webhook.java +++ b/sdk/java/src/main/java/com/pulumi/pulumiservice/Webhook.java @@ -11,6 +11,7 @@ import com.pulumi.pulumiservice.WebhookArgs; import com.pulumi.pulumiservice.enums.WebhookFilters; import com.pulumi.pulumiservice.enums.WebhookFormat; +import com.pulumi.pulumiservice.enums.WebhookGroup; import java.lang.Boolean; import java.lang.String; import java.util.List; @@ -59,6 +60,20 @@ public Output active() { public Output displayName() { return this.displayName; } + /** + * Name of the environment. Only specified if this is an environment webhook. + * + */ + @Export(name="environmentName", refs={String.class}, tree="[0]") + private Output environmentName; + + /** + * @return Name of the environment. Only specified if this is an environment webhook. + * + */ + public Output> environmentName() { + return Codegen.optional(this.environmentName); + } /** * Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. * @@ -87,6 +102,20 @@ public Output>> filters() { public Output format() { return this.format; } + /** + * Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + */ + @Export(name="groups", refs={List.class,WebhookGroup.class}, tree="[0,1]") + private Output> groups; + + /** + * @return Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + */ + public Output>> groups() { + return Codegen.optional(this.groups); + } /** * Webhook identifier generated by Pulumi Cloud. * @@ -130,14 +159,14 @@ public Output payloadUrl() { return this.payloadUrl; } /** - * Name of the project. Only specified if this is a stack webhook. + * Name of the project. Only specified if this is a stack or environment webhook. * */ @Export(name="projectName", refs={String.class}, tree="[0]") private Output projectName; /** - * @return Name of the project. Only specified if this is a stack webhook. + * @return Name of the project. Only specified if this is a stack or environment webhook. * */ public Output> projectName() { diff --git a/sdk/java/src/main/java/com/pulumi/pulumiservice/WebhookArgs.java b/sdk/java/src/main/java/com/pulumi/pulumiservice/WebhookArgs.java index 1f6d30f5..53669e7c 100644 --- a/sdk/java/src/main/java/com/pulumi/pulumiservice/WebhookArgs.java +++ b/sdk/java/src/main/java/com/pulumi/pulumiservice/WebhookArgs.java @@ -9,6 +9,7 @@ import com.pulumi.exceptions.MissingRequiredPropertyException; import com.pulumi.pulumiservice.enums.WebhookFilters; import com.pulumi.pulumiservice.enums.WebhookFormat; +import com.pulumi.pulumiservice.enums.WebhookGroup; import java.lang.Boolean; import java.lang.String; import java.util.List; @@ -51,6 +52,21 @@ public Output displayName() { return this.displayName; } + /** + * Name of the environment. Only specified if this is an environment webhook. + * + */ + @Import(name="environmentName") + private @Nullable Output environmentName; + + /** + * @return Name of the environment. Only specified if this is an environment webhook. + * + */ + public Optional> environmentName() { + return Optional.ofNullable(this.environmentName); + } + /** * Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. * @@ -81,6 +97,21 @@ public Optional> format() { return Optional.ofNullable(this.format); } + /** + * Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + */ + @Import(name="groups") + private @Nullable Output> groups; + + /** + * @return Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + */ + public Optional>> groups() { + return Optional.ofNullable(this.groups); + } + /** * Name of the organization. * @@ -112,14 +143,14 @@ public Output payloadUrl() { } /** - * Name of the project. Only needed if this is a stack webhook. + * Name of the project. Only specified if this is a stack or environment webhook. * */ @Import(name="projectName") private @Nullable Output projectName; /** - * @return Name of the project. Only needed if this is a stack webhook. + * @return Name of the project. Only specified if this is a stack or environment webhook. * */ public Optional> projectName() { @@ -161,8 +192,10 @@ private WebhookArgs() {} private WebhookArgs(WebhookArgs $) { this.active = $.active; this.displayName = $.displayName; + this.environmentName = $.environmentName; this.filters = $.filters; this.format = $.format; + this.groups = $.groups; this.organizationName = $.organizationName; this.payloadUrl = $.payloadUrl; this.projectName = $.projectName; @@ -230,6 +263,27 @@ public Builder displayName(String displayName) { return displayName(Output.of(displayName)); } + /** + * @param environmentName Name of the environment. Only specified if this is an environment webhook. + * + * @return builder + * + */ + public Builder environmentName(@Nullable Output environmentName) { + $.environmentName = environmentName; + return this; + } + + /** + * @param environmentName Name of the environment. Only specified if this is an environment webhook. + * + * @return builder + * + */ + public Builder environmentName(String environmentName) { + return environmentName(Output.of(environmentName)); + } + /** * @param filters Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. * @@ -282,6 +336,37 @@ public Builder format(WebhookFormat format) { return format(Output.of(format)); } + /** + * @param groups Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + * @return builder + * + */ + public Builder groups(@Nullable Output> groups) { + $.groups = groups; + return this; + } + + /** + * @param groups Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + * @return builder + * + */ + public Builder groups(List groups) { + return groups(Output.of(groups)); + } + + /** + * @param groups Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + * + * @return builder + * + */ + public Builder groups(WebhookGroup... groups) { + return groups(List.of(groups)); + } + /** * @param organizationName Name of the organization. * @@ -325,7 +410,7 @@ public Builder payloadUrl(String payloadUrl) { } /** - * @param projectName Name of the project. Only needed if this is a stack webhook. + * @param projectName Name of the project. Only specified if this is a stack or environment webhook. * * @return builder * @@ -336,7 +421,7 @@ public Builder projectName(@Nullable Output projectName) { } /** - * @param projectName Name of the project. Only needed if this is a stack webhook. + * @param projectName Name of the project. Only specified if this is a stack or environment webhook. * * @return builder * diff --git a/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookFilters.java b/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookFilters.java index 9bf59813..054b9e37 100644 --- a/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookFilters.java +++ b/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookFilters.java @@ -104,7 +104,62 @@ public enum WebhookFilters { * Trigger a webhook when a drift remediation run fails. * */ - DriftRemediationFailed("drift_remediation_failed"); + DriftRemediationFailed("drift_remediation_failed"), + /** + * Trigger a webhook when a new environment is created. + * + */ + EnvironmentCreated("environment_created"), + /** + * Trigger a webhook when an environment is deleted. + * + */ + EnvironmentDeleted("environment_deleted"), + /** + * Trigger a webhook when a new revision is created on an environment. + * + */ + EnvironmentRevisionCreated("environment_revision_created"), + /** + * Trigger a webhook when a revision is retracted on an environment. + * + */ + EnvironmentRevisionRetracted("environment_revision_retracted"), + /** + * Trigger a webhook when a revision tag is created on an environment. + * + */ + EnvironmentRevisionTagCreated("environment_revision_tag_created"), + /** + * Trigger a webhook when a revision tag is deleted on an environment. + * + */ + EnvironmentRevisionTagDeleted("environment_revision_tag_deleted"), + /** + * Trigger a webhook when a revision tag is updated on an environment. + * + */ + EnvironmentRevisionTagUpdated("environment_revision_tag_updated"), + /** + * Trigger a webhook when an environment tag is created. + * + */ + EnvironmentTagCreated("environment_tag_created"), + /** + * Trigger a webhook when an environment tag is deleted. + * + */ + EnvironmentTagDeleted("environment_tag_deleted"), + /** + * Trigger a webhook when an environment tag is updated. + * + */ + EnvironmentTagUpdated("environment_tag_updated"), + /** + * Trigger a webhook when an imported environment has changed. + * + */ + ImportedEnvironmentChanged("imported_environment_changed"); private final String value; diff --git a/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookGroup.java b/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookGroup.java new file mode 100644 index 00000000..1e96f0ea --- /dev/null +++ b/sdk/java/src/main/java/com/pulumi/pulumiservice/enums/WebhookGroup.java @@ -0,0 +1,46 @@ +// *** WARNING: this file was generated by pulumi. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +package com.pulumi.pulumiservice.enums; + +import com.pulumi.core.annotations.EnumType; +import java.lang.String; +import java.util.Objects; +import java.util.StringJoiner; + + @EnumType + public enum WebhookGroup { + /** + * A group of webhooks containing all stack events. + * + */ + Stacks("stacks"), + /** + * A group of webhooks containing all deployment events. + * + */ + Deployments("deployments"), + /** + * A group of webhooks containing all environment events. + * + */ + Environments("environments"); + + private final String value; + + WebhookGroup(String value) { + this.value = Objects.requireNonNull(value); + } + + @EnumType.Converter + public String getValue() { + return this.value; + } + + @Override + public java.lang.String toString() { + return new StringJoiner(", ", "WebhookGroup[", "]") + .add("value='" + this.value + "'") + .toString(); + } + } diff --git a/sdk/nodejs/types/enums/index.ts b/sdk/nodejs/types/enums/index.ts index 756f66ff..ee6dcb82 100644 --- a/sdk/nodejs/types/enums/index.ts +++ b/sdk/nodejs/types/enums/index.ts @@ -142,6 +142,50 @@ export const WebhookFilters = { * Trigger a webhook when a drift remediation run fails. */ DriftRemediationFailed: "drift_remediation_failed", + /** + * Trigger a webhook when a new environment is created. + */ + EnvironmentCreated: "environment_created", + /** + * Trigger a webhook when an environment is deleted. + */ + EnvironmentDeleted: "environment_deleted", + /** + * Trigger a webhook when a new revision is created on an environment. + */ + EnvironmentRevisionCreated: "environment_revision_created", + /** + * Trigger a webhook when a revision is retracted on an environment. + */ + EnvironmentRevisionRetracted: "environment_revision_retracted", + /** + * Trigger a webhook when a revision tag is created on an environment. + */ + EnvironmentRevisionTagCreated: "environment_revision_tag_created", + /** + * Trigger a webhook when a revision tag is deleted on an environment. + */ + EnvironmentRevisionTagDeleted: "environment_revision_tag_deleted", + /** + * Trigger a webhook when a revision tag is updated on an environment. + */ + EnvironmentRevisionTagUpdated: "environment_revision_tag_updated", + /** + * Trigger a webhook when an environment tag is created. + */ + EnvironmentTagCreated: "environment_tag_created", + /** + * Trigger a webhook when an environment tag is deleted. + */ + EnvironmentTagDeleted: "environment_tag_deleted", + /** + * Trigger a webhook when an environment tag is updated. + */ + EnvironmentTagUpdated: "environment_tag_updated", + /** + * Trigger a webhook when an imported environment has changed. + */ + ImportedEnvironmentChanged: "imported_environment_changed", } as const; export type WebhookFilters = (typeof WebhookFilters)[keyof typeof WebhookFilters]; @@ -166,3 +210,20 @@ export const WebhookFormat = { } as const; export type WebhookFormat = (typeof WebhookFormat)[keyof typeof WebhookFormat]; + +export const WebhookGroup = { + /** + * A group of webhooks containing all stack events. + */ + Stacks: "stacks", + /** + * A group of webhooks containing all deployment events. + */ + Deployments: "deployments", + /** + * A group of webhooks containing all environment events. + */ + Environments: "environments", +} as const; + +export type WebhookGroup = (typeof WebhookGroup)[keyof typeof WebhookGroup]; diff --git a/sdk/nodejs/webhook.ts b/sdk/nodejs/webhook.ts index 8b8f26ae..bbaa4169 100644 --- a/sdk/nodejs/webhook.ts +++ b/sdk/nodejs/webhook.ts @@ -53,6 +53,10 @@ export class Webhook extends pulumi.CustomResource { * The friendly name displayed in the Pulumi Cloud. */ public readonly displayName!: pulumi.Output; + /** + * Name of the environment. Only specified if this is an environment webhook. + */ + public readonly environmentName!: pulumi.Output; /** * Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. */ @@ -61,6 +65,10 @@ export class Webhook extends pulumi.CustomResource { * Format of the webhook payload. Can be either `raw`, `slack`, `ms_teams` or `pulumi_deployments`. Defaults to `raw`. */ public readonly format!: pulumi.Output; + /** + * Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + */ + public readonly groups!: pulumi.Output; /** * Webhook identifier generated by Pulumi Cloud. */ @@ -74,7 +82,7 @@ export class Webhook extends pulumi.CustomResource { */ public readonly payloadUrl!: pulumi.Output; /** - * Name of the project. Only specified if this is a stack webhook. + * Name of the project. Only specified if this is a stack or environment webhook. */ public readonly projectName!: pulumi.Output; /** @@ -111,8 +119,10 @@ export class Webhook extends pulumi.CustomResource { } resourceInputs["active"] = args ? args.active : undefined; resourceInputs["displayName"] = args ? args.displayName : undefined; + resourceInputs["environmentName"] = args ? args.environmentName : undefined; resourceInputs["filters"] = args ? args.filters : undefined; resourceInputs["format"] = (args ? args.format : undefined) ?? "raw"; + resourceInputs["groups"] = args ? args.groups : undefined; resourceInputs["organizationName"] = args ? args.organizationName : undefined; resourceInputs["payloadUrl"] = args ? args.payloadUrl : undefined; resourceInputs["projectName"] = args ? args.projectName : undefined; @@ -122,8 +132,10 @@ export class Webhook extends pulumi.CustomResource { } else { resourceInputs["active"] = undefined /*out*/; resourceInputs["displayName"] = undefined /*out*/; + resourceInputs["environmentName"] = undefined /*out*/; resourceInputs["filters"] = undefined /*out*/; resourceInputs["format"] = undefined /*out*/; + resourceInputs["groups"] = undefined /*out*/; resourceInputs["name"] = undefined /*out*/; resourceInputs["organizationName"] = undefined /*out*/; resourceInputs["payloadUrl"] = undefined /*out*/; @@ -150,6 +162,10 @@ export interface WebhookArgs { * The friendly name displayed in the Pulumi Cloud. */ displayName: pulumi.Input; + /** + * Name of the environment. Only specified if this is an environment webhook. + */ + environmentName?: pulumi.Input; /** * Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. */ @@ -158,6 +174,10 @@ export interface WebhookArgs { * Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`. */ format?: pulumi.Input; + /** + * Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + */ + groups?: pulumi.Input[]>; /** * Name of the organization. */ @@ -167,7 +187,7 @@ export interface WebhookArgs { */ payloadUrl: pulumi.Input; /** - * Name of the project. Only needed if this is a stack webhook. + * Name of the project. Only specified if this is a stack or environment webhook. */ projectName?: pulumi.Input; /** diff --git a/sdk/python/pulumi_pulumiservice/_enums.py b/sdk/python/pulumi_pulumiservice/_enums.py index 9a335e5b..6a0840bf 100644 --- a/sdk/python/pulumi_pulumiservice/_enums.py +++ b/sdk/python/pulumi_pulumiservice/_enums.py @@ -10,6 +10,7 @@ 'TeamStackPermissionScope', 'WebhookFilters', 'WebhookFormat', + 'WebhookGroup', ] @@ -147,6 +148,50 @@ class WebhookFilters(str, Enum): """ Trigger a webhook when a drift remediation run fails. """ + ENVIRONMENT_CREATED = "environment_created" + """ + Trigger a webhook when a new environment is created. + """ + ENVIRONMENT_DELETED = "environment_deleted" + """ + Trigger a webhook when an environment is deleted. + """ + ENVIRONMENT_REVISION_CREATED = "environment_revision_created" + """ + Trigger a webhook when a new revision is created on an environment. + """ + ENVIRONMENT_REVISION_RETRACTED = "environment_revision_retracted" + """ + Trigger a webhook when a revision is retracted on an environment. + """ + ENVIRONMENT_REVISION_TAG_CREATED = "environment_revision_tag_created" + """ + Trigger a webhook when a revision tag is created on an environment. + """ + ENVIRONMENT_REVISION_TAG_DELETED = "environment_revision_tag_deleted" + """ + Trigger a webhook when a revision tag is deleted on an environment. + """ + ENVIRONMENT_REVISION_TAG_UPDATED = "environment_revision_tag_updated" + """ + Trigger a webhook when a revision tag is updated on an environment. + """ + ENVIRONMENT_TAG_CREATED = "environment_tag_created" + """ + Trigger a webhook when an environment tag is created. + """ + ENVIRONMENT_TAG_DELETED = "environment_tag_deleted" + """ + Trigger a webhook when an environment tag is deleted. + """ + ENVIRONMENT_TAG_UPDATED = "environment_tag_updated" + """ + Trigger a webhook when an environment tag is updated. + """ + IMPORTED_ENVIRONMENT_CHANGED = "imported_environment_changed" + """ + Trigger a webhook when an imported environment has changed. + """ class WebhookFormat(str, Enum): @@ -166,3 +211,18 @@ class WebhookFormat(str, Enum): """ Messages formatted for consumption by Microsoft Teams incoming webhooks. """ + + +class WebhookGroup(str, Enum): + STACKS = "stacks" + """ + A group of webhooks containing all stack events. + """ + DEPLOYMENTS = "deployments" + """ + A group of webhooks containing all deployment events. + """ + ENVIRONMENTS = "environments" + """ + A group of webhooks containing all environment events. + """ diff --git a/sdk/python/pulumi_pulumiservice/webhook.py b/sdk/python/pulumi_pulumiservice/webhook.py index 4cb2eb04..2eaf0698 100644 --- a/sdk/python/pulumi_pulumiservice/webhook.py +++ b/sdk/python/pulumi_pulumiservice/webhook.py @@ -19,8 +19,10 @@ def __init__(__self__, *, display_name: pulumi.Input[str], organization_name: pulumi.Input[str], payload_url: pulumi.Input[str], + environment_name: Optional[pulumi.Input[str]] = None, filters: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]]] = None, format: Optional[pulumi.Input['WebhookFormat']] = None, + groups: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]]] = None, project_name: Optional[pulumi.Input[str]] = None, secret: Optional[pulumi.Input[str]] = None, stack_name: Optional[pulumi.Input[str]] = None): @@ -30,9 +32,11 @@ def __init__(__self__, *, :param pulumi.Input[str] display_name: The friendly name displayed in the Pulumi Cloud. :param pulumi.Input[str] organization_name: Name of the organization. :param pulumi.Input[str] payload_url: URL to send request to. + :param pulumi.Input[str] environment_name: Name of the environment. Only specified if this is an environment webhook. :param pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]] filters: Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. :param pulumi.Input['WebhookFormat'] format: Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`. - :param pulumi.Input[str] project_name: Name of the project. Only needed if this is a stack webhook. + :param pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]] groups: Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + :param pulumi.Input[str] project_name: Name of the project. Only specified if this is a stack or environment webhook. :param pulumi.Input[str] secret: Optional. secret used as the HMAC key. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#headers) for more information. :param pulumi.Input[str] stack_name: Name of the stack. Only needed if this is a stack webhook. """ @@ -40,12 +44,16 @@ def __init__(__self__, *, pulumi.set(__self__, "display_name", display_name) pulumi.set(__self__, "organization_name", organization_name) pulumi.set(__self__, "payload_url", payload_url) + if environment_name is not None: + pulumi.set(__self__, "environment_name", environment_name) if filters is not None: pulumi.set(__self__, "filters", filters) if format is None: format = 'raw' if format is not None: pulumi.set(__self__, "format", format) + if groups is not None: + pulumi.set(__self__, "groups", groups) if project_name is not None: pulumi.set(__self__, "project_name", project_name) if secret is not None: @@ -101,6 +109,18 @@ def payload_url(self) -> pulumi.Input[str]: def payload_url(self, value: pulumi.Input[str]): pulumi.set(self, "payload_url", value) + @property + @pulumi.getter(name="environmentName") + def environment_name(self) -> Optional[pulumi.Input[str]]: + """ + Name of the environment. Only specified if this is an environment webhook. + """ + return pulumi.get(self, "environment_name") + + @environment_name.setter + def environment_name(self, value: Optional[pulumi.Input[str]]): + pulumi.set(self, "environment_name", value) + @property @pulumi.getter def filters(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]]]: @@ -125,11 +145,23 @@ def format(self) -> Optional[pulumi.Input['WebhookFormat']]: def format(self, value: Optional[pulumi.Input['WebhookFormat']]): pulumi.set(self, "format", value) + @property + @pulumi.getter + def groups(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]]]: + """ + Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + """ + return pulumi.get(self, "groups") + + @groups.setter + def groups(self, value: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]]]): + pulumi.set(self, "groups", value) + @property @pulumi.getter(name="projectName") def project_name(self) -> Optional[pulumi.Input[str]]: """ - Name of the project. Only needed if this is a stack webhook. + Name of the project. Only specified if this is a stack or environment webhook. """ return pulumi.get(self, "project_name") @@ -169,8 +201,10 @@ def __init__(__self__, opts: Optional[pulumi.ResourceOptions] = None, active: Optional[pulumi.Input[bool]] = None, display_name: Optional[pulumi.Input[str]] = None, + environment_name: Optional[pulumi.Input[str]] = None, filters: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]]] = None, format: Optional[pulumi.Input['WebhookFormat']] = None, + groups: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]]] = None, organization_name: Optional[pulumi.Input[str]] = None, payload_url: Optional[pulumi.Input[str]] = None, project_name: Optional[pulumi.Input[str]] = None, @@ -192,11 +226,13 @@ def __init__(__self__, :param pulumi.ResourceOptions opts: Options for the resource. :param pulumi.Input[bool] active: Indicates whether this webhook is enabled or not. :param pulumi.Input[str] display_name: The friendly name displayed in the Pulumi Cloud. + :param pulumi.Input[str] environment_name: Name of the environment. Only specified if this is an environment webhook. :param pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]] filters: Optional set of filters to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#filters) for more information. :param pulumi.Input['WebhookFormat'] format: Format of the webhook payload. Can be either `raw` or `slack`. Defaults to `raw`. + :param pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]] groups: Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. :param pulumi.Input[str] organization_name: Name of the organization. :param pulumi.Input[str] payload_url: URL to send request to. - :param pulumi.Input[str] project_name: Name of the project. Only needed if this is a stack webhook. + :param pulumi.Input[str] project_name: Name of the project. Only specified if this is a stack or environment webhook. :param pulumi.Input[str] secret: Optional. secret used as the HMAC key. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#headers) for more information. :param pulumi.Input[str] stack_name: Name of the stack. Only needed if this is a stack webhook. """ @@ -234,8 +270,10 @@ def _internal_init(__self__, opts: Optional[pulumi.ResourceOptions] = None, active: Optional[pulumi.Input[bool]] = None, display_name: Optional[pulumi.Input[str]] = None, + environment_name: Optional[pulumi.Input[str]] = None, filters: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookFilters']]]] = None, format: Optional[pulumi.Input['WebhookFormat']] = None, + groups: Optional[pulumi.Input[Sequence[pulumi.Input['WebhookGroup']]]] = None, organization_name: Optional[pulumi.Input[str]] = None, payload_url: Optional[pulumi.Input[str]] = None, project_name: Optional[pulumi.Input[str]] = None, @@ -256,10 +294,12 @@ def _internal_init(__self__, if display_name is None and not opts.urn: raise TypeError("Missing required property 'display_name'") __props__.__dict__["display_name"] = display_name + __props__.__dict__["environment_name"] = environment_name __props__.__dict__["filters"] = filters if format is None: format = 'raw' __props__.__dict__["format"] = format + __props__.__dict__["groups"] = groups if organization_name is None and not opts.urn: raise TypeError("Missing required property 'organization_name'") __props__.__dict__["organization_name"] = organization_name @@ -296,8 +336,10 @@ def get(resource_name: str, __props__.__dict__["active"] = None __props__.__dict__["display_name"] = None + __props__.__dict__["environment_name"] = None __props__.__dict__["filters"] = None __props__.__dict__["format"] = None + __props__.__dict__["groups"] = None __props__.__dict__["name"] = None __props__.__dict__["organization_name"] = None __props__.__dict__["payload_url"] = None @@ -322,6 +364,14 @@ def display_name(self) -> pulumi.Output[str]: """ return pulumi.get(self, "display_name") + @property + @pulumi.getter(name="environmentName") + def environment_name(self) -> pulumi.Output[Optional[str]]: + """ + Name of the environment. Only specified if this is an environment webhook. + """ + return pulumi.get(self, "environment_name") + @property @pulumi.getter def filters(self) -> pulumi.Output[Optional[Sequence['WebhookFilters']]]: @@ -338,6 +388,14 @@ def format(self) -> pulumi.Output['WebhookFormat']: """ return pulumi.get(self, "format") + @property + @pulumi.getter + def groups(self) -> pulumi.Output[Optional[Sequence['WebhookGroup']]]: + """ + Optional set of filter groups to apply to the webhook. See [webhook docs](https://www.pulumi.com/docs/intro/pulumi-service/webhooks/#groups) for more information. + """ + return pulumi.get(self, "groups") + @property @pulumi.getter def name(self) -> pulumi.Output[str]: @@ -366,7 +424,7 @@ def payload_url(self) -> pulumi.Output[str]: @pulumi.getter(name="projectName") def project_name(self) -> pulumi.Output[Optional[str]]: """ - Name of the project. Only specified if this is a stack webhook. + Name of the project. Only specified if this is a stack or environment webhook. """ return pulumi.get(self, "project_name")