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

azurerm_trusted_signing_account - new resource support #27720

Merged
merged 8 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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 .github/labeler-issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ service/bots:
service/cdn:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_cdn_((.|\n)*)###'

service/codesigning:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_trusted_signing_account((.|\n)*)###'

service/cognitive-services:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(ai_services|cognitive_)((.|\n)*)###'

Expand Down
5 changes: 5 additions & 0 deletions .github/labeler-pull-request-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ service/cdn:
- any-glob-to-any-file:
- internal/services/cdn/**/*

service/codesigning:
- changed-files:
- any-glob-to-any-file:
- internal/services/codesigning/**/*

service/cognitive-services:
- changed-files:
- any-glob-to-any-file:
Expand Down
1 change: 1 addition & 0 deletions .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ var services = mapOf(
"synapse" to "Synapse",
"systemcentervirtualmachinemanager" to "System Center Virtual Machine Manager",
"trafficmanager" to "Traffic Manager",
"codesigning" to "Trusted Signing",
"vmware" to "VMware",
"voiceservices" to "Voice Services",
"web" to "Web",
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ require (
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-azure-helpers v0.70.1
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241009.1142232
github.com/hashicorp/go-azure-sdk/sdk v0.20241009.1142232
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241017.1093842
github.com/hashicorp/go-azure-sdk/sdk v0.20241017.1093842
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating the go-azure-sdk should be done in a separate PR otherwise we end up causing conflicts like has happened here.

github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-uuid v1.0.3
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-azure-helpers v0.70.1 h1:7hlnRrZobMZxpOzdlNEsayzAayj/KRG4wpDS1jgo4GM=
github.com/hashicorp/go-azure-helpers v0.70.1/go.mod h1:BmbF4JDYXK5sEmFeU5hcn8Br21uElcqLfdQxjatwQKw=
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241009.1142232 h1:LAN6wm2cHFo56ly09tg0jXHioh4ygq3SzDoX+XBsMOU=
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241009.1142232/go.mod h1:Zifz0xUVKdiNCzvp3HTa0CNCueZlxD2tdgqPf2QA3qs=
github.com/hashicorp/go-azure-sdk/sdk v0.20241009.1142232 h1:CxBWfnrsR/Vdyd+4N782xzYoqw5bczBSguwOpiF7VO8=
github.com/hashicorp/go-azure-sdk/sdk v0.20241009.1142232/go.mod h1:dMKF6bXrgGmy1d3pLzkmBpG2JIHgSAV2/OMSCEgyMwE=
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241017.1093842 h1:GRGeerwPZiUHLkujG//JgbsB0gEoE65mnKhzQR9m6pg=
github.com/hashicorp/go-azure-sdk/resource-manager v0.20241017.1093842/go.mod h1:w43bj+jYD+kL5Tp1T+cxgmZjdU5/zjlEZ5A1nwJlEOs=
github.com/hashicorp/go-azure-sdk/sdk v0.20241017.1093842 h1:lqU3vkM+F2F8TrkIGnhLB4H9nBjtLlzkOVMWxZNtio8=
github.com/hashicorp/go-azure-sdk/sdk v0.20241017.1093842/go.mod h1:dMKF6bXrgGmy1d3pLzkmBpG2JIHgSAV2/OMSCEgyMwE=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
Expand Down
5 changes: 5 additions & 0 deletions internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
blueprints "github.com/hashicorp/terraform-provider-azurerm/internal/services/blueprints/client"
bot "github.com/hashicorp/terraform-provider-azurerm/internal/services/bot/client"
cdn "github.com/hashicorp/terraform-provider-azurerm/internal/services/cdn/client"
codesigning "github.com/hashicorp/terraform-provider-azurerm/internal/services/codesigning/client"
cognitiveServices "github.com/hashicorp/terraform-provider-azurerm/internal/services/cognitive/client"
communication "github.com/hashicorp/terraform-provider-azurerm/internal/services/communication/client"
compute "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/client"
Expand Down Expand Up @@ -174,6 +175,7 @@ type Client struct {
Blueprints *blueprints.Client
Bot *bot.Client
Cdn *cdn.Client
CodeSigning *codesigning.Client
Cognitive *cognitiveServices.Client
Communication *communication.Client
Compute *compute.Client
Expand Down Expand Up @@ -347,6 +349,9 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
return fmt.Errorf("building clients for Bot: %+v", err)
}
client.Cdn = cdn.NewClient(o)
if client.CodeSigning, err = codesigning.NewClient(o); err != nil {
return fmt.Errorf("building clients for Code Signing: %+v", err)
}
if client.Cognitive, err = cognitiveServices.NewClient(o); err != nil {
return fmt.Errorf("building clients for Cognitive: %+v", err)
}
Expand Down
2 changes: 2 additions & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/services/blueprints"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/bot"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/cdn"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/codesigning"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/cognitive"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/communication"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute"
Expand Down Expand Up @@ -148,6 +149,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration {
azurestackhci.Registration{},
batch.Registration{},
bot.Registration{},
codesigning.Registration{},
cognitive.Registration{},
communication.Registration{},
compute.Registration{},
Expand Down
27 changes: 27 additions & 0 deletions internal/services/codesigning/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package client

import (
"fmt"

codesigning_v2024_09_30_preview "github.com/hashicorp/go-azure-sdk/resource-manager/codesigning/2024-09-30-preview"

"github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

type Client struct {
Client codesigning_v2024_09_30_preview.Client
}

func NewClient(o *common.ClientOptions) (*Client, error) {
V20240930previewClient, err := codesigning_v2024_09_30_preview.NewClientWithBaseURI(o.Environment.ResourceManager, func(c *resourcemanager.Client) {
o.Configure(c, o.Authorizers.ResourceManager)
})
if err != nil {
return nil, fmt.Errorf("building client for codesigning v20240930preview: %+v", err)
}

return &Client{
Client: *V20240930previewClient,
}, nil
}
40 changes: 40 additions & 0 deletions internal/services/codesigning/registration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package codesigning

import (
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
)

type Registration struct{}

var _ sdk.TypedServiceRegistration = Registration{}

func (r Registration) AssociatedGitHubLabel() string {
return "service/codesigning"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably just call this

Suggested change
return "service/codesigning"
return "service/trustedsigning"

}

// Name is the name of this Service
func (r Registration) Name() string {
return "Trusted Signing"
}

// WebsiteCategories returns a list of categories which can be used for the sidebar
func (r Registration) WebsiteCategories() []string {
return []string{
"Trusted Signing",
}
}

// DataSources returns a list of Data Sources supported by this Service
func (r Registration) DataSources() []sdk.DataSource {
return []sdk.DataSource{}
}

// Resources returns a list of Resources supported by this Service
func (r Registration) Resources() []sdk.Resource {
return []sdk.Resource{
TrustedSigningAccountResource{},
}
}
221 changes: 221 additions & 0 deletions internal/services/codesigning/trusted_signing_account_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package codesigning

import (
"context"
"fmt"
"regexp"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-sdk/resource-manager/codesigning/2024-09-30-preview/codesigningaccounts"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type TruestedSigningAccountModel struct {
Name string `tfschema:"name"`
Location string `tfschema:"location"`
ResourceGroupName string `tfschema:"resource_group_name"`
AccountUri string `tfschema:"account_uri"`
SkuName string `tfschema:"sku_name"`
Tags map[string]string `tfschema:"tags"`
}

type TrustedSigningAccountResource struct{}

var _ sdk.Resource = (*TrustedSigningAccountResource)(nil)

func (m TrustedSigningAccountResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(3, 24),
validation.StringMatch(
regexp.MustCompile("^[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*$"),
"An account's name must be between 3-24 alphanumeric characters. The name must begin with a letter, end with a letter or digit, and not contain consecutive hyphens.",
),
),
},

"location": commonschema.Location(),

"resource_group_name": commonschema.ResourceGroupName(),

"sku_name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(
codesigningaccounts.PossibleValuesForSkuName(),
false),
},

"tags": commonschema.Tags(),
}
}

