Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add opslevel_integration_custom_event_check resource #498

Merged
merged 9 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changes/unreleased/Feature-20241004-155834.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Feature
body: add opslevel_integration_endpoint resource to create and update integration endpoints
time: 2024-10-04T15:58:34.269225-05:00
1 change: 1 addition & 0 deletions examples/resources/opslevel_integration_endpoint/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import opslevel_integration_endpoint.example Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS82MDI0
154 changes: 154 additions & 0 deletions examples/resources/opslevel_integration_endpoint/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
resource "opslevel_integration_endpoint" "apiDoc" {
name = "apiDoc integration endpoint"
type = "apiDoc"
}

resource "opslevel_integration_endpoint" "aquaSecurity" {
name = "aquaSecurity integration endpoint"
type = "aquaSecurity"
}

resource "opslevel_integration_endpoint" "argocd" {
name = "argocd integration endpoint"
type = "argocd"
}

resource "opslevel_integration_endpoint" "awsEcr" {
name = "awsEcr integration endpoint"
type = "awsEcr"
}

resource "opslevel_integration_endpoint" "bugsnag" {
name = "bugsnag integration endpoint"
type = "bugsnag"
}

resource "opslevel_integration_endpoint" "circleci" {
name = "circleci integration endpoint"
type = "circleci"
}

resource "opslevel_integration_endpoint" "codacy" {
name = "codacy integration endpoint"
type = "codacy"
}

resource "opslevel_integration_endpoint" "coveralls" {
name = "coveralls integration endpoint"
type = "coveralls"
}

resource "opslevel_integration_endpoint" "customEvent" {
name = "customEvent integration endpoint"
type = "customEvent"
}

resource "opslevel_integration_endpoint" "datadogCheck" {
name = "datadogCheck integration endpoint"
type = "datadogCheck"
}

resource "opslevel_integration_endpoint" "deploy" {
name = "deploy integration endpoint"
type = "deploy"
}

resource "opslevel_integration_endpoint" "dynatrace" {
name = "dynatrace integration endpoint"
type = "dynatrace"
}

resource "opslevel_integration_endpoint" "flux" {
name = "flux integration endpoint"
type = "flux"
}

resource "opslevel_integration_endpoint" "jenkins" {
name = "jenkins integration endpoint"
type = "jenkins"
}

resource "opslevel_integration_endpoint" "jfrogXray" {
name = "jfrogXray integration endpoint"
type = "jfrogXray"
}

resource "opslevel_integration_endpoint" "githubActions" {
name = "githubActions integration endpoint"
type = "githubActions"
}

resource "opslevel_integration_endpoint" "gitlabCi" {
name = "gitlabCi integration endpoint"
type = "gitlabCi"
}

resource "opslevel_integration_endpoint" "grafana" {
name = "grafana integration endpoint"
type = "grafana"
}

resource "opslevel_integration_endpoint" "grype" {
name = "grype integration endpoint"
type = "grype"
}

resource "opslevel_integration_endpoint" "lacework" {
name = "lacework integration endpoint"
type = "lacework"
}

resource "opslevel_integration_endpoint" "newRelicCheck" {
name = "newRelicCheck integration endpoint"
type = "newRelicCheck"
}

resource "opslevel_integration_endpoint" "octopus" {
name = "octopus integration endpoint"
type = "octopus"
}

resource "opslevel_integration_endpoint" "prismaCloud" {
name = "prismaCloud integration endpoint"
type = "prismaCloud"
}

resource "opslevel_integration_endpoint" "prometheus" {
name = "prometheus integration endpoint"
type = "prometheus"
}

resource "opslevel_integration_endpoint" "rollbar" {
name = "rollbar integration endpoint"
type = "rollbar"
}

resource "opslevel_integration_endpoint" "sentry" {
name = "sentry integration endpoint"
type = "sentry"
}

resource "opslevel_integration_endpoint" "snyk" {
name = "snyk integration endpoint"
type = "snyk"
}

resource "opslevel_integration_endpoint" "sonarqube" {
name = "sonarqube integration endpoint"
type = "sonarqube"
}

resource "opslevel_integration_endpoint" "stackhawk" {
name = "stackhawk integration endpoint"
type = "stackhawk"
}

resource "opslevel_integration_endpoint" "sumoLogic" {
name = "sumoLogic integration endpoint"
type = "sumoLogic"
}

resource "opslevel_integration_endpoint" "veracode" {
name = "veracode integration endpoint"
type = "veracode"
}
1 change: 1 addition & 0 deletions opslevel/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ func (p *OpslevelProvider) Resources(context.Context) []func() resource.Resource
NewInfrastructureResource,
NewIntegrationAwsResource,
NewIntegrationAzureResourcesResource,
NewIntegrationEndpointResource,
NewIntegrationGoogleCloudResource,
NewPropertyAssignmentResource,
NewPropertyDefinitionResource,
Expand Down
2 changes: 1 addition & 1 deletion opslevel/resource_opslevel_integration_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type IntegrationAwsResource struct {
CommonResourceClient
}

