From 555b254b25f6cad690528727387a966e4f1cf9d7 Mon Sep 17 00:00:00 2001 From: Varun Mittal Date: Sun, 26 Nov 2023 21:24:44 -0500 Subject: [PATCH] Aws 1.0 transform plans along with more sql validations. (#154) Signed-off-by: Varun Mittal --- .../focus_converter/configs/base_config.py | 28 ++++ .../aws/0_dimension_dtypes_S001.yaml | 20 +++ ...D010_S001.yaml => 1_charge_type_S001.yaml} | 0 ...ion_line_item_net_unblended_cost_S001.yaml | 7 + ...on_reservation_reservation_a_r_n_S001.yaml | 7 + .../1_reservation_reservation_arn_S001.yaml | 7 + .../1_savings_plan_savings_plan_arn_S001.yaml | 7 + .../conversion_configs/aws/D001_S001.yaml | 8 -- ..._S001.yaml => availability_zone_S001.yaml} | 0 .../aws/billed_cost_S001.yaml | 8 ++ ...S001.yaml => billing_account_id_S001.yaml} | 0 ...4_S001.yaml => billing_currency_S001.yaml} | 0 ...S001.yaml => billing_period_end_S001.yaml} | 0 ...01.yaml => billing_period_start_S001.yaml} | 0 .../aws/charge_description_S001.yaml | 4 + .../aws/charge_frequency_S001.yaml | 13 ++ ..._S001.yaml => charge_period_end_S001.yaml} | 0 ...001.yaml => charge_period_start_S001.yaml} | 0 .../aws/charge_sub_category_S001.yaml | 15 ++ .../commitment_discount_category_S001.yaml | 10 ++ .../aws/commitment_discount_id_S001.yaml | 9 ++ .../aws/commitment_discount_type_S001.yaml | 10 ++ .../aws/effective_cost_S001.yaml | 18 +++ ...015_S001.yaml => invoice_issuer_S001.yaml} | 0 .../aws/list_cost_S001.yaml | 8 ++ .../aws/list_unit_price_S001.yaml | 4 + .../aws/pricing_quantity_S001.yaml | 8 ++ .../aws/pricing_unit_S001.yaml | 4 + .../{D011_S001.yaml => provider_S001.yaml} | 0 .../aws/{D018_S001.yaml => region_S001.yaml} | 0 .../{D016_S001.yaml => resource_id_S001.yaml} | 0 ...2_S002.yaml => service_category_S001.yaml} | 0 ...{D017_S001.yaml => service_name_S001.yaml} | 0 .../conversion_configs/aws/sku_id_S001.yaml | 4 + .../aws/sku_price_id_S001.yaml | 8 ++ .../aws/usage_quantity_S001.yaml | 4 + .../aws/usage_unit_S001.yaml | 4 + .../conversion_functions/__init__.py | 3 + .../conversion_functions/column_functions.py | 9 -- .../deferred_column_functions.py | 100 ++++++++++++++ .../conversion_functions/validations.py | 14 +- .../focus_converter/converter.py | 38 +++--- .../models/focus_column_names.py | 22 +++ .../converter_functions/test_column_dtypes.py | 129 ++++++++++++++++++ .../test_default_value_if_not_present.py | 3 + .../aws/test_aws_provider.py | 2 +- 46 files changed, 498 insertions(+), 37 deletions(-) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/0_dimension_dtypes_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D010_S001.yaml => 1_charge_type_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_line_item_net_unblended_cost_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_reservation_reservation_a_r_n_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/1_reservation_reservation_arn_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/1_savings_plan_savings_plan_arn_S001.yaml delete mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/D001_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D013_S001.yaml => availability_zone_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/billed_cost_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D002_S001.yaml => billing_account_id_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D014_S001.yaml => billing_currency_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D003_S001.yaml => billing_period_end_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D004_S001.yaml => billing_period_start_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/charge_description_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/charge_frequency_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D006_S001.yaml => charge_period_end_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D005_S001.yaml => charge_period_start_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/charge_sub_category_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_category_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_id_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_type_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/effective_cost_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D015_S001.yaml => invoice_issuer_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/list_cost_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/list_unit_price_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/pricing_quantity_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/pricing_unit_S001.yaml rename focus_converter_base/focus_converter/conversion_configs/aws/{D011_S001.yaml => provider_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D018_S001.yaml => region_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D016_S001.yaml => resource_id_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D012_S002.yaml => service_category_S001.yaml} (100%) rename focus_converter_base/focus_converter/conversion_configs/aws/{D017_S001.yaml => service_name_S001.yaml} (100%) create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/sku_id_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/sku_price_id_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/usage_quantity_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_configs/aws/usage_unit_S001.yaml create mode 100644 focus_converter_base/focus_converter/conversion_functions/deferred_column_functions.py create mode 100644 focus_converter_base/tests/converter_functions/test_column_dtypes.py diff --git a/focus_converter_base/focus_converter/configs/base_config.py b/focus_converter_base/focus_converter/configs/base_config.py index c68d416b..503aba68 100644 --- a/focus_converter_base/focus_converter/configs/base_config.py +++ b/focus_converter_base/focus_converter/configs/base_config.py @@ -80,6 +80,20 @@ class UnnestValueConversionArgs(BaseModel): ] = "first" +class MissingColumnDType(BaseModel): + data_type: Literal["string", "float", "int"] + + +class DTypeConversionArg(BaseModel): + column_name: str + dtype: Literal["string", "float", "int"] + strict: bool = False + + +class SetColumnDTypesConversionArgs(BaseModel): + dtype_args: List[DTypeConversionArg] + + CONFIG_FILE_PATTERN = re.compile("(.+)_S\d{3}.yaml") @@ -157,6 +171,20 @@ def conversion_args_validation(cls, v: Any, field_info: ValidationInfo) -> str: raise ValueError( e, f"Missing or bad static value argument: {field_info.data}" ) + elif conversion_type == STATIC_CONVERSION_TYPES.APPLY_DEFAULT_IF_COLUMN_MISSING: + try: + MissingColumnDType.model_validate(v) + except ValidationError as e: + raise ValueError( + e, f"Missing or bad unnest value argument: {field_info.data}" + ) + elif conversion_type == STATIC_CONVERSION_TYPES.SET_COLUMN_DTYPES: + try: + SetColumnDTypesConversionArgs.model_validate(v) + except ValidationError as e: + raise ValueError( + e, f"Missing or bad set column dtype argument: {field_info.data}" + ) return v @field_validator("column_prefix") diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/0_dimension_dtypes_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/0_dimension_dtypes_S001.yaml new file mode 100644 index 00000000..131baae5 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/0_dimension_dtypes_S001.yaml @@ -0,0 +1,20 @@ +plan_name: adds dtypes to the columns required for the conversion +conversion_type: set_column_dtypes +column: PlaceHolder +focus_column: PlaceHolder +conversion_args: + dtype_args: + - column_name: line_item_unblended_cost + dtype: float + - column_name: savings_plan_used_commitment + dtype: float + - column_name: savings_plan_used_commitment + dtype: float + - column_name: savings_plan_total_commitment_to_date + dtype: float + - column_name: reservation_unused_amortized_upfront_fee_for_billing_period + dtype: float + - column_name: reservation_unused_recurring_fee + dtype: float + - column_name: pricing_public_on_demand_rate + dtype: float diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D010_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/1_charge_type_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D010_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/1_charge_type_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_line_item_net_unblended_cost_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_line_item_net_unblended_cost_S001.yaml new file mode 100644 index 00000000..e85fe380 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_line_item_net_unblended_cost_S001.yaml @@ -0,0 +1,7 @@ +# fails if the column is not present, TODO: add a default value +plan_name: add default value to line_item_net_unblended_cost if not present in CUR dataset +conversion_type: apply_default_if_column_missing +column: line_item_net_unblended_cost +focus_column: PlaceHolder +conversion_args: + data_type: float diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_reservation_reservation_a_r_n_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_reservation_reservation_a_r_n_S001.yaml new file mode 100644 index 00000000..398d07b1 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/1_missing_dimension_reservation_reservation_a_r_n_S001.yaml @@ -0,0 +1,7 @@ +# fails if the column is not present, TODO: add a default value +plan_name: add default value to reservation_reservation_a_r_n if not present in CUR dataset +conversion_type: apply_default_if_column_missing +column: reservation_reservation_a_r_n +focus_column: PlaceHolder +conversion_args: + data_type: string diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/1_reservation_reservation_arn_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/1_reservation_reservation_arn_S001.yaml new file mode 100644 index 00000000..72559096 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/1_reservation_reservation_arn_S001.yaml @@ -0,0 +1,7 @@ +# fails if the column is not present, TODO: add a default value +plan_name: add default value to ReservationARN if not present in CUR dataset +conversion_type: apply_default_if_column_missing +column: reservation_reservation_arn +focus_column: PlaceHolder +conversion_args: + data_type: string diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/1_savings_plan_savings_plan_arn_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/1_savings_plan_savings_plan_arn_S001.yaml new file mode 100644 index 00000000..81738ec4 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/1_savings_plan_savings_plan_arn_S001.yaml @@ -0,0 +1,7 @@ +# fails if the column is not present, TODO: add a default value +plan_name: add default value to SavingsPlanArn if not present in CUR dataset +conversion_type: apply_default_if_column_missing +column: savings_plan_savings_plan_arn +focus_column: PlaceHolder +conversion_args: + data_type: string diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D001_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/D001_S001.yaml deleted file mode 100644 index 7d016168..00000000 --- a/focus_converter_base/focus_converter/conversion_configs/aws/D001_S001.yaml +++ /dev/null @@ -1,8 +0,0 @@ -plan_name: calculate amortised cost -conversion_type: sql_condition -conversion_args: - conditions: - - WHEN line_item_line_item_type = 'SavingsPlanCoveredUsage' THEN savings_plan_savings_plan_effective_cost - default_value: 0 -column: bill_payer_account_id -focus_column: AmortisedCost diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D013_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/availability_zone_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D013_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/availability_zone_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/billed_cost_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/billed_cost_S001.yaml new file mode 100644 index 00000000..ee0574d6 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/billed_cost_S001.yaml @@ -0,0 +1,8 @@ +plan_name: convert lineItem/NetUnblendedCost, lineItem/UnblendedCost to BilledCost +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN line_item_net_unblended_cost is not null THEN line_item_net_unblended_cost + default_value: line_item_unblended_cost +column: NA +focus_column: BilledCost diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D002_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/billing_account_id_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D002_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/billing_account_id_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D014_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/billing_currency_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D014_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/billing_currency_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D003_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/billing_period_end_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D003_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/billing_period_end_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D004_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/billing_period_start_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D004_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/billing_period_start_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/charge_description_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/charge_description_S001.yaml new file mode 100644 index 00000000..94ca07aa --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/charge_description_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert lineItem/LineItemDescription to ChargeDescription +conversion_type: rename_column +column: line_item_line_item_description +focus_column: ChargeDescription diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/charge_frequency_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/charge_frequency_S001.yaml new file mode 100644 index 00000000..4a00b1e7 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/charge_frequency_S001.yaml @@ -0,0 +1,13 @@ +plan_name: convert Bill/BillType to ChargeFrequency +conversion_type: map_values +conversion_args: + value_list: + - key: Refund + value: One-Time + - key: Purchase + value: One-Time + - key: Anniversary + value: Recurring + default_value: "" +column: bill_bill_type +focus_column: ChargeFrequency diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D006_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/charge_period_end_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D006_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/charge_period_end_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D005_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/charge_period_start_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D005_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/charge_period_start_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/charge_sub_category_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/charge_sub_category_S001.yaml new file mode 100644 index 00000000..23db3b3d --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/charge_sub_category_S001.yaml @@ -0,0 +1,15 @@ +plan_name: convert lineItem/NetUnblendedCost, lineItem/UnblendedCost to BilledCost +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN ChargeType = 'Usage' AND savings_plan_savings_plan_arn is not null OR reservation_reservation_arn is not null THEN 'Used Commitment' + - WHEN ChargeType = 'Usage' THEN 'On-Demand' + - WHEN ChargeType = 'Adjustment' AND line_item_line_item_type = 'BundledDiscount' THEN 'Credit' + - WHEN ChargeType = 'Adjustment' AND line_item_line_item_type = 'Credit' THEN 'Credit' + - WHEN ChargeType = 'Adjustment' AND line_item_line_item_type = 'Discount' THEN 'Credit' + - WHEN ChargeType = 'Adjustment' AND line_item_line_item_type = 'DiscountedUsage' THEN 'Credit' + - WHEN ChargeType = 'Adjustment' AND line_item_line_item_type = 'Refund' THEN 'Refund' + - WHEN ChargeType = 'Adjustment' THEN 'General Adjustment' + default_value: "NULL" +column: NA +focus_column: ChargeSubcategory diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_category_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_category_S001.yaml new file mode 100644 index 00000000..00222661 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_category_S001.yaml @@ -0,0 +1,10 @@ +# fails if the column is not present, TODO: add a default value +plan_name: convert ReservationARN/SavingsPlanArn to CommitmentDiscountCategory +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN savings_plan_savings_plan_arn is not null THEN 'Spend' + - WHEN reservation_reservation_arn is not null THEN 'Usage' + default_value: "null" +column: NA +focus_column: CommitmentDiscountCategory diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_id_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_id_S001.yaml new file mode 100644 index 00000000..c70f6a33 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_id_S001.yaml @@ -0,0 +1,9 @@ +# fails if the column is not present, TODO: add a default value +plan_name: convert ReservationARN/SavingsPlanArn to CommitmentDiscountId +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN savings_plan_savings_plan_arn is not null THEN savings_plan_savings_plan_arn + default_value: reservation_reservation_arn +column: NA +focus_column: CommitmentDiscountId diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_type_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_type_S001.yaml new file mode 100644 index 00000000..a7d6b0c4 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/commitment_discount_type_S001.yaml @@ -0,0 +1,10 @@ +# fails if the column is not present, TODO: add a default value +plan_name: convert ReservationARN/SavingsPlanArn to CommitmentDiscountType +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN savings_plan_savings_plan_arn is not null THEN 'Savings Plan' + - WHEN reservation_reservation_arn is not null THEN 'Reserved Instances (RI)' + default_value: "null" +column: NA +focus_column: CommitmentDiscountType diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/effective_cost_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/effective_cost_S001.yaml new file mode 100644 index 00000000..11e47fca --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/effective_cost_S001.yaml @@ -0,0 +1,18 @@ +plan_name: conversion plan for EffectiveCost +conversion_type: sql_query +conversion_args: > + SELECT + *, + CASE + WHEN (line_item_line_item_type = 'SavingsPlanCoveredUsage') THEN savings_plan_savings_plan_effective_cost + WHEN (line_item_line_item_type = 'SavingsPlanRecurringFee') THEN (savings_plan_total_commitment_to_date - savings_plan_used_commitment) + WHEN (line_item_line_item_type = 'SavingsPlanNegation') THEN 0 + WHEN (line_item_line_item_type = 'SavingsPlanUpfrontFee') THEN 0 + WHEN (line_item_line_item_type = 'DiscountedUsage') THEN reservation_effective_cost + WHEN (line_item_line_item_type = 'RIFee') THEN (reservation_unused_amortized_upfront_fee_for_billing_period + reservation_unused_recurring_fee) + WHEN ((line_item_line_item_type = 'Fee') AND (reservation_reservation_a_r_n <> '')) THEN 0 + ELSE line_item_unblended_cost + END AS EffectiveCost + FROM {{ TABLE_NAME }} +column: NA +focus_column: EffectiveCost diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D015_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/invoice_issuer_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D015_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/invoice_issuer_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/list_cost_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/list_cost_S001.yaml new file mode 100644 index 00000000..9225e0b1 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/list_cost_S001.yaml @@ -0,0 +1,8 @@ +plan_name: convert Pricing/publicOnDemandCost to ListCost +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN pricing_public_on_demand_rate is not null THEN pricing_public_on_demand_rate * line_item_usage_amount + default_value: pricing_public_on_demand_cost +column: NA +focus_column: ListCost diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/list_unit_price_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/list_unit_price_S001.yaml new file mode 100644 index 00000000..06947a9d --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/list_unit_price_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert Pricing/publicOnDemandRate to ListUnitPrice +conversion_type: rename_column +column: pricing_public_on_demand_rate +focus_column: ListUnitPrice diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/pricing_quantity_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/pricing_quantity_S001.yaml new file mode 100644 index 00000000..65ab5282 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/pricing_quantity_S001.yaml @@ -0,0 +1,8 @@ +plan_name: convert LineItem/UsageAmount to PricingQuantity +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN reservation_total_reserved_units is not null THEN reservation_total_reserved_units + default_value: line_item_usage_amount +column: line_item_usage_amount +focus_column: PricingQuantity diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/pricing_unit_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/pricing_unit_S001.yaml new file mode 100644 index 00000000..90da2150 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/pricing_unit_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert Pricing/PricingUnit to PricingUnit +conversion_type: rename_column +column: pricing_unit +focus_column: PricingUnit diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D011_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/provider_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D011_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/provider_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D018_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/region_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D018_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/region_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D016_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/resource_id_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D016_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/resource_id_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D012_S002.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/service_category_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D012_S002.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/service_category_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/D017_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/service_name_S001.yaml similarity index 100% rename from focus_converter_base/focus_converter/conversion_configs/aws/D017_S001.yaml rename to focus_converter_base/focus_converter/conversion_configs/aws/service_name_S001.yaml diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/sku_id_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/sku_id_S001.yaml new file mode 100644 index 00000000..290edded --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/sku_id_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert Product/sku to SkuId +conversion_type: rename_column +column: product_sku +focus_column: SkuId diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/sku_price_id_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/sku_price_id_S001.yaml new file mode 100644 index 00000000..376551b5 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/sku_price_id_S001.yaml @@ -0,0 +1,8 @@ +plan_name: convert Pricing/RateCode, Pricing/RateId to SkuPriceId +conversion_type: sql_condition +conversion_args: + conditions: + - WHEN pricing_rate_code is not null THEN pricing_rate_code + default_value: pricing_rate_id +column: NA +focus_column: SkuPriceId diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/usage_quantity_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/usage_quantity_S001.yaml new file mode 100644 index 00000000..6db368a3 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/usage_quantity_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert LineItem/UsageAmount to UsageQuantity +conversion_type: rename_column +column: line_item_usage_amount +focus_column: UsageQuantity diff --git a/focus_converter_base/focus_converter/conversion_configs/aws/usage_unit_S001.yaml b/focus_converter_base/focus_converter/conversion_configs/aws/usage_unit_S001.yaml new file mode 100644 index 00000000..6ae19d53 --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_configs/aws/usage_unit_S001.yaml @@ -0,0 +1,4 @@ +plan_name: convert Pricing/Unit to UsageUnit +conversion_type: rename_column +column: pricing_unit +focus_column: UsageUnit diff --git a/focus_converter_base/focus_converter/conversion_functions/__init__.py b/focus_converter_base/focus_converter/conversion_functions/__init__.py index 7a93aa36..2084add2 100644 --- a/focus_converter_base/focus_converter/conversion_functions/__init__.py +++ b/focus_converter_base/focus_converter/conversion_functions/__init__.py @@ -30,6 +30,9 @@ class STATIC_CONVERSION_TYPES(Enum): # apply default values if column not present APPLY_DEFAULT_IF_COLUMN_MISSING = "apply_default_if_column_missing" + # set column dtypes + SET_COLUMN_DTYPES = "set_column_dtypes" + __all__ = [ "STATIC_CONVERSION_TYPES", diff --git a/focus_converter_base/focus_converter/conversion_functions/column_functions.py b/focus_converter_base/focus_converter/conversion_functions/column_functions.py index ceaaaafe..74b61cc6 100644 --- a/focus_converter_base/focus_converter/conversion_functions/column_functions.py +++ b/focus_converter_base/focus_converter/conversion_functions/column_functions.py @@ -122,12 +122,3 @@ def assign_static_value( ) return pl.lit(conversion_args.static_value).alias(column_alias) - - @staticmethod - def apply_default_if_column_missing( - plan: ConversionPlan, column_alias, column_validator: ColumnValidator - ): - # TOTO: add option to set a default value instead of just NULL - column_validator.map_static_default_value_if_not_present( - plan=plan, column_alias=column_alias - ) diff --git a/focus_converter_base/focus_converter/conversion_functions/deferred_column_functions.py b/focus_converter_base/focus_converter/conversion_functions/deferred_column_functions.py new file mode 100644 index 00000000..34ec5beb --- /dev/null +++ b/focus_converter_base/focus_converter/conversion_functions/deferred_column_functions.py @@ -0,0 +1,100 @@ +from typing import List, Tuple + +import polars as pl + +from focus_converter.configs.base_config import ( + ConversionPlan, + MissingColumnDType, + SetColumnDTypesConversionArgs, +) +from focus_converter.conversion_functions.validations import ColumnValidator + + +class DeferredColumnFunctions: + """ + # Set of functions that can only be executed once the lazyframe is loaded and the column names available + # are known. + """ + + def __init__(self): + # missing_column_plans = [] + self.__missing_column_plans__: List[Tuple[str, ConversionPlan]] = [] + + # enforced column dtypes, need to be applied before any other conversion + # if column is present then a cast operation can be applied, if not then a new column can be added + # with null values and then cast operation can be applied + self.__enforced_column_dtypes__: List[ConversionPlan] = [] + + @staticmethod + def convert_focus_data_type_polars_dtype(focus_data_type): + if focus_data_type == "string": + return pl.Utf8 + elif focus_data_type == "float": + return pl.Float64 + elif focus_data_type == "int": + return pl.Int64 + else: + raise RuntimeError(f"data_type: {focus_data_type} not implemented") + + def map_missing_column_plan( + self, plan: ConversionPlan, column_alias, column_validator: ColumnValidator + ): + self.__missing_column_plans__.append((column_alias, plan)) + column_validator.map_static_default_value_if_not_present( + plan=plan, column_alias=column_alias + ) + + def map_dtype_plan(self, plan: ConversionPlan, column_validator: ColumnValidator): + self.__enforced_column_dtypes__.append(plan) + column_validator.map_dtype_enforced_node(plan=plan) + + def apply_missing_column_plan(self, lf: pl.LazyFrame): + for column_alias, missing_column_plan in self.__missing_column_plans__: + if missing_column_plan.column not in lf.columns: + conversion_arg: MissingColumnDType = MissingColumnDType.model_validate( + missing_column_plan.conversion_args + ) + + if conversion_arg.data_type == "string": + dtype = pl.Utf8 + elif conversion_arg.data_type == "float": + dtype = pl.Float64 + elif conversion_arg.data_type == "int": + dtype = pl.Int64 + else: + raise RuntimeError( + f"data_type: {conversion_arg.data_types} not implemented" + ) + + lf = lf.with_columns( + pl.lit(None).cast(dtype).alias(missing_column_plan.column) + ) + else: + lf = lf.with_columns( + pl.col(missing_column_plan.column).alias(missing_column_plan.column) + ) + return lf + + def apply_dtype_plan(self, lf: pl.LazyFrame): + for plan in self.__enforced_column_dtypes__: + conversion_args = SetColumnDTypesConversionArgs.model_validate( + plan.conversion_args + ) + for column_obj in conversion_args.dtype_args: + if column_obj.column_name not in lf.columns: + lf = lf.with_columns( + pl.lit(None) + .cast( + self.convert_focus_data_type_polars_dtype(column_obj.dtype), + strict=False, + ) + .alias(column_obj.column_name) + ) + else: + lf = lf.with_columns( + pl.col(column_obj.column_name).cast( + self.convert_focus_data_type_polars_dtype(column_obj.dtype), + strict=False, + ) + ) + return lf diff --git a/focus_converter_base/focus_converter/conversion_functions/validations.py b/focus_converter_base/focus_converter/conversion_functions/validations.py index 8d2d70eb..d011d60d 100644 --- a/focus_converter_base/focus_converter/conversion_functions/validations.py +++ b/focus_converter_base/focus_converter/conversion_functions/validations.py @@ -6,7 +6,10 @@ import requests import sqlglot -from focus_converter.configs.base_config import ConversionPlan +from focus_converter.configs.base_config import ( + ConversionPlan, + SetColumnDTypesConversionArgs, +) SOURCE_COLUMN_NAME = "SOURCE" SINK_COLUMN_NAME = "FOCUS_DATASET" @@ -111,6 +114,15 @@ def map_static_default_value_if_not_present( ): self.__network_graph__.add_edge(SOURCE_COLUMN_NAME, plan.column, plan=plan) + def map_dtype_enforced_node(self, plan: ConversionPlan): + conversion_args = SetColumnDTypesConversionArgs.model_validate( + plan.conversion_args + ) + for column_obj in conversion_args.dtype_args: + self.__network_graph__.add_edge( + SOURCE_COLUMN_NAME, column_obj.column_name, plan=plan + ) + def validate_lazy_frame_columns(self, lf: pl.LazyFrame): # get all columns that have edge from source source_columns = [ diff --git a/focus_converter_base/focus_converter/converter.py b/focus_converter_base/focus_converter/converter.py index cdb13923..eb3c3c45 100644 --- a/focus_converter_base/focus_converter/converter.py +++ b/focus_converter_base/focus_converter/converter.py @@ -1,7 +1,7 @@ import logging import os from operator import attrgetter -from typing import Dict, List, Optional, Tuple +from typing import Dict, List, Optional import polars as pl from pkg_resources import resource_filename @@ -12,11 +12,15 @@ from focus_converter.conversion_functions.datetime_functions import ( DateTimeConversionFunctions, ) +from focus_converter.conversion_functions.deferred_column_functions import ( + DeferredColumnFunctions, +) from focus_converter.conversion_functions.lookup_function import LookupFunction from focus_converter.conversion_functions.sql_functions import SQLFunctions from focus_converter.conversion_functions.validations import ColumnValidator from focus_converter.data_loaders.data_exporter import DataExporter from focus_converter.data_loaders.data_loader import DataLoader +from focus_converter.models.focus_column_names import FocusColumnNames # TODO: Make this path configurable so that we can load from a directory outside of the project BASE_CONVERSION_CONFIGS = resource_filename("focus_converter", "conversion_configs") @@ -41,8 +45,8 @@ class FocusConverter: # converted column prefix to be added to converted columns __converted_column_prefix__: Optional[str] = None - # missing_column_plans = [] - __missing_column_plans__: List[Tuple[str, ConversionPlan]] = [] + # deferred column plans, these plans are applied after lazyframe is loaded + __deferred_column_plans__ = DeferredColumnFunctions() def __init__(self, column_prefix=None, converted_column_prefix=None): self.__temporary_columns__ = [] @@ -106,7 +110,8 @@ def prepare_horizontal_conversion_plan(self, provider): column_alias = plan.focus_column.value # add column to plan to collect these dimensions to be added in the computed dataframe - collected_columns.append(plan.focus_column.value) + if plan.focus_column != FocusColumnNames.PLACE_HOLDER: + collected_columns.append(plan.focus_column.value) if plan.conversion_type == STATIC_CONVERSION_TYPES.CONVERT_TIMEZONE: column_exprs.append( @@ -200,13 +205,14 @@ def prepare_horizontal_conversion_plan(self, provider): plan.conversion_type == STATIC_CONVERSION_TYPES.APPLY_DEFAULT_IF_COLUMN_MISSING ): - self.__missing_column_plans__.append((column_alias, plan)) - column_exprs.append( - ColumnFunctions.apply_default_if_column_missing( - plan=plan, - column_alias=column_alias, - column_validator=self.__column_validator__, - ) + self.__deferred_column_plans__.map_missing_column_plan( + plan=plan, + column_alias=column_alias, + column_validator=self.__column_validator__, + ) + elif plan.conversion_type == STATIC_CONVERSION_TYPES.SET_COLUMN_DTYPES: + self.__deferred_column_plans__.map_dtype_plan( + plan=plan, column_validator=self.__column_validator__ ) else: raise NotImplementedError( @@ -281,13 +287,9 @@ def __process_lazy_frame__(self, lf: pl.LazyFrame): if self.__column_prefix__ is not None: lf = self.__re_map_source_columns__(lf=lf) - for column_alias, missing_column_plan in self.__missing_column_plans__: - if missing_column_plan.column not in lf.columns: - lf = lf.with_columns(pl.lit(None).alias(missing_column_plan.column)) - else: - lf = lf.with_columns( - pl.col(missing_column_plan.column).alias(missing_column_plan.column) - ) + # apply deferred column plans + lf = self.__deferred_column_plans__.apply_missing_column_plan(lf=lf) + lf = self.__deferred_column_plans__.apply_dtype_plan(lf=lf) # validate all source columns exist in the lazy frame self.__column_validator__.validate_lazy_frame_columns(lf=lf) diff --git a/focus_converter_base/focus_converter/models/focus_column_names.py b/focus_converter_base/focus_converter/models/focus_column_names.py index 55146183..66a9c22e 100644 --- a/focus_converter_base/focus_converter/models/focus_column_names.py +++ b/focus_converter_base/focus_converter/models/focus_column_names.py @@ -8,8 +8,13 @@ class FocusColumnNames(Enum): Focus column names as described in https://focus.finops.org/#specification """ + PLACE_HOLDER = "PlaceHolder" + CHARGE_PERIOD_START = "ChargePeriodStart" CHARGE_PERIOD_END = "ChargePeriodEnd" + CHARGE_FREQUENCY = "ChargeFrequency" + CHARGE_SUB_CATEGORY = "ChargeSubcategory" + CHARGE_DESCRIPTION = "ChargeDescription" BILLING_PERIOD_START = "BillingPeriodStart" BILLING_PERIOD_END = "BillingPeriodEnd" @@ -25,6 +30,7 @@ class FocusColumnNames(Enum): BILLED_COST = "BilledCost" BILLED_CURRENCY = "BilledCurrency" BILLING_CURRENCY = "BillingCurrency" + EFFECTIVE_COST = "EffectiveCost" REGION = "Region" @@ -41,5 +47,21 @@ class FocusColumnNames(Enum): RESOURCE_NAME = "ResourceName" RESOURCE_ID = "ResourceId" + COMMITMENT_DISCOUNT_ID = "CommitmentDiscountId" + COMMITMENT_DISCOUNT_TYPE = "CommitmentDiscountType" + COMMITMENT_DISCOUNT_CATEGORY = "CommitmentDiscountCategory" + + PRICING_QUANTITY = "PricingQuantity" + PRICING_UNIT = "PricingUnit" + + SKU_ID = "SkuId" + SKU_PRICE_ID = "SkuPriceId" + + LIST_UNIT_PRICE = "ListUnitPrice" + LIST_COST = "ListCost" + + USAGE_QUANTITY = "UsageQuantity" + USAGE_UNIT = "UsageUnit" + FOCUS_DATETIME_ISO_FORMAT = "%Y-%m-%dT%H:%M:%SZ" diff --git a/focus_converter_base/tests/converter_functions/test_column_dtypes.py b/focus_converter_base/tests/converter_functions/test_column_dtypes.py new file mode 100644 index 00000000..60562a50 --- /dev/null +++ b/focus_converter_base/tests/converter_functions/test_column_dtypes.py @@ -0,0 +1,129 @@ +from unittest import TestCase +from uuid import uuid4 + +import pandas as pd +import polars as pl + +from focus_converter.configs.base_config import ConversionPlan +from focus_converter.conversion_functions import STATIC_CONVERSION_TYPES +from focus_converter.converter import FocusConverter +from focus_converter.models.focus_column_names import FocusColumnNames + +RENAME_SAMPLE_PLAN = ConversionPlan( + column="test_column", + config_file_name="D001_S001.yaml", + plan_name="test-plan", + dimension_id=1, + priority=0, + conversion_type=STATIC_CONVERSION_TYPES.RENAME_COLUMN, + focus_column=FocusColumnNames.PROVIDER, +) + + +# noinspection DuplicatedCode +class TestSetColumnDTypes(TestCase): + def test_conversion_args(self): + with self.assertRaises(ValueError) as cm: + ConversionPlan( + column="test_column", + config_file_name="D001_S001.yaml", + plan_name="test-plan", + dimension_id=1, + priority=0, + conversion_type=STATIC_CONVERSION_TYPES.SET_COLUMN_DTYPES, + focus_column=FocusColumnNames.PLACE_HOLDER, + ) + self.assertIn( + "Input should be a valid dictionary or instance of SetColumnDTypesConversionArgs", + str(cm.exception), + ) + + def test_dtypes_cast_from_string_to_float(self): + df = pd.DataFrame( + [ + {"a": 1, "test_column": "2"}, + {"a": 1, "test_column": "3"}, + {"a": 1, "test_column": "4"}, + {"a": 1, "test_column": "5"}, + {"a": 1, "test_column": None}, + ] + ) + pl_df = pl.from_dataframe(df).lazy() + self.assertEqual(pl_df.dtypes[1], pl.Utf8) + + sample_provider_name = str(uuid4()) + + focus_converter = FocusConverter(column_prefix=None) + focus_converter.plans = { + sample_provider_name: [ + ConversionPlan( + column="test_column", + config_file_name="D001_S001.yaml", + plan_name="test-plan", + dimension_id=1, + priority=0, + conversion_type=STATIC_CONVERSION_TYPES.SET_COLUMN_DTYPES, + focus_column=FocusColumnNames.PLACE_HOLDER, + conversion_args={ + "dtype_args": [ + {"dtype": "float", "column_name": "test_column"}, + ] + }, + ), + RENAME_SAMPLE_PLAN, + ] + } + focus_converter.prepare_horizontal_conversion_plan( + provider=sample_provider_name + ) + modified_pl_df = focus_converter.__process_lazy_frame__(lf=pl_df).collect() + self.assertEqual(modified_pl_df.dtypes[1], pl.Float64) + self.assertEqual( + list(modified_pl_df["test_column"]), + [2.0, 3.0, 4.0, 5.0, None], + ) + + def test_dtypes_cast_from_string_to_int(self): + df = pd.DataFrame( + [ + {"a": 1, "test_column": "2"}, + {"a": 1, "test_column": "3"}, + {"a": 1, "test_column": "4"}, + {"a": 1, "test_column": "5"}, + {"a": 1, "test_column": None}, + ] + ) + pl_df = pl.from_dataframe(df).lazy() + self.assertEqual(pl_df.dtypes[1], pl.Utf8) + + sample_provider_name = str(uuid4()) + + focus_converter = FocusConverter(column_prefix=None) + focus_converter.plans = { + sample_provider_name: [ + ConversionPlan( + column="test_column", + config_file_name="D001_S001.yaml", + plan_name="test-plan", + dimension_id=1, + priority=0, + conversion_type=STATIC_CONVERSION_TYPES.SET_COLUMN_DTYPES, + focus_column=FocusColumnNames.PLACE_HOLDER, + conversion_args={ + "dtype_args": [ + {"dtype": "int", "column_name": "test_column"}, + ] + }, + ), + RENAME_SAMPLE_PLAN, + ] + } + focus_converter.prepare_horizontal_conversion_plan( + provider=sample_provider_name + ) + modified_pl_df = focus_converter.__process_lazy_frame__(lf=pl_df).collect() + self.assertEqual(modified_pl_df.dtypes[1], pl.Int64) + self.assertEqual( + list(modified_pl_df["test_column"]), + [2.0, 3.0, 4.0, 5.0, None], + ) diff --git a/focus_converter_base/tests/converter_functions/test_default_value_if_not_present.py b/focus_converter_base/tests/converter_functions/test_default_value_if_not_present.py index b8ddfaf3..98002f24 100644 --- a/focus_converter_base/tests/converter_functions/test_default_value_if_not_present.py +++ b/focus_converter_base/tests/converter_functions/test_default_value_if_not_present.py @@ -50,6 +50,7 @@ def test_if_column_present_in_source(self): conversion_type=STATIC_CONVERSION_TYPES.APPLY_DEFAULT_IF_COLUMN_MISSING, focus_column=FocusColumnNames.PROVIDER, column_prefix="tmp_prefill", + conversion_args={"data_type": "string"}, ) focus_converter = FocusConverter(column_prefix=None) @@ -85,6 +86,7 @@ def test_if_column_not_present_in_source(self): conversion_type=STATIC_CONVERSION_TYPES.APPLY_DEFAULT_IF_COLUMN_MISSING, focus_column=FocusColumnNames.PROVIDER, column_prefix="tmp_prefill", + conversion_args={"data_type": "string"}, ) focus_converter = FocusConverter(column_prefix=None) @@ -109,6 +111,7 @@ def test_uml_generation(self): conversion_type=STATIC_CONVERSION_TYPES.APPLY_DEFAULT_IF_COLUMN_MISSING, focus_column=FocusColumnNames.PROVIDER, column_prefix="tmp_prefill", + conversion_args={"data_type": "string"}, ) sample_provider_name = str(uuid4()) diff --git a/focus_converter_base/tests/provider_config_tests/aws/test_aws_provider.py b/focus_converter_base/tests/provider_config_tests/aws/test_aws_provider.py index 6f1b110e..4382add4 100644 --- a/focus_converter_base/tests/provider_config_tests/aws/test_aws_provider.py +++ b/focus_converter_base/tests/provider_config_tests/aws/test_aws_provider.py @@ -10,7 +10,7 @@ class TestAWSProvider(TestCase): def test_aws_provider_config(self): conversion_plan = ConversionPlan.load_yaml( - "focus_converter/conversion_configs/aws/D011_S001.yaml" + "focus_converter/conversion_configs/aws/provider_S001.yaml" ) focus_converter = FocusConverter()