Skip to content

Commit bb98827

Browse files
Merge pull request #6 from SkyflowFoundry/IE-521
IE-521: updated pipeline workflow, added code comments
2 parents 4b63ea6 + 95260d9 commit bb98827

9 files changed

Lines changed: 47 additions & 35 deletions

.github/workflows/migrate_pipelines.yml

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,21 @@ on:
1616
description: "Source datastore JSON. Provide either an ftpServer or s3Bucket object."
1717
required: true
1818
default: |
19-
{
20-
"ftpServer": {
21-
"transferProtocol": "FTPS",
22-
"plainText": {
23-
"hostname": "",
24-
"port": "",
25-
"username": "",
26-
"password": "",
27-
},
28-
"skyflowHosted": false
29-
}
30-
}
19+
{"ftpServer":{"transferProtocol": "FTPS","plainText": {"hostname": "","port": "","username": "","password": ""},"skyflowHosted": false}}
3120
target_datastore_config:
3221
description: "Destination datastore JSON. Provide either an ftpServer or s3Bucket object."
3322
required: true
3423
default: |
35-
{
36-
"s3Bucket": {
37-
"name": "",
38-
"region": "",
39-
"assumedRoleARN": ""
40-
}
41-
}
42-
source_vault_id:
43-
description: "Source Vault ID."
44-
required: false
24+
{"s3Bucket": {"name": "","region": "","assumedRoleARN": ""}}
4525
pipeline_id:
4626
description: "PipelineID to be migrated."
47-
required: false
27+
required: true
4828
default: ""
4929
target_vault_id:
5030
description: "Target Vault ID"
5131
required: true
5232
source_account_access_token:
53-
description: "Access token of the Source Account. (Not required, if config file is selected)"
33+
description: "Access token of the Source Account"
5434
required: false
5535
target_account_access_token:
5636
description: "Access token of the Target Account"
@@ -108,7 +88,6 @@ jobs:
10888
PIPELINE_ID: ${{ github.event.inputs.pipeline_id }}
10989
SOURCE_DATASTORE_CONFIG: ${{ github.event.inputs.source_datastore_config }}
11090
TARGET_DATASTORE_CONFIG: ${{ github.event.inputs.target_datastore_config }}
111-
SOURCE_VAULT_ID: ${{ github.event.inputs.source_vault_id }}
11291
TARGET_VAULT_ID: ${{ github.event.inputs.target_vault_id }}
11392
SOURCE_ACCOUNT_AUTH: ${{ github.event.inputs.source_account_access_token }}
11493
TARGET_ACCOUNT_AUTH: ${{ github.event.inputs.target_account_access_token }}

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,12 @@ Note: Please note that if all values are provided `config_file` will take the pr
117117

118118
### Pipelines Migration
119119

120-
Migrates a pipeline definition from the source vault to the target vault.
120+
Migrates a pipeline from the source vault to the target vault.
121121

122122
##### Parameters:
123123
- **`source_and_target_env`**: Source and Target Env's.
124-
- **`pipeline_id`**: Pipeline ID to migrate. Get the pipeline ID from Studio.
124+
- **`pipeline_id`**: Pipeline ID to migrate.
125+
- **`target_vault_id`**: Target Vault ID.
125126
- **`source_datastore_config`**: JSON object that replaces the source datastore configuration. Provide either an `ftpServer` or `s3Bucket` object with the required credentials.
126127
- **`target_datastore_config`**: JSON object that replaces the destination datastore configuration. Provide either an `ftpServer` or `s3Bucket` object with the required credentials.
127128
- **`source_account_access_token`**: Access token of the source account.

migrate_connections.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030

