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 support for Amazon Managed Service for Prometheus #16882

Merged
merged 5 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 8 additions & 0 deletions .hashibot.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ behavior "regexp_issue_labeler_v2" "service_labels" {
"service/pricing" = [
"aws_pricing_",
],
"service/prometheusservice" = [
"aws_prometheus_",
],
"service/qldb" = [
"aws_qldb_",
],
Expand Down Expand Up @@ -1324,6 +1327,11 @@ behavior "pull_request_path_labeler" "service_labels" {
"**/*_pricing_*",
"**/pricing_*"
]
"service/prometheusservice" = [
"aws/internal/service/prometheus/**/*",
"**/*_prometheus_*",
"**/prometheus_*",
]
"service/qldb" = [
"aws/internal/service/qldb/**/*",
"**/*_qldb_*",
Expand Down
3 changes: 3 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import (
"github.com/aws/aws-sdk-go/service/personalize"
"github.com/aws/aws-sdk-go/service/pinpoint"
"github.com/aws/aws-sdk-go/service/pricing"
"github.com/aws/aws-sdk-go/service/prometheusservice"
nicolai86 marked this conversation as resolved.
Show resolved Hide resolved
"github.com/aws/aws-sdk-go/service/qldb"
"github.com/aws/aws-sdk-go/service/quicksight"
"github.com/aws/aws-sdk-go/service/ram"
Expand Down Expand Up @@ -318,6 +319,7 @@ type AWSClient struct {
outpostsconn *outposts.Outposts
partition string
personalizeconn *personalize.Personalize
prometheusserviceconn *prometheusservice.PrometheusService
pinpointconn *pinpoint.Pinpoint
pricingconn *pricing.Pricing
qldbconn *qldb.QLDB
Expand Down Expand Up @@ -556,6 +558,7 @@ func (c *Config) Client() (interface{}, error) {
outpostsconn: outposts.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["outposts"])})),
partition: partition,
personalizeconn: personalize.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["personalize"])})),
prometheusserviceconn: prometheusservice.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["prometheusservice"])})),
pinpointconn: pinpoint.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["pinpoint"])})),
pricingconn: pricing.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["pricing"])})),
qldbconn: qldb.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["qldb"])})),
Expand Down
62 changes: 62 additions & 0 deletions aws/internal/service/prometheusservice/waiter/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package waiter

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/prometheusservice"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

const (
ResourceStatusFailed = "Failed"
ResourceStatusUnknown = "Unknown"
ResourceStatusDeleted = "Deleted"
)

// WorkspaceCreatedStatus fetches the Workspace and its Status.
func WorkspaceCreatedStatus(ctx context.Context, conn *prometheusservice.PrometheusService, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &prometheusservice.DescribeWorkspaceInput{
WorkspaceId: aws.String(id),
}

output, err := conn.DescribeWorkspaceWithContext(ctx, input)

if err != nil {
return output, ResourceStatusFailed, err
}

if output == nil || output.Workspace == nil {
return output, ResourceStatusUnknown, nil
}

return output.Workspace, aws.StringValue(output.Workspace.Status.StatusCode), nil
}
}

// WorkspaceDeletedStatus fetches the Workspace and its Status
func WorkspaceDeletedStatus(ctx context.Context, conn *prometheusservice.PrometheusService, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &prometheusservice.DescribeWorkspaceInput{
WorkspaceId: aws.String(id),
}

output, err := conn.DescribeWorkspaceWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, prometheusservice.ErrCodeResourceNotFoundException) {
return output, ResourceStatusDeleted, nil
}

if err != nil {
return output, ResourceStatusUnknown, err
}

if output == nil || output.Workspace == nil {
return output, ResourceStatusUnknown, nil
}

return output.Workspace, aws.StringValue(output.Workspace.Status.StatusCode), nil
}
}
50 changes: 50 additions & 0 deletions aws/internal/service/prometheusservice/waiter/waiter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package waiter

import (
"context"
"time"

"github.com/aws/aws-sdk-go/service/prometheusservice"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

const (
// Maximum amount of time to wait for a Workspace to be created, updated, or deleted
WorkspaceTimeout = 5 * time.Minute
)

// WorkspaceCreated waits for a Workspace to return "Active"
func WorkspaceCreated(ctx context.Context, conn *prometheusservice.PrometheusService, id string) (*prometheusservice.WorkspaceSummary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{prometheusservice.WorkspaceStatusCodeCreating},
Target: []string{prometheusservice.WorkspaceStatusCodeActive},
Refresh: WorkspaceCreatedStatus(ctx, conn, id),
Timeout: WorkspaceTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*prometheusservice.WorkspaceSummary); ok {
return v, err
}

return nil, err
}

