Skip to content

Commit

Permalink
Merge pull request #40 from axiomhq/fix-org-capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
toppercodes authored Jul 18, 2024
2 parents a6e4a3f + f9b604e commit 21df00d
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ HOSTNAME=locally
NAMESPACE=debug
NAME=axiom
BINARY=terraform-provider-${NAME}
VERSION=1.1.1
VERSION=1.1.2
OS_ARCH=darwin_arm64

default: install
Expand Down
2 changes: 1 addition & 1 deletion axiom/data_source_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (d *TokenDataSource) Read(ctx context.Context, req datasource.ReadRequest,
return
}

token, diagnostics := flattenToken(apiToken)
token, diagnostics := flattenToken(ctx, apiToken)
if diagnostics.HasError() {
resp.Diagnostics.Append(diagnostics...)
return
Expand Down
2 changes: 1 addition & 1 deletion axiom/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

const (
providerUserAgent = "terraform-provider-axiom/v1.1.0"
providerUserAgent = "terraform-provider-axiom/v1.1.2"
)

// Ensure the implementation satisfies the expected interfaces
Expand Down
27 changes: 26 additions & 1 deletion axiom/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ func TestAccAxiomResources_basic(t *testing.T) {
resource.TestCheckResourceAttr("axiom_token.test_token", "expires_at", "2027-06-29T13:02:54Z"),
resource.TestCheckResourceAttr("axiom_token.test_token", "dataset_capabilities.new-dataset.ingest.0", "create"),
resource.TestCheckResourceAttr("axiom_token.test_token", "org_capabilities.api_tokens.0", "read"),
testAccCheckAxiomResourcesExist(client, "axiom_token.dataset_token"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "name", "dataset only token"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "description", "Can only access a single dataset"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "expires_at", "2027-06-29T13:02:54Z"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "dataset_capabilities.new-dataset.ingest.0", "create"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "dataset_capabilities.new-dataset.query.0", "read"),
),
},
{
Expand All @@ -63,6 +69,12 @@ func TestAccAxiomResources_basic(t *testing.T) {
resource.TestCheckResourceAttr("axiom_token.test_token", "expires_at", "2027-06-29T13:02:54Z"),
resource.TestCheckResourceAttr("axiom_token.test_token", "dataset_capabilities.new-dataset.ingest.0", "create"),
resource.TestCheckResourceAttr("axiom_token.test_token", "org_capabilities.api_tokens.0", "read"),
testAccCheckAxiomResourcesExist(client, "axiom_token.dataset_token"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "name", "dataset only token"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "description", "Can only access a single dataset"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "expires_at", "2027-06-29T13:02:54Z"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "dataset_capabilities.new-dataset.ingest.0", "create"),
resource.TestCheckResourceAttr("axiom_token.dataset_token", "dataset_capabilities.new-dataset.query.0", "read"),
),
},
},
Expand Down Expand Up @@ -234,7 +246,20 @@ resource "axiom_token" "test_token" {
org_capabilities = {
api_tokens = ["read"]
}
}`
}
resource "axiom_token" "dataset_token" {
name = "dataset only token"
description = "Can only access a single dataset"
expires_at = "2027-06-29T13:02:54Z"
dataset_capabilities = {
"new-dataset" = {
ingest = ["create"],
query = ["read"]
}
}
}
`
}

func TestAccAxiomResources_data(t *testing.T) {
Expand Down
128 changes: 97 additions & 31 deletions axiom/resource_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"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-framework/types/basetypes"

"github.com/axiomhq/axiom-go/axiom"
)
Expand Down Expand Up @@ -46,13 +47,13 @@ type TokenResource struct {

// TokensResourceModel describes the resource data model.
type TokensResourceModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
ExpiresAt types.String `tfsdk:"expires_at"`
DatasetCapabilities types.Map `tfsdk:"dataset_capabilities"`
OrgCapabilities OrgCapabilities `tfsdk:"org_capabilities"`
Token types.String `tfsdk:"token"`
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
ExpiresAt types.String `tfsdk:"expires_at"`
DatasetCapabilities types.Map `tfsdk:"dataset_capabilities"`
OrgCapabilities types.Object `tfsdk:"org_capabilities"`
Token types.String `tfsdk:"token"`
}