3131
def list_connections(vault_id):
32+
"""Lists inbound + outbound connections for a vault."""
3233
connections = []
3334
response = requests.get(
3435
f"{SOURCE_ENV_URL}/v1/gateway/outboundRoutes?vaultID={vault_id}",
@@ -45,6 +46,7 @@ def list_connections(vault_id):
4546
return connections
4647

4748
def get_connection(connection_id):
49+
"""Fetches a single connection"""
4850
# /inboundRoutes can also fetch outbound connection details
4951
response = requests.get(
5052
f"{SOURCE_ENV_URL}/v1/gateway/inboundRoutes/{connection_id}",
@@ -54,6 +56,7 @@ def get_connection(connection_id):
5456
return response.json()
5557

5658
def create_connection(connection):
59+
"""Creates connection"""
5760
route = "outboundRoutes" if connection["mode"] == "EGRESS" else "inboundRoutes"
5861
response = requests.post(
5962
f"{TARGET_ENV_URL}/v1/gateway/{route}",
@@ -64,8 +67,10 @@ def create_connection(connection):
6467

6568

6669
def transform_connection_payload(source_resource):
70+
"""Transforms source connection payload to target payload."""
6771
transformed_resource = source_resource
6872
transformed_resource["vaultID"] = TARGET_VAULT_ID
73+
# drop basic audit and invocation URL
6974
if "BasicAudit" in transformed_resource.keys():
7075
del transformed_resource["BasicAudit"]
7176
for route in transformed_resource["routes"]:
@@ -74,6 +79,7 @@ def transform_connection_payload(source_resource):
7479

7580

7681
def main(connection_ids=None):
82+
"""Migrates connections"""
7783
try:
7884
print("-- Initiating Connections migration --")
7985
connections = []

migrate_pipelines.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import requests
55
from typing import Any, Dict, List, Optional
66

7+
from dotenv import load_dotenv
8+
load_dotenv()
79

810
PIPELINE_ID = os.getenv("PIPELINE_ID")
9-
SOURCE_VAULT_ID = os.getenv("SOURCE_VAULT_ID")
1011
TARGET_VAULT_ID = os.getenv("TARGET_VAULT_ID")
1112
SOURCE_ACCOUNT_ID = os.getenv("SOURCE_ACCOUNT_ID")
1213
TARGET_ACCOUNT_ID = os.getenv("TARGET_ACCOUNT_ID")
@@ -35,7 +36,7 @@
3536
}
3637

3738
def list_pipelines(vault_id: str) -> List[Dict[str, Any]]:
38-
"""Return all pipelines in the supplied vault."""
39+
"""Lists Pipelines"""
3940
pipelines = []
4041
response = requests.get(
4142
f"{SOURCE_ENV_URL}/v1/pipelines?vaultID={vault_id}",
@@ -46,7 +47,7 @@ def list_pipelines(vault_id: str) -> List[Dict[str, Any]]:
4647
return pipelines
4748

4849
def get_pipeline(pipeline_id: str) -> Dict[str, Any]:
49-
"""Fetch a single pipeline definition from the source environment."""
50+
"""Fetches a single pipeline"""
5051
response = requests.get(
5152
f"{SOURCE_ENV_URL}/v1/pipelines/{pipeline_id}",
5253
headers=SOURCE_ACCOUNT_HEADERS,
@@ -55,7 +56,7 @@ def get_pipeline(pipeline_id: str) -> Dict[str, Any]:
5556
return response.json()[PIPELINE]
5657

5758
def create_pipeline(pipeline: Dict[str, Any]) -> requests.Response:
58-
"""Create a pipeline in the target environment."""
59+
"""Creates a pipeline"""
5960
response = requests.post(
6061
f"{TARGET_ENV_URL}/v1/pipelines",
6162
json=pipeline,
@@ -170,7 +171,7 @@ def transform_pipeline_payload(
170171
source_datastore_input: Optional[Dict[str, Any]] = None,
171172
target_datastore_input: Optional[Dict[str, Any]] = None,
172173
) -> Dict[str, Any]:
173-
"""Prepare the payload for the target pipeline."""
174+
"""Transforms source pipeline payload to target payload."""
174175
transformed_resource = copy.deepcopy(source_resource)
175176
if "ID" in transformed_resource:
176177
del transformed_resource["ID"] # remove pipeline ID
@@ -187,7 +188,7 @@ def transform_pipeline_payload(
187188

188189

189190
def main(pipeline_id: str) -> None:
190-
"""pipeline migration"""
191+
"""Migrates pipeline"""
191192
try:
192193
print("-- Initiating Pipelines migration --")
193194
source_datastore_input = load_datastore_input(SOURCE_DATASTORE_CONFIG, "source")

migrate_policies.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727

2828
def get_policy(policy_id):
29+
"""Fetches a policy"""
2930
response = requests.get(
3031
f"{SOURCE_ENV_URL}/v1/policies/{policy_id}", headers=SOURCE_ACCOUNT_HEADERS
3132
)
@@ -34,6 +35,7 @@ def get_policy(policy_id):
3435

3536

3637
def create_policy(policy_data):
38+
"""Creates a policy"""
3739
response = requests.post(
3840
f"{TARGET_ENV_URL}/v1/policies", json=policy_data, headers=TARGET_ACCOUNT_HEADERS
3941
)
@@ -42,6 +44,7 @@ def create_policy(policy_data):
4244

4345

4446
def transform_policy_payload(source_resource):
47+
"""Transforms source policy payload to target payload."""
4548
transformed_resource = source_resource["policy"]
4649
transformed_resource["resource"] = {"ID": TARGET_VAULT_ID, "type": "VAULT"}
4750
policy_rules = transformed_resource["rules"]
@@ -95,6 +98,7 @@ def transform_policy_payload(source_resource):
9598

9699

97100
def main(policy_ids=None):
101+
"""Migrates policies"""
98102
try:
99103
policy_ids = policy_ids if policy_ids else ast.literal_eval(POLICY_IDS)
100104
policies_created = []

migrate_roles.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,23 @@
3232

3333

3434
def get_role(role_id):
35+
"""Fetch a single role definition from the source account."""
3536
response = requests.get(
3637
f"{SOURCE_ENV_URL}/v1/roles/{role_id}", headers=SOURCE_ACCOUNT_HEADERS
3738
)
3839
response.raise_for_status()
3940
return response.json()
4041

4142
def get_system_role(role_name):
43+
"""Return a system role present in the target vault."""
4244
response = requests.get(
4345
f"{TARGET_ENV_URL}/v1/roles?name={role_name}&resource.type=VAULT&resource.ID={TARGET_VAULT_ID}", headers=TARGET_ACCOUNT_HEADERS
4446
)
4547
response.raise_for_status()
4648
return response.json()
4749

4850
def create_role(role):
51+
"""Create a custom role in the target vault."""
4952
response = requests.post(
5053
f"{TARGET_ENV_URL}/v1/roles", json=role, headers=TARGET_ACCOUNT_HEADERS
5154
)
@@ -54,6 +57,7 @@ def create_role(role):
5457

5558

5659
def get_role_policies(role_id):
60+
"""List all policies attached to the given role."""
5761
response = requests.get(
5862
f"{SOURCE_ENV_URL}/v1/roles/{role_id}/policies", headers=SOURCE_ACCOUNT_HEADERS
5963
)
@@ -62,6 +66,7 @@ def get_role_policies(role_id):
6266

6367

6468
def get_role_by_role_name(role_name):
69+
"""Search the target vault for an existing custom role by name."""
6570
response = requests.get(
6671
f"{TARGET_ENV_URL}/v1/roles?name={role_name}&resource.type=VAULT&resource.ID={TARGET_VAULT_ID}",
6772
headers=TARGET_ACCOUNT_HEADERS,
@@ -71,6 +76,7 @@ def get_role_by_role_name(role_name):
7176

7277

7378
def assign_policy_to_role(policy_ids, role_id: list):
79+
"""Assign the provided policies to the role."""
7480
for policy_id in policy_ids:
7581
assign_request = {"ID": policy_id, "roleIDs": role_id}
7682
response = requests.post(
@@ -82,6 +88,7 @@ def assign_policy_to_role(policy_ids, role_id: list):
8288
# return response.json()
8389

8490
def list_all_roles() -> list:
91+
"""Lists custom roles"""
8592
response = requests.get(
8693
f"{SOURCE_ENV_URL}/v1/roles?type=CUSTOM&resource.ID={SOURCE_VAULT_ID}&resource.type=VAULT",
8794
headers=SOURCE_ACCOUNT_HEADERS,
@@ -91,6 +98,7 @@ def list_all_roles() -> list:
9198

9299

93100
def transform_role_payload(source_resource):
101+
"""Transforms source role payload to target payload."""
94102
transformed_resource = {}
95103
transformed_resource["roleDefinition"] = source_resource["role"]["definition"]
96104
permissions: list = source_resource["role"]["definition"]["permissions"]
@@ -104,11 +112,13 @@ def transform_role_payload(source_resource):
104112
"vaults.read:upstream",
105113
]
106114
]
115+
# remove upstream read permissions that are implicitly granted in the target account
107116
transformed_resource["roleDefinition"]["permissions"] = new_permissions
108117
transformed_resource["resource"] = {"ID": TARGET_VAULT_ID, "type": "VAULT"}
109118
return transformed_resource
110119

111120
def main(role_ids=None):
121+
"""Migrates roles and their associated policies."""
112122
try:
113123
print("-- Initializing Roles migration --")
114124
should_enable_custom_role_check = SKIP_ROLE_CREATION_IF_ROLE_EXISTS

migrate_service_accounts.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828

2929
def list_service_account_roles(service_account_id):
30+
"""Return every role assigned to the given service account."""
3031
response = requests.get(
3132
f"{SOURCE_ENV_URL}/v1/members/{service_account_id}/roles?member.type=SERVICE_ACCOUNT",
3233
headers=SOURCE_ACCOUNT_HEADERS,
@@ -36,6 +37,7 @@ def list_service_account_roles(service_account_id):
3637

3738

3839
def get_service_account(service_account_id):
40+
"""Fetch a service account definition from the source account."""
3941
response = requests.get(
4042
f"{SOURCE_ENV_URL}/v1/serviceAccounts/{service_account_id}",
4143
headers=SOURCE_ACCOUNT_HEADERS,
@@ -45,6 +47,7 @@ def get_service_account(service_account_id):
4547

4648

4749
def create_service_account(service_account):
50+
"""Create the supplied service account in the target account."""
4851
response = requests.post(
4952
f"{TARGET_ENV_URL}/v1/serviceAccounts",
5053
json=service_account,
@@ -55,6 +58,7 @@ def create_service_account(service_account):
5558

5659

5760
def assign_roles_to_service_account(role_ids, service_account_id):
61+
"""Attach the specified roles to the new service account."""
5862
for role_id in role_ids:
5963
assign_request = {
6064
"ID": role_id,
@@ -69,15 +73,17 @@ def assign_roles_to_service_account(role_ids, service_account_id):
6973

7074

7175
def transform_service_account_payload(source_resource):
76+
"""Strip source-only metadata before creating the service account."""
7277
transformed_resource = source_resource
7378
# transformed_resource["resource"] = {"ID": TARGET_VAULT_ID, "type": "VAULT"} // not require due to SA flattening change
74-
del transformed_resource["serviceAccount"]["ID"]
79+
del transformed_resource["serviceAccount"]["ID"] # IDs are regenerated per account
7580
del transformed_resource["serviceAccount"]["namespace"]
7681
del transformed_resource["serviceAccount"]["BasicAudit"]
7782
return transformed_resource
7883

7984

8085
def main(service_accounts_ids=None):
86+
"""Migrates service accounts and associated roles."""
8187
try:
8288
print("-- Initializing Service accounts migration --")
8389
service_accounts_ids = (

migrate_vault_roles_and_policies.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717

1818
def list_all_vault_custom_roles() -> list:
19+
"""Return all custom roles of the source vault."""
1920
response = requests.get(
2021
f"{SOURCE_ENV_URL}/v1/roles?type=CUSTOM&resource.ID={SOURCE_VAULT_ID}&resource.type=VAULT",
2122
headers=SOURCE_ACCOUNT_HEADERS,
@@ -25,6 +26,7 @@ def list_all_vault_custom_roles() -> list:
2526

2627

2728
def main():
29+
"""Migrates all the custom roles and policies"""
2830
try:
2931
print(f"-- Fetching roles for the vault {SOURCE_VAULT_ID} --")
3032
roles = list_all_vault_custom_roles()

migrate_vault_schema.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,20 @@
2626
"Authorization": f"Bearer {TARGET_ACCOUNT_AUTH}",
2727
"Content-Type": "application/json",
2828
}
29-
3029
def get_vault_details(vaultID: str):
30+
"""Return the vault metadata and schema"""
3131
response = requests.get(f"{SOURCE_ENV_URL}/v1/vaults/{vaultID}", headers=SOURCE_ACCOUNT_HEADERS)
3232
response.raise_for_status()
3333
return response.json()
3434

3535
def create_vault(create_vault_request_payload):
36+
"""Creates a vault"""
3637
response = requests.post(f"{TARGET_ENV_URL}/v1/vaults", json=create_vault_request_payload, headers=TARGET_ACCOUNT_HEADERS)
3738
response.raise_for_status()
3839
return response.json()
3940

4041
def transform_payload(vault_details):
42+
"""Transforms source vault payload to target payload."""
4143
create_vault_payload = {
4244
"name": VAULT_NAME if VAULT_NAME else f"UntitledVault{random.randint(0,1000)}" if VAULT_SCHEMA_CONFIG else vault_details["name"],
4345
"description": VAULT_DESCRIPTION if VAULT_DESCRIPTION else "" if VAULT_SCHEMA_CONFIG else vault_details["description"],
@@ -50,6 +52,7 @@ def transform_payload(vault_details):
5052
return create_vault_payload
5153

5254
def main():
55+
"""Migrates vault schema"""
5356
try:
5457
print("-- Initializing Vault migration --")
5558
if VAULT_SCHEMA_CONFIG is not None and VAULT_SCHEMA_CONFIG == "config_file":

0 commit comments

Comments
 (0)