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

[exporter/awss3exporter] Add canned_acl as an input #37953

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
27 changes: 27 additions & 0 deletions .chloggen/s3exporter-canned-acl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: 'enhancement'

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: awss3exporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Added `acl` option

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [37935]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
1 change: 1 addition & 0 deletions exporter/awss3exporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The following exporter configuration parameters are supported.
| `encoding_file_extension` | file format extension suffix when using the `encoding` configuration option. May be left empty for no suffix to be appended. | |
| `endpoint` | (REST API endpoint) overrides the endpoint used by the exporter instead of constructing it from `region` and `s3_bucket` | |
| `storage_class` | [S3 storageclass](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html) | STANDARD |
| `acl` | [S3 Object Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl) | private |
| `s3_force_path_style` | [set this to `true` to force the request to use path-style addressing](http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html) | false |
| `disable_ssl` | set this to `true` to disable SSL when sending requests | false |
| `compression` | should the file be compressed | none |
Expand Down
16 changes: 16 additions & 0 deletions exporter/awss3exporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type S3UploaderConfig struct {
S3ForcePathStyle bool `mapstructure:"s3_force_path_style"`
// DisableSLL forces communication to happen via HTTP instead of HTTPS.
DisableSSL bool `mapstructure:"disable_ssl"`
// ACL is the canned ACL to use when uploading objects.
ACL string `mapstructure:"acl"`

StorageClass string `mapstructure:"storage_class"`
// Compression sets the algorithm used to process the payload
Expand Down Expand Up @@ -73,6 +75,16 @@ func (c *Config) Validate() error {
"DEEP_ARCHIVE": true,
}

validACLs := map[string]bool{
"private": true,
"public-read": true,
"public-read-write": true,
"authenticated-read": true,
"aws-exec-read": true,
"bucket-owner-read": true,
"bucket-owner-full-control": true,
}

if c.S3Uploader.Region == "" {
errs = multierr.Append(errs, errors.New("region is required"))
}
Expand All @@ -84,6 +96,10 @@ func (c *Config) Validate() error {
errs = multierr.Append(errs, errors.New("invalid StorageClass"))
}

if !validACLs[c.S3Uploader.ACL] {
errs = multierr.Append(errs, errors.New("invalid ACL"))
}

compression := c.S3Uploader.Compression
if compression.IsCompressed() {
if compression != configcompression.TypeGzip {
Expand Down
43 changes: 42 additions & 1 deletion exporter/awss3exporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TestLoadConfig(t *testing.T) {
S3Bucket: "foo",
S3Partition: "minute",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_json",
}, e,
Expand Down Expand Up @@ -79,13 +80,14 @@ func TestConfig(t *testing.T) {
S3Partition: "minute",
Endpoint: "http://endpoint.com",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_json",
}, e,
)
}

func TestConfigS3StorageClaas(t *testing.T) {
func TestConfigS3StorageClass(t *testing.T) {
factories, err := otelcoltest.NopFactories()
assert.NoError(t, err)

Expand All @@ -110,6 +112,40 @@ func TestConfigS3StorageClaas(t *testing.T) {
S3Partition: "minute",
Endpoint: "http://endpoint.com",
StorageClass: "STANDARD_IA",
ACL: "private",
},
QueueSettings: queueCfg,
MarshalerName: "otlp_json",
}, e,
)
}