// IntegrationAwsResourceModel describes the AWS Integraion managed resource.
// IntegrationAwsResourceModel describes the AWS Integration managed resource.
type IntegrationAwsResourceModel struct {
ExternalID types.String `tfsdk:"external_id"`
IamRole types.String `tfsdk:"iam_role"`
Expand Down
170 changes: 170 additions & 0 deletions opslevel/resource_opslevel_integration_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package opslevel

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"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/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/opslevel/opslevel-go/v2024"
)

var _ resource.ResourceWithConfigure = &IntegrationEndpointResource{}

var _ resource.ResourceWithImportState = &IntegrationEndpointResource{}

func NewIntegrationEndpointResource() resource.Resource {
return &IntegrationEndpointResource{}
}

// IntegrationEndpointResource defines the resource implementation.
type IntegrationEndpointResource struct {
CommonResourceClient
}

// IntegrationEndpointResourceModel describes the Integration Endpoint managed resource.
type IntegrationEndpointResourceModel struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Type types.String `tfsdk:"type"`
}

func NewIntegrationEndpointResourceModel(integrationEndpoint opslevel.Integration, givenModel IntegrationEndpointResourceModel) IntegrationEndpointResourceModel {
return IntegrationEndpointResourceModel{
Id: ComputedStringValue(string(integrationEndpoint.Id)),
Name: RequiredStringValue(integrationEndpoint.Name),
Type: RequiredStringValue(givenModel.Type.ValueString()),
}
}

func (r *IntegrationEndpointResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_integration_endpoint"
}

func (r *IntegrationEndpointResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
// This description is used by the documentation generator and the language server.
MarkdownDescription: "Integration Endpoint resource",

Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "The ID of the Integration Endpoint.",
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"name": schema.StringAttribute{
Description: "The name of the integration.",
Required: true,
},
"type": schema.StringAttribute{
Description: fmt.Sprintf(
"The type of the Integration Endpoint. One of `%s`",
strings.Join(opslevel.AllEventIntegrationEnum, "`, `"),
),
Required: true,
Validators: []validator.String{
stringvalidator.OneOf(opslevel.AllEventIntegrationEnum...),
},
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
},
}
}

func (r *IntegrationEndpointResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
planModel := read[IntegrationEndpointResourceModel](ctx, &resp.Diagnostics, req.Plan)
if resp.Diagnostics.HasError() {
return
}

input := opslevel.EventIntegrationInput{
Name: planModel.Name.ValueStringPointer(),
Type: opslevel.EventIntegrationEnum(planModel.Type.ValueString()),
}

integrationEndpoint, err := r.client.CreateEventIntegration(input)
if err != nil {
resp.Diagnostics.AddError("opslevel client error", fmt.Sprintf("Unable to create Integration Endpoint, got error: %s", err))
return
}

stateModel := NewIntegrationEndpointResourceModel(*integrationEndpoint, planModel)

tflog.Trace(ctx, "created a Integration Endpoint resource")
resp.Diagnostics.Append(resp.State.Set(ctx, &stateModel)...)
}

func (r *IntegrationEndpointResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
stateModel := read[IntegrationEndpointResourceModel](ctx, &resp.Diagnostics, req.State)
if resp.Diagnostics.HasError() {
return
}

integrationEndpoint, err := r.client.GetIntegration(opslevel.ID(stateModel.Id.ValueString()))
if err != nil {
if (integrationEndpoint == nil || integrationEndpoint.Id == "") && opslevel.IsOpsLevelApiError(err) {
resp.State.RemoveResource(ctx)
return
}
resp.Diagnostics.AddError("opslevel client error", fmt.Sprintf("Unable to read Integration Endpoint, got error: %s", err))
return
}

verifiedStateModel := NewIntegrationEndpointResourceModel(*integrationEndpoint, stateModel)

// Save updated data into Terraform state
tflog.Trace(ctx, "read a Integration Endpoint resource")
resp.Diagnostics.Append(resp.State.Set(ctx, &verifiedStateModel)...)
}

func (r *IntegrationEndpointResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
planModel := read[IntegrationEndpointResourceModel](ctx, &resp.Diagnostics, req.Plan)
if resp.Diagnostics.HasError() {
return
}

input := opslevel.EventIntegrationUpdateInput{
Id: opslevel.ID(planModel.Id.ValueString()),
Name: planModel.Name.ValueString(),
}

integrationEndpoint, err := r.client.UpdateEventIntegration(input)
if err != nil {
resp.Diagnostics.AddError("opslevel client error", fmt.Sprintf("Unable to update Integration Endpoint, got error: %s", err))
return
}

stateModel := NewIntegrationEndpointResourceModel(*integrationEndpoint, planModel)

tflog.Trace(ctx, "updated a Integration Endpoint resource")
resp.Diagnostics.Append(resp.State.Set(ctx, &stateModel)...)
}

func (r *IntegrationEndpointResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
stateModel := read[IntegrationEndpointResourceModel](ctx, &resp.Diagnostics, req.State)
if resp.Diagnostics.HasError() {
return
}

if err := r.client.DeleteIntegration(stateModel.Id.ValueString()); err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete Integration Endpoint, got error: %s", err))
return
}
tflog.Trace(ctx, "deleted an Integration Endpoint resource")
}

func (r *IntegrationEndpointResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
Loading
Loading