Finish first passes at baseline tenant integration
Add last of the integrations for setting up billing and reporting a CLIN.
This commit is contained in:
parent
161462f3cb
commit
81f23ebc22
@ -231,15 +231,15 @@ class BillingProfileCSPPayload(BaseCSPPayload):
|
|||||||
|
|
||||||
|
|
||||||
class BillingProfileCreateCSPResult(AliasModel):
|
class BillingProfileCreateCSPResult(AliasModel):
|
||||||
location: str
|
billing_profile_validate_url: str
|
||||||
retry_after: int
|
retry_after: int
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
fields = {"location": "Location", "retry_after": "Retry-After"}
|
fields = {"billing_profile_validate_url": "Location", "retry_after": "Retry-After"}
|
||||||
|
|
||||||
|
|
||||||
class BillingProfileVerifyCSPPayload(BaseCSPPayload):
|
class BillingProfileVerifyCSPPayload(BaseCSPPayload):
|
||||||
location: str
|
billing_profile_validate_url: str
|
||||||
|
|
||||||
|
|
||||||
class BillingInvoiceSection(AliasModel):
|
class BillingInvoiceSection(AliasModel):
|
||||||
@ -269,6 +269,70 @@ class BillingProfileCSPResult(AliasModel):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BillingRoleAssignmentCSPPayload(BaseCSPPayload):
|
||||||
|
tenant_id: str
|
||||||
|
user_object_id: str
|
||||||
|
billing_account_name: str
|
||||||
|
billing_profile_name: str
|
||||||
|
|
||||||
|
|
||||||
|
class BillingRoleAssignmentCSPResult(AliasModel):
|
||||||
|
billing_role_assignment_id: str
|
||||||
|
billing_role_assignment_name: str
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
fields = {
|
||||||
|
"billing_role_assignment_id": "id",
|
||||||
|
"billing_role_assignment_name": "name",
|
||||||
|
}
|
||||||
|
|
||||||
|
class EnableTaskOrderBillingCSPPayload(BaseCSPPayload):
|
||||||
|
billing_account_name: str
|
||||||
|
billing_profile_name: str
|
||||||
|
|
||||||
|
class EnableTaskOrderBillingCSPResult(AliasModel):
|
||||||
|
task_order_billing_validation_url: str
|
||||||
|
retry_after: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
fields = {"task_order_billing_validation_url": "Location", "retry_after": "Retry-After"}
|
||||||
|
|
||||||
|
class VerifyTaskOrderBillingCSPPayload(BaseCSPPayload):
|
||||||
|
task_order_billing_validation_url: str
|
||||||
|
|
||||||
|
class BillingProfileEnabledPlanDetails(AliasModel):
|
||||||
|
enabled_azure_plans: List[Dict]
|
||||||
|
|
||||||
|
|
||||||
|
class BillingProfileEnabledCSPResult(AliasModel):
|
||||||
|
billing_profile_id: str
|
||||||
|
billing_profile_name: str
|
||||||
|
billing_profile_enabled_plan_details: BillingProfileEnabledPlanDetails
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
fields = {
|
||||||
|
"billing_profile_id": "id",
|
||||||
|
"billing_profile_name": "name",
|
||||||
|
"billing_profile_enabled_plan_details": "properties",
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReportCLINCSPPayload(BaseCSPPayload):
|
||||||
|
amount: float
|
||||||
|
start_date: str
|
||||||
|
end_date: str
|
||||||
|
clin_type: str
|
||||||
|
task_order_id: str
|
||||||
|
billing_account_name: str
|
||||||
|
billing_profile_name: str
|
||||||
|
|
||||||
|
class ReportCLINCSPResult(AliasModel):
|
||||||
|
reported_clin_name: str
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
fields = {
|
||||||
|
"reported_clin_name": "name",
|
||||||
|
}
|
||||||
|
|
||||||
class CloudProviderInterface:
|
class CloudProviderInterface:
|
||||||
def root_creds(self) -> Dict:
|
def root_creds(self) -> Dict:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -705,7 +769,6 @@ class AzureCloudProvider(CloudProviderInterface):
|
|||||||
create_tenant_body = payload.dict(by_alias=True)
|
create_tenant_body = payload.dict(by_alias=True)
|
||||||
|
|
||||||
create_tenant_headers = {
|
create_tenant_headers = {
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Authorization": f"Bearer {sp_token}",
|
"Authorization": f"Bearer {sp_token}",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +793,6 @@ class AzureCloudProvider(CloudProviderInterface):
|
|||||||
create_billing_account_body = payload.dict(by_alias=True)
|
create_billing_account_body = payload.dict(by_alias=True)
|
||||||
|
|
||||||
create_billing_account_headers = {
|
create_billing_account_headers = {
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Authorization": f"Bearer {sp_token}",
|
"Authorization": f"Bearer {sp_token}",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +807,11 @@ class AzureCloudProvider(CloudProviderInterface):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if result.status_code == 202:
|
if result.status_code == 202:
|
||||||
|
# 202 has location/retry after headers
|
||||||
return self._ok(BillingProfileCreateCSPResult(**result.headers))
|
return self._ok(BillingProfileCreateCSPResult(**result.headers))
|
||||||
|
elif result.status_code == 200:
|
||||||
|
# NB: Swagger docs imply call can sometimes resolve immediately
|
||||||
|
return self._ok(BillingProfileCSPResult(**result.json()))
|
||||||
else:
|
else:
|
||||||
return self._error(result.json())
|
return self._error(result.json())
|
||||||
|
|
||||||
@ -760,56 +826,116 @@ class AzureCloudProvider(CloudProviderInterface):
|
|||||||
"Authorization": f"Bearer {sp_token}",
|
"Authorization": f"Bearer {sp_token}",
|
||||||
}
|
}
|
||||||
|
|
||||||
result = self.sdk.requests.get(payload.location, headers=auth_header)
|
result = self.sdk.requests.get(payload.billing_profile_validate_url, headers=auth_header)
|
||||||
|
|
||||||
if result.status_code == 200:
|
if result.status_code == 202:
|
||||||
|
# 202 has location/retry after headers
|
||||||
|
return self._ok(BillingProfileCreateCSPResult(**result.headers))
|
||||||
|
elif result.status_code == 200:
|
||||||
return self._ok(BillingProfileCSPResult(**result.json()))
|
return self._ok(BillingProfileCSPResult(**result.json()))
|
||||||
else:
|
else:
|
||||||
return self._error(result.json())
|
return self._error(result.json())
|
||||||
|
|
||||||
def create_billing_owner(self, creds, tenant_admin_details):
|
def grant_billing_profile_tenant_access(self, payload: BillingRoleAssignmentCSPPayload):
|
||||||
# authenticate as tenant_admin
|
sp_token = self._get_sp_token(payload.creds)
|
||||||
# create billing owner identity
|
request_body = {
|
||||||
|
"properties": {
|
||||||
# TODO: Lookup response format
|
"principalTenantId": payload.tenant_id, # from tenant creation
|
||||||
# Managed service identity?
|
"principalId": payload.user_object_id, # from tenant creationn
|
||||||
response = {"id": "string"}
|
"roleDefinitionId": f"/providers/Microsoft.Billing/billingAccounts/{payload.billing_account_name}/billingProfiles/{payload.billing_profile_name}/billingRoleDefinitions/40000000-aaaa-bbbb-cccc-100000000000",
|
||||||
return self._ok({"billing_owner_id": response["id"]})
|
|
||||||
|
|
||||||
def assign_billing_owner(self, creds, billing_owner_id, tenant_id):
|
|
||||||
# TODO: Do we source role definition ID from config, api or self-defined?
|
|
||||||
# TODO: If from api,
|
|
||||||
"""
|
|
||||||
{
|
|
||||||
"principalId": "string",
|
|
||||||
"principalTenantId": "string",
|
|
||||||
"billingRoleDefinitionId": "string"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.ok()
|
|
||||||
|
|
||||||
def report_clin(self, creds, clin_id, clin_amount, clin_start, clin_end, clin_to):
|
|
||||||
# should consumer be responsible for reporting each clin or
|
|
||||||
# should this take a list and manage the sequential reporting?
|
|
||||||
""" Payload
|
|
||||||
{
|
|
||||||
"enabledAzurePlans": [
|
|
||||||
{
|
|
||||||
"skuId": "string"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"clinBudget": {
|
|
||||||
"amount": 0,
|
|
||||||
"startDate": "2019-12-18T16:47:40.909Z",
|
|
||||||
"endDate": "2019-12-18T16:47:40.909Z",
|
|
||||||
"externalReferenceId": "string"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
|
||||||
|
|
||||||
# we don't need any of the returned info for this
|
headers = {
|
||||||
return self._ok()
|
"Authorization": f"Bearer {sp_token}",
|
||||||
|
}
|
||||||
|
|
||||||
|
url = f"https://management.azure.com/providers/Microsoft.Billing/billingAccounts/{payload.billing_account_name}/billingProfiles/{payload.billing_profile_name}/createBillingRoleAssignment?api-version=2019-10-01-preview"
|
||||||
|
|
||||||
|
result = self.sdk.requests.post(url, headers=headers, json=request_body)
|
||||||
|
if result.status_code == 201:
|
||||||
|
return self._ok(BillingRoleAssignmentCSPResult(**result.json()))
|
||||||
|
else:
|
||||||
|
return self._error(result.json())
|
||||||
|
|
||||||
|
def enable_task_order_billing(self, payload: EnableTaskOrderBillingCSPPayload):
|
||||||
|
sp_token = self._get_sp_token(payload.creds)
|
||||||
|
request_body = [
|
||||||
|
{
|
||||||
|
"op": "replace",
|
||||||
|
"path": "/enabledAzurePlans",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"skuId": "0001"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
request_headers = {
|
||||||
|
"Authorization": f"Bearer {sp_token}",
|
||||||
|
}
|
||||||
|
|
||||||
|
url = f"https://management.azure.com/providers/Microsoft.Billing/billingAccounts/{payload.billing_account_name}/billingProfiles/{payload.billing_profile_name}?api-version=2019-10-01-preview"
|
||||||
|
|
||||||
|
result = self.sdk.requests.patch(url, headers=request_headers, json=request_body)
|
||||||
|
|
||||||
|
if result.status_code == 202:
|
||||||
|
# 202 has location/retry after headers
|
||||||
|
return self._ok(BillingProfileCreateCSPResult(**result.headers))
|
||||||
|
elif result.status_code == 200:
|
||||||
|
return self._ok(BillingProfileEnabledCSPResult(**result.json()))
|
||||||
|
else:
|
||||||
|
return self._error(result.json())
|
||||||
|
|
||||||
|
def validate_task_order_billing_enabled(self, payload: VerifyTaskOrderBillingCSPPayload):
|
||||||
|
sp_token = self._get_sp_token(payload.creds)
|
||||||
|
if sp_token is None:
|
||||||
|
raise AuthenticationException(
|
||||||
|
"Could not resolve token for task order billing validation"
|
||||||
|
)
|
||||||
|
|
||||||
|
auth_header = {
|
||||||
|
"Authorization": f"Bearer {sp_token}",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.sdk.requests.get(payload.task_order_billing_validation_url, headers=auth_header)
|
||||||
|
|
||||||
|
if result.status_code == 202:
|
||||||
|
# 202 has location/retry after headers
|
||||||
|
return self._ok(EnableTaskOrderBillingCSPResult(**result.headers))
|
||||||
|
elif result.status_code == 200:
|
||||||
|
return self._ok(BillingProfileEnabledCSPResult(**result.json()))
|
||||||
|
else:
|
||||||
|
return self._error(result.json())
|
||||||
|
|
||||||
|
def report_clin(self, payload: ReportCLINCSPPayload):
|
||||||
|
sp_token = self._get_sp_token(payload.creds)
|
||||||
|
if sp_token is None:
|
||||||
|
raise AuthenticationException(
|
||||||
|
"Could not resolve token for task order billing validation"
|
||||||
|
)
|
||||||
|
|
||||||
|
request_body = {
|
||||||
|
"properties": {
|
||||||
|
"amount": payload.amount,
|
||||||
|
"startDate": payload.start_date,
|
||||||
|
"endDate": payload.end_date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url = f"https://management.azure.com/providers/Microsoft.Billing/billingAccounts/{payload.billing_account_name}/billingProfiles/{payload.billing_profile_name}/instructions/{payload.task_order_id}:CLIN00{payload.clin_type}?api-version=2019-10-01-preview"
|
||||||
|
|
||||||
|
auth_header = {
|
||||||
|
"Authorization": f"Bearer {sp_token}",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.sdk.requests.put(url, headers=auth_header, json=request_body)
|
||||||
|
|
||||||
|
if result.status_code == 200:
|
||||||
|
return self._ok(ReportCLINCSPResult(**result.json()))
|
||||||
|
else:
|
||||||
|
return self._error(result.json())
|
||||||
|
|
||||||
def create_remote_admin(self, creds, tenant_details):
|
def create_remote_admin(self, creds, tenant_details):
|
||||||
# create app/service principal within tenant, with name constructed from tenant details
|
# create app/service principal within tenant, with name constructed from tenant details
|
||||||
|
@ -12,6 +12,13 @@ from atst.domain.csp.cloud import (
|
|||||||
BillingProfileCreateCSPResult,
|
BillingProfileCreateCSPResult,
|
||||||
BillingProfileVerifyCSPPayload,
|
BillingProfileVerifyCSPPayload,
|
||||||
BillingProfileCSPResult,
|
BillingProfileCSPResult,
|
||||||
|
BillingRoleAssignmentCSPPayload,
|
||||||
|
BillingRoleAssignmentCSPResult,
|
||||||
|
EnableTaskOrderBillingCSPPayload,
|
||||||
|
VerifyTaskOrderBillingCSPPayload,
|
||||||
|
BillingProfileEnabledCSPResult,
|
||||||
|
ReportCLINCSPPayload,
|
||||||
|
ReportCLINCSPResult,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.mock_azure import mock_azure, AUTH_CREDENTIALS
|
from tests.mock_azure import mock_azure, AUTH_CREDENTIALS
|
||||||
@ -25,7 +32,7 @@ from tests.factories import EnvironmentFactory, ApplicationFactory
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
@pytest.mark.skip("Skipping legacy azure integration tests")
|
||||||
def test_create_subscription_succeeds(mock_azure: AzureCloudProvider):
|
def test_create_subscription_succeeds(mock_azure: AzureCloudProvider):
|
||||||
environment = EnvironmentFactory.create()
|
environment = EnvironmentFactory.create()
|
||||||
|
|
||||||
@ -60,14 +67,13 @@ def test_create_subscription_succeeds(mock_azure: AzureCloudProvider):
|
|||||||
assert result == subscription_id
|
assert result == subscription_id
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
|
||||||
def mock_management_group_create(mock_azure, spec_dict):
|
def mock_management_group_create(mock_azure, spec_dict):
|
||||||
mock_azure.sdk.managementgroups.ManagementGroupsAPI.return_value.management_groups.create_or_update.return_value.result.return_value = Mock(
|
mock_azure.sdk.managementgroups.ManagementGroupsAPI.return_value.management_groups.create_or_update.return_value.result.return_value = Mock(
|
||||||
**spec_dict
|
**spec_dict
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
@pytest.mark.skip("Skipping legacy azure integration tests")
|
||||||
def test_create_environment_succeeds(mock_azure: AzureCloudProvider):
|
def test_create_environment_succeeds(mock_azure: AzureCloudProvider):
|
||||||
environment = EnvironmentFactory.create()
|
environment = EnvironmentFactory.create()
|
||||||
|
|
||||||
@ -80,7 +86,7 @@ def test_create_environment_succeeds(mock_azure: AzureCloudProvider):
|
|||||||
assert result.id == "Test Id"
|
assert result.id == "Test Id"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
@pytest.mark.skip("Skipping legacy azure integration tests")
|
||||||
def test_create_application_succeeds(mock_azure: AzureCloudProvider):
|
def test_create_application_succeeds(mock_azure: AzureCloudProvider):
|
||||||
application = ApplicationFactory.create()
|
application = ApplicationFactory.create()
|
||||||
|
|
||||||
@ -91,7 +97,7 @@ def test_create_application_succeeds(mock_azure: AzureCloudProvider):
|
|||||||
assert result.id == "Test Id"
|
assert result.id == "Test Id"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
@pytest.mark.skip("Skipping legacy azure integration tests")
|
||||||
def test_create_atat_admin_user_succeeds(mock_azure: AzureCloudProvider):
|
def test_create_atat_admin_user_succeeds(mock_azure: AzureCloudProvider):
|
||||||
environment_id = str(uuid4())
|
environment_id = str(uuid4())
|
||||||
|
|
||||||
@ -106,7 +112,7 @@ def test_create_atat_admin_user_succeeds(mock_azure: AzureCloudProvider):
|
|||||||
assert result.get("csp_user_id") == csp_user_id
|
assert result.get("csp_user_id") == csp_user_id
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip()
|
@pytest.mark.skip("Skipping legacy azure integration tests")
|
||||||
def test_create_policy_definition_succeeds(mock_azure: AzureCloudProvider):
|
def test_create_policy_definition_succeeds(mock_azure: AzureCloudProvider):
|
||||||
subscription_id = str(uuid4())
|
subscription_id = str(uuid4())
|
||||||
management_group_id = str(uuid4())
|
management_group_id = str(uuid4())
|
||||||
@ -148,33 +154,32 @@ def test_create_tenant(mock_azure: AzureCloudProvider):
|
|||||||
payload = TenantCSPPayload(
|
payload = TenantCSPPayload(
|
||||||
**dict(
|
**dict(
|
||||||
creds={"username": "mock-cloud", "pass": "shh"},
|
creds={"username": "mock-cloud", "pass": "shh"},
|
||||||
user_id="123",
|
user_id="admin",
|
||||||
password="123",
|
password="JediJan13$coot",
|
||||||
domain_name="123",
|
domain_name="jediccpospawnedtenant2",
|
||||||
first_name="john",
|
first_name="Tedry",
|
||||||
last_name="doe",
|
last_name="Tenet",
|
||||||
country_code="US",
|
country_code="US",
|
||||||
password_recovery_email_address="password@email.com",
|
password_recovery_email_address="thomas@promptworks.com",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
result = mock_azure.create_tenant(payload)
|
result = mock_azure.create_tenant(payload)
|
||||||
print(result)
|
|
||||||
body: TenantCSPResult = result.get("body")
|
body: TenantCSPResult = result.get("body")
|
||||||
assert body.tenant_id == "60ff9d34-82bf-4f21-b565-308ef0533435"
|
assert body.tenant_id == "60ff9d34-82bf-4f21-b565-308ef0533435"
|
||||||
|
|
||||||
|
|
||||||
def test_create_billing_profile(mock_azure: AzureCloudProvider):
|
def test_create_billing_profile(mock_azure: AzureCloudProvider):
|
||||||
# mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
||||||
# "accessToken": "TOKEN"
|
"accessToken": "TOKEN"
|
||||||
# }
|
}
|
||||||
|
|
||||||
# mock_result = Mock()
|
mock_result = Mock()
|
||||||
# mock_result.headers = {
|
mock_result.headers = {
|
||||||
# "Location": "http://retry-url",
|
"Location": "http://retry-url",
|
||||||
# "Retry-After": "10",
|
"Retry-After": "10",
|
||||||
# }
|
}
|
||||||
# mock_result.status_code = 202
|
mock_result.status_code = 202
|
||||||
# mock_azure.sdk.requests.post.return_value = mock_result
|
mock_azure.sdk.requests.post.return_value = mock_result
|
||||||
payload = BillingProfileCSPPayload(
|
payload = BillingProfileCSPPayload(
|
||||||
**dict(
|
**dict(
|
||||||
address=dict(
|
address=dict(
|
||||||
@ -191,7 +196,6 @@ def test_create_billing_profile(mock_azure: AzureCloudProvider):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
result = mock_azure.create_billing_profile(payload)
|
result = mock_azure.create_billing_profile(payload)
|
||||||
print(result)
|
|
||||||
body: BillingProfileCreateCSPResult = result.get("body")
|
body: BillingProfileCreateCSPResult = result.get("body")
|
||||||
assert body.retry_after == 10
|
assert body.retry_after == 10
|
||||||
|
|
||||||
@ -204,8 +208,8 @@ def test_validate_billing_profile_creation(mock_azure: AzureCloudProvider):
|
|||||||
mock_result = Mock()
|
mock_result = Mock()
|
||||||
mock_result.status_code = 200
|
mock_result.status_code = 200
|
||||||
mock_result.json.return_value = {
|
mock_result.json.return_value = {
|
||||||
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/XC36-GRNZ-BG7-TGB",
|
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB",
|
||||||
"name": "XC36-GRNZ-BG7-TGB",
|
"name": "KQWI-W2SU-BG7-TGB",
|
||||||
"properties": {
|
"properties": {
|
||||||
"address": {
|
"address": {
|
||||||
"addressLine1": "123 S Broad Street, Suite 2400",
|
"addressLine1": "123 S Broad Street, Suite 2400",
|
||||||
@ -223,7 +227,7 @@ def test_validate_billing_profile_creation(mock_azure: AzureCloudProvider):
|
|||||||
"invoiceEmailOptIn": False,
|
"invoiceEmailOptIn": False,
|
||||||
"invoiceSections": [
|
"invoiceSections": [
|
||||||
{
|
{
|
||||||
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/XC36-GRNZ-BG7-TGB/invoiceSections/6HMZ-2HLO-PJA-TGB",
|
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB/invoiceSections/6HMZ-2HLO-PJA-TGB",
|
||||||
"name": "6HMZ-2HLO-PJA-TGB",
|
"name": "6HMZ-2HLO-PJA-TGB",
|
||||||
"properties": {"displayName": "First Portfolio Billing Profile"},
|
"properties": {"displayName": "First Portfolio Billing Profile"},
|
||||||
"type": "Microsoft.Billing/billingAccounts/billingProfiles/invoiceSections",
|
"type": "Microsoft.Billing/billingAccounts/billingProfiles/invoiceSections",
|
||||||
@ -241,15 +245,194 @@ def test_validate_billing_profile_creation(mock_azure: AzureCloudProvider):
|
|||||||
"password": "password",
|
"password": "password",
|
||||||
"tenant_id": "tenant_id",
|
"tenant_id": "tenant_id",
|
||||||
},
|
},
|
||||||
location="https://management.azure.com/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/operationResults/createBillingProfile_478d5706-71f9-4a8b-8d4e-2cbaca27a668?api-version=2019-10-01-preview",
|
billing_profile_validate_url="https://management.azure.com/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/operationResults/createBillingProfile_478d5706-71f9-4a8b-8d4e-2cbaca27a668?api-version=2019-10-01-preview",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
result = mock_azure.validate_billing_profile_created(payload)
|
result = mock_azure.validate_billing_profile_created(payload)
|
||||||
body: BillingProfileCreateCSPResult = result.get("body")
|
body: BillingProfileCreateCSPResult = result.get("body")
|
||||||
assert body.billing_profile_name == "XC36-GRNZ-BG7-TGB"
|
assert body.billing_profile_name == "KQWI-W2SU-BG7-TGB"
|
||||||
assert (
|
assert (
|
||||||
body.billing_profile_properties.display_name
|
body.billing_profile_properties.display_name
|
||||||
== "First Portfolio Billing Profile"
|
== "First Portfolio Billing Profile"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_grant_billing_profile_tenant_access(mock_azure: AzureCloudProvider):
|
||||||
|
mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
||||||
|
"accessToken": "TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_result = Mock()
|
||||||
|
mock_result.status_code = 201
|
||||||
|
mock_result.json.return_value = {
|
||||||
|
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB/billingRoleAssignments/40000000-aaaa-bbbb-cccc-100000000000_0a5f4926-e3ee-4f47-a6e3-8b0a30a40e3d",
|
||||||
|
"name": "40000000-aaaa-bbbb-cccc-100000000000_0a5f4926-e3ee-4f47-a6e3-8b0a30a40e3d",
|
||||||
|
"properties": {
|
||||||
|
"createdOn": "2020-01-14T14:39:26.3342192+00:00",
|
||||||
|
"createdByPrincipalId": "82e2b376-3297-4096-8743-ed65b3be0b03",
|
||||||
|
"principalId": "0a5f4926-e3ee-4f47-a6e3-8b0a30a40e3d",
|
||||||
|
"principalTenantId": "60ff9d34-82bf-4f21-b565-308ef0533435",
|
||||||
|
"roleDefinitionId": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB/billingRoleDefinitions/40000000-aaaa-bbbb-cccc-100000000000",
|
||||||
|
"scope": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB",
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Billing/billingRoleAssignments",
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_azure.sdk.requests.post.return_value = mock_result
|
||||||
|
|
||||||
|
payload = BillingRoleAssignmentCSPPayload(
|
||||||
|
**dict(
|
||||||
|
creds={
|
||||||
|
"username": "username",
|
||||||
|
"password": "password",
|
||||||
|
"tenant_id": "tenant_id",
|
||||||
|
},
|
||||||
|
tenant_id="60ff9d34-82bf-4f21-b565-308ef0533435",
|
||||||
|
user_object_id="0a5f4926-e3ee-4f47-a6e3-8b0a30a40e3d",
|
||||||
|
billing_account_name="7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31",
|
||||||
|
billing_profile_name="KQWI-W2SU-BG7-TGB",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
result = mock_azure.grant_billing_profile_tenant_access(payload)
|
||||||
|
body: BillingRoleAssignmentCSPResult = result.get("body")
|
||||||
|
assert (
|
||||||
|
body.billing_role_assignment_name
|
||||||
|
== "40000000-aaaa-bbbb-cccc-100000000000_0a5f4926-e3ee-4f47-a6e3-8b0a30a40e3d"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_enable_task_order_billing(mock_azure: AzureCloudProvider):
|
||||||
|
mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
||||||
|
"accessToken": "TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_result = Mock()
|
||||||
|
mock_result.status_code = 202
|
||||||
|
mock_result.headers = {
|
||||||
|
"Location": "https://management.azure.com/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/operationResults/patchBillingProfile_KQWI-W2SU-BG7-TGB:02715576-4118-466c-bca7-b1cd3169ff46?api-version=2019-10-01-preview",
|
||||||
|
"Retry-After": "10",
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_azure.sdk.requests.patch.return_value = mock_result
|
||||||
|
|
||||||
|
payload = EnableTaskOrderBillingCSPPayload(
|
||||||
|
**dict(
|
||||||
|
creds={
|
||||||
|
"username": "username",
|
||||||
|
"password": "password",
|
||||||
|
"tenant_id": "tenant_id",
|
||||||
|
},
|
||||||
|
billing_account_name="7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31",
|
||||||
|
billing_profile_name="KQWI-W2SU-BG7-TGB",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
result = mock_azure.enable_task_order_billing(payload)
|
||||||
|
body: BillingProfileCreateCSPResult = result.get("body")
|
||||||
|
assert (
|
||||||
|
body.billing_profile_validate_url
|
||||||
|
== "https://management.azure.com/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/operationResults/patchBillingProfile_KQWI-W2SU-BG7-TGB:02715576-4118-466c-bca7-b1cd3169ff46?api-version=2019-10-01-preview"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_task_order_billing_enabled(mock_azure):
|
||||||
|
mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
||||||
|
"accessToken": "TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_result = Mock()
|
||||||
|
mock_result.status_code = 200
|
||||||
|
mock_result.json.return_value = {
|
||||||
|
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB",
|
||||||
|
"name": "KQWI-W2SU-BG7-TGB",
|
||||||
|
"properties": {
|
||||||
|
"address": {
|
||||||
|
"addressLine1": "123 S Broad Street, Suite 2400",
|
||||||
|
"city": "Philadelphia",
|
||||||
|
"companyName": "Promptworks",
|
||||||
|
"country": "US",
|
||||||
|
"postalCode": "19109",
|
||||||
|
"region": "PA",
|
||||||
|
},
|
||||||
|
"currency": "USD",
|
||||||
|
"displayName": "Test Billing Profile",
|
||||||
|
"enabledAzurePlans": [
|
||||||
|
{
|
||||||
|
"productId": "DZH318Z0BPS6",
|
||||||
|
"skuId": "0001",
|
||||||
|
"skuDescription": "Microsoft Azure Plan",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hasReadAccess": True,
|
||||||
|
"invoiceDay": 5,
|
||||||
|
"invoiceEmailOptIn": False,
|
||||||
|
"invoiceSections": [
|
||||||
|
{
|
||||||
|
"id": "/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/billingProfiles/KQWI-W2SU-BG7-TGB/invoiceSections/CHCO-BAAR-PJA-TGB",
|
||||||
|
"name": "CHCO-BAAR-PJA-TGB",
|
||||||
|
"properties": {"displayName": "Test Billing Profile"},
|
||||||
|
"type": "Microsoft.Billing/billingAccounts/billingProfiles/invoiceSections",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Billing/billingAccounts/billingProfiles",
|
||||||
|
}
|
||||||
|
mock_azure.sdk.requests.get.return_value = mock_result
|
||||||
|
|
||||||
|
payload = VerifyTaskOrderBillingCSPPayload(
|
||||||
|
**dict(
|
||||||
|
creds={
|
||||||
|
"username": "username",
|
||||||
|
"password": "password",
|
||||||
|
"tenant_id": "tenant_id",
|
||||||
|
},
|
||||||
|
task_order_billing_validation_url="https://management.azure.com/providers/Microsoft.Billing/billingAccounts/7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31/operationResults/createBillingProfile_478d5706-71f9-4a8b-8d4e-2cbaca27a668?api-version=2019-10-01-preview",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
result = mock_azure.validate_task_order_billing_enabled(payload)
|
||||||
|
body: BillingProfileEnabledCSPResult = result.get("body")
|
||||||
|
assert body.billing_profile_name == "KQWI-W2SU-BG7-TGB"
|
||||||
|
assert (
|
||||||
|
body.billing_profile_enabled_plan_details.enabled_azure_plans[0].get("skuId")
|
||||||
|
== "0001"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_report_clin(mock_azure: AzureCloudProvider):
|
||||||
|
mock_azure.sdk.adal.AuthenticationContext.return_value.context.acquire_token_with_client_credentials.return_value = {
|
||||||
|
"accessToken": "TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_result = Mock()
|
||||||
|
mock_result.status_code = 200
|
||||||
|
mock_result.json.return_value = {
|
||||||
|
"name": "TO1:CLIN001",
|
||||||
|
"properties": {
|
||||||
|
"amount": 1000.0,
|
||||||
|
"endDate": "2020-03-01T00:00:00+00:00",
|
||||||
|
"startDate": "2020-01-01T00:00:00+00:00",
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Billing/billingAccounts/billingProfiles/billingInstructions",
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_azure.sdk.requests.put.return_value = mock_result
|
||||||
|
|
||||||
|
payload = ReportCLINCSPPayload(
|
||||||
|
**dict(
|
||||||
|
creds={},
|
||||||
|
amount=1000.00,
|
||||||
|
start_date="2020/1/1",
|
||||||
|
end_date="2020/3/1",
|
||||||
|
clin_type="1",
|
||||||
|
task_order_id="TO1",
|
||||||
|
billing_account_name="7c89b735-b22b-55c0-ab5a-c624843e8bf6:de4416ce-acc6-44b1-8122-c87c4e903c91_2019-05-31",
|
||||||
|
billing_profile_name="KQWI-W2SU-BG7-TGB",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
result = mock_azure.report_clin(payload)
|
||||||
|
body: ReportCLINCSPResult = result.get("body")
|
||||||
|
assert body.reported_clin_name == "TO1:CLIN001"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user