func TestConfigS3ACL(t *testing.T) {
factories, err := otelcoltest.NopFactories()
assert.NoError(t, err)

factory := NewFactory()
factories.Exporters[factory.Type()] = factory
// https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33594
cfg, err := otelcoltest.LoadConfigAndValidate(
filepath.Join("testdata", "config-s3_storage_class.yaml"), factories)

require.NoError(t, err)
require.NotNil(t, cfg)

e := cfg.Exporters[component.MustNewID("awss3")].(*Config)
queueCfg := exporterhelper.NewDefaultQueueConfig()
queueCfg.Enabled = false

assert.Equal(t, &Config{
S3Uploader: S3UploaderConfig{
Region: "us-east-1",
S3Bucket: "foo",
S3Prefix: "bar",
S3Partition: "minute",
Endpoint: "http://endpoint.com",
StorageClass: "STANDARD_IA",
ACL: "private",
},
QueueSettings: queueCfg,
MarshalerName: "otlp_json",
Expand Down Expand Up @@ -145,6 +181,7 @@ func TestConfigForS3CompatibleSystems(t *testing.T) {
S3ForcePathStyle: true,
DisableSSL: true,
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_json",
}, e,
Expand Down Expand Up @@ -256,6 +293,7 @@ func TestMarshallerName(t *testing.T) {
S3Bucket: "foo",
S3Partition: "minute",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "sumo_ic",
}, e,
Expand All @@ -270,6 +308,7 @@ func TestMarshallerName(t *testing.T) {
S3Bucket: "bar",
S3Partition: "minute",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_proto",
}, e,
Expand Down Expand Up @@ -301,6 +340,7 @@ func TestCompressionName(t *testing.T) {
S3Partition: "minute",
Compression: "gzip",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_json",
}, e,
Expand All @@ -316,6 +356,7 @@ func TestCompressionName(t *testing.T) {
S3Partition: "minute",
Compression: "none",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_proto",
}, e,
Expand Down
1 change: 1 addition & 0 deletions exporter/awss3exporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func createDefaultConfig() component.Config {
Region: "us-east-1",
S3Partition: "minute",
StorageClass: "STANDARD",
ACL: "private",
},
MarshalerName: "otlp_json",
}
Expand Down
5 changes: 4 additions & 1 deletion exporter/awss3exporter/internal/upload/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ type s3manager struct {
builder *PartitionKeyBuilder
uploader *manager.Uploader
storageClass s3types.StorageClass
acl s3types.ObjectCannedACL
}

var _ Manager = (*s3manager)(nil)

func NewS3Manager(bucket string, builder *PartitionKeyBuilder, service *s3.Client, storageClass s3types.StorageClass) Manager {
func NewS3Manager(bucket string, builder *PartitionKeyBuilder, service *s3.Client, storageClass s3types.StorageClass, acl s3types.ObjectCannedACL) Manager {
return &s3manager{
bucket: bucket,
builder: builder,
uploader: manager.NewUploader(service),
storageClass: storageClass,
acl: acl,
}
}

Expand All @@ -61,6 +63,7 @@ func (sw *s3manager) Upload(ctx context.Context, data []byte) error {
Body: content,
ContentEncoding: aws.String(encoding),
StorageClass: sw.storageClass,
ACL: sw.acl,
})

return err
Expand Down
2 changes: 2 additions & 0 deletions exporter/awss3exporter/internal/upload/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestNewS3Manager(t *testing.T) {
&PartitionKeyBuilder{},
s3.New(s3.Options{}),
"STANDARD",
"private",
)

assert.NotNil(t, sm, "Must have a valid client returned")
Expand Down Expand Up @@ -154,6 +155,7 @@ func TestS3ManagerUpload(t *testing.T) {
Region: "local",
}),
"STANDARD_IA",
"private",
)

// Using a mocked virtual clock to fix the timestamp used
Expand Down
1 change: 1 addition & 0 deletions exporter/awss3exporter/s3_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@ func newUploadManager(
},
s3.NewFromConfig(cfg, s3Opts...),
s3types.StorageClass(conf.S3Uploader.StorageClass),
s3types.ObjectCannedACL(conf.S3Uploader.ACL),
), nil
}
23 changes: 23 additions & 0 deletions exporter/awss3exporter/testdata/config-s3_acl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
receivers:
nop:

exporters:
awss3:
s3uploader:
region: 'us-east-1'
s3_bucket: 'foo'
s3_prefix: 'bar'
s3_partition: 'minute'
endpoint: "http://endpoint.com"
storage_class: "STANDARD"
acl: "bucket-owner-full-control"

processors:
nop:

service:
pipelines:
traces:
receivers: [nop]
processors: [nop]
exporters: [awss3]
Loading