func (m TrustedSigningAccountResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"account_uri": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func (m TrustedSigningAccountResource) ModelObject() interface{} {
return &TruestedSigningAccountModel{}
}

func (m TrustedSigningAccountResource) ResourceType() string {
return "azurerm_trusted_signing_account"
}

func (m TrustedSigningAccountResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
client := meta.Client.CodeSigning.Client.CodeSigningAccounts

var model TruestedSigningAccountModel
if err := meta.Decode(&model); err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These errors should be wrapped

Suggested change
return err
return fmt.Errorf("decoding: %+v", err)

}

subscriptionID := meta.Client.Account.SubscriptionId
id := codesigningaccounts.NewCodeSigningAccountID(subscriptionID, model.ResourceGroupName, model.Name)
existing, err := client.Get(ctx, id)
if !response.WasNotFound(existing.HttpResponse) {
if err != nil {
return fmt.Errorf("retrieving %s: %v", id, err)
}
return meta.ResourceRequiresImport(m.ResourceType(), id)
}

req := codesigningaccounts.CodeSigningAccount{}
req.Name = &model.Name
req.Location = model.Location
req.Properties = pointer.To(codesigningaccounts.CodeSigningAccountProperties{})
req.Properties.Sku = pointer.To(codesigningaccounts.AccountSku{
Name: codesigningaccounts.SkuName(model.SkuName),
})
req.Tags = &model.Tags
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update this to

Suggested change
req := codesigningaccounts.CodeSigningAccount{}
req.Name = &model.Name
req.Location = model.Location
req.Properties = pointer.To(codesigningaccounts.CodeSigningAccountProperties{})
req.Properties.Sku = pointer.To(codesigningaccounts.AccountSku{
Name: codesigningaccounts.SkuName(model.SkuName),
})
req.Tags = &model.Tags
req := codesigningaccounts.CodeSigningAccount{
Name: &model.Name
Location: location.Normalize(model.Location)
Tags: &model.Tags
Properties: &codesigningaccounts.CodeSigningAccountProperties{
Sku: &codesigningaccounts.AccountSku{
Name: codesigningaccounts.SkuName(model.SkuName),
}
}
}


err = client.CreateThenPoll(ctx, id, req)
if err != nil {
return fmt.Errorf("creating %s: %v", id, err)
}

meta.SetID(id)
return nil
},
}
}

