jsii icon indicating copy to clipboard operation
jsii copied to clipboard

golang generates duplicate methods

Open snowiow opened this issue 3 years ago • 2 comments

Describe the bug

We have an internal constructs library where we set internal best practices on top of the base constructs. Here is an example how we define our S3Bucket:

import * as s3 from 'aws-cdk-lib/aws-s3';
import { Bucket, BucketProps } from 'aws-cdk-lib/aws-s3';
import type { Construct } from 'constructs';

export class OurBucket extends Bucket {
  public constructor(scope: Construct, id: string, bucketProps: BucketProps) {
    super(scope, id, {
      accessControl: bucketProps.accessControl ?? s3.BucketAccessControl.PRIVATE,
      encryption: s3.BucketEncryption.S3_MANAGED,
      versioned: true,
      ...bucketProps,
    });
  }
}

Expected Behavior

We expect it to generate a go file with OurBucket where every method is defined once.

We either expect a struct like this:

type OurBucket interface {
	awss3.Bucket
}

or

type OurBucket interface {
	AutoCreatePolicy() *bool
	SetAutoCreatePolicy(val *bool)
	BucketArn() *string
	BucketDomainName() *string
	BucketDualStackDomainName() *string
	BucketName() *string
	BucketRegionalDomainName() *string
	BucketWebsiteDomainName() *string
	BucketWebsiteUrl() *string
	DisallowPublicAccess() *bool
	SetDisallowPublicAccess(val *bool)
	EncryptionKey() awskms.IKey
	Env() *awscdk.ResourceEnvironment
	IsWebsite() *bool
	Node() constructs.Node
	NotificationsHandlerRole() awsiam.IRole
	SetNotificationsHandlerRole(val awsiam.IRole)
	PhysicalName() *string
	Policy() awss3.BucketPolicy
	SetPolicy(val awss3.BucketPolicy)
	Stack() awscdk.Stack
	AddEventNotification(event awss3.EventType, dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddInventory(inventory *awss3.Inventory)
	AddLifecycleRule(rule *awss3.LifecycleRule)
	AddMetric(metric *awss3.BucketMetrics)
	AddObjectCreatedNotification(dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddObjectRemovedNotification(dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddToResourcePolicy(permission awsiam.PolicyStatement) *awsiam.AddToResourcePolicyResult
	ApplyRemovalPolicy(policy awscdk.RemovalPolicy)
	ArnForObjects(keyPattern *string) *string
	EnableEventBridgeNotification()
	GeneratePhysicalName() *string
	GetResourceArnAttribute(arnAttr *string, arnComponents *awscdk.ArnComponents) *string
	GetResourceNameAttribute(nameAttr *string) *string
	GrantDelete(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantPublicAccess(keyPrefix *string, allowedActions ...*string) awsiam.Grant
	GrantPut(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantPutAcl(identity awsiam.IGrantable, objectsKeyPattern *string) awsiam.Grant
	GrantRead(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantReadWrite(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantWrite(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	OnCloudTrailEvent(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	OnCloudTrailPutObject(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	OnCloudTrailWriteObject(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	ToString() *string
	UrlForObject(key *string) *string
	VirtualHostedUrlForObject(key *string, options *awss3.VirtualHostedStyleUrlOptions) *string
}


### Current Behavior

Instead we get this kind of struct in go (without all the comments):

```go
type OurBucket interface {
	awss3.Bucket
	AutoCreatePolicy() *bool
	SetAutoCreatePolicy(val *bool)
	BucketArn() *string
	BucketDomainName() *string
	BucketDualStackDomainName() *string
	BucketName() *string
	BucketRegionalDomainName() *string
	BucketWebsiteDomainName() *string
	BucketWebsiteUrl() *string
	DisallowPublicAccess() *bool
	SetDisallowPublicAccess(val *bool)
	EncryptionKey() awskms.IKey
	Env() *awscdk.ResourceEnvironment
	IsWebsite() *bool
	Node() constructs.Node
	NotificationsHandlerRole() awsiam.IRole
	SetNotificationsHandlerRole(val awsiam.IRole)
	PhysicalName() *string
	Policy() awss3.BucketPolicy
	SetPolicy(val awss3.BucketPolicy)
	Stack() awscdk.Stack
	AddEventNotification(event awss3.EventType, dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddInventory(inventory *awss3.Inventory)
	AddLifecycleRule(rule *awss3.LifecycleRule)
	AddMetric(metric *awss3.BucketMetrics)
	AddObjectCreatedNotification(dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddObjectRemovedNotification(dest awss3.IBucketNotificationDestination, filters ...*awss3.NotificationKeyFilter)
	AddToResourcePolicy(permission awsiam.PolicyStatement) *awsiam.AddToResourcePolicyResult
	ApplyRemovalPolicy(policy awscdk.RemovalPolicy)
	ArnForObjects(keyPattern *string) *string
	EnableEventBridgeNotification()
	GeneratePhysicalName() *string
	GetResourceArnAttribute(arnAttr *string, arnComponents *awscdk.ArnComponents) *string
	GetResourceNameAttribute(nameAttr *string) *string
	GrantDelete(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantPublicAccess(keyPrefix *string, allowedActions ...*string) awsiam.Grant
	GrantPut(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantPutAcl(identity awsiam.IGrantable, objectsKeyPattern *string) awsiam.Grant
	GrantRead(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantReadWrite(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	GrantWrite(identity awsiam.IGrantable, objectsKeyPattern interface{}) awsiam.Grant
	OnCloudTrailEvent(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	OnCloudTrailPutObject(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	OnCloudTrailWriteObject(id *string, options *awss3.OnCloudTrailBucketEventOptions) awsevents.Rule
	ToString() *string
	UrlForObject(key *string) *string
	VirtualHostedUrlForObject(key *string, options *awss3.VirtualHostedStyleUrlOptions) *string
}

and when we try to use the generated go library we get for example this error:

# github.com/our-org/our-cdk-construct-library-go/ourcdk/v2
vendor/github.com/our-org/our-cdk-construct-library-go/ourcdk/v2/ourcdk_OurBucket.go:18:2: duplicate method GrantWrite
vendor/github.com/our-org/our-cdk-construct-library-go/ourcdk/v2/ourcdk_OurBucket.go:223:2: other declaration of GrantWrite

because once all the methods are defined by importing the parent type awss3.Bucket and then all methods are defined a second time in the type itself.

Reproduction Steps

This is our jsii config snippet to generate go:

  "jsii": {
    "outdir": "dist",
    "targets": {
      "go": {
        "moduleName": "github.com/our-org/our-cdk-construct-library-go",
        "packageName": "ourcdk"
      }
    }
  },

Possible Solution

I'm not sure if this is a bug or if we do a mistake in how we use jsii. So maybe there is another way how we should code these constructs, so that they generate correct go code. But the currently produced go code doesn't seem to be the expected result.

Thanks already for looking into this and for any kind of guidance :pray:

Additional Information/Context

No response

SDK version used

1.79.0

Environment details (OS name and version, etc.)

Linux

snowiow avatar Mar 31 '23 13:03 snowiow

Ran into this myself, might be related to v1.119.0?

polothy avatar Nov 20 '25 17:11 polothy

nvm, I didn't realize how old this issue was and I was able to resolve my problem by performing some reverts and redoing go get -u ./... - I was testing via a replace in my go.mod so I suspect something got messed up when I removed it.

polothy avatar Nov 20 '25 22:11 polothy