diff --git a/plugins/filter_aws/aws.c b/plugins/filter_aws/aws.c index e30d236e38d..afe94a8a466 100644 --- a/plugins/filter_aws/aws.c +++ b/plugins/filter_aws/aws.c @@ -54,53 +54,87 @@ static void expose_aws_meta(struct flb_filter_aws *ctx) flb_env_set(env, "aws", "enabled"); - if (ctx->availability_zone_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_AVAILABILITY_ZONE_KEY, - ctx->availability_zone); + if (ctx->group_az.done && + !ctx->group_az.exposed) { + if (ctx->availability_zone_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_AVAILABILITY_ZONE_KEY, + ctx->availability_zone); + } + ctx->group_az.exposed = FLB_TRUE; } - if (ctx->instance_id_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_INSTANCE_ID_KEY, - ctx->instance_id); + if (ctx->group_instance_id.done && + !ctx->group_instance_id.exposed) { + if (ctx->instance_id_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_INSTANCE_ID_KEY, + ctx->instance_id); + } + ctx->group_instance_id.exposed = FLB_TRUE; } - if (ctx->instance_type_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_INSTANCE_TYPE_KEY, - ctx->instance_type); + if (ctx->group_instance_type.done && + !ctx->group_instance_type.exposed) { + if (ctx->instance_type_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_INSTANCE_TYPE_KEY, + ctx->instance_type); + } + ctx->group_instance_type.exposed = FLB_TRUE; } - if (ctx->private_ip_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_PRIVATE_IP_KEY, - ctx->private_ip); + if (ctx->group_private_ip.done && + !ctx->group_private_ip.exposed) { + if (ctx->private_ip_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_PRIVATE_IP_KEY, + ctx->private_ip); + } + ctx->group_private_ip.exposed = FLB_TRUE; } - if (ctx->vpc_id_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_VPC_ID_KEY, - ctx->vpc_id); + if (ctx->group_vpc_id.done && + !ctx->group_vpc_id.exposed) { + if (ctx->vpc_id_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_VPC_ID_KEY, + ctx->vpc_id); + } + ctx->group_vpc_id.exposed = FLB_TRUE; } - if (ctx->ami_id_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_AMI_ID_KEY, - ctx->ami_id); + if (ctx->group_ami_id.done && + !ctx->group_ami_id.exposed) { + if (ctx->ami_id_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_AMI_ID_KEY, + ctx->ami_id); + } + ctx->group_ami_id.exposed = FLB_TRUE; } - if (ctx->account_id_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_ACCOUNT_ID_KEY, - ctx->account_id); + if (ctx->group_account_id.done && + !ctx->group_account_id.exposed) { + if (ctx->account_id_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_ACCOUNT_ID_KEY, + ctx->account_id); + } + ctx->group_account_id.exposed = FLB_TRUE; } - if (ctx->hostname_include) { - flb_env_set(env, - "aws." FLB_FILTER_AWS_HOSTNAME_KEY, - ctx->hostname); + if (ctx->group_hostname.done && + !ctx->group_hostname.exposed) { + if (ctx->hostname_include) { + flb_env_set(env, + "aws." FLB_FILTER_AWS_HOSTNAME_KEY, + ctx->hostname); + } + ctx->group_hostname.exposed = FLB_TRUE; } + + /* TODO: expose aws ec2 tags in flb_env_set */ } static int cb_aws_init(struct flb_filter_instance *f_ins, @@ -185,15 +219,14 @@ static int cb_aws_init(struct flb_filter_instance *f_ins, return -1; } - ctx->metadata_retrieved = FLB_FALSE; - /* Retrieve metadata */ ret = get_ec2_metadata(ctx); if (ret < 0) { /* If the metadata fetch fails, the plugin continues to work. */ /* Every flush will attempt to fetch ec2 metadata, if needed. */ - /* In the error is unrecoverable (-3), it exits and does not retry. */ - if (ret == -3) { + /* If the error is unrecoverable, it exits and does not retry. */ + /* e.g.: unrecoverable errors might be related to invalid configuration. */ + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { flb_free(ctx); return -1; } @@ -528,7 +561,7 @@ static int get_ec2_tag_enabled(struct flb_filter_aws *ctx) if (tags_include && tags_exclude) { flb_plg_error(ctx->ins, "configuration is invalid, both tags_include" " and tags_exclude are specified at the same time"); - return -3; + return FLB_FILTER_AWS_CONFIGURATION_ERROR; } if (!tags_include && tags_exclude) { /* copy const string in order to use strtok which modifes the string */ @@ -603,14 +636,9 @@ static int get_ec2_tags(struct flb_filter_aws *ctx) return 0; } -/* - * Makes a call to IMDS to set get the values of all metadata fields. - * It can be called repeatedly if some metadata calls initially do not succeed. - */ -static int get_ec2_metadata(struct flb_filter_aws *ctx) +static int get_ec2_metadata_instance_id(struct flb_filter_aws *ctx) { int ret; - int i; if (ctx->instance_id_include && !ctx->instance_id) { ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_INSTANCE_ID_PATH, @@ -620,20 +648,14 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get instance ID"); return -1; } - ctx->new_keys++; } - if (ctx->availability_zone_include && !ctx->availability_zone) { - ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_AZ_PATH, - &ctx->availability_zone, - &ctx->availability_zone_len); + return 0; +} - if (ret < 0) { - flb_plg_error(ctx->ins, "Failed to get instance AZ"); - return -1; - } - ctx->new_keys++; - } +static int get_ec2_metadata_instance_type(struct flb_filter_aws *ctx) +{ + int ret; if (ctx->instance_type_include && !ctx->instance_type) { ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_INSTANCE_TYPE_PATH, @@ -643,9 +665,15 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get instance type"); return -1; } - ctx->new_keys++; } + return 0; +} + +static int get_ec2_metadata_private_ip(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->private_ip_include && !ctx->private_ip) { ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_PRIVATE_IP_PATH, &ctx->private_ip, &ctx->private_ip_len); @@ -654,9 +682,15 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get instance private IP"); return -1; } - ctx->new_keys++; } + return 0; +} + +static int get_ec2_metadata_vpc_id(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->vpc_id_include && !ctx->vpc_id) { ret = get_vpc_id(ctx); @@ -664,9 +698,15 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get instance VPC ID"); return -1; } - ctx->new_keys++; } + return 0; +} + +static int get_ec2_metadata_ami_id(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->ami_id_include && !ctx->ami_id) { ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_AMI_ID_PATH, &ctx->ami_id, &ctx->ami_id_len); @@ -675,9 +715,15 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get AMI ID"); return -1; } - ctx->new_keys++; } + return 0; +} + +static int get_ec2_metadata_account_id(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->account_id_include && !ctx->account_id) { ret = flb_aws_imds_request_by_key(ctx->client_imds, FLB_AWS_IMDS_ACCOUNT_ID_PATH, &ctx->account_id, &ctx->account_id_len, @@ -687,9 +733,16 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get Account ID"); return -1; } - ctx->new_keys++; } + + return 0; +} + +static int get_ec2_metadata_hostname(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->hostname_include && !ctx->hostname) { ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_HOSTNAME_PATH, &ctx->hostname, &ctx->hostname_len); @@ -698,23 +751,180 @@ static int get_ec2_metadata(struct flb_filter_aws *ctx) flb_plg_error(ctx->ins, "Failed to get Hostname"); return -1; } - ctx->new_keys++; } + return 0; +} + +static int get_ec2_metadata_az(struct flb_filter_aws *ctx) +{ + int ret; + + if (ctx->availability_zone_include && !ctx->availability_zone) { + ret = flb_aws_imds_request(ctx->client_imds, FLB_AWS_IMDS_AZ_PATH, + &ctx->availability_zone, + &ctx->availability_zone_len); + + if (ret < 0) { + flb_plg_error(ctx->ins, "Failed to get instance AZ"); + return -1; + } + } + + return 0; +} + + +static int get_ec2_metadata_tags(struct flb_filter_aws *ctx) +{ + int ret; + if (ctx->tags_enabled && !ctx->tags_fetched) { ret = get_ec2_tags(ctx); if (ret < 0) { flb_plg_error(ctx->ins, "Failed to get instance EC2 Tags"); return ret; } - for (i = 0; i < ctx->tags_count; i++) { - if (ctx->tag_is_enabled[i] == FLB_TRUE) { - ctx->new_keys++; - } + } + + return 0; +} + +static int ec2_metadata_group_should_fetch(struct flb_filter_aws *ctx, + struct flb_filter_aws_metadata_group *group) +{ + time_t now, required_interval, interval; + + required_interval = ctx->retry_required_interval; + if (required_interval == 0) { + return FLB_TRUE; + } + + now = time(NULL); + + interval = now - group->last_fetch_attempt; + + if (interval < required_interval) { + return FLB_FALSE; + } + return FLB_TRUE; +} + +static int get_ec2_metadata_group(struct flb_filter_aws *ctx, + struct flb_filter_aws_metadata_group *group, + int (*fetch_func)(struct flb_filter_aws *ctx)) +{ + int ret; + if (group->done) { + return 0; + } + if (!ec2_metadata_group_should_fetch(ctx, group)) { + return -1; + } + group->last_fetch_attempt = time(NULL); + ret = fetch_func(ctx); + if (ret == 0) { + group->done = FLB_TRUE; + } + return ret; +} + +/* + * Fetches all metadata values, including tags, from IMDS. + * Function handles retries as configured for each metadata group. + * + * Returns 0 on success, negative values on failures. + * Returns FLB_FILTER_AWS_CONFIGURATION_ERROR in case of configuration error. + */ +static int get_ec2_metadata(struct flb_filter_aws *ctx) +{ + int ret; + int metadata_fetched = FLB_TRUE; + + if (ctx->metadata_retrieved) { + return 0; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_instance_id, + get_ec2_metadata_instance_id); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_account_id, + get_ec2_metadata_account_id); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_instance_type, + get_ec2_metadata_instance_type); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_private_ip, + get_ec2_metadata_private_ip); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_vpc_id, get_ec2_metadata_vpc_id); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_ami_id, get_ec2_metadata_ami_id); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_hostname, get_ec2_metadata_hostname); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_az, get_ec2_metadata_az); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + ret = get_ec2_metadata_group(ctx, &ctx->group_tag, get_ec2_metadata_tags); + if (ret < 0) { + if (ret == FLB_FILTER_AWS_CONFIGURATION_ERROR) { + return ret; + } + metadata_fetched = FLB_FALSE; + } + + if (metadata_fetched == FLB_TRUE) { + ctx->metadata_retrieved = FLB_TRUE; } - ctx->metadata_retrieved = FLB_TRUE; return 0; } @@ -741,10 +951,11 @@ static int cb_aws_filter(const void *data, size_t bytes, /* First check that the metadata has been retrieved */ if (!ctx->metadata_retrieved) { - ret = get_ec2_metadata(ctx); - if (ret < 0) { - return FLB_FILTER_NOTOUCH; - } + get_ec2_metadata(ctx); /* ignore the error */ + /* it assumes the error cannot be the configuration error, as it would fail */ + /* during the _init function; */ + /* even if get_ec2_metadata failed, it may have been able to fetch some groups */ + /* therefore we continue flushing the logs with what we've got */ expose_aws_meta(ctx); } @@ -797,6 +1008,7 @@ static int cb_aws_filter(const void *data, size_t bytes, /* append new keys */ if (ctx->availability_zone_include && + ctx->group_az.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -806,6 +1018,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->instance_id_include && + ctx->group_instance_id.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -815,6 +1028,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->instance_type_include && + ctx->group_instance_type.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -824,6 +1038,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->private_ip_include && + ctx->group_private_ip.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -833,6 +1048,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->vpc_id_include && + ctx->group_vpc_id.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -842,6 +1058,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->ami_id_include && + ctx->group_ami_id.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -851,6 +1068,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->account_id_include && + ctx->group_account_id.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -860,6 +1078,7 @@ static int cb_aws_filter(const void *data, size_t bytes, } if (ctx->hostname_include && + ctx->group_hostname.done && ret == FLB_EVENT_ENCODER_SUCCESS) { ret = flb_log_event_encoder_append_body_values( &log_encoder, @@ -1048,6 +1267,11 @@ static struct flb_config_map config_map[] = { "if both tags_include and tags_exclude are specified, configuration is invalid" " and plugin fails" }, + { + FLB_CONFIG_MAP_INT, "retry_interval_s", "300", + 0, FLB_TRUE, offsetof(struct flb_filter_aws, retry_required_interval), + "Defines minimum duration between retries for fetching metadata groups" + }, {0} }; diff --git a/plugins/filter_aws/aws.h b/plugins/filter_aws/aws.h index fa6843ceeb7..f369f0bbcc7 100644 --- a/plugins/filter_aws/aws.h +++ b/plugins/filter_aws/aws.h @@ -40,6 +40,24 @@ #define FLB_FILTER_AWS_HOSTNAME_KEY "hostname" #define FLB_FILTER_AWS_HOSTNAME_KEY_LEN 8 +/* defines returned value for cases when configuration is invalid and program should exit */ +#define FLB_FILTER_AWS_CONFIGURATION_ERROR -100 + +struct flb_filter_aws_metadata_group { + /* defines if fetch function for the information group was already done successfully + * if set to FLB_FALSE after first attempt, then most likely another retry will be + * required + * done set to FLB_TRUE does not mean that information was retrieved, as it might + * be disabled */ + int done; + /* defines if information was already exposed in the filter for envs */ + int exposed; + + /* defines a timestamp of last execution of fetch method related to the group */ + /* unit: timestamp in seconds */ + time_t last_fetch_attempt; +}; + struct flb_filter_aws { struct flb_filter_aws_init_options *options; @@ -112,9 +130,21 @@ struct flb_filter_aws { /* e.g.: if tag_is_enabled[0] = FALSE, then filter aws should not inject first tag */ int *tag_is_enabled; - /* number of new keys added by this plugin */ - int new_keys; - + /* metadata group contains information for potential retries and + * if group was already fetched successfully */ + struct flb_filter_aws_metadata_group group_az; + struct flb_filter_aws_metadata_group group_instance_id; + struct flb_filter_aws_metadata_group group_instance_type; + struct flb_filter_aws_metadata_group group_private_ip; + struct flb_filter_aws_metadata_group group_vpc_id; + struct flb_filter_aws_metadata_group group_ami_id; + struct flb_filter_aws_metadata_group group_account_id; + struct flb_filter_aws_metadata_group group_hostname; + struct flb_filter_aws_metadata_group group_tag; + /* defines a minimal interval before consecutive retries */ + /* unit: seconds */ + time_t retry_required_interval; + /* defines if all metadata groups were fetched successfully */ int metadata_retrieved; /* Plugin can use EC2 metadata v1 or v2; default is v2 */ diff --git a/tests/runtime/filter_aws.c b/tests/runtime/filter_aws.c index 770915a01ba..f25430b1bda 100644 --- a/tests/runtime/filter_aws.c +++ b/tests/runtime/filter_aws.c @@ -42,6 +42,801 @@ int callback_test(void* data, size_t size, void* cb_data) return 0; } +void flb_test_aws_instance_id() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/instance-id/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "i-0e66fc7f9809d7168"), + set(PAYLOAD_SIZE, 19) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"ec2_instance_id\":\"i-0e66fc7f9809d7168\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_instance_type() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/instance-type/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "t2.micro"), + set(PAYLOAD_SIZE, 8) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_type", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"ec2_instance_type\":\"t2.micro\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_private_ip() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/local-ipv4/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "10.158.112.84"), + set(PAYLOAD_SIZE, 13) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "private_ip", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"private_ip\":\"10.158.112.84\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_vpc_id() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/mac/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "00:00:5e:00:53:af"), + set(PAYLOAD_SIZE, 17) + ), + response( + expect(URI, "/latest/meta-data/network/interfaces/macs/00:00:5e:00:53:af/vpc-id/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "vpc-2928ea42"), + set(PAYLOAD_SIZE, 12) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "vpc_id", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"vpc_id\":\"vpc-2928ea42\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_ami_id() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/ami-id/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "ami-5fb8c835"), + set(PAYLOAD_SIZE, 12) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ami_id", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"ami_id\":\"ami-5fb8c835\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_account_id() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/dynamic/instance-identity/document/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "{\"devpayProductCodes\":null,\"marketplaceProductCodes\":[\"1abc2defghijklm3nopqrs4tu\"],\"availabilityZone\":\"us-east-1a\",\"privateIp\":\"10.158.112.84\",\"version\":\"2017-09-30\",\"instanceId\":\"i-1234567890abcdef0\",\"billingProducts\":null,\"instanceType\":\"t2.micro\",\"accountId\":\"123456789012\",\"imageId\":\"ami-5fb8c835\",\"pendingTime\":\"2016-11-19T16:32:11Z\",\"architecture\":\"x86_64\",\"kernelId\":null,\"ramdiskId\":null,\"region\":\"us-east-1\"}"), + set(PAYLOAD_SIZE, 417) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "account_id", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"account_id\":\"123456789012\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_hostname() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/hostname/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "ip-10-158-112-84.us-west-2.compute.internal"), + set(PAYLOAD_SIZE, 43) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "hostname", "true", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"hostname\":\"ip-10-158-112-84.us-west-2.compute.internal\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + +void flb_test_aws_az() { + int ret; + int bytes; + char *p = "[0, {\"log\": \"hello, from my ec2 instance\"}]"; + flb_ctx_t *ctx; + int in_ffd; + int out_ffd; + int filter_ffd; + struct flb_lib_out_cb cb_data; + struct flb_aws_client_generator *client_generator; + struct flb_filter_aws_init_options *ops; + struct flb_aws_client_mock_request_chain *request_chain; + char *output = NULL; + char *result; + + request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/placement/availability-zone/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "us-east-1a"), + set(PAYLOAD_SIZE, 10) + ) + ); + flb_aws_client_mock_configure_generator(request_chain); + + client_generator = flb_aws_client_get_mock_generator(); + ops = flb_calloc(1, sizeof(struct flb_filter_aws_init_options)); + if (ops == NULL) { + TEST_MSG("calloc for aws plugin options failed\n"); + TEST_CHECK(false); + return; + } + ops->client_generator = client_generator; + + ctx = flb_create(); + + in_ffd = flb_input(ctx, (char *) "lib", NULL); + TEST_CHECK(in_ffd >= 0); + flb_input_set(ctx, in_ffd, "tag", "test", NULL); + + + /* Prepare output callback context*/ + cb_data.cb = callback_test; + cb_data.data = NULL; + + /* Lib output */ + out_ffd = flb_output(ctx, (char *) "lib", (void *)&cb_data); + TEST_CHECK(out_ffd >= 0); + flb_output_set(ctx, out_ffd, + "match", "*", + "format", "json", + NULL); + + filter_ffd = flb_filter(ctx, (char *) "aws", ops); + TEST_CHECK(filter_ffd >= 0); + ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + TEST_CHECK(ret == 0); + ret = flb_filter_set(ctx, filter_ffd, "az", "true", NULL); + TEST_CHECK(ret == 0); + + ret = flb_start(ctx); + TEST_CHECK(ret == 0); + + bytes = flb_lib_push(ctx, in_ffd, p, strlen(p)); + if (!TEST_CHECK(bytes > 0)) { + TEST_MSG("zero bytes were pushed\n"); + } + + flb_time_msleep(1500); /* waiting flush */ + + output = get_output(); + if (output) { + result = strstr(output, "\"az\":\"us-east-1a\""); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + result = strstr(output, "hello, from my ec2 instance"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("output:%s\n", output); + } + } + else { + TEST_CHECK(false); + TEST_MSG("output is empty\n"); + } + + flb_stop(ctx); + flb_aws_client_mock_destroy_generator(); + flb_destroy(ctx); + flb_free(ops); + + set_output(NULL); +} + void flb_test_aws_ec2_tags_present() { int ret; int bytes; @@ -287,6 +1082,13 @@ void flb_test_aws_ec2_tags_list_500() { char *result; request_chain = FLB_AWS_CLIENT_MOCK( + response( + expect(URI, "/latest/meta-data/instance-id/"), + expect(METHOD, FLB_HTTP_GET), + set(STATUS, 200), + set(PAYLOAD, "i-0e66fc7f9809d7168"), + set(PAYLOAD_SIZE, 19) + ), response( expect(URI, "/latest/meta-data/tags/instance"), expect(METHOD, FLB_HTTP_GET), @@ -332,7 +1134,7 @@ void flb_test_aws_ec2_tags_list_500() { TEST_CHECK(filter_ffd >= 0); ret = flb_filter_set(ctx, filter_ffd, "match", "*", NULL); TEST_CHECK(ret == 0); - ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "false", NULL); + ret = flb_filter_set(ctx, filter_ffd, "ec2_instance_id", "true", NULL); TEST_CHECK(ret == 0); ret = flb_filter_set(ctx, filter_ffd, "az", "false", NULL); TEST_CHECK(ret == 0); @@ -355,6 +1157,12 @@ void flb_test_aws_ec2_tags_list_500() { if (!TEST_CHECK(result != NULL)) { TEST_MSG("output:%s\n", output); } + result = strstr(output, "i-0e66fc7f9809d7168"); + if (!TEST_CHECK(result != NULL)) { + TEST_MSG("ec2 instance id is not present in the output log\n"); + TEST_MSG("however, it should be injected despite ec2 tags fetching errors\n"); + TEST_MSG("output:%s\n", output); + } } else { TEST_CHECK(false); @@ -835,6 +1643,14 @@ void flb_test_aws_ec2_tags_exclude() { TEST_LIST = { + {"aws_instance_id", flb_test_aws_instance_id}, + {"aws_instance_type", flb_test_aws_instance_type}, + {"aws_private_ip", flb_test_aws_private_ip}, + {"aws_vpc_id", flb_test_aws_vpc_id}, + {"aws_ami_id", flb_test_aws_ami_id}, + {"aws_account_id", flb_test_aws_account_id}, + {"aws_hostname", flb_test_aws_hostname}, + {"aws_az", flb_test_aws_az}, {"aws_ec2_tags_present", flb_test_aws_ec2_tags_present}, {"aws_ec2_tags_404", flb_test_aws_ec2_tags_404}, {"aws_ec2_tags_list_500", flb_test_aws_ec2_tags_list_500},