func (m TrustedSigningAccountResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := codesigningaccounts.ParseCodeSigningAccountID(meta.ResourceData.Id())
if err != nil {
return err
}

client := meta.Client.CodeSigning.Client.CodeSigningAccounts
result, err := client.Get(ctx, *id)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return err
return fmt.Errorf("retrieving %s: %+v", id, err)

}

if result.Model == nil {
return fmt.Errorf("retrieving %s got nil model", id)
}
var output TruestedSigningAccountModel
output.Name = id.CodeSigningAccountName
output.ResourceGroupName = id.ResourceGroupName

if result.Model == nil {
return fmt.Errorf("Get response nil Model")
}
model := result.Model
output.Location = model.Location
output.Tags = pointer.From(model.Tags)
if ptrProp := model.Properties; ptrProp != nil {
itemProp := *ptrProp
output.AccountUri = pointer.From(itemProp.AccountUri)
if ptrSku := itemProp.Sku; ptrSku != nil {
itemSku := *ptrSku
output.SkuName = string(itemSku.Name)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't error if the model is nil in the read, yet we're doing it twice here. This is also inconsistent with our contributor guidelines and the rest of the provider. Please refactor this

Suggested change
if result.Model == nil {
return fmt.Errorf("retrieving %s got nil model", id)
}
var output TruestedSigningAccountModel
output.Name = id.CodeSigningAccountName
output.ResourceGroupName = id.ResourceGroupName
if result.Model == nil {
return fmt.Errorf("Get response nil Model")
}
model := result.Model
output.Location = model.Location
output.Tags = pointer.From(model.Tags)
if ptrProp := model.Properties; ptrProp != nil {
itemProp := *ptrProp
output.AccountUri = pointer.From(itemProp.AccountUri)
if ptrSku := itemProp.Sku; ptrSku != nil {
itemSku := *ptrSku
output.SkuName = string(itemSku.Name)
}
}
var output TruestedSigningAccountModel
output.Name = id.CodeSigningAccountName
output.ResourceGroupName = id.ResourceGroupName
if model := result.Model; model != nil {
output.Location = location.Normalize(model.Location)
output.Tags = pointer.From(model.Tags)
if props := model.Properties; props != nil {
output.AccountUri = pointer.From(props.AccountUri)
if sku := props.Sku; sku != nil {
output.SkuName = string(sku.Name)
}
}
}


return meta.Encode(&output)
},
}
}