type DatasetCapabilities struct {
Expand Down Expand Up @@ -87,6 +88,24 @@ type OrgCapabilities struct {
Users types.List `tfsdk:"users"`
}

func (o OrgCapabilities) Types() map[string]attr.Type {
return map[string]attr.Type{
"annotations": types.ListType{ElemType: types.StringType},
"api_tokens": types.ListType{ElemType: types.StringType},
"billing": types.ListType{ElemType: types.StringType},
"dashboards": types.ListType{ElemType: types.StringType},
"datasets": types.ListType{ElemType: types.StringType},
"endpoints": types.ListType{ElemType: types.StringType},
"flows": types.ListType{ElemType: types.StringType},
"integrations": types.ListType{ElemType: types.StringType},
"monitors": types.ListType{ElemType: types.StringType},
"notifiers": types.ListType{ElemType: types.StringType},
"rbac": types.ListType{ElemType: types.StringType},
"shared_access_keys": types.ListType{ElemType: types.StringType},
"users": types.ListType{ElemType: types.StringType},
}
}

func (r *TokenResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_token"
}
Expand Down Expand Up @@ -414,7 +433,7 @@ func (r *TokenResource) Create(ctx context.Context, req resource.CreateRequest,
return
}

orgCapabilities, diags := extractOrgCapabilities(ctx, plan)
orgCapabilities, diags := extractOrgCapabilities(ctx, plan.OrgCapabilities)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
Expand Down Expand Up @@ -443,7 +462,7 @@ func (r *TokenResource) Create(ctx context.Context, req resource.CreateRequest,
return
}

createTokenResponse, diagnostics := flattenCreateTokenResponse(token)
createTokenResponse, diagnostics := flattenCreateTokenResponse(ctx, token)
if diagnostics.HasError() {
resp.Diagnostics.Append(diagnostics...)
return
Expand All @@ -468,7 +487,7 @@ func (r *TokenResource) Read(ctx context.Context, req resource.ReadRequest, resp
return
}

token, diagnostics := flattenToken(apiToken)
token, diagnostics := flattenToken(ctx, apiToken)
if diagnostics.HasError() {
resp.Diagnostics.Append(diagnostics...)
return
Expand Down Expand Up @@ -501,18 +520,23 @@ func (r *TokenResource) ImportState(ctx context.Context, req resource.ImportStat
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}

func flattenToken(token *axiom.APIToken) (TokensResourceModel, diag.Diagnostics) {
func flattenToken(ctx context.Context, token *axiom.APIToken) (TokensResourceModel, diag.Diagnostics) {
dsCapabilities, diags := flattenDatasetCapabilities(context.Background(), token.DatasetCapabilities)
if diags.HasError() {
return TokensResourceModel{}, diags
}

orgCapabilities, diags := flattenOrgCapabilities(ctx, token.OrganisationCapabilities)
if diags.HasError() {
return TokensResourceModel{}, diags
}

t := TokensResourceModel{
ID: types.StringValue(token.ID),
Name: types.StringValue(token.Name),
Description: types.StringValue(token.Description),
DatasetCapabilities: dsCapabilities,
OrgCapabilities: flattenOrgCapabilities(token.OrganisationCapabilities),
OrgCapabilities: orgCapabilities,
}

if !token.ExpiresAt.IsZero() {
Expand All @@ -521,18 +545,22 @@ func flattenToken(token *axiom.APIToken) (TokensResourceModel, diag.Diagnostics)
return t, nil
}

func flattenCreateTokenResponse(token *axiom.CreateTokenResponse) (TokensResourceModel, diag.Diagnostics) {
func flattenCreateTokenResponse(ctx context.Context, token *axiom.CreateTokenResponse) (TokensResourceModel, diag.Diagnostics) {
dsCapabilities, diags := flattenDatasetCapabilities(context.Background(), token.DatasetCapabilities)
if diags.HasError() {
return TokensResourceModel{}, diags
}

orgCapabilities, diags := flattenOrgCapabilities(ctx, token.OrganisationCapabilities)
if diags.HasError() {
return TokensResourceModel{}, diags
}
t := TokensResourceModel{
ID: types.StringValue(token.ID),
Name: types.StringValue(token.Name),
Description: types.StringValue(token.Description),
DatasetCapabilities: dsCapabilities,
OrgCapabilities: flattenOrgCapabilities(token.OrganisationCapabilities),
OrgCapabilities: orgCapabilities,
Token: types.StringValue(token.Token),
}

Expand All @@ -542,8 +570,26 @@ func flattenCreateTokenResponse(token *axiom.CreateTokenResponse) (TokensResourc
return t, nil
}

func flattenOrgCapabilities(orgCapabilities axiom.OrganisationCapabilities) OrgCapabilities {
return OrgCapabilities{
func flattenOrgCapabilities(ctx context.Context, orgCapabilities axiom.OrganisationCapabilities) (types.Object, diag.Diagnostics) {
if allEmpty(
orgCapabilities.Annotations,
orgCapabilities.APITokens,
orgCapabilities.Billing,
orgCapabilities.Dashboards,
orgCapabilities.Datasets,
orgCapabilities.Endpoints,
orgCapabilities.Flows,
orgCapabilities.Integrations,
orgCapabilities.Monitors,
orgCapabilities.Notifiers,
orgCapabilities.RBAC,
orgCapabilities.SharedAccessKeys,
orgCapabilities.Users,
) {
return types.ObjectNull(OrgCapabilities{}.Types()), nil
}

return types.ObjectValueFrom(ctx, OrgCapabilities{}.Types(), OrgCapabilities{
Annotations: flattenAxiomActionSlice(orgCapabilities.Annotations),
APITokens: flattenAxiomActionSlice(orgCapabilities.APITokens),
Billing: flattenAxiomActionSlice(orgCapabilities.Billing),
Expand All @@ -557,7 +603,7 @@ func flattenOrgCapabilities(orgCapabilities axiom.OrganisationCapabilities) OrgC
Rbac: flattenAxiomActionSlice(orgCapabilities.RBAC),
SharedAccessKeys: flattenAxiomActionSlice(orgCapabilities.SharedAccessKeys),
Users: flattenAxiomActionSlice(orgCapabilities.Users),
}
})
}

func flattenDatasetCapabilities(ctx context.Context, datasetCapabilities map[string]axiom.DatasetCapabilities) (types.Map, diag.Diagnostics) {
Expand Down Expand Up @@ -634,81 +680,91 @@ func extractDatasetCapabilities(ctx context.Context, plan TokensResourceModel) (
return datasetCapabilities, nil
}

func extractOrgCapabilities(ctx context.Context, plan TokensResourceModel) (*axiom.OrganisationCapabilities, diag.Diagnostics) {
func extractOrgCapabilities(ctx context.Context, orgCap types.Object) (*axiom.OrganisationCapabilities, diag.Diagnostics) {
orgCapabilities := &axiom.OrganisationCapabilities{}
values, diags := typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Annotations.Elements())
if orgCap.IsNull() || orgCap.IsUnknown() {
return orgCapabilities, nil
}
planCapabilties := &OrgCapabilities{}

diags := orgCap.As(context.Background(), planCapabilties, basetypes.ObjectAsOptions{})
if diags.HasError() {
return nil, diags
}

values, diags := typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Annotations.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Annotations = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.APITokens.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.APITokens.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.APITokens = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Billing.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Billing.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Billing = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Dashboards.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Dashboards.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Dashboards = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Datasets.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Datasets.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Datasets = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Endpoints.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Endpoints.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Endpoints = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Flows.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Flows.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Flows = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Integrations.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Integrations.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Integrations = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Monitors.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Monitors.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Monitors = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Notifiers.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Notifiers.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.Notifiers = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Rbac.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Rbac.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.RBAC = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.SharedAccessKeys.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.SharedAccessKeys.Elements())
if diags.HasError() {
return nil, diags
}
orgCapabilities.SharedAccessKeys = values

values, diags = typeAxiomActionSliceToStringSlice(ctx, plan.OrgCapabilities.Users.Elements())
values, diags = typeAxiomActionSliceToStringSlice(ctx, planCapabilties.Users.Elements())
if diags.HasError() {
return nil, diags
}
Expand Down Expand Up @@ -776,3 +832,13 @@ func axiomActionFromString(value string) (axiom.Action, error) {
}
return action, nil
}

func allEmpty(val ...[]axiom.Action) bool {
for _, v := range val {
if len(v) != 0 {
return false
}
}
return true

}

0 comments on commit 21df00d

Please sign in to comment.