//go:build linux && unit // +build linux,unit // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may // not use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. package firelens import ( "bytes" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var ( testFluentdOptions = map[string]string{ "@type": "kinesis_firehose", "region": "us-west-2", "deliver_stream_name": "my-stream", "include-pattern": "*failure*", "exclude-pattern": "*success*", } testFluentbitOptions = map[string]string{ "Name": "kinesis_firehose", "region": "us-west-2", "deliver_stream_name": "my-stream", "include-pattern": "*failure*", "exclude-pattern": "*success*", } expectedFluentdBridgeModeConfig = ` @type unix path /var/run/fluent.sock @type forward bind 0.0.0.0 port 24224 @type grep key log pattern *failure* @type grep key log pattern *success* @type record_transformer ec2_instance_id i-123456789a ecs_cluster mycluster ecs_task_arn arn:aws:ecs:us-east-2:01234567891011:task/mycluster/3de392df-6bfa-470b-97ed-aa6f482cd7a ecs_task_definition taskdefinition:1 @include /tmp/dummy.conf @type kinesis_firehose deliver_stream_name my-stream region us-west-2 ` expectedFluentdAWSVPCConfig = ` @type unix path /var/run/fluent.sock @type forward bind 127.0.0.1 port 24224 @type grep key log pattern *failure* @type grep key log pattern *success* @type record_transformer ec2_instance_id i-123456789a ecs_cluster mycluster ecs_task_arn arn:aws:ecs:us-east-2:01234567891011:task/mycluster/3de392df-6bfa-470b-97ed-aa6f482cd7a ecs_task_definition taskdefinition:1 @include /tmp/dummy.conf @type kinesis_firehose deliver_stream_name my-stream region us-west-2 ` expectedFluentdDefaultModeConfig = ` @type unix path /var/run/fluent.sock @type grep key log pattern *failure* @type grep key log pattern *success* @type record_transformer ec2_instance_id i-123456789a ecs_cluster mycluster ecs_task_arn arn:aws:ecs:us-east-2:01234567891011:task/mycluster/3de392df-6bfa-470b-97ed-aa6f482cd7a ecs_task_definition taskdefinition:1 @include /tmp/dummy.conf @type kinesis_firehose deliver_stream_name my-stream region us-west-2 ` expectedFluentbitConfig = ` [INPUT] Name forward unix_path /var/run/fluent.sock [INPUT] Name forward Listen 0.0.0.0 Port 24224 [INPUT] Name tcp Tag firelens-healthcheck Listen 127.0.0.1 Port 8877 [FILTER] Name grep Match container-firelens* Regex log *failure* [FILTER] Name grep Match container-firelens* Exclude log *success* [FILTER] Name record_modifier Match * Record ec2_instance_id i-123456789a Record ecs_cluster mycluster Record ecs_task_arn arn:aws:ecs:us-east-2:01234567891011:task/mycluster/3de392df-6bfa-470b-97ed-aa6f482cd7a Record ecs_task_definition taskdefinition:1 @INCLUDE /fluent-bit/etc/external.conf [OUTPUT] Name null Match firelens-healthcheck [OUTPUT] Name kinesis_firehose Match container-firelens* deliver_stream_name my-stream region us-west-2 ` expectedFluentdConfigWithoutECSMetadata = ` @type unix path /var/run/fluent.sock @type forward bind 0.0.0.0 port 24224 @type grep key log pattern *failure* @type grep key log pattern *success* @include /tmp/dummy.conf @type kinesis_firehose deliver_stream_name my-stream region us-west-2 ` expectedFluentbitConfigWithoutOutputSection = ` [INPUT] Name forward unix_path /var/run/fluent.sock [INPUT] Name forward Listen 0.0.0.0 Port 24224 [INPUT] Name tcp Tag firelens-healthcheck Listen 127.0.0.1 Port 8877 [FILTER] Name grep Match container-firelens* Regex log *failure* [FILTER] Name grep Match container-firelens* Exclude log *success* [FILTER] Name record_modifier Match * Record ec2_instance_id i-123456789a Record ecs_cluster mycluster Record ecs_task_arn arn:aws:ecs:us-east-2:01234567891011:task/mycluster/3de392df-6bfa-470b-97ed-aa6f482cd7a Record ecs_task_definition taskdefinition:1 @INCLUDE /fluent-bit/etc/external.conf [OUTPUT] Name null Match firelens-healthcheck ` ) func TestGenerateFluentdBridgeModeConfig(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": testFluentdOptions, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentd, testRegion, bridgeNetworkMode, testFirelensOptionsFile, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentdConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentdBridgeModeConfig, configBytes.String()) } func TestGenerateFluentdAWSVPCModeConfig(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": testFluentdOptions, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentd, testRegion, awsvpcNetworkMode, testFirelensOptionsFile, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentdConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentdAWSVPCConfig, configBytes.String()) } func TestGenerateFluentdDefaultModeConfig(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": testFluentdOptions, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentd, testRegion, "", testFirelensOptionsFile, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentdConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentdDefaultModeConfig, configBytes.String()) } func TestGenerateFluentbitConfig(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": testFluentbitOptions, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentbit, testRegion, bridgeNetworkMode, testFirelensOptionsS3, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentBitConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentbitConfig, configBytes.String()) } func TestGenerateFluentdConfigMissingOutputName(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": { "key1": "value1", }, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentd, testRegion, bridgeNetworkMode, testFirelensOptionsFile, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) _, err = firelensResource.generateConfig() assert.Error(t, err) } func TestGenerateFLuentbitConfigMissingOutputName(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": { "key1": "value1", }, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentbit, testRegion, bridgeNetworkMode, testFirelensOptionsFile, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) _, err = firelensResource.generateConfig() assert.Error(t, err) } func TestGenerateConfigWithECSMetadataDisabled(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": testFluentdOptions, } testFirelensOptions := map[string]string{ "enable-ecs-log-metadata": "false", "config-file-type": "file", "config-file-value": "/tmp/dummy.conf", } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentd, testRegion, bridgeNetworkMode, testFirelensOptions, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentdConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentdConfigWithoutECSMetadata, configBytes.String()) } func TestGenerateConfigWithoutOutputSection(t *testing.T) { containerToLogOptions := map[string]map[string]string{ "container": { "include-pattern": "*failure*", "exclude-pattern": "*success*", }, } firelensResource, err := NewFirelensResource(testCluster, testTaskARN, testTaskDefinition, testEC2InstanceID, testDataDir, FirelensConfigTypeFluentbit, testRegion, bridgeNetworkMode, testFirelensOptionsS3, containerToLogOptions, nil, testExecutionCredentialsID) require.NoError(t, err) config, err := firelensResource.generateConfig() assert.NoError(t, err) configBytes := new(bytes.Buffer) err = config.WriteFluentBitConfig(configBytes) assert.NoError(t, err) assert.Equal(t, expectedFluentbitConfigWithoutOutputSection, configBytes.String()) }