diff --git a/docs/resources/cron_monitor.md b/docs/resources/cron_monitor.md new file mode 100644 index 000000000..17ef573ce --- /dev/null +++ b/docs/resources/cron_monitor.md @@ -0,0 +1,21 @@ + +# sentry_cron_monitor + +Manages a Sentry Cron Monitor. + +## Example Usage + +```hcl +resource "sentry_cron_monitor" "example" { + organization = "my-org" + project = "my-project" + name = "daily-cron" + schedule_type = "crontab" + schedule = "0 0 * * *" + check_in_margin = 5 + max_runtime = 30 + timezone = "UTC" + alert_rule_enabled = true + alert_threshold = 1 +} +``` diff --git a/internal/apiclient/api.yaml b/internal/apiclient/api.yaml index 538d505fa..363bfa2bc 100644 --- a/internal/apiclient/api.yaml +++ b/internal/apiclient/api.yaml @@ -801,6 +801,93 @@ paths: description: Forbidden "404": description: Not Found + /api/0/projects/{organization_id_or_slug}/{project_id_or_slug}/monitors/: + get: + operationId: listMonitors + parameters: + - $ref: "#/components/parameters/organization_id_or_slug" + - $ref: "#/components/parameters/project_id_or_slug" + responses: + "200": + description: A list of monitors + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Monitor" + post: + operationId: createMonitor + parameters: + - $ref: "#/components/parameters/organization_id_or_slug" + - $ref: "#/components/parameters/project_id_or_slug" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/MonitorRequest" + responses: + "200": + description: The created monitor + content: + application/json: + schema: + $ref: "#/components/schemas/Monitor" + /api/0/projects/{organization_id_or_slug}/{project_id_or_slug}/monitors/{monitor_slug}/: + get: + operationId: getMonitor + parameters: + - $ref: "#/components/parameters/organization_id_or_slug" + - $ref: "#/components/parameters/project_id_or_slug" + - name: monitor_slug + in: path + required: true + schema: + type: string + responses: + "200": + description: A monitor + content: + application/json: + schema: + $ref: "#/components/schemas/Monitor" + put: + operationId: updateMonitor + parameters: + - $ref: "#/components/parameters/organization_id_or_slug" + - $ref: "#/components/parameters/project_id_or_slug" + - name: monitor_slug + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/MonitorRequest" + responses: + "200": + description: Updated monitor + content: + application/json: + schema: + $ref: "#/components/schemas/Monitor" + delete: + operationId: deleteMonitor + parameters: + - $ref: "#/components/parameters/organization_id_or_slug" + - $ref: "#/components/parameters/project_id_or_slug" + - name: monitor_slug + in: path + required: true + schema: + type: string + responses: + "204": + description: Deleted successfully security: - bearerAuth: [] @@ -2031,3 +2118,58 @@ components: type: string name: type: string + Monitor: + type: object + properties: + id: + type: string + slug: + type: string + name: + type: string + type: + type: string + config: + type: object + additionalProperties: true + status: + type: string + created_at: + type: string + last_check_in: + type: string + project: + type: string + organization: + type: string + MonitorRequest: + type: object + required: + - name + - type + - config + properties: + name: + type: string + type: + type: string + enum: [cron_job] + config: + type: object + required: + - schedule + - timezone + properties: + schedule: + type: string + example: "0 * * * *" + timezone: + type: string + checkin_margin: + type: integer + max_runtime: + type: integer + failure_issue_threshold: + type: integer + recovery_threshold: + type: integer diff --git a/internal/apiclient/apiclient.gen.go b/internal/apiclient/apiclient.gen.go index b4ed5f2fd..4a27af3d3 100644 --- a/internal/apiclient/apiclient.gen.go +++ b/internal/apiclient/apiclient.gen.go @@ -22,6 +22,11 @@ const ( BearerAuthScopes = "bearerAuth.Scopes" ) +// Defines values for MonitorRequestType. +const ( + CronJob MonitorRequestType = "cron_job" +) + // Defines values for OrganizationIntegrationOpsgenieProviderKey. const ( Opsgenie OrganizationIntegrationOpsgenieProviderKey = "opsgenie" @@ -193,6 +198,37 @@ const ( Inactive ListProjectClientKeysParamsStatus = "inactive" ) +// Monitor defines model for Monitor. +type Monitor struct { + Config *map[string]interface{} `json:"config,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + Id *string `json:"id,omitempty"` + LastCheckIn *string `json:"last_check_in,omitempty"` + Name *string `json:"name,omitempty"` + Organization *string `json:"organization,omitempty"` + Project *string `json:"project,omitempty"` + Slug *string `json:"slug,omitempty"` + Status *string `json:"status,omitempty"` + Type *string `json:"type,omitempty"` +} + +// MonitorRequest defines model for MonitorRequest. +type MonitorRequest struct { + Config struct { + CheckinMargin *int `json:"checkin_margin,omitempty"` + FailureIssueThreshold *int `json:"failure_issue_threshold,omitempty"` + MaxRuntime *int `json:"max_runtime,omitempty"` + RecoveryThreshold *int `json:"recovery_threshold,omitempty"` + Schedule string `json:"schedule"` + Timezone string `json:"timezone"` + } `json:"config"` + Name string `json:"name"` + Type MonitorRequestType `json:"type"` +} + +// MonitorRequestType defines model for MonitorRequest.Type. +type MonitorRequestType string + // Organization defines model for Organization. type Organization struct { Features *[]string `json:"features,omitempty"` @@ -989,6 +1025,12 @@ type UpdateProjectRuleJSONRequestBody UpdateProjectRuleJSONBody // CreateOrganizationTeamProjectJSONRequestBody defines body for CreateOrganizationTeamProject for application/json ContentType. type CreateOrganizationTeamProjectJSONRequestBody CreateOrganizationTeamProjectJSONBody +// CreateMonitorJSONRequestBody defines body for CreateMonitor for application/json ContentType. +type CreateMonitorJSONRequestBody = MonitorRequest + +// UpdateMonitorJSONRequestBody defines body for UpdateMonitor for application/json ContentType. +type UpdateMonitorJSONRequestBody = MonitorRequest + // AsOrganizationIntegrationOpsgenie returns the union data inside the OrganizationIntegration as a OrganizationIntegrationOpsgenie func (t OrganizationIntegration) AsOrganizationIntegrationOpsgenie() (OrganizationIntegrationOpsgenie, error) { var body OrganizationIntegrationOpsgenie @@ -2547,6 +2589,25 @@ type ClientInterface interface { CreateOrganizationTeamProjectWithBody(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, teamIdOrSlug TeamIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) CreateOrganizationTeamProject(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, teamIdOrSlug TeamIdOrSlug, body CreateOrganizationTeamProjectJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // ListMonitors request + ListMonitors(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CreateMonitorWithBody request with any body + CreateMonitorWithBody(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // DeleteMonitor request + DeleteMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetMonitor request + GetMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpdateMonitorWithBody request with any body + UpdateMonitorWithBody(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpdateMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, body UpdateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) } func (c *Client) HealthCheck(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -3017,6 +3078,90 @@ func (c *Client) CreateOrganizationTeamProject(ctx context.Context, organization return c.Client.Do(req) } +func (c *Client) ListMonitors(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewListMonitorsRequest(c.Server, organizationIdOrSlug, projectIdOrSlug) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateMonitorWithBody(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateMonitorRequestWithBody(c.Server, organizationIdOrSlug, projectIdOrSlug, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateMonitorRequest(c.Server, organizationIdOrSlug, projectIdOrSlug, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) DeleteMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteMonitorRequest(c.Server, organizationIdOrSlug, projectIdOrSlug, monitorSlug) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetMonitorRequest(c.Server, organizationIdOrSlug, projectIdOrSlug, monitorSlug) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateMonitorWithBody(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateMonitorRequestWithBody(c.Server, organizationIdOrSlug, projectIdOrSlug, monitorSlug, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateMonitor(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, body UpdateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateMonitorRequest(c.Server, organizationIdOrSlug, projectIdOrSlug, monitorSlug, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + // NewHealthCheckRequest generates requests for HealthCheck func NewHealthCheckRequest(server string) (*http.Request, error) { var err error @@ -4437,119 +4582,371 @@ func NewCreateOrganizationTeamProjectRequestWithBody(server string, organization return req, nil } -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } +// NewListMonitorsRequest generates requests for ListMonitors +func NewListMonitorsRequest(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization_id_or_slug", runtime.ParamLocationPath, organizationIdOrSlug) + if err != nil { + return nil, err } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "project_id_or_slug", runtime.ParamLocationPath, projectIdOrSlug) + if err != nil { + return nil, err } - return nil -} -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) + operationPath := fmt.Sprintf("/api/0/projects/%s/%s/monitors/", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) if err != nil { return nil, err } - return &ClientWithResponses{client}, nil + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil } -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil +// NewCreateMonitorRequest calls the generic CreateMonitor builder with application/json body +func NewCreateMonitorRequest(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateMonitorJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err } + bodyReader = bytes.NewReader(buf) + return NewCreateMonitorRequestWithBody(server, organizationIdOrSlug, projectIdOrSlug, "application/json", bodyReader) } -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // HealthCheckWithResponse request - HealthCheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*HealthCheckResponse, error) +// NewCreateMonitorRequestWithBody generates requests for CreateMonitor with any type of body +func NewCreateMonitorRequestWithBody(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader) (*http.Request, error) { + var err error - // GetOrganizationWithResponse request - GetOrganizationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, reqEditors ...RequestEditorFn) (*GetOrganizationResponse, error) + var pathParam0 string - // ListOrganizationIntegrationsWithResponse request - ListOrganizationIntegrationsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationIntegrationsParams, reqEditors ...RequestEditorFn) (*ListOrganizationIntegrationsResponse, error) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization_id_or_slug", runtime.ParamLocationPath, organizationIdOrSlug) + if err != nil { + return nil, err + } - // GetOrganizationIntegrationWithResponse request - GetOrganizationIntegrationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, reqEditors ...RequestEditorFn) (*GetOrganizationIntegrationResponse, error) + var pathParam1 string - // UpdateOrganizationIntegrationWithBodyWithResponse request with any body - UpdateOrganizationIntegrationWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationIntegrationResponse, error) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "project_id_or_slug", runtime.ParamLocationPath, projectIdOrSlug) + if err != nil { + return nil, err + } - UpdateOrganizationIntegrationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, body UpdateOrganizationIntegrationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationIntegrationResponse, error) + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } - // ListOrganizationMembersWithResponse request - ListOrganizationMembersWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationMembersParams, reqEditors ...RequestEditorFn) (*ListOrganizationMembersResponse, error) + operationPath := fmt.Sprintf("/api/0/projects/%s/%s/monitors/", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } - // CreateOrganizationMemberWithBodyWithResponse request with any body - CreateOrganizationMemberWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateOrganizationMemberResponse, error) + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } - CreateOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body CreateOrganizationMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateOrganizationMemberResponse, error) + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } - // DeleteOrganizationMemberWithResponse request - DeleteOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, reqEditors ...RequestEditorFn) (*DeleteOrganizationMemberResponse, error) + req.Header.Add("Content-Type", contentType) - // GetOrganizationMemberWithResponse request - GetOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, reqEditors ...RequestEditorFn) (*GetOrganizationMemberResponse, error) + return req, nil +} - // UpdateOrganizationMemberWithBodyWithResponse request with any body - UpdateOrganizationMemberWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationMemberResponse, error) +// NewDeleteMonitorRequest generates requests for DeleteMonitor +func NewDeleteMonitorRequest(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string) (*http.Request, error) { + var err error - UpdateOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, body UpdateOrganizationMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationMemberResponse, error) + var pathParam0 string - // ListOrganizationProjectsWithResponse request - ListOrganizationProjectsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationProjectsParams, reqEditors ...RequestEditorFn) (*ListOrganizationProjectsResponse, error) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization_id_or_slug", runtime.ParamLocationPath, organizationIdOrSlug) + if err != nil { + return nil, err + } - // DisableSpikeProtectionWithBodyWithResponse request with any body - DisableSpikeProtectionWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DisableSpikeProtectionResponse, error) + var pathParam1 string - DisableSpikeProtectionWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body DisableSpikeProtectionJSONRequestBody, reqEditors ...RequestEditorFn) (*DisableSpikeProtectionResponse, error) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "project_id_or_slug", runtime.ParamLocationPath, projectIdOrSlug) + if err != nil { + return nil, err + } - // EnableSpikeProtectionWithBodyWithResponse request with any body - EnableSpikeProtectionWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*EnableSpikeProtectionResponse, error) + var pathParam2 string - EnableSpikeProtectionWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body EnableSpikeProtectionJSONRequestBody, reqEditors ...RequestEditorFn) (*EnableSpikeProtectionResponse, error) + pathParam2, err = runtime.StyleParamWithLocation("simple", false, "monitor_slug", runtime.ParamLocationPath, monitorSlug) + if err != nil { + return nil, err + } - // DeleteOrganizationProjectWithResponse request - DeleteOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*DeleteOrganizationProjectResponse, error) + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } - // GetOrganizationProjectWithResponse request - GetOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*GetOrganizationProjectResponse, error) + operationPath := fmt.Sprintf("/api/0/projects/%s/%s/monitors/%s/", pathParam0, pathParam1, pathParam2) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } - // UpdateOrganizationProjectWithBodyWithResponse request with any body - UpdateOrganizationProjectWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationProjectResponse, error) + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } - UpdateOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body UpdateOrganizationProjectJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationProjectResponse, error) + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } - // ListProjectClientKeysWithResponse request - ListProjectClientKeysWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, params *ListProjectClientKeysParams, reqEditors ...RequestEditorFn) (*ListProjectClientKeysResponse, error) + return req, nil +} - // CreateProjectClientKeyWithBodyWithResponse request with any body - CreateProjectClientKeyWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateProjectClientKeyResponse, error) +// NewGetMonitorRequest generates requests for GetMonitor +func NewGetMonitorRequest(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string) (*http.Request, error) { + var err error - CreateProjectClientKeyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateProjectClientKeyJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateProjectClientKeyResponse, error) + var pathParam0 string - // DeleteProjectClientKeyWithResponse request - DeleteProjectClientKeyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, keyId string, reqEditors ...RequestEditorFn) (*DeleteProjectClientKeyResponse, error) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization_id_or_slug", runtime.ParamLocationPath, organizationIdOrSlug) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "project_id_or_slug", runtime.ParamLocationPath, projectIdOrSlug) + if err != nil { + return nil, err + } + + var pathParam2 string + + pathParam2, err = runtime.StyleParamWithLocation("simple", false, "monitor_slug", runtime.ParamLocationPath, monitorSlug) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/0/projects/%s/%s/monitors/%s/", pathParam0, pathParam1, pathParam2) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewUpdateMonitorRequest calls the generic UpdateMonitor builder with application/json body +func NewUpdateMonitorRequest(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, body UpdateMonitorJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpdateMonitorRequestWithBody(server, organizationIdOrSlug, projectIdOrSlug, monitorSlug, "application/json", bodyReader) +} + +// NewUpdateMonitorRequestWithBody generates requests for UpdateMonitor with any type of body +func NewUpdateMonitorRequestWithBody(server string, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization_id_or_slug", runtime.ParamLocationPath, organizationIdOrSlug) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "project_id_or_slug", runtime.ParamLocationPath, projectIdOrSlug) + if err != nil { + return nil, err + } + + var pathParam2 string + + pathParam2, err = runtime.StyleParamWithLocation("simple", false, "monitor_slug", runtime.ParamLocationPath, monitorSlug) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/0/projects/%s/%s/monitors/%s/", pathParam0, pathParam1, pathParam2) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PUT", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses creates a new ClientWithResponses, which wraps +// Client with return type handling +func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { + client, err := NewClient(server, opts...) + if err != nil { + return nil, err + } + return &ClientWithResponses{client}, nil +} + +// WithBaseURL overrides the baseURL. +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) error { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // HealthCheckWithResponse request + HealthCheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*HealthCheckResponse, error) + + // GetOrganizationWithResponse request + GetOrganizationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, reqEditors ...RequestEditorFn) (*GetOrganizationResponse, error) + + // ListOrganizationIntegrationsWithResponse request + ListOrganizationIntegrationsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationIntegrationsParams, reqEditors ...RequestEditorFn) (*ListOrganizationIntegrationsResponse, error) + + // GetOrganizationIntegrationWithResponse request + GetOrganizationIntegrationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, reqEditors ...RequestEditorFn) (*GetOrganizationIntegrationResponse, error) + + // UpdateOrganizationIntegrationWithBodyWithResponse request with any body + UpdateOrganizationIntegrationWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationIntegrationResponse, error) + + UpdateOrganizationIntegrationWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, integrationId IntegrationId, body UpdateOrganizationIntegrationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationIntegrationResponse, error) + + // ListOrganizationMembersWithResponse request + ListOrganizationMembersWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationMembersParams, reqEditors ...RequestEditorFn) (*ListOrganizationMembersResponse, error) + + // CreateOrganizationMemberWithBodyWithResponse request with any body + CreateOrganizationMemberWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateOrganizationMemberResponse, error) + + CreateOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body CreateOrganizationMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateOrganizationMemberResponse, error) + + // DeleteOrganizationMemberWithResponse request + DeleteOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, reqEditors ...RequestEditorFn) (*DeleteOrganizationMemberResponse, error) + + // GetOrganizationMemberWithResponse request + GetOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, reqEditors ...RequestEditorFn) (*GetOrganizationMemberResponse, error) + + // UpdateOrganizationMemberWithBodyWithResponse request with any body + UpdateOrganizationMemberWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationMemberResponse, error) + + UpdateOrganizationMemberWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, memberId MemberId, body UpdateOrganizationMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationMemberResponse, error) + + // ListOrganizationProjectsWithResponse request + ListOrganizationProjectsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, params *ListOrganizationProjectsParams, reqEditors ...RequestEditorFn) (*ListOrganizationProjectsResponse, error) + + // DisableSpikeProtectionWithBodyWithResponse request with any body + DisableSpikeProtectionWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DisableSpikeProtectionResponse, error) + + DisableSpikeProtectionWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body DisableSpikeProtectionJSONRequestBody, reqEditors ...RequestEditorFn) (*DisableSpikeProtectionResponse, error) + + // EnableSpikeProtectionWithBodyWithResponse request with any body + EnableSpikeProtectionWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*EnableSpikeProtectionResponse, error) + + EnableSpikeProtectionWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, body EnableSpikeProtectionJSONRequestBody, reqEditors ...RequestEditorFn) (*EnableSpikeProtectionResponse, error) + + // DeleteOrganizationProjectWithResponse request + DeleteOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*DeleteOrganizationProjectResponse, error) + + // GetOrganizationProjectWithResponse request + GetOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*GetOrganizationProjectResponse, error) + + // UpdateOrganizationProjectWithBodyWithResponse request with any body + UpdateOrganizationProjectWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateOrganizationProjectResponse, error) + + UpdateOrganizationProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body UpdateOrganizationProjectJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateOrganizationProjectResponse, error) + + // ListProjectClientKeysWithResponse request + ListProjectClientKeysWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, params *ListProjectClientKeysParams, reqEditors ...RequestEditorFn) (*ListProjectClientKeysResponse, error) + + // CreateProjectClientKeyWithBodyWithResponse request with any body + CreateProjectClientKeyWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateProjectClientKeyResponse, error) + + CreateProjectClientKeyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateProjectClientKeyJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateProjectClientKeyResponse, error) + + // DeleteProjectClientKeyWithResponse request + DeleteProjectClientKeyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, keyId string, reqEditors ...RequestEditorFn) (*DeleteProjectClientKeyResponse, error) // GetProjectClientKeyWithResponse request GetProjectClientKeyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, keyId string, reqEditors ...RequestEditorFn) (*GetProjectClientKeyResponse, error) @@ -4585,6 +4982,25 @@ type ClientWithResponsesInterface interface { CreateOrganizationTeamProjectWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, teamIdOrSlug TeamIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateOrganizationTeamProjectResponse, error) CreateOrganizationTeamProjectWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, teamIdOrSlug TeamIdOrSlug, body CreateOrganizationTeamProjectJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateOrganizationTeamProjectResponse, error) + + // ListMonitorsWithResponse request + ListMonitorsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*ListMonitorsResponse, error) + + // CreateMonitorWithBodyWithResponse request with any body + CreateMonitorWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateMonitorResponse, error) + + CreateMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateMonitorResponse, error) + + // DeleteMonitorWithResponse request + DeleteMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*DeleteMonitorResponse, error) + + // GetMonitorWithResponse request + GetMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*GetMonitorResponse, error) + + // UpdateMonitorWithBodyWithResponse request with any body + UpdateMonitorWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateMonitorResponse, error) + + UpdateMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, body UpdateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateMonitorResponse, error) } type HealthCheckResponse struct { @@ -5198,6 +5614,115 @@ func (r CreateOrganizationTeamProjectResponse) StatusCode() int { return 0 } +type ListMonitorsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]Monitor +} + +// Status returns HTTPResponse.Status +func (r ListMonitorsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ListMonitorsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type CreateMonitorResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Monitor +} + +// Status returns HTTPResponse.Status +func (r CreateMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreateMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type DeleteMonitorResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r DeleteMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetMonitorResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Monitor +} + +// Status returns HTTPResponse.Status +func (r GetMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpdateMonitorResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Monitor +} + +// Status returns HTTPResponse.Status +func (r UpdateMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpdateMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + // HealthCheckWithResponse request returning *HealthCheckResponse func (c *ClientWithResponses) HealthCheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*HealthCheckResponse, error) { rsp, err := c.HealthCheck(ctx, reqEditors...) @@ -5538,6 +6063,67 @@ func (c *ClientWithResponses) CreateOrganizationTeamProjectWithResponse(ctx cont return ParseCreateOrganizationTeamProjectResponse(rsp) } +// ListMonitorsWithResponse request returning *ListMonitorsResponse +func (c *ClientWithResponses) ListMonitorsWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, reqEditors ...RequestEditorFn) (*ListMonitorsResponse, error) { + rsp, err := c.ListMonitors(ctx, organizationIdOrSlug, projectIdOrSlug, reqEditors...) + if err != nil { + return nil, err + } + return ParseListMonitorsResponse(rsp) +} + +// CreateMonitorWithBodyWithResponse request with arbitrary body returning *CreateMonitorResponse +func (c *ClientWithResponses) CreateMonitorWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateMonitorResponse, error) { + rsp, err := c.CreateMonitorWithBody(ctx, organizationIdOrSlug, projectIdOrSlug, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateMonitorResponse(rsp) +} + +func (c *ClientWithResponses) CreateMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, body CreateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateMonitorResponse, error) { + rsp, err := c.CreateMonitor(ctx, organizationIdOrSlug, projectIdOrSlug, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateMonitorResponse(rsp) +} + +// DeleteMonitorWithResponse request returning *DeleteMonitorResponse +func (c *ClientWithResponses) DeleteMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*DeleteMonitorResponse, error) { + rsp, err := c.DeleteMonitor(ctx, organizationIdOrSlug, projectIdOrSlug, monitorSlug, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteMonitorResponse(rsp) +} + +// GetMonitorWithResponse request returning *GetMonitorResponse +func (c *ClientWithResponses) GetMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, reqEditors ...RequestEditorFn) (*GetMonitorResponse, error) { + rsp, err := c.GetMonitor(ctx, organizationIdOrSlug, projectIdOrSlug, monitorSlug, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetMonitorResponse(rsp) +} + +// UpdateMonitorWithBodyWithResponse request with arbitrary body returning *UpdateMonitorResponse +func (c *ClientWithResponses) UpdateMonitorWithBodyWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateMonitorResponse, error) { + rsp, err := c.UpdateMonitorWithBody(ctx, organizationIdOrSlug, projectIdOrSlug, monitorSlug, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateMonitorResponse(rsp) +} + +func (c *ClientWithResponses) UpdateMonitorWithResponse(ctx context.Context, organizationIdOrSlug OrganizationIdOrSlug, projectIdOrSlug ProjectIdOrSlug, monitorSlug string, body UpdateMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateMonitorResponse, error) { + rsp, err := c.UpdateMonitor(ctx, organizationIdOrSlug, projectIdOrSlug, monitorSlug, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateMonitorResponse(rsp) +} + // ParseHealthCheckResponse parses an HTTP response from a HealthCheckWithResponse call func ParseHealthCheckResponse(rsp *http.Response) (*HealthCheckResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -6194,3 +6780,123 @@ func ParseCreateOrganizationTeamProjectResponse(rsp *http.Response) (*CreateOrga return response, nil } + +// ParseListMonitorsResponse parses an HTTP response from a ListMonitorsWithResponse call +func ParseListMonitorsResponse(rsp *http.Response) (*ListMonitorsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &ListMonitorsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []Monitor + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseCreateMonitorResponse parses an HTTP response from a CreateMonitorWithResponse call +func ParseCreateMonitorResponse(rsp *http.Response) (*CreateMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreateMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Monitor + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseDeleteMonitorResponse parses an HTTP response from a DeleteMonitorWithResponse call +func ParseDeleteMonitorResponse(rsp *http.Response) (*DeleteMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParseGetMonitorResponse parses an HTTP response from a GetMonitorWithResponse call +func ParseGetMonitorResponse(rsp *http.Response) (*GetMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Monitor + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseUpdateMonitorResponse parses an HTTP response from a UpdateMonitorWithResponse call +func ParseUpdateMonitorResponse(rsp *http.Response) (*UpdateMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpdateMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Monitor + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} diff --git a/internal/provider/resource_cron_monitor.go b/internal/provider/resource_cron_monitor.go new file mode 100644 index 000000000..50e06d07f --- /dev/null +++ b/internal/provider/resource_cron_monitor.go @@ -0,0 +1,272 @@ +package provider + +import ( + "context" + "encoding/json" + "net/http" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/jianyuan/terraform-provider-sentry/internal/apiclient" + "github.com/jianyuan/terraform-provider-sentry/internal/diagutils" +) + +type CronMonitorResourceModel struct { + ID types.String `tfsdk:"id"` + Organization types.String `tfsdk:"organization"` + Project types.String `tfsdk:"project"` + Name types.String `tfsdk:"name"` + Schedule types.String `tfsdk:"schedule"` + ScheduleType types.String `tfsdk:"schedule_type"` + CheckinMargin types.Int64 `tfsdk:"checkin_margin"` + MaxRuntime types.Int64 `tfsdk:"max_runtime"` + Timezone types.String `tfsdk:"timezone"` + Environment types.String `tfsdk:"environment"` + Enabled types.Bool `tfsdk:"enabled"` +} + +type CronMonitorResource struct { + baseResource +} + +func NewCronMonitorResource() resource.Resource { + return &CronMonitorResource{} +} + +func (r *CronMonitorResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_cron_monitor" +} + +func (r *CronMonitorResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "organization": schema.StringAttribute{ + Required: true, + }, + "project": schema.StringAttribute{ + Required: true, + }, + "name": schema.StringAttribute{ + Required: true, + }, + "schedule": schema.StringAttribute{ + Required: true, + }, + "schedule_type": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("cron_job"), + }, + "checkin_margin": schema.Int64Attribute{ + Optional: true, + }, + "max_runtime": schema.Int64Attribute{ + Optional: true, + }, + "timezone": schema.StringAttribute{ + Optional: true, + Default: stringdefault.StaticString("UTC"), + }, + "environment": schema.StringAttribute{ + Optional: true, + }, + "enabled": schema.BoolAttribute{ + Optional: true, + Computed: true, + Default: booldefault.StaticBool(true), + }, + }, + } +} + +func (r *CronMonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data CronMonitorResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + createBody := map[string]interface{}{ + "name": data.Name.ValueString(), + "type": "cron_job", + "config": map[string]interface{}{ + "schedule": data.Schedule.ValueString(), + "timezone": data.Timezone.ValueString(), + "checkin_margin": data.CheckinMargin.ValueInt64Pointer(), + "max_runtime": data.MaxRuntime.ValueInt64Pointer(), + }, + "environment": data.Environment.ValueString(), + "enabled": data.Enabled.ValueBool(), + } + + body, err := json.Marshal(createBody) + if err != nil { + resp.Diagnostics.AddError("Failed to marshal request body", err.Error()) + return + } + + httpResp, err := r.apiClient.CreateMonitorWithBodyWithResponse( + ctx, + data.Organization.ValueString(), + data.Project.ValueString(), + "application/json", + strings.NewReader(string(body)), + ) + if err != nil { + resp.Diagnostics.Append(diagutils.NewClientError("create", err)) + return + } else if httpResp.StatusCode() != http.StatusCreated { + resp.Diagnostics.Append(diagutils.NewClientStatusError("create", httpResp.StatusCode(), httpResp.Body)) + return + } + + var monitor apiclient.Monitor + if err := json.Unmarshal(httpResp.Body, &monitor); err != nil { + resp.Diagnostics.AddError("Failed to parse response body", err.Error()) + return + } + + data.ID = types.StringValue(*monitor.Id) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *CronMonitorResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data CronMonitorResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.apiClient.GetMonitorWithResponse( + ctx, + data.Organization.ValueString(), + data.Project.ValueString(), + data.ID.ValueString(), + ) + if err != nil { + resp.Diagnostics.Append(diagutils.NewClientError("read", err)) + return + } else if httpResp.StatusCode() == http.StatusNotFound { + resp.Diagnostics.Append(diagutils.NewNotFoundError("cron monitor")) + resp.State.RemoveResource(ctx) + return + } else if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.Append(diagutils.NewClientStatusError("read", httpResp.StatusCode(), httpResp.Body)) + return + } + + var monitor apiclient.Monitor + if err := json.Unmarshal(httpResp.Body, &monitor); err != nil { + resp.Diagnostics.AddError("Failed to parse response body", err.Error()) + return + } + + data.Name = types.StringValue(*monitor.Name) + if monitor.Config != nil { + config := *monitor.Config + if schedule, ok := config["schedule"].(string); ok { + data.Schedule = types.StringValue(schedule) + } + if timezone, ok := config["timezone"].(string); ok { + data.Timezone = types.StringValue(timezone) + } + if checkinMargin, ok := config["checkin_margin"].(float64); ok { + data.CheckinMargin = types.Int64Value(int64(checkinMargin)) + } + if maxRuntime, ok := config["max_runtime"].(float64); ok { + data.MaxRuntime = types.Int64Value(int64(maxRuntime)) + } + } + data.ScheduleType = types.StringValue(*monitor.Type) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *CronMonitorResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data CronMonitorResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + updateBody := map[string]interface{}{ + "name": data.Name.ValueString(), + "type": "cron_job", + "config": map[string]interface{}{ + "schedule": data.Schedule.ValueString(), + "timezone": data.Timezone.ValueString(), + "checkin_margin": data.CheckinMargin.ValueInt64Pointer(), + "max_runtime": data.MaxRuntime.ValueInt64Pointer(), + }, + "environment": data.Environment.ValueString(), + "enabled": data.Enabled.ValueBool(), + } + + body, err := json.Marshal(updateBody) + if err != nil { + resp.Diagnostics.AddError("Failed to marshal request body", err.Error()) + return + } + + httpResp, err := r.apiClient.UpdateMonitorWithBodyWithResponse( + ctx, + data.Organization.ValueString(), + data.Project.ValueString(), + data.ID.ValueString(), + "application/json", + strings.NewReader(string(body)), + ) + if err != nil { + resp.Diagnostics.Append(diagutils.NewClientError("update", err)) + return + } else if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.Append(diagutils.NewClientStatusError("update", httpResp.StatusCode(), httpResp.Body)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *CronMonitorResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data CronMonitorResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.apiClient.DeleteMonitorWithResponse( + ctx, + data.Organization.ValueString(), + data.Project.ValueString(), + data.ID.ValueString(), + ) + if err != nil { + resp.Diagnostics.Append(diagutils.NewClientError("delete", err)) + return + } else if httpResp.StatusCode() == http.StatusNotFound { + return + } else if httpResp.StatusCode() != http.StatusNoContent { + resp.Diagnostics.Append(diagutils.NewClientStatusError("delete", httpResp.StatusCode(), httpResp.Body)) + return + } +} + +func (r *CronMonitorResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + // Expect format: org/project/id + parts := strings.Split(req.ID, "/") + if len(parts) != 3 { + resp.Diagnostics.AddError("Unexpected Import Identifier", "Expected format: organization/project/id") + return + } + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("organization"), parts[0])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project"), parts[1])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), parts[2])...) +} \ No newline at end of file diff --git a/internal/provider/resource_cron_monitor_test.go b/internal/provider/resource_cron_monitor_test.go new file mode 100644 index 000000000..36f076def --- /dev/null +++ b/internal/provider/resource_cron_monitor_test.go @@ -0,0 +1,87 @@ +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/jianyuan/terraform-provider-sentry/internal/acctest" + "github.com/jianyuan/terraform-provider-sentry/internal/tfutils" +) + +func TestAccCronMonitorResource(t *testing.T) { + rn := "sentry_cron_monitor.test" + team := acctest.RandomWithPrefix("tf-team") + project := acctest.RandomWithPrefix("tf-project") + name := acctest.RandomWithPrefix("tf-cron-monitor") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccCronMonitorConfig(team, project, name, "* * * * *", "UTC", true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(rn, "organization", acctest.TestOrganization), + resource.TestCheckResourceAttr(rn, "project", project), + resource.TestCheckResourceAttr(rn, "name", name), + resource.TestCheckResourceAttr(rn, "schedule", "* * * * *"), + resource.TestCheckResourceAttr(rn, "schedule_type", "crontab"), + resource.TestCheckResourceAttr(rn, "timezone", "UTC"), + resource.TestCheckResourceAttr(rn, "enabled", "true"), + ), + }, + { + Config: testAccCronMonitorConfig(team, project, name, "*/5 * * * *", "America/New_York", false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(rn, "schedule", "*/5 * * * *"), + resource.TestCheckResourceAttr(rn, "timezone", "America/New_York"), + resource.TestCheckResourceAttr(rn, "enabled", "false"), + ), + }, + { + ResourceName: rn, + ImportState: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[rn] + if !ok { + return "", fmt.Errorf("not found: %s", rn) + } + org := rs.Primary.Attributes["organization"] + project := rs.Primary.Attributes["project"] + id := rs.Primary.ID + return tfutils.BuildThreePartId(org, project, id), nil + }, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCronMonitorConfig(team, project, name, schedule, timezone string, enabled bool) string { + return fmt.Sprintf(` +resource "sentry_team" "test" { + organization = "%s" + name = "%s" + slug = "%s" +} + +resource "sentry_project" "test" { + organization = sentry_team.test.organization + teams = [sentry_team.test.id] + name = "%s" + platform = "go" +} + +resource "sentry_cron_monitor" "test" { + organization = sentry_team.test.organization + project = sentry_project.test.slug + name = "%s" + schedule = "%s" + schedule_type = "crontab" + timezone = "%s" + enabled = %t +} +`, acctest.TestOrganization, team, team, project, name, schedule, timezone, enabled) +} \ No newline at end of file