Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -1,161 +1,202 @@
package pubsub

import (
"fmt"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
{{- if ne $.Compiler "terraformgoogleconversion-codegen"}}
"github.com/hashicorp/terraform-provider-google/google/registry"
{{- end}}
"github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/pubsub/v1"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/list"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
{{- if ne $.Compiler "terraformgoogleconversion-codegen"}}
"github.com/hashicorp/terraform-provider-google/google/registry"
{{- end}}
"github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/pubsub/v1"
)

var IamPubsubSubscriptionSchema = map[string]*schema.Schema{
"subscription": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"subscription": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
}

type PubsubSubscriptionIamUpdater struct {
subscription string
d tpgresource.TerraformResourceData
Config *transport_tpg.Config
subscription string
d tpgresource.TerraformResourceData
Config *transport_tpg.Config
}

func NewPubsubSubscriptionIamUpdater(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (tpgiamresource.ResourceIamUpdater, error) {
project, err := tpgresource.GetProject(d, config)
if err != nil {
return nil, err
}

subscription := GetComputedSubscriptionName(project, d.Get("subscription").(string))

return &PubsubSubscriptionIamUpdater{
subscription: subscription,
d: d,
Config: config,
}, nil
project, err := tpgresource.GetProject(d, config)
if err != nil {
return nil, err
}

subscription := GetComputedSubscriptionName(project, d.Get("subscription").(string))

return &PubsubSubscriptionIamUpdater{
subscription: subscription,
d: d,
Config: config,
}, nil
}

func PubsubSubscriptionIdParseFunc(d *schema.ResourceData, _ *transport_tpg.Config) error {
if err := d.Set("subscription", d.Id()); err != nil {
return fmt.Errorf("Error setting subscription: %s", err)
}
return nil
if err := d.Set("subscription", d.Id()); err != nil {
return fmt.Errorf("Error setting subscription: %s", err)
}
return nil
}

func (u *PubsubSubscriptionIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
if err != nil {
return nil, err
}
userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
if err != nil {
return nil, err
}

p, err := NewClient(u.Config, userAgent).Projects.Subscriptions.GetIamPolicy(u.subscription).Do()
p, err := NewClient(u.Config, userAgent).Projects.Subscriptions.GetIamPolicy(u.subscription).Do()

if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{"{{"}}err{{"}}"}}", u.DescribeResource()), err)
}
if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{"{{"}}err{{"}}"}}", u.DescribeResource()), err)
}

v1Policy, err := pubsubToResourceManagerPolicy(p)
if err != nil {
return nil, err
}
v1Policy, err := pubsubToResourceManagerPolicy(p)
if err != nil {
return nil, err
}

return v1Policy, nil
return v1Policy, nil
}

func (u *PubsubSubscriptionIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
if err != nil {
return err
}
userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent)
if err != nil {
return err
}

pubsubPolicy, err := resourceManagerToPubsubPolicy(policy)
if err != nil {
return err
}
pubsubPolicy, err := resourceManagerToPubsubPolicy(policy)
if err != nil {
return err
}

_, err = NewClient(u.Config, userAgent).Projects.Subscriptions.SetIamPolicy(u.subscription, &pubsub.SetIamPolicyRequest{
Policy: pubsubPolicy,
}).Do()
_, err = NewClient(u.Config, userAgent).Projects.Subscriptions.SetIamPolicy(u.subscription, &pubsub.SetIamPolicyRequest{
Policy: pubsubPolicy,
}).Do()

if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{"{{"}}err{{"}}"}}", u.DescribeResource()), err)
}
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{"{{"}}err{{"}}"}}", u.DescribeResource()), err)
}

return nil
return nil
}

func (u *PubsubSubscriptionIamUpdater) GetResourceId() string {
return u.subscription
return u.subscription
}

func (u *PubsubSubscriptionIamUpdater) GetMutexKey() string {
return fmt.Sprintf("iam-pubsub-subscription-%s", u.subscription)
return fmt.Sprintf("iam-pubsub-subscription-%s", u.subscription)
}

func (u *PubsubSubscriptionIamUpdater) DescribeResource() string {
return fmt.Sprintf("pubsub subscription %q", u.subscription)
return fmt.Sprintf("pubsub subscription %q", u.subscription)
}

// v1 and v2 policy are identical
func resourceManagerToPubsubPolicy(in *cloudresourcemanager.Policy) (*pubsub.Policy, error) {
out := &pubsub.Policy{}
err := tpgresource.Convert(in, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a v1 policy to a pubsub policy: {{"{{"}}err{{"}}"}}", err)
}
return out, nil
out := &pubsub.Policy{}
err := tpgresource.Convert(in, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a v1 policy to a pubsub policy: {{"{{"}}err{{"}}"}}", err)
}
return out, nil
}