// WorkspaceDeleted waits for a Workspace to return "Deleted"
func WorkspaceDeleted(ctx context.Context, conn *prometheusservice.PrometheusService, arn string) (*prometheusservice.WorkspaceSummary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{prometheusservice.WorkspaceStatusCodeDeleting},
Target: []string{ResourceStatusDeleted},
Refresh: WorkspaceDeletedStatus(ctx, conn, arn),
Timeout: WorkspaceTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*prometheusservice.WorkspaceSummary); ok {
return v, err
}

return nil, err
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ func Provider() *schema.Provider {
"aws_organizations_policy_attachment": resourceAwsOrganizationsPolicyAttachment(),
"aws_organizations_organizational_unit": resourceAwsOrganizationsOrganizationalUnit(),
"aws_placement_group": resourceAwsPlacementGroup(),
"aws_prometheus_workspace": resourceAwsPrometheusWorkspace(),
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
"aws_qldb_ledger": resourceAwsQLDBLedger(),
"aws_quicksight_group": resourceAwsQuickSightGroup(),
Expand Down
128 changes: 128 additions & 0 deletions aws/resource_aws_prometheus_workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package aws

import (
"context"
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/prometheusservice"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/prometheusservice/waiter"
)

func resourceAwsPrometheusWorkspace() *schema.Resource {
return &schema.Resource{
CreateContext: resourceAwsPrometheusWorkspaceCreate,
ReadContext: resourceAwsPrometheusWorkspaceRead,
UpdateContext: resourceAwsPrometheusWorkspaceUpdate,
DeleteContext: resourceAwsPrometheusWorkspaceDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"alias": {
Type: schema.TypeString,
Optional: true,
},
"prometheus_endpoint": {
Type: schema.TypeString,
Computed: true,
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceAwsPrometheusWorkspaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[INFO] Reading AMP workspace %s", d.Id())
conn := meta.(*AWSClient).prometheusserviceconn

details, err := conn.DescribeWorkspaceWithContext(ctx, &prometheusservice.DescribeWorkspaceInput{
WorkspaceId: aws.String(d.Id()),
})
if tfawserr.ErrCodeEquals(err, prometheusservice.ErrCodeResourceNotFoundException) {
log.Printf("[WARN] Prometheus Workspace (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
nicolai86 marked this conversation as resolved.
Show resolved Hide resolved
return diag.FromErr(fmt.Errorf("error reading Prometheus Workspace (%s): %w", d.Id(), err))
}

if details.Workspace != nil {
ws := details.Workspace
if ws.Arn != nil {
d.Set("arn", ws.Arn)
}
if ws.PrometheusEndpoint != nil {
d.Set("prometheus_endpoint", ws.PrometheusEndpoint)
}
if ws.Alias != nil {
d.Set("alias", ws.Alias)
}
}
bflad marked this conversation as resolved.
Show resolved Hide resolved

return nil
}

func resourceAwsPrometheusWorkspaceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[INFO] Updating AMP workspace %s", d.Id())

req := &prometheusservice.UpdateWorkspaceAliasInput{
WorkspaceId: aws.String(d.Id()),
}
if v, ok := d.GetOk("alias"); ok {
req.Alias = aws.String(v.(string))
}
conn := meta.(*AWSClient).prometheusserviceconn
if _, err := conn.UpdateWorkspaceAliasWithContext(ctx, req); err != nil {
return diag.FromErr(fmt.Errorf("error updating Prometheus WorkSpace (%s): %w", d.Id(), err))
}

return resourceAwsPrometheusWorkspaceRead(ctx, d, meta)
}

func resourceAwsPrometheusWorkspaceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[INFO] Creating AMP workspace %s", d.Id())
conn := meta.(*AWSClient).prometheusserviceconn

req := &prometheusservice.CreateWorkspaceInput{}
if v, ok := d.GetOk("alias"); ok {
req.Alias = aws.String(v.(string))
}

result, err := conn.CreateWorkspaceWithContext(ctx, req)
if err != nil {
return diag.FromErr(fmt.Errorf("error creating Prometheus WorkSpace (%s): %w", d.Id(), err))
}
d.SetId(aws.StringValue(result.WorkspaceId))

if _, err := waiter.WorkspaceCreated(ctx, conn, d.Id()); err != nil {
return diag.FromErr(fmt.Errorf("error waiting for Workspace (%s) to be created: %w", d.Id(), err))
}

return resourceAwsPrometheusWorkspaceRead(ctx, d, meta)
}

func resourceAwsPrometheusWorkspaceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[INFO] Deleting AMP workspace %s", d.Id())
conn := meta.(*AWSClient).prometheusserviceconn

_, err := conn.DeleteWorkspaceWithContext(ctx, &prometheusservice.DeleteWorkspaceInput{
WorkspaceId: aws.String(d.Id()),
})

if _, err := waiter.WorkspaceDeleted(ctx, conn, d.Id()); err != nil {
return diag.FromErr(fmt.Errorf("error waiting for Workspace (%s) to be deleted: %w", d.Id(), err))
}

return diag.FromErr(err)
bflad marked this conversation as resolved.
Show resolved Hide resolved
}
Loading