focus-data-toolkit 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- focus_data_toolkit/__init__.py +69 -0
- focus_data_toolkit/__main__.py +6 -0
- focus_data_toolkit/_version.py +8 -0
- focus_data_toolkit/cli.py +968 -0
- focus_data_toolkit/context/__init__.py +88 -0
- focus_data_toolkit/context/billing.py +54 -0
- focus_data_toolkit/context/provider.py +90 -0
- focus_data_toolkit/convert/__init__.py +708 -0
- focus_data_toolkit/convert/billing_period.py +65 -0
- focus_data_toolkit/convert/contract_applied.py +235 -0
- focus_data_toolkit/convert/contract_commitment.py +182 -0
- focus_data_toolkit/convert/cost_and_usage.py +179 -0
- focus_data_toolkit/convert/detect.py +39 -0
- focus_data_toolkit/convert/invoice_detail.py +199 -0
- focus_data_toolkit/convert/streaming.py +1030 -0
- focus_data_toolkit/errors.py +145 -0
- focus_data_toolkit/focus_json.py +68 -0
- focus_data_toolkit/generators/__init__.py +61 -0
- focus_data_toolkit/generators/_shim.py +43 -0
- focus_data_toolkit/generators/engine/__init__.py +14 -0
- focus_data_toolkit/generators/engine/context.py +12 -0
- focus_data_toolkit/generators/engine/determinism.py +117 -0
- focus_data_toolkit/generators/engine/json_focus.py +63 -0
- focus_data_toolkit/generators/engine/ladder.py +71 -0
- focus_data_toolkit/generators/engine/scenarios_core.py +380 -0
- focus_data_toolkit/generators/engine/serialize.py +151 -0
- focus_data_toolkit/generators/generate_aws_focus_1_2.py +19 -0
- focus_data_toolkit/generators/generate_aws_focus_1_3.py +20 -0
- focus_data_toolkit/generators/generate_azure_focus_1_2.py +17 -0
- focus_data_toolkit/generators/generate_azure_focus_1_3.py +17 -0
- focus_data_toolkit/generators/generate_gcp_focus_1_2.py +17 -0
- focus_data_toolkit/generators/generate_gcp_focus_1_3.py +17 -0
- focus_data_toolkit/generators/providers/__init__.py +29 -0
- focus_data_toolkit/generators/providers/aws.py +186 -0
- focus_data_toolkit/generators/providers/azure.py +191 -0
- focus_data_toolkit/generators/providers/gcp.py +194 -0
- focus_data_toolkit/generators/providers/profile.py +123 -0
- focus_data_toolkit/generators/scenarios.py +178 -0
- focus_data_toolkit/generators/versions/__init__.py +17 -0
- focus_data_toolkit/generators/versions/adapter.py +41 -0
- focus_data_toolkit/generators/versions/v1_2.py +111 -0
- focus_data_toolkit/generators/versions/v1_3.py +154 -0
- focus_data_toolkit/io/__init__.py +1 -0
- focus_data_toolkit/io/atomic_writer.py +462 -0
- focus_data_toolkit/io/csv_io.py +128 -0
- focus_data_toolkit/io/parquet_io.py +528 -0
- focus_data_toolkit/io/records.py +92 -0
- focus_data_toolkit/io/row_source.py +117 -0
- focus_data_toolkit/lifecycle.py +342 -0
- focus_data_toolkit/manifest.py +114 -0
- focus_data_toolkit/model/__init__.py +43 -0
- focus_data_toolkit/model/capabilities.py +66 -0
- focus_data_toolkit/model/focus_1_4_decimal_scale.json +10 -0
- focus_data_toolkit/model/focus_1_4_model.json +1913 -0
- focus_data_toolkit/model/focus_1_4_servicesubcategory.json +84 -0
- focus_data_toolkit/model/focus_json_keys.py +112 -0
- focus_data_toolkit/model/iso_4217_currencies.json +23 -0
- focus_data_toolkit/model/json_schema_check.py +205 -0
- focus_data_toolkit/model/json_schemas/allocatedmethoddetailsobjectschema.json +82 -0
- focus_data_toolkit/model/json_schemas/commitmentprogrameligibilitydetailsobjectschema.json +41 -0
- focus_data_toolkit/model/json_schemas/contractappliedobjectschema.json +104 -0
- focus_data_toolkit/model/json_schemas/contractcommitmentapplicabilityobjectschema.json +290 -0
- focus_data_toolkit/model/json_schemas/json_schemas_provenance.json +38 -0
- focus_data_toolkit/model/model_provenance.json +58 -0
- focus_data_toolkit/model/validator.py +498 -0
- focus_data_toolkit/modes.py +18 -0
- focus_data_toolkit/official_validator.py +61 -0
- focus_data_toolkit/progress.py +89 -0
- focus_data_toolkit/provenance.py +106 -0
- focus_data_toolkit/py.typed +1 -0
- focus_data_toolkit/runtime.py +243 -0
- focus_data_toolkit/schema/__init__.py +17 -0
- focus_data_toolkit/schema/detection.py +274 -0
- focus_data_toolkit/schema/registry.py +127 -0
- focus_data_toolkit/storage/__init__.py +1 -0
- focus_data_toolkit/storage/external_index.py +99 -0
- focus_data_toolkit/storage/spill.py +150 -0
- focus_data_toolkit/studio/__init__.py +19 -0
- focus_data_toolkit/studio/app.py +467 -0
- focus_data_toolkit/studio/config.py +42 -0
- focus_data_toolkit/studio/frontend/app.js +214 -0
- focus_data_toolkit/studio/frontend/index.html +101 -0
- focus_data_toolkit/studio/frontend/style.css +60 -0
- focus_data_toolkit/studio/jobs.py +142 -0
- focus_data_toolkit/studio/preview.py +32 -0
- focus_data_toolkit/studio/security.py +125 -0
- focus_data_toolkit/studio/server.py +71 -0
- focus_data_toolkit/supplement/__init__.py +50 -0
- focus_data_toolkit/supplement/adapters/__init__.py +21 -0
- focus_data_toolkit/supplement/adapters/adapters_provenance.json +39 -0
- focus_data_toolkit/supplement/adapters/aws_invoice_summary.json +24 -0
- focus_data_toolkit/supplement/adapters/aws_savings_plans.json +31 -0
- focus_data_toolkit/supplement/adapters/azure_invoice.json +25 -0
- focus_data_toolkit/supplement/adapters/gcp_compute_commitments.json +28 -0
- focus_data_toolkit/supplement/adapters/registry.py +215 -0
- focus_data_toolkit/supplement/apply.py +318 -0
- focus_data_toolkit/supplement/gaps.py +219 -0
- focus_data_toolkit/supplement/kinds.py +118 -0
- focus_data_toolkit/supplement/loader.py +409 -0
- focus_data_toolkit/supplement/spec.py +74 -0
- focus_data_toolkit/supplement/validate.py +215 -0
- focus_data_toolkit/validate/__init__.py +15 -0
- focus_data_toolkit/validate/allocation.py +333 -0
- focus_data_toolkit/validate/bundle.py +254 -0
- focus_data_toolkit/validate/codes.py +93 -0
- focus_data_toolkit/validate/corrections.py +245 -0
- focus_data_toolkit/validate/reconciliation.py +98 -0
- focus_data_toolkit/validate/referential.py +289 -0
- focus_data_toolkit-0.11.0.dist-info/METADATA +519 -0
- focus_data_toolkit-0.11.0.dist-info/RECORD +116 -0
- focus_data_toolkit-0.11.0.dist-info/WHEEL +5 -0
- focus_data_toolkit-0.11.0.dist-info/entry_points.txt +2 -0
- focus_data_toolkit-0.11.0.dist-info/licenses/LICENSE +21 -0
- focus_data_toolkit-0.11.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +156 -0
- focus_data_toolkit-0.11.0.dist-info/licenses/NOTICE +60 -0
- focus_data_toolkit-0.11.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""AWS provider profile (FOCUS synthetic data)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import random
|
|
7
|
+
from decimal import Decimal
|
|
8
|
+
|
|
9
|
+
from focus_data_toolkit.generators.engine.determinism import hexid
|
|
10
|
+
from focus_data_toolkit.generators.providers.profile import (
|
|
11
|
+
CommitmentModel,
|
|
12
|
+
ProviderProfile,
|
|
13
|
+
ResourceRef,
|
|
14
|
+
RowContext,
|
|
15
|
+
ServiceSpec,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_SERVICES: tuple[ServiceSpec, ...] = (
|
|
19
|
+
ServiceSpec(
|
|
20
|
+
"AmazonEC2", "Compute", "Virtual Machines", "EC2 Instance",
|
|
21
|
+
"Compute", "Hours", "Linux on-demand m6i.large", Decimal("0.096"),
|
|
22
|
+
Decimal("1"), Decimal("1"), "i-", "hourly", True, True,
|
|
23
|
+
id_fields={"arn_kind": "instance"},
|
|
24
|
+
sku_details={
|
|
25
|
+
"InstanceType": "m6i.large", "InstanceSeries": "M6i", "CoreCount": 2,
|
|
26
|
+
"MemorySize": 8, "OperatingSystem": "Linux", "x_Tenancy": "Shared",
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
ServiceSpec(
|
|
30
|
+
"AmazonS3", "Storage", "Object Storage", "S3 Bucket",
|
|
31
|
+
"Storage", "GB-Months", "S3 Standard storage", Decimal("0.023"),
|
|
32
|
+
Decimal("50"), Decimal("8000"), "bucket-", "monthly", False, False,
|
|
33
|
+
id_fields={"arn_kind": "bucket"},
|
|
34
|
+
sku_details={"StorageClass": "Standard", "Redundancy": "LRS"},
|
|
35
|
+
),
|
|
36
|
+
ServiceSpec(
|
|
37
|
+
"AmazonRDS", "Databases", "Relational Databases", "RDS Instance",
|
|
38
|
+
"Database", "Hours", "RDS PostgreSQL db.r6g.large", Decimal("0.240"),
|
|
39
|
+
Decimal("1"), Decimal("1"), "db-", "hourly", False, False,
|
|
40
|
+
id_fields={"arn_kind": "db"},
|
|
41
|
+
sku_details={
|
|
42
|
+
"InstanceType": "db.r6g.large", "InstanceSeries": "R6g", "CoreCount": 2,
|
|
43
|
+
"MemorySize": 16, "x_Engine": "PostgreSQL",
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
ServiceSpec(
|
|
47
|
+
"AWSLambda", "Compute", "Serverless Compute", "Lambda Function",
|
|
48
|
+
"Compute", "GB-Seconds", "Lambda function duration", Decimal("0.0000166667"),
|
|
49
|
+
Decimal("100000"), Decimal("5000000"), "fn-", "hourly", False, False,
|
|
50
|
+
id_fields={"arn_kind": "function"},
|
|
51
|
+
sku_details={"x_Runtime": "python3.12", "x_Architecture": "arm64"},
|
|
52
|
+
),
|
|
53
|
+
ServiceSpec(
|
|
54
|
+
"AmazonVPC", "Networking", "Network Connectivity", "NAT Gateway",
|
|
55
|
+
"Data Transfer", "GB", "NAT gateway data processed", Decimal("0.045"),
|
|
56
|
+
Decimal("1"), Decimal("500"), "nat-", "daily", False, False,
|
|
57
|
+
id_fields={"arn_kind": "natgateway"},
|
|
58
|
+
sku_details={"x_TransferType": "InterAZ"},
|
|
59
|
+
),
|
|
60
|
+
ServiceSpec(
|
|
61
|
+
"AmazonCloudWatch", "Management and Governance", "Observability", "Metric",
|
|
62
|
+
"Monitoring", "Metrics", "Custom metrics", Decimal("0.300"),
|
|
63
|
+
Decimal("1"), Decimal("200"), "metric-", "daily", False, False,
|
|
64
|
+
id_fields={"arn_kind": "metric"},
|
|
65
|
+
sku_details={"x_MetricType": "Custom"},
|
|
66
|
+
),
|
|
67
|
+
ServiceSpec(
|
|
68
|
+
"AmazonDynamoDB", "Databases", "NoSQL Databases", "DynamoDB Table",
|
|
69
|
+
"Database", "Requests", "DynamoDB on-demand write requests", Decimal("0.00000125"),
|
|
70
|
+
Decimal("100000"), Decimal("5000000"), "table-", "daily", False, False,
|
|
71
|
+
id_fields={"arn_kind": "table"},
|
|
72
|
+
sku_details={"x_CapacityMode": "On-Demand"},
|
|
73
|
+
),
|
|
74
|
+
ServiceSpec(
|
|
75
|
+
"AWSGlue", "Analytics", "Data Processing", "Glue Job",
|
|
76
|
+
"Data Processing", "DPU-Hours", "Glue ETL job run", Decimal("0.440"),
|
|
77
|
+
Decimal("1"), Decimal("200"), "job-", "daily", False, False,
|
|
78
|
+
id_fields={"arn_kind": "job"},
|
|
79
|
+
sku_details={"x_WorkerType": "G.1X"},
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
_REGIONS: tuple[tuple[str, str, tuple[str, ...]], ...] = (
|
|
84
|
+
("us-east-1", "US East (N. Virginia)", ("us-east-1a", "us-east-1b", "us-east-1c")),
|
|
85
|
+
("us-west-2", "US West (Oregon)", ("us-west-2a", "us-west-2b")),
|
|
86
|
+
("eu-west-1", "EU (Ireland)", ("eu-west-1a", "eu-west-1b")),
|
|
87
|
+
("ap-southeast-1", "Asia Pacific (Singapore)", ("ap-southeast-1a", "ap-southeast-1b")),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
_BILLING_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
91
|
+
("100000000001", "ExampleCorp Master Payer"),
|
|
92
|
+
("100000000002", "ExampleCorp Secondary Payer"),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
_SUB_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
96
|
+
("200000000011", "prod-platform"),
|
|
97
|
+
("200000000012", "staging-platform"),
|
|
98
|
+
("200000000013", "data-analytics"),
|
|
99
|
+
("200000000014", "sandbox-dev"),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _resource_id(ref: ResourceRef) -> str:
|
|
104
|
+
svc = ref.spec.name[6:].lower() or "svc"
|
|
105
|
+
return (
|
|
106
|
+
f"arn:aws:{svc}:{ref.region_id}:{ref.billing_id}:"
|
|
107
|
+
f"{ref.spec.id_fields['arn_kind']}/{ref.resource_name}"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _resource_name(rng: random.Random, spec: ServiceSpec) -> str:
|
|
112
|
+
return f"{spec.name_prefix}{hexid(rng, 12)}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _committed_resource_name(rng: random.Random, spec: ServiceSpec, k: int) -> str:
|
|
116
|
+
return f"{spec.name_prefix}{k:04d}{hexid(rng, 8)}"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _sku_id(rng: random.Random, spec: ServiceSpec) -> str:
|
|
120
|
+
return f"SKU-{spec.name[:6].upper()}-{hexid(rng, 6)}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _sku_price_id(rng: random.Random) -> str:
|
|
124
|
+
return f"SPRICE-{hexid(rng, 8)}"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _allocated_resource_id(rng: random.Random, region_id: str, ctx: RowContext, workload: str) -> str:
|
|
128
|
+
return f"arn:aws:eks:{region_id}:{ctx.billing_id}:workload/{workload}-{hexid(rng, 6)}"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _commit_id(rng: random.Random, region_id: str, sub_id: str, spend_based: bool) -> str:
|
|
132
|
+
commit_kind = "savingsplan" if spend_based else "reservation"
|
|
133
|
+
service = "savingsplans" if spend_based else "ec2"
|
|
134
|
+
return f"arn:aws:{service}:{region_id}::{commit_kind}/{hexid(rng, 16)}"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _commit_resource_name(rng: random.Random, spend_based: bool) -> str:
|
|
138
|
+
commit_kind = "savingsplan" if spend_based else "reservation"
|
|
139
|
+
return f"{commit_kind}-{hexid(rng, 12)}"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _purchase_sku_id(rng: random.Random) -> str:
|
|
143
|
+
return f"SKU-COMMIT-{hexid(rng, 6)}"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _purchase_sku_details(spend_based: bool) -> str:
|
|
147
|
+
return json.dumps({"x_PurchaseTerm": "1yr", "x_PaymentOption": "AllUpfront"}, separators=(",", ":"))
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
AWS = ProviderProfile(
|
|
151
|
+
key="aws",
|
|
152
|
+
provider_name="AWS",
|
|
153
|
+
publisher_name="AWS",
|
|
154
|
+
service_provider_name="AWS",
|
|
155
|
+
host_provider_name="AWS",
|
|
156
|
+
invoice_issuer_name="AWS",
|
|
157
|
+
billing_account_type="Payer Account",
|
|
158
|
+
sub_account_type="Linked Account",
|
|
159
|
+
split_allocation_description="Shared EC2 host cost allocated to workload",
|
|
160
|
+
tag_keys=("Environment", "CostCenter", "Owner"),
|
|
161
|
+
invoice_id=lambda billing_id: f"INV-2026-05-{billing_id[-4:]}",
|
|
162
|
+
services=_SERVICES,
|
|
163
|
+
regions=_REGIONS,
|
|
164
|
+
billing_accounts=_BILLING_ACCOUNTS,
|
|
165
|
+
sub_accounts=_SUB_ACCOUNTS,
|
|
166
|
+
resource_id=_resource_id,
|
|
167
|
+
resource_name=_resource_name,
|
|
168
|
+
committed_resource_name=_committed_resource_name,
|
|
169
|
+
sku_id=_sku_id,
|
|
170
|
+
sku_price_id=_sku_price_id,
|
|
171
|
+
allocated_resource_id=_allocated_resource_id,
|
|
172
|
+
commitment=CommitmentModel(
|
|
173
|
+
commit_id_before_base_row=True,
|
|
174
|
+
commit_id=_commit_id,
|
|
175
|
+
commit_resource_name=_commit_resource_name,
|
|
176
|
+
purchase_sku_id=_purchase_sku_id,
|
|
177
|
+
purchase_sku_details=_purchase_sku_details,
|
|
178
|
+
purchase_description=lambda commit_type: f"{commit_type} commitment purchase (all upfront)",
|
|
179
|
+
commit_name=lambda spend_based: (
|
|
180
|
+
"ComputeSavingsPlan-1yr-AllUpfront" if spend_based else "EC2ReservedInstance-1yr-AllUpfront"
|
|
181
|
+
),
|
|
182
|
+
commit_type=lambda spend_based: "Savings Plan" if spend_based else "Reserved Instance",
|
|
183
|
+
commit_category=lambda spend_based: "Spend" if spend_based else "Usage",
|
|
184
|
+
commit_unit=lambda spend_based: "USD" if spend_based else "Hours",
|
|
185
|
+
),
|
|
186
|
+
)
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Microsoft Azure provider profile (FOCUS synthetic data)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import random
|
|
7
|
+
from decimal import Decimal
|
|
8
|
+
|
|
9
|
+
from focus_data_toolkit.generators.engine.determinism import hexid
|
|
10
|
+
from focus_data_toolkit.generators.providers.profile import (
|
|
11
|
+
CommitmentModel,
|
|
12
|
+
ProviderProfile,
|
|
13
|
+
ResourceRef,
|
|
14
|
+
RowContext,
|
|
15
|
+
ServiceSpec,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_SERVICES: tuple[ServiceSpec, ...] = (
|
|
19
|
+
ServiceSpec(
|
|
20
|
+
"Virtual Machines", "Compute", "Virtual Machines", "Virtual Machine",
|
|
21
|
+
"Compute", "Hours", "Standard_D4s_v5 instance", Decimal("0.192"),
|
|
22
|
+
Decimal("1"), Decimal("1"), "vm-", "hourly", True, True,
|
|
23
|
+
id_fields={"arm_type": "Microsoft.Compute/virtualMachines"},
|
|
24
|
+
sku_details={
|
|
25
|
+
"InstanceType": "Standard_D4s_v5", "InstanceSeries": "Ddsv5", "CoreCount": 4,
|
|
26
|
+
"MemorySize": 16, "OperatingSystem": "Linux", "x_Tenancy": "Shared",
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
ServiceSpec(
|
|
30
|
+
"Azure Blob Storage", "Storage", "Object Storage", "Storage Account",
|
|
31
|
+
"Storage", "GB-Months", "Hot LRS data stored", Decimal("0.0184"),
|
|
32
|
+
Decimal("50"), Decimal("8000"), "stor", "monthly", False, False,
|
|
33
|
+
id_fields={"arm_type": "Microsoft.Storage/storageAccounts"},
|
|
34
|
+
sku_details={"StorageClass": "Hot", "Redundancy": "LRS"},
|
|
35
|
+
),
|
|
36
|
+
ServiceSpec(
|
|
37
|
+
"Azure SQL Database", "Databases", "Relational Databases", "SQL Database",
|
|
38
|
+
"Database", "Hours", "General Purpose 4 vCore", Decimal("0.504"),
|
|
39
|
+
Decimal("1"), Decimal("1"), "sqldb-", "hourly", False, False,
|
|
40
|
+
id_fields={"arm_type": "Microsoft.Sql/servers/databases"},
|
|
41
|
+
sku_details={"InstanceType": "GP_Gen5_4", "CoreCount": 4, "MemorySize": 20, "x_Engine": "SQLServer"},
|
|
42
|
+
),
|
|
43
|
+
ServiceSpec(
|
|
44
|
+
"Azure Functions", "Compute", "Serverless Compute", "Function App",
|
|
45
|
+
"Compute", "GB-Seconds", "Function execution duration", Decimal("0.000016"),
|
|
46
|
+
Decimal("100000"), Decimal("4000000"), "func-", "hourly", False, False,
|
|
47
|
+
id_fields={"arm_type": "Microsoft.Web/sites"},
|
|
48
|
+
sku_details={"x_Plan": "Consumption", "x_Runtime": "dotnet8"},
|
|
49
|
+
),
|
|
50
|
+
ServiceSpec(
|
|
51
|
+
"Azure Kubernetes Service", "Compute", "Containers", "Managed Cluster",
|
|
52
|
+
"Compute", "Hours", "AKS node pool hours", Decimal("0.192"),
|
|
53
|
+
Decimal("1"), Decimal("1"), "aks-", "hourly", False, False,
|
|
54
|
+
id_fields={"arm_type": "Microsoft.ContainerService/managedClusters"},
|
|
55
|
+
sku_details={
|
|
56
|
+
"InstanceType": "Standard_D4s_v5", "CoreCount": 4, "MemorySize": 16,
|
|
57
|
+
"x_NodePool": "system",
|
|
58
|
+
},
|
|
59
|
+
),
|
|
60
|
+
ServiceSpec(
|
|
61
|
+
"Azure Monitor", "Management and Governance", "Observability", "Log Analytics Workspace",
|
|
62
|
+
"Monitoring", "GB", "Log data ingested", Decimal("2.30"),
|
|
63
|
+
Decimal("1"), Decimal("500"), "law-", "daily", False, False,
|
|
64
|
+
id_fields={"arm_type": "Microsoft.OperationalInsights/workspaces"},
|
|
65
|
+
sku_details={"x_DataType": "Logs"},
|
|
66
|
+
),
|
|
67
|
+
ServiceSpec(
|
|
68
|
+
"Azure Cosmos DB", "Databases", "NoSQL Databases", "Cosmos DB Account",
|
|
69
|
+
"Database", "Hours", "Provisioned throughput", Decimal("0.008"),
|
|
70
|
+
Decimal("1"), Decimal("1"), "cosmos-", "hourly", False, False,
|
|
71
|
+
id_fields={"arm_type": "Microsoft.DocumentDB/databaseAccounts"},
|
|
72
|
+
sku_details={"x_CapacityMode": "Provisioned"},
|
|
73
|
+
),
|
|
74
|
+
ServiceSpec(
|
|
75
|
+
"Virtual Network", "Networking", "Network Connectivity", "Virtual Network",
|
|
76
|
+
"Data Transfer", "GB", "VNet peering data transfer", Decimal("0.010"),
|
|
77
|
+
Decimal("1"), Decimal("5000"), "vnet-", "daily", False, False,
|
|
78
|
+
id_fields={"arm_type": "Microsoft.Network/virtualNetworks"},
|
|
79
|
+
sku_details={"x_TransferType": "Peering"},
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
_REGIONS: tuple[tuple[str, str, tuple[str, ...]], ...] = (
|
|
84
|
+
("eastus", "East US", ("eastus-1", "eastus-2", "eastus-3")),
|
|
85
|
+
("westeurope", "West Europe", ("westeurope-1", "westeurope-2")),
|
|
86
|
+
("westus2", "West US 2", ("westus2-1", "westus2-2")),
|
|
87
|
+
("southeastasia", "Southeast Asia", ("southeastasia-1", "southeastasia-2")),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
_BILLING_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
91
|
+
("8a1b2c3d-0000-4a00-9000-000000000001", "ExampleCorp MCA - Primary"),
|
|
92
|
+
("8a1b2c3d-0000-4a00-9000-000000000002", "ExampleCorp MCA - Secondary"),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
_SUB_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
96
|
+
("11111111-1111-4111-8111-111111111111", "prod-platform"),
|
|
97
|
+
("22222222-2222-4222-8222-222222222222", "staging-platform"),
|
|
98
|
+
("33333333-3333-4333-8333-333333333333", "data-analytics"),
|
|
99
|
+
("44444444-4444-4444-8444-444444444444", "sandbox-dev"),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _arm_id(ref: ResourceRef) -> str:
|
|
104
|
+
return (
|
|
105
|
+
f"/subscriptions/{ref.sub_id}/resourceGroups/rg-{ref.sub_name}"
|
|
106
|
+
f"/providers/{ref.spec.id_fields['arm_type']}/{ref.resource_name}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _resource_name(rng: random.Random, spec: ServiceSpec) -> str:
|
|
111
|
+
return f"{spec.name_prefix}{hexid(rng, 8)}"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _committed_resource_name(rng: random.Random, spec: ServiceSpec, k: int) -> str:
|
|
115
|
+
return f"{spec.name_prefix}{k:04d}{hexid(rng, 6)}"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _sku_id(rng: random.Random, spec: ServiceSpec) -> str:
|
|
119
|
+
return f"AZ-{spec.name[:4].upper().strip()}-{hexid(rng, 6)}"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _sku_price_id(rng: random.Random) -> str:
|
|
123
|
+
return f"AZSP-{hexid(rng, 8)}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _allocated_resource_id(rng: random.Random, region_id: str, ctx: RowContext, workload: str) -> str:
|
|
127
|
+
return (
|
|
128
|
+
f"/subscriptions/{ctx.sub_id}/resourceGroups/rg-{ctx.sub_name}"
|
|
129
|
+
f"/providers/Microsoft.ContainerService/managedClusters/aks-{hexid(rng, 6)}"
|
|
130
|
+
f"/workloads/{workload}"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _commit_id(rng: random.Random, region_id: str, sub_id: str, spend_based: bool) -> str:
|
|
135
|
+
commit_kind = "savingsPlans" if spend_based else "reservations"
|
|
136
|
+
return (
|
|
137
|
+
f"/subscriptions/{sub_id}/providers/Microsoft.BillingBenefits"
|
|
138
|
+
f"/{commit_kind}/{hexid(rng, 12)}"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _commit_resource_name(rng: random.Random, spend_based: bool) -> str:
|
|
143
|
+
commit_kind = "savingsPlans" if spend_based else "reservations"
|
|
144
|
+
return f"{commit_kind}-{hexid(rng, 10)}"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _purchase_sku_id(rng: random.Random) -> str:
|
|
148
|
+
return f"AZ-COMMIT-{hexid(rng, 6)}"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _purchase_sku_details(spend_based: bool) -> str:
|
|
152
|
+
return json.dumps({"x_Term": "P1Y", "x_PaymentOption": "AllUpfront"}, separators=(",", ":"))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
AZURE = ProviderProfile(
|
|
156
|
+
key="azure",
|
|
157
|
+
provider_name="Microsoft Azure",
|
|
158
|
+
publisher_name="Microsoft",
|
|
159
|
+
service_provider_name="Microsoft Azure",
|
|
160
|
+
host_provider_name="Microsoft Azure",
|
|
161
|
+
invoice_issuer_name="Microsoft Azure",
|
|
162
|
+
billing_account_type="Microsoft Customer Agreement",
|
|
163
|
+
sub_account_type="Subscription",
|
|
164
|
+
split_allocation_description="Shared VM host cost allocated to workload",
|
|
165
|
+
tag_keys=("Environment", "CostCenter", "Owner"),
|
|
166
|
+
invoice_id=lambda billing_id: f"INV-2026-05-{billing_id[-6:]}",
|
|
167
|
+
services=_SERVICES,
|
|
168
|
+
regions=_REGIONS,
|
|
169
|
+
billing_accounts=_BILLING_ACCOUNTS,
|
|
170
|
+
sub_accounts=_SUB_ACCOUNTS,
|
|
171
|
+
resource_id=_arm_id,
|
|
172
|
+
resource_name=_resource_name,
|
|
173
|
+
committed_resource_name=_committed_resource_name,
|
|
174
|
+
sku_id=_sku_id,
|
|
175
|
+
sku_price_id=_sku_price_id,
|
|
176
|
+
allocated_resource_id=_allocated_resource_id,
|
|
177
|
+
commitment=CommitmentModel(
|
|
178
|
+
commit_id_before_base_row=False,
|
|
179
|
+
commit_id=_commit_id,
|
|
180
|
+
commit_resource_name=_commit_resource_name,
|
|
181
|
+
purchase_sku_id=_purchase_sku_id,
|
|
182
|
+
purchase_sku_details=_purchase_sku_details,
|
|
183
|
+
purchase_description=lambda commit_type: f"{commit_type} commitment purchase (all upfront)",
|
|
184
|
+
commit_name=lambda spend_based: (
|
|
185
|
+
"AzureSavingsPlan-1yr-AllUpfront" if spend_based else "AzureReservation-1yr-AllUpfront"
|
|
186
|
+
),
|
|
187
|
+
commit_type=lambda spend_based: "Savings Plan" if spend_based else "Reservation",
|
|
188
|
+
commit_category=lambda spend_based: "Spend" if spend_based else "Usage",
|
|
189
|
+
commit_unit=lambda spend_based: "USD" if spend_based else "Hours",
|
|
190
|
+
),
|
|
191
|
+
)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Google Cloud provider profile (FOCUS synthetic data)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import random
|
|
7
|
+
from decimal import Decimal
|
|
8
|
+
|
|
9
|
+
from focus_data_toolkit.generators.engine.determinism import HEX_UPPER, hexid
|
|
10
|
+
from focus_data_toolkit.generators.providers.profile import (
|
|
11
|
+
CommitmentModel,
|
|
12
|
+
ProviderProfile,
|
|
13
|
+
ResourceRef,
|
|
14
|
+
RowContext,
|
|
15
|
+
ServiceSpec,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_SERVICES: tuple[ServiceSpec, ...] = (
|
|
19
|
+
ServiceSpec(
|
|
20
|
+
"Compute Engine", "Compute", "Virtual Machines", "Compute Instance",
|
|
21
|
+
"Compute", "Hours", "e2-standard-4 running", Decimal("0.134"),
|
|
22
|
+
Decimal("1"), Decimal("1"), "instance-", "hourly", True, True,
|
|
23
|
+
id_fields={"api": "compute.googleapis.com", "collection": "instances"},
|
|
24
|
+
sku_details={
|
|
25
|
+
"InstanceType": "e2-standard-4", "InstanceSeries": "E2", "CoreCount": 4,
|
|
26
|
+
"MemorySize": 16, "OperatingSystem": "Linux", "x_Preemptible": "false",
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
ServiceSpec(
|
|
30
|
+
"Cloud Storage", "Storage", "Object Storage", "Storage Bucket",
|
|
31
|
+
"Storage", "GB-Months", "Standard storage", Decimal("0.020"),
|
|
32
|
+
Decimal("50"), Decimal("8000"), "bucket-", "monthly", False, False,
|
|
33
|
+
id_fields={"api": "storage.googleapis.com", "collection": "buckets"},
|
|
34
|
+
sku_details={"StorageClass": "Standard"},
|
|
35
|
+
),
|
|
36
|
+
ServiceSpec(
|
|
37
|
+
"Cloud SQL", "Databases", "Relational Databases", "Cloud SQL Instance",
|
|
38
|
+
"Database", "Hours", "Cloud SQL custom 4 vCPU", Decimal("0.200"),
|
|
39
|
+
Decimal("1"), Decimal("1"), "sql-", "hourly", False, False,
|
|
40
|
+
id_fields={"api": "sqladmin.googleapis.com", "collection": "instances"},
|
|
41
|
+
sku_details={"InstanceType": "db-custom-4-16384", "CoreCount": 4, "MemorySize": 16,
|
|
42
|
+
"x_Engine": "PostgreSQL"},
|
|
43
|
+
),
|
|
44
|
+
ServiceSpec(
|
|
45
|
+
"Cloud Functions", "Compute", "Serverless Compute", "Cloud Function",
|
|
46
|
+
"Compute", "GB-Seconds", "Function execution duration", Decimal("0.0000025"),
|
|
47
|
+
Decimal("100000"), Decimal("8000000"), "fn-", "hourly", False, False,
|
|
48
|
+
id_fields={"api": "cloudfunctions.googleapis.com", "collection": "functions"},
|
|
49
|
+
sku_details={"x_Runtime": "python312", "x_Generation": "gen2"},
|
|
50
|
+
),
|
|
51
|
+
ServiceSpec(
|
|
52
|
+
"Google Kubernetes Engine", "Compute", "Containers", "GKE Cluster",
|
|
53
|
+
"Compute", "Hours", "GKE node pool hours", Decimal("0.134"),
|
|
54
|
+
Decimal("1"), Decimal("1"), "gke-", "hourly", False, False,
|
|
55
|
+
id_fields={"api": "container.googleapis.com", "collection": "clusters"},
|
|
56
|
+
sku_details={
|
|
57
|
+
"InstanceType": "e2-standard-4", "CoreCount": 4, "MemorySize": 16,
|
|
58
|
+
"x_NodePool": "default",
|
|
59
|
+
},
|
|
60
|
+
),
|
|
61
|
+
ServiceSpec(
|
|
62
|
+
"Cloud Monitoring", "Management and Governance", "Observability", "Monitoring Workspace",
|
|
63
|
+
"Monitoring", "MiB", "Monitoring data ingested", Decimal("0.2580"),
|
|
64
|
+
Decimal("1"), Decimal("300"), "mon-", "daily", False, False,
|
|
65
|
+
id_fields={"api": "monitoring.googleapis.com", "collection": "metricsScopes"},
|
|
66
|
+
sku_details={"x_DataType": "Metrics"},
|
|
67
|
+
),
|
|
68
|
+
ServiceSpec(
|
|
69
|
+
"BigQuery", "Databases", "Data Warehouses", "BigQuery Dataset",
|
|
70
|
+
"Analysis", "TiB", "On-demand query analysis", Decimal("6.250"),
|
|
71
|
+
Decimal("0.01"), Decimal("50"), "ds_", "daily", False, False,
|
|
72
|
+
id_fields={"api": "bigquery.googleapis.com", "collection": "datasets"},
|
|
73
|
+
sku_details={"x_Edition": "OnDemand"},
|
|
74
|
+
),
|
|
75
|
+
ServiceSpec(
|
|
76
|
+
"Cloud Run", "Compute", "Serverless Compute", "Cloud Run Service",
|
|
77
|
+
"Compute", "Core-Seconds", "Cloud Run vCPU allocation", Decimal("0.000024"),
|
|
78
|
+
Decimal("100000"), Decimal("5000000"), "svc-", "hourly", False, False,
|
|
79
|
+
id_fields={"api": "run.googleapis.com", "collection": "services"},
|
|
80
|
+
sku_details={"x_Generation": "gen2"},
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
_REGIONS: tuple[tuple[str, str, tuple[str, ...]], ...] = (
|
|
85
|
+
("us-central1", "Iowa", ("us-central1-a", "us-central1-b", "us-central1-c")),
|
|
86
|
+
("europe-west1", "Belgium", ("europe-west1-b", "europe-west1-c")),
|
|
87
|
+
("us-east1", "South Carolina", ("us-east1-b", "us-east1-c")),
|
|
88
|
+
("asia-southeast1", "Singapore", ("asia-southeast1-a", "asia-southeast1-b")),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
_BILLING_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
92
|
+
("01A2B3-C4D5E6-F70819", "ExampleCorp Billing - Primary"),
|
|
93
|
+
("11C2D3-E4F506-A7B8C9", "ExampleCorp Billing - Secondary"),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
_SUB_ACCOUNTS: tuple[tuple[str, str], ...] = (
|
|
97
|
+
("examplecorp-prod-481627", "prod-platform"),
|
|
98
|
+
("examplecorp-staging-552831", "staging-platform"),
|
|
99
|
+
("examplecorp-data-739104", "data-analytics"),
|
|
100
|
+
("examplecorp-sandbox-160942", "sandbox-dev"),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _sku(rng: random.Random) -> str:
|
|
105
|
+
def block() -> str:
|
|
106
|
+
return hexid(rng, 4, HEX_UPPER)
|
|
107
|
+
|
|
108
|
+
return f"{block()}-{block()}-{block()}"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _resource_id(ref: ResourceRef) -> str:
|
|
112
|
+
return (
|
|
113
|
+
f"//{ref.spec.id_fields['api']}/projects/{ref.sub_id}"
|
|
114
|
+
f"/{ref.spec.id_fields['collection']}/{ref.resource_name}"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _resource_name(rng: random.Random, spec: ServiceSpec) -> str:
|
|
119
|
+
return f"{spec.name_prefix}{hexid(rng, 8)}"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _committed_resource_name(rng: random.Random, spec: ServiceSpec, k: int) -> str:
|
|
123
|
+
return f"{spec.name_prefix}{k:04d}{hexid(rng, 6)}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _sku_id(rng: random.Random, spec: ServiceSpec) -> str:
|
|
127
|
+
return _sku(rng)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _sku_price_id(rng: random.Random) -> str:
|
|
131
|
+
return _sku(rng)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _allocated_resource_id(rng: random.Random, region_id: str, ctx: RowContext, workload: str) -> str:
|
|
135
|
+
return (
|
|
136
|
+
f"//container.googleapis.com/projects/{ctx.sub_id}/clusters/gke-{hexid(rng, 6)}"
|
|
137
|
+
f"/workloads/{workload}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _commit_id(rng: random.Random, region_id: str, sub_id: str, spend_based: bool) -> str:
|
|
142
|
+
return (
|
|
143
|
+
f"//compute.googleapis.com/projects/{sub_id}/regions/{region_id}"
|
|
144
|
+
f"/commitments/cud-{hexid(rng, 10)}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _commit_resource_name(rng: random.Random, spend_based: bool) -> str:
|
|
149
|
+
return f"cud-{hexid(rng, 10)}"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _purchase_sku_id(rng: random.Random) -> str:
|
|
153
|
+
return _sku(rng)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _purchase_sku_details(spend_based: bool) -> str:
|
|
157
|
+
return json.dumps({"x_Plan": "TWELVE_MONTH", "x_Type": "COMPUTE_OPTIMIZED"}, separators=(",", ":"))
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
GCP = ProviderProfile(
|
|
161
|
+
key="gcp",
|
|
162
|
+
provider_name="Google Cloud",
|
|
163
|
+
publisher_name="Google",
|
|
164
|
+
service_provider_name="Google Cloud",
|
|
165
|
+
host_provider_name="Google Cloud",
|
|
166
|
+
invoice_issuer_name="Google Cloud",
|
|
167
|
+
billing_account_type="Billing Account",
|
|
168
|
+
sub_account_type="Project",
|
|
169
|
+
split_allocation_description="Shared Compute Engine host cost allocated to workload",
|
|
170
|
+
tag_keys=("environment", "cost-center", "owner"),
|
|
171
|
+
invoice_id=lambda billing_id: f"INV-2026-05-{billing_id.replace('-', '')[-6:]}",
|
|
172
|
+
services=_SERVICES,
|
|
173
|
+
regions=_REGIONS,
|
|
174
|
+
billing_accounts=_BILLING_ACCOUNTS,
|
|
175
|
+
sub_accounts=_SUB_ACCOUNTS,
|
|
176
|
+
resource_id=_resource_id,
|
|
177
|
+
resource_name=_resource_name,
|
|
178
|
+
committed_resource_name=_committed_resource_name,
|
|
179
|
+
sku_id=_sku_id,
|
|
180
|
+
sku_price_id=_sku_price_id,
|
|
181
|
+
allocated_resource_id=_allocated_resource_id,
|
|
182
|
+
commitment=CommitmentModel(
|
|
183
|
+
commit_id_before_base_row=False,
|
|
184
|
+
commit_id=_commit_id,
|
|
185
|
+
commit_resource_name=_commit_resource_name,
|
|
186
|
+
purchase_sku_id=_purchase_sku_id,
|
|
187
|
+
purchase_sku_details=_purchase_sku_details,
|
|
188
|
+
purchase_description=lambda commit_type: "Committed Use Discount purchase (all upfront)",
|
|
189
|
+
commit_name=lambda spend_based: "SpendBasedCUD-1yr" if spend_based else "ResourceBasedCUD-1yr-Compute",
|
|
190
|
+
commit_type=lambda spend_based: "Committed Use Discount",
|
|
191
|
+
commit_category=lambda spend_based: "Spend" if spend_based else "Usage",
|
|
192
|
+
commit_unit=lambda spend_based: "USD" if spend_based else "Hours",
|
|
193
|
+
),
|
|
194
|
+
)
|