func pubsubToResourceManagerPolicy(in *pubsub.Policy) (*cloudresourcemanager.Policy, error) {
out := &cloudresourcemanager.Policy{}
err := tpgresource.Convert(in, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a pubsub policy to a v1 policy: {{"{{"}}err{{"}}"}}", err)
}
return out, nil
out := &cloudresourcemanager.Policy{}
err := tpgresource.Convert(in, out)
if err != nil {
return nil, errwrap.Wrapf("Cannot convert a pubsub policy to a v1 policy: {{"{{"}}err{{"}}"}}", err)
}
return out, nil
}

// PubsubSubscriptionIamParentResourceIdentityParser resolves the parent topic id from import identity.
func PubsubSubscriptionIamParentResourceIdentityParser(d *schema.ResourceData, identity *schema.IdentityData, config *transport_tpg.Config) (string, error) {
return tpgiamresource.ParseIamResourceIdentity(d, identity, config, tpgiamresource.IamResourceIdentityConfig{
Params: []tpgiamresource.IamIdentityParam{
{Key: "project", IdentityKey: "project"},
{Key: "subscription", IdentityKey: "subscription"},
},
UriFormat: "projects/%s/subscriptions/%s",
})
}

func PubsubSubscriptionIamMemberResource() *schema.Resource {
return tpgiamresource.ResourceIamMember(
IamPubsubSubscriptionSchema,
NewPubsubSubscriptionIamUpdater,
PubsubSubscriptionIdParseFunc,
tpgiamresource.IamWithParentResourceIdentity(PubsubSubscriptionIamParentResourceIdentityParser),
)
}

func NewPubsubSubscriptionIamMemberListResource() list.ListResource {
return tpgiamresource.NewIamMemberListResource(
"google_pubsub_subscription_iam_member",
PubsubSubscriptionIamMemberResource(),
NewPubsubSubscriptionIamUpdater,
tpgiamresource.IamMemberListCallConfig{
ParentResourceField: "subscription",
EnableRoleFilter: true,
EnableMemberFilter: true,
EnableProjectField: true,
},
)
}

{{- if ne $.Compiler "terraformgoogleconversion-codegen"}}

func init() {
registry.Schema{
Name: "google_pubsub_subscription_iam_member",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: tpgiamresource.ResourceIamMember(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_binding",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: tpgiamresource.ResourceIamBinding(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_policy",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: tpgiamresource.ResourceIamPolicy(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_policy",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMDataSource,
Schema: tpgiamresource.DataSourceIamPolicy(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_member",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: PubsubSubscriptionIamMemberResource(),
}.Register()
registry.FrameworkListResource{
Name: "google_pubsub_subscription_iam_member",
ProductName: "pubsub",
Func: NewPubsubSubscriptionIamMemberListResource,
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_binding",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: tpgiamresource.ResourceIamBinding(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_policy",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMResource,
Schema: tpgiamresource.ResourceIamPolicy(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
}.Register()
registry.Schema{
Name: "google_pubsub_subscription_iam_policy",
ProductName: "pubsub",
Type: registry.SchemaTypeIAMDataSource,
Schema: tpgiamresource.DataSourceIamPolicy(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater),
}.Register()
}
{{- end}}
{{- end}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package pubsub

import "testing"

func TestPubsubSubscriptionIamMemberResource_HasIdentity(t *testing.T) {
resource := PubsubSubscriptionIamMemberResource()
if resource.Identity == nil {
t.Fatalf("expected google_pubsub_subscription_iam_member resource identity to be configured")
}
}

func TestStorageBucketIamParentResourceIdentityParser(t *testing.T) {
tests := []struct {
name string
projectValue string
subscriptionValue string
want string
}{
{
name: "short subscription name",
projectValue: "my-project",
subscriptionValue: "my-subscription",
want: "projects/my-project/subscriptions/my-subscription",
},
{
name: "canonical subscription name",
projectValue: "my-project",
subscriptionValue: "projects/my-project/subscriptions/my-subscription",
want: "projects/my-project/subscriptions/my-subscription",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource := PubsubSubscriptionIamMemberResource()
rd := resource.TestResourceData()
identity, err := rd.Identity()
if err != nil {
t.Fatalf("creating identity: %v", err)
}
if err := identity.Set("project", tt.projectValue); err != nil {
t.Fatalf("setting identity project: %v", err)
}
if err := identity.Set("subscription", tt.subscriptionValue); err != nil {
t.Fatalf("setting identity subscription: %v", err)
}

got, err := PubsubSubscriptionIamParentResourceIdentityParser(rd, identity, nil)
if err != nil {
t.Fatalf("parsing identity: %v", err)
}
if got != tt.want {
t.Fatalf("unexpected parsed id: got %q, want %q", got, tt.want)
}
})
}
}
Loading
Loading