func (m TrustedSigningAccountResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) (err error) {
client := meta.Client.CodeSigning.Client.CodeSigningAccounts
id, err := codesigningaccounts.ParseCodeSigningAccountID(meta.ResourceData.Id())
if err != nil {
return err
}
var model TruestedSigningAccountModel
if err = meta.Decode(&model); err != nil {
return fmt.Errorf("decoding %s: %+v", id, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return fmt.Errorf("decoding %s: %+v", id, err)
return fmt.Errorf("decoding: %+v", err)

}

var upd codesigningaccounts.CodeSigningAccountPatch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor but upd is not a known acronym or shorthand for update which isn't a long variable name in itself. Can we please be consistent with other resources in the provider and name these one of payload, request, param or spell this out completely to update?

if meta.ResourceData.HasChange("sku_name") {
upd.Properties = pointer.To(codesigningaccounts.CodeSigningAccountPatchProperties{
Sku: pointer.To(codesigningaccounts.AccountSkuPatch{
Name: pointer.To(codesigningaccounts.SkuName(model.SkuName)),
}),
})
}
if meta.ResourceData.HasChange("tags") {
upd.Tags = pointer.To(model.Tags)
}

if err = client.UpdateThenPoll(ctx, *id, upd); err != nil {
return fmt.Errorf("updating %s: %v", id, err)
}

return nil
},
}
}

func (m TrustedSigningAccountResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := codesigningaccounts.ParseCodeSigningAccountID(meta.ResourceData.Id())
if err != nil {
return err
}

meta.Logger.Infof("deleting %s", id)
client := meta.Client.CodeSigning.Client.CodeSigningAccounts
if _, err = client.Delete(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %v", id, err)
}
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider the ordering of variable declarations within the CRUD functions, there is no good reason to reorder this when 99% of the provider follows the sequence suggested below.

Suggested change
id, err := codesigningaccounts.ParseCodeSigningAccountID(meta.ResourceData.Id())
if err != nil {
return err
}
meta.Logger.Infof("deleting %s", id)
client := meta.Client.CodeSigning.Client.CodeSigningAccounts
if _, err = client.Delete(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %v", id, err)
}
return nil
client := meta.Client.CodeSigning.Client.CodeSigningAccounts
id, err := codesigningaccounts.ParseCodeSigningAccountID(meta.ResourceData.Id())
if err != nil {
return err
}
meta.Logger.Infof("deleting %s", id)
if _, err = client.Delete(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %v", id, err)
}
return nil

},
}
}

func (m TrustedSigningAccountResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return codesigningaccounts.ValidateCodeSigningAccountID
}
Loading
Loading