From 95684ec870289686ed0ec25ce77a778bc9ac6dca Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Thu, 18 Sep 2025 14:18:57 +0530 Subject: [PATCH 01/33] CD3 Automation Toolkit Release v2025.2.0 --- Dockerfile | 107 ----- OCIWorkVMStack/scripts/installToolkit.sh | 7 +- .../CostManagement/__init__.py | 1 - .../DeveloperServices/__init__.py | 5 - cd3_automation_toolkit/Governance/__init__.py | 6 - cd3_automation_toolkit/Identity/__init__.py | 10 - .../notifications-subscriptions-template | 57 --- .../ManagementServices/__init__.py | 4 - cd3_automation_toolkit/Network/__init__.py | 7 - cd3_automation_toolkit/Release-Notes | 12 + cd3_automation_toolkit/Security/__init__.py | 6 - cd3_automation_toolkit/Storage/__init__.py | 6 - cd3_automation_toolkit/__init__.py | 5 - cd3_automation_toolkit/azurecloud/__init__.py | 1 + .../azurecloud/python/__init__.py | 4 + .../azurecloud/python/azrCommonTools.py | 84 ++++ .../azurecloud/python/database/__init__.py | 7 + .../database/create_terraform_adb_azure.py | 134 ++++++ .../create_terraform_exa_infra_azure.py | 118 +++++ .../create_terraform_exa_vmclusters_azure.py | 153 ++++++ .../python/database/export_adb_azure.py | 343 +++++++++++++ .../database/templates/adb-azure-template | 94 ++++ .../database/templates/adb-gcp-template | 108 +++++ .../templates/exa-infra-azure-template | 59 +++ .../templates/exa-vmcluster-azure-template | 113 +++++ .../azurecloud/terraform/adb-azure.tf | 93 ++++ .../azurecloud/terraform/exadata-azure.tf | 125 +++++ .../terraform/modules/azurerm-oci-adb/main.tf | 59 +++ .../modules/azurerm-oci-adb/outputs.tf | 37 ++ .../modules/azurerm-oci-adb/provider_req.tf} | 4 + .../modules/azurerm-oci-adb/variables.tf | 126 +++++ .../modules/azurerm-oci-exa-infra/main.tf | 56 +++ .../modules/azurerm-oci-exa-infra/outputs.tf | 28 ++ .../azurerm-oci-exa-infra/provider_req.tf} | 4 + .../azurerm-oci-exa-infra/variables.tf | 91 ++++ .../modules/azurerm-oci-exa-vmcluster/main.tf | 97 ++++ .../azurerm-oci-exa-vmcluster/outputs.tf | 47 ++ .../azurerm-oci-exa-vmcluster/provider_req.tf | 14 + .../azurerm-oci-exa-vmcluster/variables.tf | 178 +++++++ .../azurecloud/terraform/provider.tf | 9 + .../azurecloud/terraform/variables.tf | 118 +++++ .../Compute/oci_restrict_instance_types.rego | 0 .../opa}/Compute/oci_secure_vm_access.rego | 0 .../Identity/deny_api_keys_admin_group.rego | 0 .../opa}/Identity/deny_iam_admin.rego | 0 .../deny_storage_admins_delete_resources.rego | 0 .../opa}/Identity/dynamic_groups_check.rego | 0 .../Identity/enable_service_level_admins.rego | 0 .../opa}/Identity/ensure_mfa_for_users.rego | 0 .../ensure_tenancy_admins_access.rego | 0 .../opa}/Identity/iam_email_check.rego | 0 .../opa}/Identity/oci_iam_policy_checks.rego | 0 .../default_tags_check.rego | 0 .../oci_bucket_write_logging_check.rego | 0 .../oci_log_groups_checks.rego | 0 .../Logging_Monitoring/oci_resource_tags.rego | 0 .../oci_vcn_flow_logs_check.rego | 0 .../Network/oci_adb_access_restrictions.rego | 0 .../opa}/Network/oci_default_sl_checks.rego | 0 .../Network/oci_deny_ingress_for_nsg.rego | 0 .../opa}/Network/oci_deny_ingress_for_sl.rego | 0 .../Network/oci_enforce_container_config.rego | 0 .../opa}/Network/oci_enforce_dns_zones.rego | 0 .../opa}/Network/oci_enforce_lb_config.rego | 0 .../Network/oci_enforce_network_security.rego | 0 .../Network/oci_oic_access_restrictions.rego | 0 .../oci_check_score_constriant.rego | 0 .../opa}/Storage/oci_block_volumes.rego | 0 .../opa}/Storage/oci_deny_public_bucket.rego | 0 .../OPA => common/opa}/Storage/oci_fss.rego | 0 .../opa}/Storage/oci_secure_database.rego | 0 .../opa}/Storage/oci_secure_storage.rego | 0 .../common/python/__init__.py | 7 + .../common/python/commonTools.py | 322 +++++++++++++ .../connectAzure.properties | 23 + cd3_automation_toolkit/connectCloud.py | 30 ++ cd3_automation_toolkit/connectGCP.properties | 31 ++ cd3_automation_toolkit/connectOCI.properties | 94 ++++ .../example/CD3-Azure-template.xlsx | Bin 0 -> 62191 bytes .../example/CD3-Blank-template.xlsx | Bin 235286 -> 235451 bytes .../CD3-CIS-ManagementServices-template.xlsx | Bin 74833 -> 74803 bytes .../example/CD3-CIS-template.xlsx | Bin 298418 -> 300038 bytes .../example/CD3-Firewall-template.xlsx | Bin 116032 -> 194533 bytes .../example/CD3-HubSpoke-template.xlsx | Bin 270527 -> 271275 bytes cd3_automation_toolkit/example/OCI_Regions | 42 -- cd3_automation_toolkit/example/config | 7 - cd3_automation_toolkit/ocicloud/__init__.py | 3 + .../{ => ocicloud/python}/Excel_Columns | 7 +- .../{ => ocicloud/python}/OCI_Protocols | 0 .../{ => ocicloud/python}/OCI_Regions | 22 +- .../ocicloud/python/__init__.py | 19 + .../python}/cd3FirewallValidator.py | 175 ++++++- .../ocicloud/python/cd3Services.py | 138 ++++++ .../{ => ocicloud/python}/cd3Validator.py | 55 ++- .../python/compute}/__init__.py | 0 .../create_terraform_dedicatedhosts.py | 9 +- .../compute}/create_terraform_instances.py | 10 +- .../export_dedicatedvmhosts_nonGreenField.py | 13 +- .../export_instances_nonGreenField.py | 12 +- .../templates/dedicatedvmhosts-template | 0 .../compute}/templates/instances-template | 0 .../python/costmanagement/__init__.py | 1 + .../python/costmanagement/budget}/__init__.py | 0 .../budget}/create_terraform_budget.py | 12 +- .../budget}/export_budgets_nonGreenField.py | 11 +- .../templates/budget-alert-rule-template | 0 .../budget}/templates/budget-template | 0 .../python/database}/__init__.py | 0 .../python/database}/create_terraform_adb.py | 10 +- .../create_terraform_dbsystems_vm_bm.py | 11 +- .../database}/create_terraform_exa_infra.py | 10 +- .../create_terraform_exa_vmclusters.py | 10 +- .../create_terraform_mysql_configuration.py | 6 +- .../database}/create_terraform_mysql_db.py | 4 +- .../database}/export_adb_nonGreenField.py | 12 +- .../export_dbsystems_vm_bm_nonGreenField.py | 12 +- .../export_exa_infra_nonGreenField.py | 6 +- .../export_exa_vmclusters_nonGreenField.py | 10 +- ...xport_mysql_configuration_nonGreenField.py | 6 +- .../export_mysql_db_nonGreenField.py | 12 +- .../python/database}/templates/adb-template | 0 .../templates/dbsystems-vm-bm-template | 0 .../database}/templates/exa-infra-template | 0 .../templates/exa-vmclusters-template | 0 .../templates/mysql-configuration-template | 0 .../python/database}/templates/mysql-template | 0 .../python/developerservices/__init__.py | 5 + .../python/developerservices/oke}/__init__.py | 0 .../oke}/create_terraform_oke.py | 11 +- .../oke}/export_oke_nonGreenField.py | 40 +- .../oke}/templates/cluster-template | 0 .../oke}/templates/nodepool-template | 0 .../oke}/templates/virtual-nodepool-template | 0 .../resourcemanager}/__init__.py | 0 .../create_resource_manager_stack.py | 6 +- .../ocicloud/python/governance/__init__.py | 6 + .../python/governance/quota}/__init__.py | 0 .../quota}/create_terraform_quotas.py | 10 +- .../quota}/export_quotas_nonGreenField.py | 17 +- .../quota}/templates/quota-template | 0 .../python/governance/tagging}/__init__.py | 0 .../tagging}/create_terraform_tags.py | 9 +- .../tagging}/export_tags_nonGreenField.py | 12 +- .../tagging}/templates/tags-defaults-template | 0 .../tagging}/templates/tags-keys-template | 0 .../templates/tags-namespaces-template | 0 .../ocicloud/python/identity/__init__.py | 8 + .../python/identity/compartments}/__init__.py | 0 .../create_terraform_compartments.py | 10 +- .../templates/compartments-template | 0 .../export_identity_nonGreenField.py | 21 +- .../python/identity/groups}/__init__.py | 0 .../groups}/create_terraform_groups.py | 14 +- .../groups}/templates/groups-template | 0 .../templates/identity-domain-groups-template | 0 .../identity/networksources}/__init__.py | 0 .../create_terraform_networkSources.py | 10 +- .../export_networkSources_nonGreenField.py | 7 +- .../templates/network-sources-template | 0 .../python/identity/policies}/__init__.py | 0 .../policies}/create_terraform_policies.py | 12 +- .../policies}/templates/policies-template | 0 .../python/identity/users}/__init__.py | 0 .../identity/users}/create_terraform_users.py | 14 +- .../users}/export_users_nonGreenField.py | 12 +- .../templates/identity-domain-users-template | 0 .../identity/users}/templates/users-template | 0 .../python/managementservices/__init__.py | 4 + .../eventsnotifications}/__init__.py | 0 .../create_terraform_events.py | 9 +- .../create_terraform_notifications.py | 70 ++- ...port_events_notifications_nonGreenField.py | 25 +- .../templates/actions-template | 0 .../templates/events-template | 0 .../templates/notifications-template} | 17 +- .../managementservices/logging}/__init__.py | 0 .../logging}/enable_terraform_logging.py | 10 +- .../logging}/templates/logging-template | 0 .../monitoring}/__init__.py | 0 .../monitoring}/create_terraform_alarms.py | 9 +- .../export_alarms_nonGreenField.py | 12 +- .../monitoring}/templates/alarms-template | 0 .../serviceconnectorhub}/__init__.py | 0 .../create_terraform_service_connectors.py | 10 +- .../export_sch_nonGreenField.py | 12 +- .../templates/service-connectors-template | 0 .../python/network}/Global/__init__.py | 0 .../network}/Global/create_rpc_resources.py | 17 +- .../Global/templates/rpc-module-template | 0 .../rpc-provider-terraform-template | 0 .../rpc-source-destination-terraform-template | 0 .../rpc-variables-terraform-template | 0 .../templates/rpc-root-terraform-template | 0 .../ocicloud/python/network/__init__.py | 7 + .../python/network/basenetwork}/__init__.py | 0 .../python/network/basenetwork}/cd3parser.py | 0 .../basenetwork}/create_all_tf_objects.py | 8 +- .../basenetwork}/create_major_objects.py | 22 +- .../basenetwork}/create_terraform_defaults.py | 9 +- .../create_terraform_dhcp_options.py | 10 +- .../basenetwork}/create_terraform_nsg.py | 11 +- .../basenetwork}/create_terraform_route.py | 21 +- .../basenetwork}/create_terraform_seclist.py | 11 +- .../create_terraform_subnet_vlan.py | 10 +- .../python/network/basenetwork}/exportNSG.py | 21 +- .../network/basenetwork}/exportRoutetable.py | 24 +- .../network/basenetwork}/exportSeclist.py | 24 +- .../export_network_nonGreenField.py | 47 +- .../basenetwork}/export_seclist_to_tf.py | 0 .../basenetwork}/modify_routerules_tf.py | 30 +- .../basenetwork}/modify_secrules_tf.py | 14 +- .../templates/custom-dhcp-template | 0 .../templates/default-route-table-template | 0 .../templates/default-seclist-template | 0 .../templates/drg-data-source-template | 0 .../drg-route-distribution-statement-template | 0 .../templates/drg-route-distribution-template | 0 .../templates/drg-route-rule-template | 0 .../templates/drg-route-table-template | 0 .../major-objects-default-dhcp-template | 0 .../major-objects-drg-attachments-template | 0 .../templates/major-objects-drgs-template | 0 .../templates/major-objects-igws-template | 0 .../templates/major-objects-lpgs-template | 0 .../templates/major-objects-ngws-template | 0 .../templates/major-objects-sgws-template | 0 .../templates/major-objects-vcns-template | 16 +- .../basenetwork}/templates/nsg-rule-template | 0 .../basenetwork}/templates/nsg-template | 0 .../templates/route-rule-template | 0 .../templates/route-table-template | 0 .../basenetwork}/templates/sec-rule-template | 2 +- .../basenetwork}/templates/seclist-template | 0 .../basenetwork}/templates/subnet-template | 0 .../basenetwork}/templates/vlan-template | 0 .../python/network/dns}/__init__.py | 0 .../network/dns}/create_dns_resolvers.py | 10 +- .../python/network/dns}/create_dns_rrsets.py | 6 +- .../python/network/dns}/create_dns_views.py | 10 +- .../python/network/dns}/create_dns_zones.py | 10 +- .../network/dns}/export_dns_resolvers.py | 16 +- .../dns}/export_dns_views_zones_records.py | 18 +- .../dns}/templates/dns-records-template | 0 .../dns}/templates/dns-resolvers-template | 0 .../network/dns}/templates/dns-views-template | 0 .../network/dns}/templates/dns-zones-template | 0 .../python/network/loadbalancers}/__init__.py | 0 .../create_backendset_backendservers.py | 9 +- .../network/loadbalancers}/create_listener.py | 9 +- .../create_nlb_backendset_backendservers.py | 13 +- .../loadbalancers}/create_path_route_set.py | 9 +- .../loadbalancers}/create_routing_policy.py | 9 +- .../network/loadbalancers}/create_ruleset.py | 9 +- .../create_terraform_lbr_hostname_certs.py | 13 +- .../create_terraform_nlb_listener.py | 9 +- .../export_lbr_nonGreenField.py | 33 +- .../export_nlb_nonGreenField.py | 23 +- .../templates/access-control-rules-template | 0 .../templates/access-method-rules-template | 0 .../templates/backend-set-template | 0 .../templates/backends-template | 0 .../templates/certificate-template | 0 .../templates/cipher-suite-template | 0 .../templates/hostname-template | 0 .../templates/http-header-rules-template | 0 .../templates/lb-routing-policy-template | 0 .../templates/lbr-reserved-ips-template | 0 .../loadbalancers}/templates/lbr-template | 0 .../templates/listener-template | 0 .../templates/nlb-backend-set-template | 0 .../templates/nlb-backends-template | 0 .../templates/nlb-listener-template | 0 .../templates/nlb-reserved-ips-template | 0 .../loadbalancers}/templates/nlb-template | 0 .../templates/path-route-rules-template | 0 .../templates/path-route-set-template | 0 .../request-response-header-rules-template | 0 .../templates/rule-set-template | 0 .../templates/uri-redirect-rules-template | 0 .../python/ociCommonTools.py} | 452 +----------------- .../python/sddc}/__init__.py | 0 .../python/sddc}/create_terraform_sddc.py | 10 +- .../python/sddc}/export_sddc_nonGreenField.py | 11 +- .../sddc}/templates/sddc-cluster-template | 0 .../python/sddc}/templates/sddc-template | 0 .../ocicloud/python/security/__init__.py | 6 + .../python/security/cloudguard}/__init__.py | 0 .../enable_terraform_cloudguard.py | 6 +- .../templates/cloud-guard-config-template | 0 .../templates/cloud-guard-target-template | 0 .../python/security/firewall}/__init__.py | 1 + .../firewall}/clone_firewallpolicy.py | 6 +- ...loneexport_firewallpolicy_nonGreenField.py | 41 +- .../firewall}/delete_firewallpolicy.py | 6 +- .../export_firewall_nonGreenField.py | 16 +- .../export_firewallpolicy_nonGreenField.py | 155 ++++-- .../python/security/firewall}/fw_create.py | 15 +- .../security/firewall}/fwpolicy_create.py | 11 +- .../firewall}/fwpolicy_create_address.py | 6 +- .../fwpolicy_create_applicationlist.py | 7 +- .../firewall}/fwpolicy_create_apps.py | 6 +- .../fwpolicy_create_decryptionprofile.py | 10 +- .../firewall}/fwpolicy_create_decryptrules.py | 7 +- .../firewall/fwpolicy_create_natrules.py | 185 +++++++ .../firewall}/fwpolicy_create_secret.py | 7 +- .../firewall}/fwpolicy_create_secrules.py | 6 +- .../firewall}/fwpolicy_create_service.py | 6 +- .../firewall}/fwpolicy_create_servicelist.py | 6 +- .../fwpolicy_create_tunnelinspection.py | 6 +- .../firewall}/fwpolicy_create_urllist.py | 6 +- .../templates/firewall-policies-template | 0 .../firewall}/templates/firewalls-template | 3 + .../templates/policy-addresslists-template | 0 .../policy-applicationlists-template | 0 .../firewall}/templates/policy-apps-template | 0 .../policy-decryptionprofiles-template | 0 .../templates/policy-decryptrules-template | 2 +- .../templates/policy-natrules-template | 39 ++ .../templates/policy-secrets-template | 0 .../templates/policy-secrules-template | 2 +- .../templates/policy-servicelists-template | 0 .../templates/policy-services-template | 0 .../templates/policy-tunnelinspect-template | 2 +- .../templates/policy-urllists-template | 0 .../python/security/keyvault}/__init__.py | 0 .../keyvault}/create_terraform_keyvaults.py | 9 +- .../export_keyvaults_nonGreenField.py | 5 +- .../keyvault}/templates/keys-template | 0 .../keyvault}/templates/vaults-template | 0 .../ocicloud/python/storage/__init__.py | 5 + .../python/storage/blockvolume}/__init__.py | 0 .../create_terraform_block_volumes.py | 9 +- .../export_blockvolumes_nonGreenField.py | 12 +- .../templates/blockvolumes-template | 0 .../python/storage/filesystem}/__init__.py | 0 .../filesystem}/create_terraform_fss.py | 9 +- .../filesystem}/export_fss_nonGreenField.py | 12 +- .../templates/export-options-template | 0 .../templates/export-resource-template | 0 .../templates/fss-replication-template | 0 .../filesystem}/templates/fss-template | 0 .../templates/mount-target-template | 0 .../python/storage/objectstorage}/__init__.py | 0 .../objectstorage}/create_terraform_oss.py | 10 +- .../objectstorage}/export_terraform_oss.py | 16 +- .../objectstorage}/templates/oss-template | 0 .../terraform/README.md | 0 .../terraform/adb.tf | 0 .../terraform/backend.tf | 2 +- .../terraform/block-volume.tf | 0 .../terraform/budget.tf | 0 .../terraform/cloud-guard.tf | 0 .../terraform/database-exacs.tf | 0 .../terraform/dbsystem-vm-bm.tf | 0 .../terraform/dedicated-vm-host.tf | 0 .../terraform/dns.tf | 0 .../terraform/firewall.tf | 37 +- .../terraform/fss.tf | 0 .../terraform/identity.tf | 0 .../terraform/instance.tf | 0 .../terraform/kms.tf | 0 .../terraform/loadbalancer.tf | 0 .../terraform/managementservices.tf | 30 +- .../modules/compute/dedicated-vm-host/main.tf | 0 .../compute/dedicated-vm-host/outputs.tf | 0 .../compute/dedicated-vm-host/variables.tf | 0 .../modules/compute/instance/data.tf | 0 .../modules/compute/instance/main.tf | 0 .../modules/compute/instance/outputs.tf | 0 .../modules/compute/instance/variables.tf | 0 .../costmanagement/budget-alert-rule/main.tf | 0 .../budget-alert-rule}/oracle_provider_req.tf | 0 .../budget-alert-rule/outputs.tf | 0 .../budget-alert-rule/variables.tf | 0 .../modules/costmanagement/budget/main.tf | 0 .../budget}/oracle_provider_req.tf | 0 .../modules/costmanagement/budget/outputs.tf | 0 .../costmanagement/budget/variables.tf | 0 .../terraform/modules/database/adb/data.tf | 0 .../terraform/modules/database/adb/main.tf | 0 .../database/adb}/oracle_provider_req.tf | 0 .../terraform/modules/database/adb/outputs.tf | 0 .../modules/database/adb/variables.tf | 0 .../modules/database/dbsystem-vm-bm/data.tf | 0 .../modules/database/dbsystem-vm-bm/main.tf | 0 .../dbsystem-vm-bm}/oracle_provider_req.tf | 0 .../database/dbsystem-vm-bm/outputs.tf | 0 .../database/dbsystem-vm-bm/variables.tf | 0 .../modules/database/exa-infra/main.tf | 0 .../exa-infra}/oracle_provider_req.tf | 0 .../modules/database/exa-infra/outputs.tf | 0 .../modules/database/exa-infra/variables.tf | 0 .../modules/database/exa-vmcluster/data.tf | 0 .../modules/database/exa-vmcluster/main.tf | 0 .../exa-vmcluster}/oracle_provider_req.tf | 0 .../modules/database/exa-vmcluster/outputs.tf | 0 .../database/exa-vmcluster/variables.tf | 0 .../database/mysql-configuration/data.tf | 0 .../database/mysql-configuration/main.tf | 0 .../oracle_provider_req.tf | 0 .../database/mysql-configuration/outputs.tf | 0 .../database/mysql-configuration/variables.tf | 0 .../modules/database/mysql-dbsystem/data.tf | 0 .../modules/database/mysql-dbsystem/main.tf | 0 .../mysql-dbsystem}/oracle_provider_req.tf | 0 .../database/mysql-dbsystem/outputs.tf | 0 .../database/mysql-dbsystem/variables.tf | 0 .../modules/governance/quota-policy/main.tf | 0 .../quota-policy}/oracle_provider_req.tf | 0 .../governance/quota-policy/outputs.tf | 0 .../governance/quota-policy/variables.tf | 0 .../governance/tagging/tag-default/main.tf | 0 .../tag-default}/oracle_provider_req.tf | 0 .../governance/tagging/tag-default/outputs.tf | 0 .../tagging/tag-default/variables.tf | 0 .../governance/tagging/tag-key/main.tf | 0 .../tagging/tag-key}/oracle_provider_req.tf | 0 .../governance/tagging/tag-key/outputs.tf | 0 .../governance/tagging/tag-key/variables.tf | 0 .../governance/tagging/tag-namespace/main.tf | 0 .../tag-namespace}/oracle_provider_req.tf | 0 .../tagging/tag-namespace/outputs.tf | 0 .../tagging/tag-namespace/variables.tf | 0 .../modules/identity/iam-compartment/main.tf | 0 .../iam-compartment}/oracle_provider_req.tf | 0 .../identity/iam-compartment/outputs.tf | 0 .../identity/iam-compartment/variables.tf | 0 .../modules/identity/iam-group/data.tf | 0 .../modules/identity/iam-group/main.tf | 0 .../iam-group}/oracle_provider_req.tf | 0 .../modules/identity/iam-group/outputs.tf | 0 .../modules/identity/iam-group/variables.tf | 0 .../identity/iam-network-sources/main.tf | 0 .../oracle_provider_req.tf | 0 .../identity/iam-network-sources/outputs.tf | 0 .../identity/iam-network-sources/variables.tf | 0 .../modules/identity/iam-policy/main.tf | 0 .../iam-policy}/oracle_provider_req.tf | 0 .../modules/identity/iam-policy/outputs.tf | 0 .../modules/identity/iam-policy/variables.tf | 0 .../modules/identity/iam-user/data.tf | 0 .../modules/identity/iam-user/main.tf | 0 .../identity/iam-user}/oracle_provider_req.tf | 0 .../modules/identity/iam-user/outputs.tf | 0 .../modules/identity/iam-user/variables.tf | 0 .../identity/identity-domain-group/data.tf | 0 .../identity/identity-domain-group/main.tf | 0 .../oracle_provider_req.tf | 0 .../identity/identity-domain-group/outputs.tf | 0 .../identity-domain-group/variables.tf | 0 .../identity/identity-domain-user/data.tf | 0 .../identity/identity-domain-user/main.tf | 0 .../oracle_provider_req.tf | 0 .../identity/identity-domain-user/outputs.tf | 0 .../identity-domain-user/variables.tf | 0 .../modules/ip/public-ip-pool/main.tf | 0 .../ip/public-ip-pool}/oracle_provider_req.tf | 0 .../modules/ip/public-ip-pool/outputs.tf | 0 .../modules/ip/public-ip-pool/variables.tf | 0 .../modules/ip/reserved-public-ip/main.tf | 0 .../oracle_provider_req.tf | 0 .../modules/ip/reserved-public-ip/outputs.tf | 0 .../ip/reserved-public-ip/variables.tf | 0 .../modules/ip/secondary-private-ip/main.tf | 0 .../oracle_provider_req.tf | 0 .../ip/secondary-private-ip/outputs.tf | 0 .../ip/secondary-private-ip/variables.tf | 0 .../loadbalancer/lb-backend-set/main.tf | 0 .../lb-backend-set}/oracle_provider_req.tf | 0 .../loadbalancer/lb-backend-set/outputs.tf | 0 .../loadbalancer/lb-backend-set/variables.tf | 0 .../modules/loadbalancer/lb-backend/main.tf | 0 .../lb-backend}/oracle_provider_req.tf | 0 .../loadbalancer/lb-backend/outputs.tf | 0 .../loadbalancer/lb-backend/variables.tf | 0 .../loadbalancer/lb-certificate/main.tf | 0 .../lb-certificate}/oracle_provider_req.tf | 0 .../loadbalancer/lb-certificate/outputs.tf | 0 .../loadbalancer/lb-certificate/variables.tf | 0 .../loadbalancer/lb-cipher-suite/main.tf | 0 .../lb-cipher-suite}/oracle_provider_req.tf | 0 .../loadbalancer/lb-cipher-suite/outputs.tf | 0 .../loadbalancer/lb-cipher-suite/variables.tf | 0 .../modules/loadbalancer/lb-hostname/main.tf | 0 .../lb-hostname}/oracle_provider_req.tf | 0 .../loadbalancer/lb-hostname/outputs.tf | 0 .../loadbalancer/lb-hostname/variables.tf | 0 .../modules/loadbalancer/lb-listener/main.tf | 0 .../lb-listener}/oracle_provider_req.tf | 0 .../loadbalancer/lb-listener/outputs.tf | 0 .../loadbalancer/lb-listener/variables.tf | 0 .../loadbalancer/lb-load-balancer/data.tf | 0 .../loadbalancer/lb-load-balancer/main.tf | 0 .../lb-load-balancer}/oracle_provider_req.tf | 0 .../loadbalancer/lb-load-balancer/outputs.tf | 0 .../lb-load-balancer/variables.tf | 0 .../loadbalancer/lb-path-route-set/main.tf | 0 .../lb-path-route-set}/oracle_provider_req.tf | 0 .../loadbalancer/lb-path-route-set/outputs.tf | 0 .../lb-path-route-set/variables.tf | 0 .../loadbalancer/lb-routing-policy/main.tf | 0 .../lb-routing-policy}/oracle_provider_req.tf | 0 .../loadbalancer/lb-routing-policy/outputs.tf | 0 .../lb-routing-policy/variables.tf | 0 .../modules/loadbalancer/lb-rule-set/main.tf | 0 .../lb-rule-set}/oracle_provider_req.tf | 0 .../loadbalancer/lb-rule-set/outputs.tf | 0 .../loadbalancer/lb-rule-set/variables.tf | 0 .../modules/managementservices/alarm/main.tf | 0 .../alarm}/oracle_provider_req.tf | 0 .../managementservices/alarm/outputs.tf | 0 .../managementservices/alarm/variables.tf | 0 .../modules/managementservices/event/main.tf | 0 .../event}/oracle_provider_req.tf | 0 .../managementservices/event/outputs.tf | 0 .../managementservices/event/variables.tf | 0 .../managementservices/log-group/main.tf | 0 .../log-group}/oracle_provider_req.tf | 0 .../managementservices/log-group/outputs.tf | 0 .../managementservices/log-group/variables.tf | 0 .../modules/managementservices/log/main.tf | 0 .../log}/oracle_provider_req.tf | 0 .../modules/managementservices/log/outputs.tf | 0 .../managementservices/log/variables.tf | 0 .../managementservices/notification}/main.tf | 17 + .../notification}/oracle_provider_req.tf | 0 .../notification}/outputs.tf | 0 .../notification}/variables.tf | 4 + .../service-connector/data.tf | 0 .../service-connector/main.tf | 0 .../service-connector}/oracle_provider_req.tf | 0 .../service-connector/outputs.tf | 0 .../service-connector/variables.tf | 0 .../modules/network/custom-dhcp/main.tf | 0 .../custom-dhcp}/oracle_provider_req.tf | 0 .../modules/network/custom-dhcp/outputs.tf | 0 .../modules/network/custom-dhcp/variables.tf | 0 .../modules/network/default-dhcp/main.tf | 0 .../default-dhcp}/oracle_provider_req.tf | 0 .../modules/network/default-dhcp/outputs.tf | 0 .../modules/network/default-dhcp/variables.tf | 0 .../modules/network/dns/dns_resolver/main.tf | 0 .../dns/dns_resolver}/oracle_provider_req.tf | 0 .../network/dns/dns_resolver/outputs.tf | 0 .../network/dns/dns_resolver/variables.tf | 0 .../modules/network/dns/rrset/main.tf | 0 .../network/dns/rrset}/oracle_provider_req.tf | 0 .../modules/network/dns/rrset/outputs.tf | 0 .../modules/network/dns/rrset/variables.tf | 0 .../modules/network/dns/view/main.tf | 0 .../network/dns/view}/oracle_provider_req.tf | 0 .../modules/network/dns/view/outputs.tf | 0 .../modules/network/dns/view/variables.tf | 0 .../modules/network/dns/zone/main.tf | 0 .../network/dns/zone}/oracle_provider_req.tf | 0 .../modules/network/dns/zone/outputs.tf | 0 .../modules/network/dns/zone/variables.tf | 0 .../modules/network/drg-attachment/main.tf | 0 .../drg-attachment}/oracle_provider_req.tf | 0 .../modules/network/drg-attachment/outputs.tf | 0 .../network/drg-attachment/variables.tf | 0 .../drg-route-distribution-statement/main.tf | 0 .../oracle_provider_req.tf | 0 .../outputs.tf | 0 .../variables.tf | 0 .../network/drg-route-distribution/main.tf | 0 .../oracle_provider_req.tf | 0 .../network/drg-route-distribution/outputs.tf | 0 .../drg-route-distribution/variables.tf | 0 .../modules/network/drg-route-rule/main.tf | 0 .../drg-route-rule}/oracle_provider_req.tf | 0 .../modules/network/drg-route-rule/outputs.tf | 0 .../network/drg-route-rule/variables.tf | 0 .../modules/network/drg-route-table/main.tf | 0 .../drg-route-table}/oracle_provider_req.tf | 0 .../network/drg-route-table/outputs.tf | 0 .../network/drg-route-table/variables.tf | 0 .../terraform/modules/network/drg/main.tf | 0 .../network/drg}/oracle_provider_req.tf | 0 .../terraform/modules/network/drg/outputs.tf | 0 .../modules/network/drg/variables.tf | 0 .../terraform/modules/network/igw/main.tf | 0 .../network/igw}/oracle_provider_req.tf | 0 .../terraform/modules/network/igw/outputs.tf | 0 .../modules/network/igw/variables.tf | 0 .../terraform/modules/network/lpg/main.tf | 0 .../network/lpg}/oracle_provider_req.tf | 0 .../terraform/modules/network/lpg/outputs.tf | 0 .../modules/network/lpg/variables.tf | 0 .../terraform/modules/network/ngw/main.tf | 0 .../network/ngw}/oracle_provider_req.tf | 0 .../terraform/modules/network/ngw/outputs.tf | 0 .../modules/network/ngw/variables.tf | 0 .../modules/network/nsg-rule/main.tf | 0 .../network/nsg-rule}/oracle_provider_req.tf | 0 .../modules/network/nsg-rule/outputs.tf | 0 .../modules/network/nsg-rule/variables.tf | 0 .../terraform/modules/network/nsg/main.tf | 0 .../network/nsg}/oracle_provider_req.tf | 0 .../terraform/modules/network/nsg/outputs.tf | 0 .../modules/network/nsg/variables.tf | 0 .../modules/network/route-table/main.tf | 0 .../route-table}/oracle_provider_req.tf | 0 .../modules/network/route-table/outputs.tf | 0 .../modules/network/route-table/variables.tf | 0 .../modules/network/sec-list/main.tf | 0 .../network/sec-list}/oracle_provider_req.tf | 0 .../modules/network/sec-list/outputs.tf | 0 .../modules/network/sec-list/variables.tf | 0 .../terraform/modules/network/sgw/main.tf | 0 .../network/sgw}/oracle_provider_req.tf | 0 .../terraform/modules/network/sgw/outputs.tf | 0 .../modules/network/sgw/variables.tf | 0 .../terraform/modules/network/subnet/main.tf | 3 +- .../network/subnet}/oracle_provider_req.tf | 0 .../modules/network/subnet/outputs.tf | 0 .../modules/network/subnet/variables.tf | 0 .../terraform/modules/network/vcn/main.tf | 0 .../network/vcn}/oracle_provider_req.tf | 0 .../terraform/modules/network/vcn/outputs.tf | 0 .../modules/network/vcn/variables.tf | 0 .../terraform/modules/network/vlan/data.tf | 0 .../terraform/modules/network/vlan/main.tf | 0 .../network/vlan}/oracle_provider_req.tf | 0 .../terraform/modules/network/vlan/outputs.tf | 0 .../modules/network/vlan/variables.tf | 0 .../networkloadbalancer/nlb-backend/data.tf | 0 .../networkloadbalancer/nlb-backend/main.tf | 0 .../nlb-backend}/oracle_provider_req.tf | 0 .../nlb-backend/outputs.tf | 0 .../nlb-backend/variables.tf | 0 .../nlb-backendset/main.tf | 0 .../nlb-backendset}/oracle_provider_req.tf | 0 .../nlb-backendset/outputs.tf | 0 .../nlb-backendset/variables.tf | 0 .../networkloadbalancer/nlb-listener/main.tf | 0 .../nlb-listener}/oracle_provider_req.tf | 0 .../nlb-listener/outputs.tf | 0 .../nlb-listener/variables.tf | 0 .../modules/networkloadbalancer/nlb/data.tf | 0 .../modules/networkloadbalancer/nlb/main.tf | 0 .../nlb}/oracle_provider_req.tf | 0 .../networkloadbalancer/nlb/outputs.tf | 0 .../networkloadbalancer/nlb/variables.tf | 0 .../terraform/modules/oke/cluster/data.tf | 0 .../terraform/modules/oke/cluster/main.tf | 0 .../oke/cluster}/oracle_provider_req.tf | 0 .../terraform/modules/oke/cluster/outputs.tf | 0 .../modules/oke/cluster/variables.tf | 0 .../terraform/modules/oke/nodepool/data.tf | 0 .../terraform/modules/oke/nodepool/main.tf | 0 .../oke/nodepool}/oracle_provider_req.tf | 0 .../terraform/modules/oke/nodepool/outputs.tf | 0 .../modules/oke/nodepool/variables.tf | 0 .../modules/oke/virtual-nodepool/data.tf | 0 .../modules/oke/virtual-nodepool/main.tf | 0 .../virtual-nodepool}/oracle_provider_req.tf | 0 .../modules/oke/virtual-nodepool/outputs.tf | 0 .../modules/oke/virtual-nodepool/variables.tf | 0 .../modules/sddc/sddc-cluster/main.tf | 0 .../sddc/sddc-cluster}/oracle_provider_req.tf | 0 .../modules/sddc/sddc-cluster/outputs.tf | 0 .../modules/sddc/sddc-cluster/variables.tf | 0 .../terraform/modules/sddc/sddc/main.tf | 0 .../modules/sddc/sddc}/oracle_provider_req.tf | 0 .../terraform/modules/sddc/sddc/outputs.tf | 0 .../terraform/modules/sddc/sddc/variables.tf | 0 .../cloud-guard-configuration/main.tf | 0 .../oracle_provider_req.tf | 0 .../cloud-guard-configuration/outputs.tf | 0 .../cloud-guard-configuration/variables.tf | 0 .../security/cloud-guard-target/data.tf | 0 .../security/cloud-guard-target/main.tf | 0 .../oracle_provider_req.tf | 0 .../security/cloud-guard-target/outputs.tf | 0 .../security/cloud-guard-target/variables.tf | 0 .../security/firewall/address-list/data.tf | 0 .../security/firewall/address-list/main.tf | 0 .../address-list}/oracle_provider_req.tf | 0 .../security/firewall/address-list/output.tf | 0 .../firewall/address-list/variable.tf | 0 .../firewall/application-group/data.tf | 0 .../firewall/application-group/main.tf | 0 .../application-group}/oracle_provider_req.tf | 0 .../firewall/application-group/output.tf | 0 .../firewall/application-group/variable.tf | 0 .../security/firewall/application/data.tf | 0 .../security/firewall/application/main.tf | 0 .../application}/oracle_provider_req.tf | 0 .../security/firewall/application/output.tf | 0 .../security/firewall/application/variable.tf | 0 .../firewall/decryption-profile/data.tf | 0 .../firewall/decryption-profile/main.tf | 0 .../oracle_provider_req.tf | 0 .../firewall/decryption-profile/output.tf | 0 .../firewall/decryption-profile/variable.tf | 0 .../firewall/decryption-rules/data.tf | 0 .../firewall/decryption-rules/main.tf | 0 .../decryption-rules}/oracle_provider_req.tf | 0 .../firewall/decryption-rules/output.tf | 0 .../firewall/decryption-rules/variable.tf | 0 .../security/firewall/firewall-policy/main.tf | 0 .../firewall-policy}/oracle_provider_req.tf | 0 .../firewall/firewall-policy/output.tf | 0 .../firewall/firewall-policy/variable.tf | 0 .../security/firewall/firewall/data.tf | 0 .../security/firewall/firewall/main.tf | 3 + .../firewall/firewall}/oracle_provider_req.tf | 0 .../security/firewall/firewall/output.tf | 0 .../security/firewall/firewall/variable.tf | 6 + .../security/firewall/nat-rules}/data.tf | 0 .../security/firewall/nat-rules/main.tf | 22 + .../nat-rules}/oracle_provider_req.tf | 0 .../security/firewall/nat-rules/output.tf | 6 + .../security/firewall/nat-rules/variable.tf | 155 ++++++ .../modules/security/firewall/secret/data.tf | 4 +- .../modules/security/firewall/secret/main.tf | 2 +- .../firewall/secret}/oracle_provider_req.tf | 0 .../security/firewall/secret/output.tf | 0 .../security/firewall/secret/variable.tf | 0 .../security/firewall/security-rules}/data.tf | 0 .../security/firewall/security-rules/main.tf | 0 .../security-rules}/oracle_provider_req.tf | 0 .../firewall/security-rules/output.tf | 0 .../firewall/security-rules/variable.tf | 0 .../security/firewall/service-list/data.tf | 0 .../security/firewall/service-list/main.tf | 0 .../service-list}/oracle_provider_req.tf | 0 .../security/firewall/service-list/output.tf | 0 .../firewall/service-list/variable.tf | 0 .../security/firewall/service}/data.tf | 0 .../modules/security/firewall/service/main.tf | 0 .../firewall/service}/oracle_provider_req.tf | 0 .../security/firewall/service/output.tf | 0 .../security/firewall/service/variable.tf | 0 .../security/firewall/tunnel-inspect}/data.tf | 0 .../security/firewall/tunnel-inspect/main.tf | 0 .../tunnel-inspect}/oracle_provider_req.tf | 0 .../firewall/tunnel-inspect/output.tf | 0 .../firewall/tunnel-inspect/variable.tf | 0 .../security/firewall/url-list/data.tf | 11 + .../security/firewall/url-list/main.tf | 0 .../firewall/url-list}/oracle_provider_req.tf | 0 .../security/firewall/url-list/output.tf | 0 .../security/firewall/url-list/variable.tf | 0 .../terraform/modules/security/key/main.tf | 0 .../security/key}/oracle_provider_req.tf | 0 .../terraform/modules/security/key/outputs.tf | 0 .../modules/security/key/variables.tf | 0 .../terraform/modules/security/vault/main.tf | 0 .../security/vault}/oracle_provider_req.tf | 0 .../modules/security/vault/outputs.tf | 0 .../modules/security/vault/variables.tf | 0 .../modules/storage/block-volume/data.tf | 0 .../modules/storage/block-volume/main.tf | 0 .../block-volume}/oracle_provider_req.tf | 0 .../modules/storage/block-volume/outputs.tf | 0 .../modules/storage/block-volume/variables.tf | 0 .../file-storage/export-option/main.tf | 0 .../export-option}/oracle_provider_req.tf | 0 .../file-storage/export-option/outputs.tf | 0 .../file-storage/export-option/variables.tf | 0 .../file-storage/fss-replication/main.tf | 0 .../fss-replication}/oracle_provider_req.tf | 0 .../file-storage/fss-replication/outputs.tf | 0 .../file-storage/fss-replication/variables.tf | 0 .../modules/storage/file-storage/fss/data.tf | 0 .../modules/storage/file-storage/fss/main.tf | 0 .../file-storage/fss}/oracle_provider_req.tf | 0 .../storage/file-storage/fss/outputs.tf | 0 .../storage/file-storage/fss/variables.tf | 0 .../storage/file-storage/mount-target/data.tf | 0 .../storage/file-storage/mount-target/main.tf | 0 .../mount-target}/oracle_provider_req.tf | 0 .../file-storage/mount-target/outputs.tf | 0 .../file-storage/mount-target/variables.tf | 0 .../modules/storage/object-storage/main.tf | 0 .../object-storage}/oracle_provider_req.tf | 0 .../modules/storage/object-storage/outputs.tf | 0 .../storage/object-storage/variables.tf | 0 .../terraform/mysql-dbsystem.tf | 0 .../terraform/network.tf | 0 .../terraform/networkloadbalancer.tf | 0 .../terraform/nsg.tf | 2 +- .../terraform/object-storage.tf | 0 .../terraform/oci-data.tf | 0 .../terraform/oke.tf | 0 .../terraform/provider.tf | 2 +- .../terraform/quota.tf | 0 .../terraform/scripts/bastion-ssh-key | 0 .../terraform/scripts/default.sh | 0 .../terraform/scripts/default.yaml | 0 .../terraform/scripts/server-ssh-key | 0 .../terraform/sddc.tf | 0 .../terraform/tagging.tf | 0 .../terraform/variables_example.tf | 40 +- .../terraform/vlan.tf | 0 cd3_automation_toolkit/setUpAzure.properties | 25 + cd3_automation_toolkit/setUpCloud.py | 30 ++ cd3_automation_toolkit/setUpOCI.properties | 8 +- cd3_automation_toolkit/setUpOCI.py | 294 ++++++------ cd3_automation_toolkit/shell_script.sh | 7 +- .../.outdir_structure_file.properties | 36 ++ .../user-scripts/__init__.py | 2 +- .../user-scripts/connectAzure.py | 193 ++++++++ .../user-scripts/connectGCP.py | 284 +++++++++++ .../user-scripts/createTenancyConfig.py | 22 +- .../user-scripts/deleteTenancyConfig.py | 8 +- .../user-scripts/setUpAzure.py | 243 ++++++++++ .../notification-subscription/main.tf | 21 - .../notification-subscription/outputs.tf | 12 - .../notification-subscription/variables.tf | 35 -- jenkins_install/apply.groovy | 2 +- jenkins_install/jenkins.sh | 4 +- 814 files changed, 5655 insertions(+), 1647 deletions(-) delete mode 100755 Dockerfile delete mode 100644 cd3_automation_toolkit/CostManagement/__init__.py delete mode 100644 cd3_automation_toolkit/DeveloperServices/__init__.py delete mode 100644 cd3_automation_toolkit/Governance/__init__.py delete mode 100644 cd3_automation_toolkit/Identity/__init__.py delete mode 100644 cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-subscriptions-template delete mode 100755 cd3_automation_toolkit/ManagementServices/__init__.py delete mode 100644 cd3_automation_toolkit/Network/__init__.py delete mode 100644 cd3_automation_toolkit/Security/__init__.py delete mode 100644 cd3_automation_toolkit/Storage/__init__.py delete mode 100644 cd3_automation_toolkit/__init__.py create mode 100644 cd3_automation_toolkit/azurecloud/__init__.py create mode 100644 cd3_automation_toolkit/azurecloud/python/__init__.py create mode 100644 cd3_automation_toolkit/azurecloud/python/azrCommonTools.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/__init__.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/create_terraform_adb_azure.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_infra_azure.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_vmclusters_azure.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/export_adb_azure.py create mode 100644 cd3_automation_toolkit/azurecloud/python/database/templates/adb-azure-template create mode 100644 cd3_automation_toolkit/azurecloud/python/database/templates/adb-gcp-template create mode 100644 cd3_automation_toolkit/azurecloud/python/database/templates/exa-infra-azure-template create mode 100644 cd3_automation_toolkit/azurecloud/python/database/templates/exa-vmcluster-azure-template create mode 100644 cd3_automation_toolkit/azurecloud/terraform/adb-azure.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/exadata-azure.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/main.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/outputs.tf rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf => azurecloud/terraform/modules/azurerm-oci-adb/provider_req.tf} (76%) create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/variables.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/main.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/outputs.tf rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/object-storage/oracle_provider_req.tf => azurecloud/terraform/modules/azurerm-oci-exa-infra/provider_req.tf} (76%) create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/variables.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/main.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/outputs.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/provider_req.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/variables.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/provider.tf create mode 100644 cd3_automation_toolkit/azurecloud/terraform/variables.tf rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Compute/oci_restrict_instance_types.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Compute/oci_secure_vm_access.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/deny_api_keys_admin_group.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/deny_iam_admin.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/deny_storage_admins_delete_resources.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/dynamic_groups_check.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/enable_service_level_admins.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/ensure_mfa_for_users.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/ensure_tenancy_admins_access.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/iam_email_check.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Identity/oci_iam_policy_checks.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Logging_Monitoring/default_tags_check.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Logging_Monitoring/oci_bucket_write_logging_check.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Logging_Monitoring/oci_log_groups_checks.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Logging_Monitoring/oci_resource_tags.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Logging_Monitoring/oci_vcn_flow_logs_check.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_adb_access_restrictions.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_default_sl_checks.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_deny_ingress_for_nsg.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_deny_ingress_for_sl.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_enforce_container_config.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_enforce_dns_zones.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_enforce_lb_config.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_enforce_network_security.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Network/oci_oic_access_restrictions.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Risk_score/oci_check_score_constriant.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Storage/oci_block_volumes.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Storage/oci_deny_public_bucket.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Storage/oci_fss.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Storage/oci_secure_database.rego (100%) rename cd3_automation_toolkit/{user-scripts/OPA => common/opa}/Storage/oci_secure_storage.rego (100%) create mode 100644 cd3_automation_toolkit/common/python/__init__.py create mode 100644 cd3_automation_toolkit/common/python/commonTools.py create mode 100644 cd3_automation_toolkit/connectAzure.properties create mode 100644 cd3_automation_toolkit/connectCloud.py create mode 100644 cd3_automation_toolkit/connectGCP.properties create mode 100644 cd3_automation_toolkit/connectOCI.properties create mode 100644 cd3_automation_toolkit/example/CD3-Azure-template.xlsx delete mode 100644 cd3_automation_toolkit/example/OCI_Regions delete mode 100644 cd3_automation_toolkit/example/config create mode 100644 cd3_automation_toolkit/ocicloud/__init__.py rename cd3_automation_toolkit/{ => ocicloud/python}/Excel_Columns (98%) rename cd3_automation_toolkit/{ => ocicloud/python}/OCI_Protocols (100%) rename cd3_automation_toolkit/{ => ocicloud/python}/OCI_Regions (70%) create mode 100644 cd3_automation_toolkit/ocicloud/python/__init__.py rename cd3_automation_toolkit/{ => ocicloud/python}/cd3FirewallValidator.py (87%) create mode 100644 cd3_automation_toolkit/ocicloud/python/cd3Services.py rename cd3_automation_toolkit/{ => ocicloud/python}/cd3Validator.py (98%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/__init__.py (100%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/create_terraform_dedicatedhosts.py (94%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/create_terraform_instances.py (97%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/export_dedicatedvmhosts_nonGreenField.py (91%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/export_instances_nonGreenField.py (97%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/templates/dedicatedvmhosts-template (100%) rename cd3_automation_toolkit/{Compute => ocicloud/python/compute}/templates/instances-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/costmanagement/__init__.py rename cd3_automation_toolkit/{CostManagement/Budget => ocicloud/python/costmanagement/budget}/__init__.py (100%) rename cd3_automation_toolkit/{CostManagement/Budget => ocicloud/python/costmanagement/budget}/create_terraform_budget.py (95%) rename cd3_automation_toolkit/{CostManagement/Budget => ocicloud/python/costmanagement/budget}/export_budgets_nonGreenField.py (96%) rename cd3_automation_toolkit/{CostManagement/Budget => ocicloud/python/costmanagement/budget}/templates/budget-alert-rule-template (100%) rename cd3_automation_toolkit/{CostManagement/Budget => ocicloud/python/costmanagement/budget}/templates/budget-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/__init__.py (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_adb.py (96%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_dbsystems_vm_bm.py (97%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_exa_infra.py (94%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_exa_vmclusters.py (97%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_mysql_configuration.py (97%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/create_terraform_mysql_db.py (99%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_adb_nonGreenField.py (95%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_dbsystems_vm_bm_nonGreenField.py (96%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_exa_infra_nonGreenField.py (97%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_exa_vmclusters_nonGreenField.py (97%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_mysql_configuration_nonGreenField.py (99%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/export_mysql_db_nonGreenField.py (96%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/adb-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/dbsystems-vm-bm-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/exa-infra-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/exa-vmclusters-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/mysql-configuration-template (100%) rename cd3_automation_toolkit/{Database => ocicloud/python/database}/templates/mysql-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/developerservices/__init__.py rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/__init__.py (100%) rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/create_terraform_oke.py (98%) rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/export_oke_nonGreenField.py (95%) rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/templates/cluster-template (100%) rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/templates/nodepool-template (100%) rename cd3_automation_toolkit/{DeveloperServices/OKE => ocicloud/python/developerservices/oke}/templates/virtual-nodepool-template (100%) rename cd3_automation_toolkit/{DeveloperServices/ResourceManager => ocicloud/python/developerservices/resourcemanager}/__init__.py (100%) rename cd3_automation_toolkit/{DeveloperServices/ResourceManager => ocicloud/python/developerservices/resourcemanager}/create_resource_manager_stack.py (99%) create mode 100644 cd3_automation_toolkit/ocicloud/python/governance/__init__.py rename cd3_automation_toolkit/{Governance/Quota => ocicloud/python/governance/quota}/__init__.py (100%) rename cd3_automation_toolkit/{Governance/Quota => ocicloud/python/governance/quota}/create_terraform_quotas.py (94%) rename cd3_automation_toolkit/{Governance/Quota => ocicloud/python/governance/quota}/export_quotas_nonGreenField.py (88%) rename cd3_automation_toolkit/{Governance/Quota => ocicloud/python/governance/quota}/templates/quota-template (100%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/__init__.py (100%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/create_terraform_tags.py (97%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/export_tags_nonGreenField.py (96%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/templates/tags-defaults-template (100%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/templates/tags-keys-template (100%) rename cd3_automation_toolkit/{Governance/Tagging => ocicloud/python/governance/tagging}/templates/tags-namespaces-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/identity/__init__.py rename cd3_automation_toolkit/{Identity/Compartments => ocicloud/python/identity/compartments}/__init__.py (100%) rename cd3_automation_toolkit/{Identity/Compartments => ocicloud/python/identity/compartments}/create_terraform_compartments.py (97%) rename cd3_automation_toolkit/{Identity/Compartments => ocicloud/python/identity/compartments}/templates/compartments-template (100%) rename cd3_automation_toolkit/{Identity => ocicloud/python/identity}/export_identity_nonGreenField.py (96%) rename cd3_automation_toolkit/{Identity/Groups => ocicloud/python/identity/groups}/__init__.py (100%) rename cd3_automation_toolkit/{Identity/Groups => ocicloud/python/identity/groups}/create_terraform_groups.py (93%) rename cd3_automation_toolkit/{Identity/Groups => ocicloud/python/identity/groups}/templates/groups-template (100%) rename cd3_automation_toolkit/{Identity/Groups => ocicloud/python/identity/groups}/templates/identity-domain-groups-template (100%) rename cd3_automation_toolkit/{Identity/NetworkSources => ocicloud/python/identity/networksources}/__init__.py (100%) rename cd3_automation_toolkit/{Identity/NetworkSources => ocicloud/python/identity/networksources}/create_terraform_networkSources.py (95%) rename cd3_automation_toolkit/{Identity/NetworkSources => ocicloud/python/identity/networksources}/export_networkSources_nonGreenField.py (94%) rename cd3_automation_toolkit/{Identity/NetworkSources => ocicloud/python/identity/networksources}/templates/network-sources-template (100%) rename cd3_automation_toolkit/{Identity/Policies => ocicloud/python/identity/policies}/__init__.py (100%) rename cd3_automation_toolkit/{Identity/Policies => ocicloud/python/identity/policies}/create_terraform_policies.py (96%) rename cd3_automation_toolkit/{Identity/Policies => ocicloud/python/identity/policies}/templates/policies-template (100%) rename cd3_automation_toolkit/{Identity/Users => ocicloud/python/identity/users}/__init__.py (100%) rename cd3_automation_toolkit/{Identity/Users => ocicloud/python/identity/users}/create_terraform_users.py (94%) rename cd3_automation_toolkit/{Identity/Users => ocicloud/python/identity/users}/export_users_nonGreenField.py (93%) rename cd3_automation_toolkit/{Identity/Users => ocicloud/python/identity/users}/templates/identity-domain-users-template (100%) rename cd3_automation_toolkit/{Identity/Users => ocicloud/python/identity/users}/templates/users-template (100%) create mode 100755 cd3_automation_toolkit/ocicloud/python/managementservices/__init__.py rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/__init__.py (100%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/create_terraform_events.py (97%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/create_terraform_notifications.py (70%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/export_events_notifications_nonGreenField.py (95%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/templates/actions-template (100%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications => ocicloud/python/managementservices/eventsnotifications}/templates/events-template (100%) rename cd3_automation_toolkit/{ManagementServices/EventsAndNotifications/templates/notifications-topics-template => ocicloud/python/managementservices/eventsnotifications/templates/notifications-template} (82%) rename cd3_automation_toolkit/{ManagementServices/Logging => ocicloud/python/managementservices/logging}/__init__.py (100%) rename cd3_automation_toolkit/{ManagementServices/Logging => ocicloud/python/managementservices/logging}/enable_terraform_logging.py (95%) rename cd3_automation_toolkit/{ManagementServices/Logging => ocicloud/python/managementservices/logging}/templates/logging-template (100%) rename cd3_automation_toolkit/{ManagementServices/Monitoring => ocicloud/python/managementservices/monitoring}/__init__.py (100%) rename cd3_automation_toolkit/{ManagementServices/Monitoring => ocicloud/python/managementservices/monitoring}/create_terraform_alarms.py (95%) rename cd3_automation_toolkit/{ManagementServices/Monitoring => ocicloud/python/managementservices/monitoring}/export_alarms_nonGreenField.py (93%) rename cd3_automation_toolkit/{ManagementServices/Monitoring => ocicloud/python/managementservices/monitoring}/templates/alarms-template (100%) rename cd3_automation_toolkit/{ManagementServices/ServiceConnectorHub => ocicloud/python/managementservices/serviceconnectorhub}/__init__.py (100%) rename cd3_automation_toolkit/{ManagementServices/ServiceConnectorHub => ocicloud/python/managementservices/serviceconnectorhub}/create_terraform_service_connectors.py (97%) rename cd3_automation_toolkit/{ManagementServices/ServiceConnectorHub => ocicloud/python/managementservices/serviceconnectorhub}/export_sch_nonGreenField.py (98%) rename cd3_automation_toolkit/{ManagementServices/ServiceConnectorHub => ocicloud/python/managementservices/serviceconnectorhub}/templates/service-connectors-template (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/__init__.py (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/create_rpc_resources.py (95%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/templates/rpc-module-template (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/templates/rpc-module/rpc-provider-terraform-template (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/templates/rpc-module/rpc-source-destination-terraform-template (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/templates/rpc-module/rpc-variables-terraform-template (100%) rename cd3_automation_toolkit/{Network => ocicloud/python/network}/Global/templates/rpc-root-terraform-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/network/__init__.py rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/__init__.py (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/cd3parser.py (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_all_tf_objects.py (94%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_major_objects.py (97%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_defaults.py (98%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_dhcp_options.py (97%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_nsg.py (96%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_route.py (98%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_seclist.py (97%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/create_terraform_subnet_vlan.py (98%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/exportNSG.py (93%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/exportRoutetable.py (96%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/exportSeclist.py (93%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/export_network_nonGreenField.py (97%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/export_seclist_to_tf.py (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/modify_routerules_tf.py (96%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/modify_secrules_tf.py (96%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/custom-dhcp-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/default-route-table-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/default-seclist-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/drg-data-source-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/drg-route-distribution-statement-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/drg-route-distribution-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/drg-route-rule-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/drg-route-table-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-default-dhcp-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-drg-attachments-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-drgs-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-igws-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-lpgs-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-ngws-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-sgws-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/major-objects-vcns-template (88%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/nsg-rule-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/nsg-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/route-rule-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/route-table-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/sec-rule-template (99%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/seclist-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/subnet-template (100%) rename cd3_automation_toolkit/{Network/BaseNetwork => ocicloud/python/network/basenetwork}/templates/vlan-template (100%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/__init__.py (100%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/create_dns_resolvers.py (97%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/create_dns_rrsets.py (97%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/create_dns_views.py (94%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/create_dns_zones.py (94%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/export_dns_resolvers.py (97%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/export_dns_views_zones_records.py (94%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/templates/dns-records-template (100%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/templates/dns-resolvers-template (100%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/templates/dns-views-template (100%) rename cd3_automation_toolkit/{Network/DNS => ocicloud/python/network/dns}/templates/dns-zones-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/__init__.py (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_backendset_backendservers.py (97%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_listener.py (96%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_nlb_backendset_backendservers.py (94%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_path_route_set.py (95%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_routing_policy.py (94%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_ruleset.py (97%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_terraform_lbr_hostname_certs.py (97%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/create_terraform_nlb_listener.py (97%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/export_lbr_nonGreenField.py (97%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/export_nlb_nonGreenField.py (94%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/access-control-rules-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/access-method-rules-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/backend-set-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/backends-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/certificate-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/cipher-suite-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/hostname-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/http-header-rules-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/lb-routing-policy-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/lbr-reserved-ips-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/lbr-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/listener-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/nlb-backend-set-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/nlb-backends-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/nlb-listener-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/nlb-reserved-ips-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/nlb-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/path-route-rules-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/path-route-set-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/request-response-header-rules-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/rule-set-template (100%) rename cd3_automation_toolkit/{Network/LoadBalancers => ocicloud/python/network/loadbalancers}/templates/uri-redirect-rules-template (100%) rename cd3_automation_toolkit/{commonTools.py => ocicloud/python/ociCommonTools.py} (71%) rename cd3_automation_toolkit/{SDDC => ocicloud/python/sddc}/__init__.py (100%) rename cd3_automation_toolkit/{SDDC => ocicloud/python/sddc}/create_terraform_sddc.py (96%) rename cd3_automation_toolkit/{SDDC => ocicloud/python/sddc}/export_sddc_nonGreenField.py (97%) rename cd3_automation_toolkit/{SDDC => ocicloud/python/sddc}/templates/sddc-cluster-template (100%) rename cd3_automation_toolkit/{SDDC => ocicloud/python/sddc}/templates/sddc-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/security/__init__.py rename cd3_automation_toolkit/{Security/CloudGuard => ocicloud/python/security/cloudguard}/__init__.py (100%) rename cd3_automation_toolkit/{Security/CloudGuard => ocicloud/python/security/cloudguard}/enable_terraform_cloudguard.py (95%) rename cd3_automation_toolkit/{Security/CloudGuard => ocicloud/python/security/cloudguard}/templates/cloud-guard-config-template (100%) rename cd3_automation_toolkit/{Security/CloudGuard => ocicloud/python/security/cloudguard}/templates/cloud-guard-target-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/__init__.py (94%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/clone_firewallpolicy.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/cloneexport_firewallpolicy_nonGreenField.py (95%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/delete_firewallpolicy.py (95%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/export_firewall_nonGreenField.py (92%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/export_firewallpolicy_nonGreenField.py (87%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fw_create.py (92%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create.py (93%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_address.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_applicationlist.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_apps.py (98%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_decryptionprofile.py (93%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_decryptrules.py (97%) create mode 100644 cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_natrules.py rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_secret.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_secrules.py (98%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_service.py (98%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_servicelist.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_tunnelinspection.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/fwpolicy_create_urllist.py (97%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/firewall-policies-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/firewalls-template (96%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-addresslists-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-applicationlists-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-apps-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-decryptionprofiles-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-decryptrules-template (98%) create mode 100644 cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-natrules-template rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-secrets-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-secrules-template (99%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-servicelists-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-services-template (100%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-tunnelinspect-template (81%) rename cd3_automation_toolkit/{Security/Firewall => ocicloud/python/security/firewall}/templates/policy-urllists-template (100%) rename cd3_automation_toolkit/{Security/KeyVault => ocicloud/python/security/keyvault}/__init__.py (100%) rename cd3_automation_toolkit/{Security/KeyVault => ocicloud/python/security/keyvault}/create_terraform_keyvaults.py (97%) rename cd3_automation_toolkit/{Security/KeyVault => ocicloud/python/security/keyvault}/export_keyvaults_nonGreenField.py (99%) rename cd3_automation_toolkit/{Security/KeyVault => ocicloud/python/security/keyvault}/templates/keys-template (100%) rename cd3_automation_toolkit/{Security/KeyVault => ocicloud/python/security/keyvault}/templates/vaults-template (100%) create mode 100644 cd3_automation_toolkit/ocicloud/python/storage/__init__.py rename cd3_automation_toolkit/{Storage/BlockVolume => ocicloud/python/storage/blockvolume}/__init__.py (100%) rename cd3_automation_toolkit/{Storage/BlockVolume => ocicloud/python/storage/blockvolume}/create_terraform_block_volumes.py (98%) rename cd3_automation_toolkit/{Storage/BlockVolume => ocicloud/python/storage/blockvolume}/export_blockvolumes_nonGreenField.py (97%) rename cd3_automation_toolkit/{Storage/BlockVolume => ocicloud/python/storage/blockvolume}/templates/blockvolumes-template (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/__init__.py (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/create_terraform_fss.py (98%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/export_fss_nonGreenField.py (98%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/templates/export-options-template (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/templates/export-resource-template (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/templates/fss-replication-template (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/templates/fss-template (100%) rename cd3_automation_toolkit/{Storage/FileSystem => ocicloud/python/storage/filesystem}/templates/mount-target-template (100%) rename cd3_automation_toolkit/{Storage/ObjectStorage => ocicloud/python/storage/objectstorage}/__init__.py (100%) rename cd3_automation_toolkit/{Storage/ObjectStorage => ocicloud/python/storage/objectstorage}/create_terraform_oss.py (98%) rename cd3_automation_toolkit/{Storage/ObjectStorage => ocicloud/python/storage/objectstorage}/export_terraform_oss.py (96%) rename cd3_automation_toolkit/{Storage/ObjectStorage => ocicloud/python/storage/objectstorage}/templates/oss-template (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/README.md (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/adb.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/backend.tf (96%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/block-volume.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/budget.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/cloud-guard.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/database-exacs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/dbsystem-vm-bm.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/dedicated-vm-host.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/dns.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/firewall.tf (87%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/fss.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/identity.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/instance.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/kms.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/loadbalancer.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/managementservices.tf (84%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/dedicated-vm-host/main.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/dedicated-vm-host/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/dedicated-vm-host/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/instance/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/instance/main.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/instance/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/compute/instance/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget-alert-rule/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/compute/dedicated-vm-host => ocicloud/terraform/modules/costmanagement/budget-alert-rule}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget-alert-rule/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget-alert-rule/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/compute/instance => ocicloud/terraform/modules/costmanagement/budget}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/costmanagement/budget/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/adb/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/adb/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/costmanagement/budget-alert-rule => ocicloud/terraform/modules/database/adb}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/adb/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/adb/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/dbsystem-vm-bm/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/dbsystem-vm-bm/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/costmanagement/budget => ocicloud/terraform/modules/database/dbsystem-vm-bm}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/dbsystem-vm-bm/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/dbsystem-vm-bm/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-infra/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/adb => ocicloud/terraform/modules/database/exa-infra}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-infra/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-infra/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-vmcluster/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-vmcluster/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/dbsystem-vm-bm => ocicloud/terraform/modules/database/exa-vmcluster}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-vmcluster/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/exa-vmcluster/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-configuration/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-configuration/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/exa-infra => ocicloud/terraform/modules/database/mysql-configuration}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-configuration/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-configuration/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-dbsystem/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-dbsystem/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/exa-vmcluster => ocicloud/terraform/modules/database/mysql-dbsystem}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-dbsystem/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/database/mysql-dbsystem/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/quota-policy/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/mysql-configuration => ocicloud/terraform/modules/governance/quota-policy}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/quota-policy/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/quota-policy/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-default/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/database/mysql-dbsystem => ocicloud/terraform/modules/governance/tagging/tag-default}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-default/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-default/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-key/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/governance/quota-policy => ocicloud/terraform/modules/governance/tagging/tag-key}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-key/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-key/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-namespace/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/governance/tagging/tag-default => ocicloud/terraform/modules/governance/tagging/tag-namespace}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-namespace/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/governance/tagging/tag-namespace/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-compartment/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/governance/tagging/tag-key => ocicloud/terraform/modules/identity/iam-compartment}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-compartment/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-compartment/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-group/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-group/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/governance/tagging/tag-namespace => ocicloud/terraform/modules/identity/iam-group}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-group/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-group/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-network-sources/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/iam-compartment => ocicloud/terraform/modules/identity/iam-network-sources}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-network-sources/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-network-sources/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-policy/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/iam-group => ocicloud/terraform/modules/identity/iam-policy}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-policy/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-policy/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-user/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-user/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/iam-network-sources => ocicloud/terraform/modules/identity/iam-user}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-user/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/iam-user/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-group/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-group/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/iam-policy => ocicloud/terraform/modules/identity/identity-domain-group}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-group/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-group/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-user/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-user/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/iam-user => ocicloud/terraform/modules/identity/identity-domain-user}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-user/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/identity/identity-domain-user/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/public-ip-pool/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/identity-domain-group => ocicloud/terraform/modules/ip/public-ip-pool}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/public-ip-pool/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/public-ip-pool/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/reserved-public-ip/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/identity/identity-domain-user => ocicloud/terraform/modules/ip/reserved-public-ip}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/reserved-public-ip/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/reserved-public-ip/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/secondary-private-ip/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/ip/public-ip-pool => ocicloud/terraform/modules/ip/secondary-private-ip}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/secondary-private-ip/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/ip/secondary-private-ip/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend-set/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/ip/reserved-public-ip => ocicloud/terraform/modules/loadbalancer/lb-backend-set}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend-set/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend-set/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/ip/secondary-private-ip => ocicloud/terraform/modules/loadbalancer/lb-backend}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-backend/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-certificate/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-backend-set => ocicloud/terraform/modules/loadbalancer/lb-certificate}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-certificate/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-certificate/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-cipher-suite/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-backend => ocicloud/terraform/modules/loadbalancer/lb-cipher-suite}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-cipher-suite/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-cipher-suite/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-hostname/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-certificate => ocicloud/terraform/modules/loadbalancer/lb-hostname}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-hostname/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-hostname/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-listener/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-cipher-suite => ocicloud/terraform/modules/loadbalancer/lb-listener}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-listener/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-listener/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-load-balancer/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-load-balancer/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-hostname => ocicloud/terraform/modules/loadbalancer/lb-load-balancer}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-load-balancer/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-load-balancer/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-path-route-set/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-listener => ocicloud/terraform/modules/loadbalancer/lb-path-route-set}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-path-route-set/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-path-route-set/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-routing-policy/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-load-balancer => ocicloud/terraform/modules/loadbalancer/lb-routing-policy}/oracle_provider_req.tf (100%) mode change 100644 => 100755 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-routing-policy/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-routing-policy/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-rule-set/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-path-route-set => ocicloud/terraform/modules/loadbalancer/lb-rule-set}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-rule-set/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/loadbalancer/lb-rule-set/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/alarm/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-routing-policy => ocicloud/terraform/modules/managementservices/alarm}/oracle_provider_req.tf (100%) mode change 100755 => 100644 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/alarm/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/alarm/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/event/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/loadbalancer/lb-rule-set => ocicloud/terraform/modules/managementservices/event}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/event/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/event/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log-group/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/alarm => ocicloud/terraform/modules/managementservices/log-group}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log-group/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log-group/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/event => ocicloud/terraform/modules/managementservices/log}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/log/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/notification-topic => ocicloud/terraform/modules/managementservices/notification}/main.tf (54%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/log-group => ocicloud/terraform/modules/managementservices/notification}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/notification-topic => ocicloud/terraform/modules/managementservices/notification}/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/notification-topic => ocicloud/terraform/modules/managementservices/notification}/variables.tf (91%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/service-connector/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/service-connector/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/log => ocicloud/terraform/modules/managementservices/service-connector}/oracle_provider_req.tf (100%) mode change 100644 => 100755 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/service-connector/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/managementservices/service-connector/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/custom-dhcp/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/notification-subscription => ocicloud/terraform/modules/network/custom-dhcp}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/custom-dhcp/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/custom-dhcp/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/default-dhcp/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/notification-topic => ocicloud/terraform/modules/network/default-dhcp}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/default-dhcp/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/default-dhcp/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/dns_resolver/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/managementservices/service-connector => ocicloud/terraform/modules/network/dns/dns_resolver}/oracle_provider_req.tf (100%) mode change 100755 => 100644 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/dns_resolver/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/dns_resolver/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/rrset/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/custom-dhcp => ocicloud/terraform/modules/network/dns/rrset}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/rrset/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/rrset/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/view/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/default-dhcp => ocicloud/terraform/modules/network/dns/view}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/view/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/view/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/zone/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/dns/dns_resolver => ocicloud/terraform/modules/network/dns/zone}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/zone/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/dns/zone/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-attachment/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/dns/rrset => ocicloud/terraform/modules/network/drg-attachment}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-attachment/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-attachment/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution-statement/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/dns/view => ocicloud/terraform/modules/network/drg-route-distribution-statement}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution-statement/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution-statement/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/dns/zone => ocicloud/terraform/modules/network/drg-route-distribution}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-distribution/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-rule/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg-attachment => ocicloud/terraform/modules/network/drg-route-rule}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-rule/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-rule/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-table/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg-route-distribution-statement => ocicloud/terraform/modules/network/drg-route-table}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-table/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg-route-table/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg-route-distribution => ocicloud/terraform/modules/network/drg}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/drg/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/igw/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg-route-rule => ocicloud/terraform/modules/network/igw}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/igw/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/igw/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/lpg/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg-route-table => ocicloud/terraform/modules/network/lpg}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/lpg/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/lpg/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/ngw/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/drg => ocicloud/terraform/modules/network/ngw}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/ngw/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/ngw/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg-rule/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/igw => ocicloud/terraform/modules/network/nsg-rule}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg-rule/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg-rule/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/lpg => ocicloud/terraform/modules/network/nsg}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/nsg/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/route-table/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/ngw => ocicloud/terraform/modules/network/route-table}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/route-table/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/route-table/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sec-list/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/nsg-rule => ocicloud/terraform/modules/network/sec-list}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sec-list/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sec-list/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sgw/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/nsg => ocicloud/terraform/modules/network/sgw}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sgw/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/sgw/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/subnet/main.tf (90%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/route-table => ocicloud/terraform/modules/network/subnet}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/subnet/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/subnet/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vcn/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/sec-list => ocicloud/terraform/modules/network/vcn}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vcn/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vcn/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vlan/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vlan/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/sgw => ocicloud/terraform/modules/network/vlan}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vlan/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/network/vlan/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backend/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backend/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/subnet => ocicloud/terraform/modules/networkloadbalancer/nlb-backend}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backend/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backend/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backendset/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/vcn => ocicloud/terraform/modules/networkloadbalancer/nlb-backendset}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backendset/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-backendset/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-listener/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/network/vlan => ocicloud/terraform/modules/networkloadbalancer/nlb-listener}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-listener/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb-listener/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/networkloadbalancer/nlb-backend => ocicloud/terraform/modules/networkloadbalancer/nlb}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/networkloadbalancer/nlb/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/cluster/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/cluster/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/networkloadbalancer/nlb-backendset => ocicloud/terraform/modules/oke/cluster}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/cluster/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/cluster/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/nodepool/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/nodepool/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/networkloadbalancer/nlb-listener => ocicloud/terraform/modules/oke/nodepool}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/nodepool/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/nodepool/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/virtual-nodepool/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/virtual-nodepool/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/networkloadbalancer/nlb => ocicloud/terraform/modules/oke/virtual-nodepool}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/virtual-nodepool/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/oke/virtual-nodepool/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc-cluster/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/oke/cluster => ocicloud/terraform/modules/sddc/sddc-cluster}/oracle_provider_req.tf (100%) mode change 100644 => 100755 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc-cluster/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc-cluster/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/oke/nodepool => ocicloud/terraform/modules/sddc/sddc}/oracle_provider_req.tf (100%) mode change 100644 => 100755 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/sddc/sddc/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-configuration/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/oke/virtual-nodepool => ocicloud/terraform/modules/security/cloud-guard-configuration}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-configuration/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-configuration/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-target/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-target/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/sddc/sddc-cluster => ocicloud/terraform/modules/security/cloud-guard-target}/oracle_provider_req.tf (100%) mode change 100755 => 100644 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-target/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/cloud-guard-target/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/address-list/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/address-list/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/sddc/sddc => ocicloud/terraform/modules/security/firewall/address-list}/oracle_provider_req.tf (100%) mode change 100755 => 100644 rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/address-list/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/address-list/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application-group/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application-group/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/cloud-guard-configuration => ocicloud/terraform/modules/security/firewall/application-group}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application-group/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application-group/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/cloud-guard-target => ocicloud/terraform/modules/security/firewall/application}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/application/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-profile/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-profile/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/address-list => ocicloud/terraform/modules/security/firewall/decryption-profile}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-profile/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-profile/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-rules/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-rules/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/application-group => ocicloud/terraform/modules/security/firewall/decryption-rules}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-rules/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/decryption-rules/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall-policy/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/application => ocicloud/terraform/modules/security/firewall/firewall-policy}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall-policy/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall-policy/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall/main.tf (90%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/decryption-profile => ocicloud/terraform/modules/security/firewall/firewall}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/firewall/variable.tf (94%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/security-rules => ocicloud/terraform/modules/security/firewall/nat-rules}/data.tf (100%) create mode 100644 cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/main.tf rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/decryption-rules => ocicloud/terraform/modules/security/firewall/nat-rules}/oracle_provider_req.tf (100%) create mode 100755 cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/output.tf create mode 100644 cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/variable.tf rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/secret/data.tf (94%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/secret/main.tf (92%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/firewall-policy => ocicloud/terraform/modules/security/firewall/secret}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/secret/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/secret/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/service => ocicloud/terraform/modules/security/firewall/security-rules}/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/security-rules/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/firewall => ocicloud/terraform/modules/security/firewall/security-rules}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/security-rules/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/security-rules/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service-list/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service-list/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/secret => ocicloud/terraform/modules/security/firewall/service-list}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service-list/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service-list/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/tunnel-inspect => ocicloud/terraform/modules/security/firewall/service}/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/security-rules => ocicloud/terraform/modules/security/firewall/service}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/service/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/url-list => ocicloud/terraform/modules/security/firewall/tunnel-inspect}/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/tunnel-inspect/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/service-list => ocicloud/terraform/modules/security/firewall/tunnel-inspect}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/tunnel-inspect/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/tunnel-inspect/variable.tf (100%) create mode 100644 cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/data.tf rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/url-list/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/service => ocicloud/terraform/modules/security/firewall/url-list}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/url-list/output.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/firewall/url-list/variable.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/key/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/tunnel-inspect => ocicloud/terraform/modules/security/key}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/key/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/key/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/vault/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/firewall/url-list => ocicloud/terraform/modules/security/vault}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/vault/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/security/vault/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/block-volume/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/block-volume/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/key => ocicloud/terraform/modules/storage/block-volume}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/block-volume/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/block-volume/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/export-option/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/security/vault => ocicloud/terraform/modules/storage/file-storage/export-option}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/export-option/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/export-option/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss-replication/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/block-volume => ocicloud/terraform/modules/storage/file-storage/fss-replication}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss-replication/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss-replication/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/file-storage/export-option => ocicloud/terraform/modules/storage/file-storage/fss}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/fss/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/mount-target/data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/mount-target/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/file-storage/fss-replication => ocicloud/terraform/modules/storage/file-storage/mount-target}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/mount-target/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/file-storage/mount-target/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/object-storage/main.tf (100%) rename cd3_automation_toolkit/{user-scripts/terraform/modules/storage/file-storage/fss => ocicloud/terraform/modules/storage/object-storage}/oracle_provider_req.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/object-storage/outputs.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/modules/storage/object-storage/variables.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/mysql-dbsystem.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/network.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/networkloadbalancer.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/nsg.tf (93%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/object-storage.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/oci-data.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/oke.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/provider.tf (96%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/quota.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/scripts/bastion-ssh-key (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/scripts/default.sh (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/scripts/default.yaml (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/scripts/server-ssh-key (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/sddc.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/tagging.tf (100%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/variables_example.tf (99%) rename cd3_automation_toolkit/{user-scripts => ocicloud}/terraform/vlan.tf (100%) create mode 100644 cd3_automation_toolkit/setUpAzure.properties create mode 100644 cd3_automation_toolkit/setUpCloud.py create mode 100644 cd3_automation_toolkit/user-scripts/.outdir_structure_file.properties create mode 100644 cd3_automation_toolkit/user-scripts/connectAzure.py create mode 100644 cd3_automation_toolkit/user-scripts/connectGCP.py create mode 100644 cd3_automation_toolkit/user-scripts/setUpAzure.py delete mode 100644 cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/main.tf delete mode 100644 cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/outputs.tf delete mode 100644 cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/variables.tf diff --git a/Dockerfile b/Dockerfile deleted file mode 100755 index 81d5956f0..000000000 --- a/Dockerfile +++ /dev/null @@ -1,107 +0,0 @@ -FROM oraclelinux:9-slim -LABEL maintainer="Team at Oracle" -LABEL description="OCI format to generate CD3 image" - - -########### Input Parameters for image creation ############ -# UID of user on underlying OS. eg 503 for Mac -ARG USER_UID=1001 -# Whether to download Jenkins as part of image creation -ARG USE_DEVOPS=YES -############################################################# - - -ARG USERNAME=cd3user -ARG USER_GID=$USER_UID -# Whether to download Provider as part of image creation -ARG DOWNLOAD_PROVIDER=NO -# TF Provider version -ARG TF_OCI_PROVIDER=7.8.0 -ARG TF_NULL_PROVIDER=3.2.3 - -RUN microdnf install -y sudo && \ - groupadd --gid $USER_GID $USERNAME && \ - useradd --uid $USER_UID --gid $USER_GID -d /$USERNAME -m $USERNAME && \ - echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \ - chmod 0440 /etc/sudoers.d/$USERNAME && \ - mkdir -p /cd3user/tenancies && \ - chown -R $USERNAME:$USERNAME /cd3user/tenancies/ && \ - microdnf install -y vim && \ - microdnf install -y dnf && \ - microdnf install -y wget && \ - microdnf install -y unzip && \ - microdnf install -y graphviz && \ - ln -sf /usr/bin/python3 /usr/bin/python && \ - echo 'alias vi="vim"' >> /etc/bashrc - -USER $USERNAME -WORKDIR /cd3user/oci_tools/ -COPY cd3_automation_toolkit cd3_automation_toolkit/ -COPY othertools othertools/ - -WORKDIR /cd3user/ - -RUN sudo dnf install -y oraclelinux-release-el9 && \ -sudo chown -R $USERNAME:$USERNAME /cd3user/ && \ -sudo sed -i -e 's/\r$//' /cd3user/oci_tools/cd3_automation_toolkit/shell_script.sh && \ -bash /cd3user/oci_tools/cd3_automation_toolkit/shell_script.sh && \ -sudo dnf clean all && \ -sudo rm -rf /var/cache/dnf && \ -sudo chmod -R 740 /cd3user/ && \ -sudo chown -R cd3user:cd3user /cd3user/ - - -RUN if [ "$DOWNLOAD_PROVIDER" == "YES" ]; then \ -# oci provider -sudo wget https://releases.hashicorp.com/terraform-provider-oci/${TF_OCI_PROVIDER}/terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip && \ -sudo mkdir -p /cd3user/.terraform.d/plugins/registry.terraform.io/oracle/oci/${TF_OCI_PROVIDER}/linux_amd64 && \ -sudo unzip terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip -d /cd3user/.terraform.d/plugins/registry.terraform.io/oracle/oci/${TF_OCI_PROVIDER}/linux_amd64 && \ -# null provider -sudo wget https://releases.hashicorp.com/terraform-provider-null/${TF_NULL_PROVIDER}/terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip && \ -sudo mkdir -p /cd3user/.terraform.d/plugins/registry.terraform.io/hashicorp/null/${TF_NULL_PROVIDER}/linux_amd64 && \ -sudo unzip terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip -d /cd3user/.terraform.d/plugins/registry.terraform.io/hashicorp/null/${TF_NULL_PROVIDER}/linux_amd64 && \ -sudo cp -r /cd3user/.terraform.d/plugins/registry.terraform.io /cd3user/.terraform.d/plugins/registry.opentofu.org && \ -sudo chown -R cd3user:cd3user /cd3user/ && \ -sudo rm -rf terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip ;\ - -fi - -##################################### START INSTALLING JENKINS ################################### -ARG JENKINS_VERSION=2.504.1 -ARG JENKINS_SHA=81026db18b0c4aad6b62cf408e4c42e5797661b41c517b37df606238e89b9df1 -ARG JENKINS_PLUGIN_MANAGER_VERSION=2.12.13 -ARG PLUGIN_CLI_URL=https://github.com/jenkinsci/plugin-installation-manager-tool/releases/download/${JENKINS_PLUGIN_MANAGER_VERSION}/jenkins-plugin-manager-${JENKINS_PLUGIN_MANAGER_VERSION}.jar - -ARG JENKINS_HOME=/cd3user/tenancies/jenkins_home -ARG JENKINS_INSTALL=/usr/share/jenkins -ARG REF=/usr/share/jenkins/ref - -ENV USE_DEVOPS ${USE_DEVOPS} -ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk -ENV JENKINS_HOME ${JENKINS_HOME} -ENV JENKINS_INSTALL ${JENKINS_INSTALL} -ENV REF ${REF} -ENV JENKINS_UC https://updates.jenkins.io -ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental -ENV JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals -ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false" -ENV COPY_REFERENCE_FILE_LOG ${JENKINS_HOME}/copy_reference_file.log -ENV CASC_JENKINS_CONFIG ${JENKINS_HOME}/jcasc.yaml -COPY --chown=cd3user:cd3user jenkins_install ${JENKINS_INSTALL}/ -COPY --chown=cd3user:cd3user jenkins_install/init/*.groovy ${REF}/init.groovy.d/ -COPY --chown=cd3user:cd3user jenkins_install/plugins.txt ${REF}/plugins.txt - - -RUN if [ "$USE_DEVOPS" == "YES" ]; then \ - sudo microdnf install -y java-21-openjdk && \ - sudo microdnf install -y java-21-openjdk-devel && \ - sudo microdnf install git-2.39.3 -y && \ - sudo mkdir -p ${REF}/init.groovy.d && \ - sudo chown -R cd3user:cd3user ${JENKINS_INSTALL} && \ - sudo curl -fsSL http://updates.jenkins-ci.org/download/war/${JENKINS_VERSION}/jenkins.war -o ${JENKINS_INSTALL}/jenkins.war && \ - echo "${JENKINS_SHA} ${JENKINS_INSTALL}/jenkins.war" | sha256sum -c - && \ - sudo curl -fsSL ${PLUGIN_CLI_URL} -o ${JENKINS_INSTALL}/jenkins-plugin-manager.jar && \ - sudo java -jar ${JENKINS_INSTALL}/jenkins-plugin-manager.jar --war ${JENKINS_INSTALL}/jenkins.war --verbose -f ${REF}/plugins.txt && \ - sudo chown -R cd3user:cd3user ${JENKINS_INSTALL} && \ - sudo chmod +x ${JENKINS_INSTALL}/jenkins.sh ; \ - fi diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 66b3e2541..657aeca4b 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -1,7 +1,8 @@ #!/bin/bash username=cd3user -sudo mkdir -p /$username/mount_path +sudo mkdir -p /$username/mount_path/tenancies +sudo mkdir -p /$username/mount_path/oci_tools logfile="/$username/mount_path/installToolkit.log" toolkit_dir="/tmp/githubCode" tenancyconfig_properties="$toolkit_dir/cd3_automation_toolkit/user-scripts/tenancyconfig.properties" @@ -67,6 +68,8 @@ sudo podman --version >> $logfile 2>&1 || true echo "***Download Toolkit***" >> $logfile 2>&1 sudo git clone https://github.com/oracle-devrel/cd3-automation-toolkit.git $toolkit_dir >> $logfile 2>&1 +cp -r $toolkit_dir/cd3_automation_toolkit /cd3user/oci_tools/ +cp -r $toolkit_dir/othertools /cd3user/oci_tools/ stop_exec curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/ -o /tmp/metadata.json @@ -99,4 +102,4 @@ duration_sec=$(echo "$(date +%s.%N) - $start" | bc) duration_min=$(echo "$duration_sec%3600/60" | bc) execution_time=`printf "%.2f seconds" $duration_sec` echo "Script Execution Time in Seconds: $execution_time" >> $logfile 2>&1 -echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 +echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 \ No newline at end of file diff --git a/cd3_automation_toolkit/CostManagement/__init__.py b/cd3_automation_toolkit/CostManagement/__init__.py deleted file mode 100644 index 2c187a105..000000000 --- a/cd3_automation_toolkit/CostManagement/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .Budget import * \ No newline at end of file diff --git a/cd3_automation_toolkit/DeveloperServices/__init__.py b/cd3_automation_toolkit/DeveloperServices/__init__.py deleted file mode 100644 index 006227503..000000000 --- a/cd3_automation_toolkit/DeveloperServices/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 - -from .ResourceManager import * -from .OKE import * - diff --git a/cd3_automation_toolkit/Governance/__init__.py b/cd3_automation_toolkit/Governance/__init__.py deleted file mode 100644 index b755e9d6c..000000000 --- a/cd3_automation_toolkit/Governance/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - - -from .Tagging import * -from .Quota import * - diff --git a/cd3_automation_toolkit/Identity/__init__.py b/cd3_automation_toolkit/Identity/__init__.py deleted file mode 100644 index c9ed93a69..000000000 --- a/cd3_automation_toolkit/Identity/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -from .Compartments import create_terraform_compartments -from .Users import create_terraform_users -from .Groups import create_terraform_groups -from .Policies import create_terraform_policies -from .export_identity_nonGreenField import export_identity -from .NetworkSources import export_networkSources -from .NetworkSources import create_terraform_networkSources -from .Users import export_users diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-subscriptions-template b/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-subscriptions-template deleted file mode 100644 index 326111ac2..000000000 --- a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-subscriptions-template +++ /dev/null @@ -1,57 +0,0 @@ -{% if skeleton %} -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. -# -############################ -# ManagementServices -# Notifications_Subscriptions - tfvars -# Allowed Values: -# topic_id can be ocid or the key of notifications_topics (map) -# compartment_id can be the ocid or the name of the compartment hierarchy delimited by double hiphens "--" -# Example : compartment_id = "ocid1.compartment.oc1..aaaaaaaahwwiefb56epvdlzfic6ah6jy3xf3c" or compartment_id = "Security--Prod" where "Security" is the parent of "Prod" compartment -############################ - -notifications_subscriptions = { - ##Add New Subscriptions for {{ region|lower }} here## -} -{% else %} - {{ subscription_tf_name }} = { - subscription_name = "{{ subscription_tf_name }}" - compartment_id = "{{ compartment_tf_name }}" - endpoint = "{{ endpoint }}" - protocol = "{{ protocol }}" - topic_id = "{{ topic_tf_name }}" - - {# ##Do not modify below this line## #} - {# #} - {# ###Section for adding Defined and Freeform Tags### #} - {% if subscription_defined_tags and subscription_defined_tags != 'nan' and subscription_defined_tags != '' and subscription_defined_tags != [['nan']] %} - {% if subscription_defined_tags[0] %} - defined_tags = { - {% for tags in subscription_defined_tags %} - {% if not loop.last %} - "{{ tags[0] }}"= "{{ tags[1] }}" , - {% else %} - "{{ tags[0] }}"= "{{ tags[1] }}" - {% endif %} - {% endfor %} - } - {% endif %} - {% endif %} - {% if subscription_freeform_tags and subscription_freeform_tags != 'nan' and subscription_freeform_tags != '' and subscription_freeform_tags != [['nan']] %} - {% if subscription_freeform_tags[0] %} - freeform_tags = { - {% for tags in subscription_freeform_tags %} - {% if not loop.last %} - "{{ tags[0] }}"="{{ tags[1] }}", - {% else %} - "{{ tags[0] }}"="{{ tags[1] }}" - {% endif %} - {% endfor %} - } - {% endif %} - {% endif %} - {# ###Section for adding Defined and Freeform Tags ends here### #} - }, - -{% endif %} \ No newline at end of file diff --git a/cd3_automation_toolkit/ManagementServices/__init__.py b/cd3_automation_toolkit/ManagementServices/__init__.py deleted file mode 100755 index 320106094..000000000 --- a/cd3_automation_toolkit/ManagementServices/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .EventsAndNotifications import * -from .Monitoring import * -from .Logging import * -from .ServiceConnectorHub import * \ No newline at end of file diff --git a/cd3_automation_toolkit/Network/__init__.py b/cd3_automation_toolkit/Network/__init__.py deleted file mode 100644 index 6e0889176..000000000 --- a/cd3_automation_toolkit/Network/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -from .BaseNetwork import * -from .LoadBalancers import * -from .DNS import * -from .Global import * -#from .IPManagement import * \ No newline at end of file diff --git a/cd3_automation_toolkit/Release-Notes b/cd3_automation_toolkit/Release-Notes index 171cfd696..0d56c0f26 100644 --- a/cd3_automation_toolkit/Release-Notes +++ b/cd3_automation_toolkit/Release-Notes @@ -1,3 +1,15 @@ +------------------------------------- +CD3 Automation Toolkit Tag v2025.2.0 +Oct 9th, 2025 +------------------------------------- +1. MultiCloud Support - Create and Export ADB @Azure using CD3. Documentation Link - +2. Support full functionality of OCI Network Firewall using CD3. +3. Upgrade ADB Excel and Terraform to support all features. +4. Notifications terraform performance tuning. +4. Support for IPv6 under networking. +4. Bug fixes wrt terraform for identity + + ------------------------------------- CD3 Automation Toolkit Tag v2025.1.4 Sep 17th, 2025 diff --git a/cd3_automation_toolkit/Security/__init__.py b/cd3_automation_toolkit/Security/__init__.py deleted file mode 100644 index ae781f9cf..000000000 --- a/cd3_automation_toolkit/Security/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from .CloudGuard import * -from .KeyVault import * -from .Firewall import * - diff --git a/cd3_automation_toolkit/Storage/__init__.py b/cd3_automation_toolkit/Storage/__init__.py deleted file mode 100644 index d14dd28ed..000000000 --- a/cd3_automation_toolkit/Storage/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from .BlockVolume import * -from .FileSystem import * -from .ObjectStorage import * - diff --git a/cd3_automation_toolkit/__init__.py b/cd3_automation_toolkit/__init__.py deleted file mode 100644 index 84c6c55a8..000000000 --- a/cd3_automation_toolkit/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 - -from .cd3Validator import validate_cd3 -from .cd3FirewallValidator import validate_firewall_cd3 - diff --git a/cd3_automation_toolkit/azurecloud/__init__.py b/cd3_automation_toolkit/azurecloud/__init__.py new file mode 100644 index 000000000..5f7ce86af --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/python/__init__.py b/cd3_automation_toolkit/azurecloud/python/__init__.py new file mode 100644 index 000000000..6332da756 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +from .azrCommonTools import * +from .database import * \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/python/azrCommonTools.py b/cd3_automation_toolkit/azurecloud/python/azrCommonTools.py new file mode 100644 index 000000000..f5f40cd9b --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/azrCommonTools.py @@ -0,0 +1,84 @@ + + +from typing import Dict +from common.python.commonTools import * +from typing import Dict, Optional +import os +# Azure SDKs +try: + from azure.identity import ClientSecretCredential + from azure.core.exceptions import HttpResponseError + +except ImportError as e: + raise ImportError( + "Missing Azure SDK packages. Install with:\n" + " pip install azure-identity azure-mgmt-oracledatabase\n" + ) + + + +def _read_properties_file(filepath: str) -> Dict[str, str]: + """Read key=value pairs from setUpAzure.properties into a dict.""" + if not os.path.exists(filepath): + raise FileNotFoundError(f"Azure properties file not found: {filepath}") + props: Dict[str, str] = {} + with open(filepath, "r", encoding="utf-8") as f: + for raw in f: + line = raw.strip() + if not line or line.startswith("#"): + continue + if "=" not in line: + continue + k, v = line.split("=", 1) + props[k.strip()] = v.strip() + required = ["subscription_id", "tenant_id", "client_id", "client_secret"] + missing = [k for k in required if not props.get(k)] + if missing: + return "Missing required Azure credentials in {filepath}: {', '.join(missing)}" + + return props + + +class azrCommonTools(): + tagColumns = {'common tags', 'common_tags'} + def authenticate(self,azure_properties_file): + # Azure credential & client + az = _read_properties_file(azure_properties_file) + if "Missing required" in az: + print("\nCannot run export workflow as authentication parameters are missing!!\n") + exit() + credential = ClientSecretCredential( + tenant_id=az["tenant_id"], + client_id=az["client_id"], + client_secret=az["client_secret"], + ) + credentials=[credential,az["subscription_id"]] + return credentials + + def split_tag_values(columnname, columnvalue, tempdict): + columnvalue = columnvalue.replace("\n", "") + if ";" in columnvalue: + # If there are more than one tag; split them by ";" and "=" + + columnname = commonTools.check_column_headers(columnname) + multivalues = columnvalue.split(";") + multivalues = [part.split("=") for part in multivalues if part] + + tempdict = {columnname: multivalues} + else: + # If there is only one tag; split them only by "="; each key-value pair is stored as a list + columnname = commonTools.check_column_headers(columnname) + multivalues = columnvalue.split("=") + multivalues = [str(part).strip() for part in multivalues if part] + + tempdict = {columnname: [multivalues]} + return tempdict + + def _flatten_tags(tags: Optional[Dict[str, str]]) -> str: + if not tags: + return "" + try: + return ";".join([f"{k}={v}" for k, v in tags.items() if v is not None]) + except Exception: + return "" + diff --git a/cd3_automation_toolkit/azurecloud/python/database/__init__.py b/cd3_automation_toolkit/azurecloud/python/database/__init__.py new file mode 100644 index 000000000..1952d113f --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +from .create_terraform_adb_azure import create_terraform_adb_azure +from .export_adb_azure import export_adb_azure +from .create_terraform_exa_infra_azure import create_terraform_exa_infra_azure +from .create_terraform_exa_vmclusters_azure import create_terraform_exa_vmclusters_azure + diff --git a/cd3_automation_toolkit/azurecloud/python/database/create_terraform_adb_azure.py b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_adb_azure.py new file mode 100644 index 000000000..38371a071 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_adb_azure.py @@ -0,0 +1,134 @@ +#!/usr/bin/python3 +# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# +# This script will produce a Terraform file that will be used to set up OCI Database +# Autonomous Database @Azure +# +# Author: Suruchi +# Oracle Consulting +# +import os +import sys +from jinja2 import Environment, FileSystemLoader +from pathlib import Path +sys.path.append(os.getcwd()+"/..") +from common.python.commonTools import * +import azurecloud.python.azrCommonTools as azrCommonTools + + +###### +# Required Inputs- CD3 excel file, prefix AND outdir +###### +# Execution of the code begins here +def create_terraform_adb_azure(inputfile, outdir, prefix): + + filename = inputfile + sheetName = "ADB-Azure" + resource=sheetName.lower() + auto_tfvars_filename = prefix + '_' + sheetName.lower() + '.auto.tfvars' + + # Load the template file + file_loader = FileSystemLoader(f'{Path(__file__).parent}/templates') + env = Environment(loader=file_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True) + template = env.get_template('adb-azure-template') + + tfStr='' + + + # Read cd3 using pandas dataframe + df, col_headers = commonTools.read_cd3(filename, sheetName) + #Remove empty rows + df = df.dropna(how='all') + df = df.reset_index(drop=True) + + # List of the column headers + dfcolumns = df.columns.values.tolist() + + # Iterate over rows + for i in df.index: + region = str(df.loc[i, 'Region']).strip() + # Encountered + if (region in commonTools.endNames): + break + + region=region.strip().lower() + + # temporary dictionary1 and dictionary2 + tempStr = {} + tempdict = {} + + # All columns ar mandatory except customer contacts and tags + if (str(df.loc[i, 'Region']).lower() == 'nan' or \ + str(df.loc[i, 'Resource Group Name']).lower() == 'nan' or \ + str(df.loc[i, 'Network Details']).lower() == 'nan' or \ + str(df.loc[i, 'DB Version']).lower() == 'nan'): + print("\nAll fields except Customer Contacts and Common Tags are mandatory. Please enter a value and try again !!") + print("\n** Exiting **") + exit(1) + + + for columnname in dfcolumns: + # Column value + columnvalue = str(df[columnname][i]).strip() + + # Check for boolean/null in column values + columnvalue = commonTools.check_columnvalue(columnvalue) + + # Check for multivalued columns + tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) + + + # Process Defined and Freeform Tags + if columnname.lower() in azrCommonTools.tagColumns: + tempdict = azrCommonTools.split_tag_values(columnname, columnvalue, tempdict) + + if columnname == "ADB Display Name": + display_tf_name = columnvalue.strip() + display_tf_name = commonTools.check_tf_variable(display_tf_name) + tempdict = {'display_tf_name': display_tf_name} + + if columnname == "Resource Group Name": + container_id = columnvalue.strip() + tempdict = {'container_id': container_id} + + + if columnname == 'Database Workload': + autonomous_value = columnvalue.strip().lower() + tempdict = {'autonomous_value': autonomous_value} + + if columnname == "Network Details": + if len(columnvalue.split("@")) == 2: + network_container_id = columnvalue.split("@")[0].strip() + vcn_subnet_name = columnvalue.split("@")[1].strip() + else: + network_container_id = container_id + vcn_subnet_name = columnvalue + + if ("::" not in vcn_subnet_name): + print("Invalid Network Details format specified for row " + str(i + 3) + ". Exiting!!!") + exit(1) + else: + vcn_name = vcn_subnet_name.split("::")[0].strip() + subnet_id = vcn_subnet_name.split("::")[1].strip() + + tempdict = {'network_container_id': network_container_id, 'vnet_name': vcn_name,'subnet_id': subnet_id} + + + columnname = commonTools.check_column_headers(columnname) + tempStr[columnname] = str(columnvalue).strip() + tempStr.update(tempdict) + + # Write all info to TF string + tfStr=tfStr + template.render(tempStr) + + + if(tfStr!=''): + outfile = outdir + "/" + auto_tfvars_filename + commonTools.backup_file(outdir, resource, auto_tfvars_filename) + src = "##Add New ADB @Azure here##" + tfStr= template.render(count=0).replace(src, tfStr + "\n" + src) + tfStr = "".join([s for s in tfStr.strip().splitlines(True) if s.strip("\r\n").strip()]) + oname=open(outfile,'w') + oname.write(tfStr) + oname.close() + print(outfile + " containing TF for ADB @Azure has been created") diff --git a/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_infra_azure.py b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_infra_azure.py new file mode 100644 index 000000000..bdc3778de --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_infra_azure.py @@ -0,0 +1,118 @@ +#!/usr/bin/python3 +# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# +# This script will produce a Terraform file that will be used to set up OCI Database +# Database EXA +# +# Author: Suruchi +# Oracle Consulting +# + +import os +import sys +from jinja2 import Environment, FileSystemLoader +from pathlib import Path +sys.path.append(os.getcwd()+"/..") +from common.python.commonTools import * +import azurecloud.python.azrCommonTools as azrCommonTools + + +###### +# Required Inputs- CD3 excel file, prefix AND outdir +###### +# Execution of the code begins here +def create_terraform_exa_infra_azure(inputfile, outdir, prefix): + + filename = inputfile + sheetName = "EXA-Infra-Azure" + auto_tfvars_filename = prefix + '_' + sheetName.lower() + '.auto.tfvars' + resource = sheetName.lower() + + # Load the template file + file_loader = FileSystemLoader(f'{Path(__file__).parent}/templates') + env = Environment(loader=file_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True) + template = env.get_template('exa-infra-azure-template') + + # Read cd3 using pandas dataframe + df, col_headers = commonTools.read_cd3(filename, sheetName) + + #Remove empty rows + df = df.dropna(how='all') + df = df.reset_index(drop=True) + tfStr = '' + + # List of the column headers + dfcolumns = df.columns.values.tolist() + + # Iterate over rows + for i in df.index: + region = str(df.loc[i, 'Region']).strip() + + # Encountered + if (region in commonTools.endNames): + break + + if region.lower() == 'nan': + continue + + region=region.strip().lower() + + # temporary dictionary1 and dictionary2 + tempStr = {} + tempdict = {} + + # Check if values are entered for mandatory fields + if str(df.loc[i, 'Region']).lower() == 'nan' or \ + str(df.loc[i, 'Resource Group Name']).lower() == 'nan' or \ + str(df.loc[i, 'Exadata Infra Display Name']).lower() == 'nan' or \ + str(df.loc[i, 'Shape']).lower() == 'nan': + print("\nAll fields except Maintenane Window, Customer Contacts and Common Tags are mandatory. Please enter a value and try again !!") + + exit(1) + + #tempdict = {'oracle_db_software_edition' : 'ENTERPRISE_EDITION_EXTREME_PERFORMANCE'} + + for columnname in dfcolumns: + # Column value + columnvalue = str(df[columnname][i]).strip() + + # Check for boolean/null in column values + columnvalue = commonTools.check_columnvalue(columnvalue) + + # Check for multivalued columns + tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) + + + # Process Defined and Freeform Tags + if columnname.lower() in azrCommonTools.tagColumns: + tempdict = azrCommonTools.split_tag_values(columnname, columnvalue, tempdict) + + if columnname == "Exadata Infra Display Name": + display_name = columnvalue.strip() + display_tf_name = commonTools.check_tf_variable(display_name) + tempdict = {'display_name': display_name, 'display_tf_name': display_tf_name} + + if columnname == "Resource Group Name": + container_id = columnvalue.strip() + tempdict = {'container_id': container_id} + + + columnname = commonTools.check_column_headers(columnname) + tempStr[columnname] = str(columnvalue).strip() + tempStr.update(tempdict) + + + # Write all info to TF string + tfStr = tfStr + template.render(tempStr) + + # Write TF string to the file + if (tfStr != ''): + outfile = outdir + "/" + auto_tfvars_filename + commonTools.backup_file(outdir, resource, auto_tfvars_filename) + src = "##Add New Exa-Infra @Azure here##" + tfStr = template.render(count=0).replace(src, tfStr + "\n" + src) + tfStr = "".join([s for s in tfStr.strip().splitlines(True) if s.strip("\r\n").strip()]) + oname = open(outfile, 'w') + oname.write(tfStr) + oname.close() + print(outfile + " containing TF for Exa-Infra @Azure has been created") \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_vmclusters_azure.py b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_vmclusters_azure.py new file mode 100644 index 000000000..ffd857a5b --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/create_terraform_exa_vmclusters_azure.py @@ -0,0 +1,153 @@ +#!/usr/bin/python3 +# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# +# This script will produce a Terraform file that will be used to set up OCI Database +# Database EXA +# +# Author: Kartikey Rajput +# Oracle Consulting +# Modified (TF Upgrade): Kartikey Rajput +# +import os +import sys +from jinja2 import Environment, FileSystemLoader +from pathlib import Path +sys.path.append(os.getcwd()+"/..") +from common.python.commonTools import * +import azurecloud.python.azrCommonTools as azrCommonTools + + +###### +# Required Inputs- CD3 excel file, Config file, prefix AND outdir +###### +# Execution of the code begins here +def create_terraform_exa_vmclusters_azure(inputfile, outdir, prefix): + filename = inputfile + + sheetName = "EXA-VMClusters-Azure" + auto_tfvars_filename = prefix + '_' + sheetName.lower() + '.auto.tfvars' + resource = sheetName.lower() + + + # Load the template file + file_loader = FileSystemLoader(f'{Path(__file__).parent}/templates') + env = Environment(loader=file_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True) + template = env.get_template('exa-vmcluster-azure-template') + + # Read cd3 using pandas dataframe + df, col_headers = commonTools.read_cd3(filename, sheetName) + tfStr = '' + + # Remove empty rows + df = df.dropna(how='all') + df = df.reset_index(drop=True) + + # List of the column headers + dfcolumns = df.columns.values.tolist() + #subnets = parseSubnets(filename) + + + # Iterate over rows + for i in df.index: + region = str(df.loc[i, 'Region']).strip() + + # Encountered + if (region in commonTools.endNames): + break + + if region.lower() == 'nan': + continue + + region = region.strip().lower() + + + # temporary dictionary1 and dictionary2 + tempStr = {} + tempdict = {} + + + # Check if values are entered for mandatory fields + ''' + if str(df.loc[i, 'Region']).lower() == 'nan' or \ + str(df.loc[i, 'Compartment Name']).lower() == 'nan' or \ + str(df.loc[i, 'Exadata Infra Display Name']).lower() == 'nan' or \ + str(df.loc[i, 'VM Cluster Display Name']).lower() == 'nan' or \ + str(df.loc[i, 'Client Network Details']).lower() == 'nan' or \ + str(df.loc[i, 'Backup Network Details']).lower() == 'nan' or \ + str(df.loc[i, 'CPU Core Count']).lower() == 'nan' or \ + str(df.loc[i, 'SSH Key Var Name']).lower() == 'nan' or \ + str(df.loc[i, 'Hostname Prefix']).lower() == 'nan' or \ + str(df.loc[i, 'Oracle Grid Infrastructure Version']).lower() == 'nan': + print("\nRegion, Compartment Name, Exadata Infra Display Name, VM Cluster Display Name, Network Details, CPU Core Count, Hostname Prefix, Oracle Grid Infrastructure Version, SSH Key Var Name are mandatory fields. Please enter a value and try again.......Exiting!!") + exit(1) + ''' + + # tempdict = {'oracle_db_software_edition' : 'ENTERPRISE_EDITION_EXTREME_PERFORMANCE'} + + for columnname in dfcolumns: + # Column value + columnvalue = str(df[columnname][i]).strip() + + # Check for boolean/null in column values + columnvalue = commonTools.check_columnvalue(columnvalue) + + # Check for multivalued columns + tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) + + if columnname == "Resource Group Name": + container_id = columnvalue.strip() + tempdict = {'container_id': container_id} + + if columnname == "VM Cluster Display Name": + display_name = columnvalue.strip() + display_tf_name = commonTools.check_tf_variable(display_name) + tempdict = {'display_tf_name': display_tf_name, 'display_name': display_name} + + if columnname == "Network Details": + if len(columnvalue.split("@")) == 2: + network_container_id = columnvalue.split("@")[0].strip() + vcn_subnet_name = columnvalue.split("@")[1].strip() + else: + network_container_id = container_id + vcn_subnet_name = columnvalue + + if ("::" not in vcn_subnet_name): + print("Invalid Network Details format specified for row " + str(i + 3) + ". Exiting!!!") + exit(1) + else: + vcn_name = vcn_subnet_name.split("::")[0].strip() + subnet_id = vcn_subnet_name.split("::")[1].strip() + + tempdict = {'network_container_id': network_container_id, 'vnet_name': vcn_name,'subnet_id': subnet_id} + + + # Process Defined and Freeform Tags + if columnname.lower() in azrCommonTools.tagColumns: + tempdict = azrCommonTools.split_tag_values(columnname, columnvalue, tempdict) + + + if columnname == "Exadata Infra Display Name": + exadata_infrastructure_name = columnvalue.strip() + tempdict = {'exadata_infrastructure_name': exadata_infrastructure_name} + + + columnname = commonTools.check_column_headers(columnname) + tempStr[columnname] = str(columnvalue).strip() + tempStr.update(tempdict) + + + + # Write all info to TF string + tfStr = tfStr + template.render(tempStr) + + # Write TF string to the file + if (tfStr != ''): + outfile = outdir + "/" + auto_tfvars_filename + commonTools.backup_file(outdir, resource, auto_tfvars_filename) + src = "##Add New Exa-VMCluster @Azure here##" + tfStr = template.render(count=0).replace(src, tfStr + "\n" + src) + tfStr = "".join([s for s in tfStr.strip().splitlines(True) if s.strip("\r\n").strip()]) + oname = open(outfile, 'w') + oname.write(tfStr) + oname.close() + print(outfile + " containing TF for Exa-VMCluster @Azure has been created") \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/python/database/export_adb_azure.py b/cd3_automation_toolkit/azurecloud/python/database/export_adb_azure.py new file mode 100644 index 000000000..cc527154a --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/export_adb_azure.py @@ -0,0 +1,343 @@ +#!/usr/bin/python3 +# Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. +# This script will Export ADB @Azure resources into CD3 (existing worksheet) and write Terraform/tofu import commands +# Author: Ulaganathan N +# Oracle Consulting +############################################################################### +import os +import sys +import subprocess as sp +sys.path.append(os.getcwd()+"/..") +from common.python.commonTools import * +import azurecloud.python.azrCommonTools as azrCommonTools +from typing import Dict, List, Optional +try: + from azure.mgmt.oracledatabase import OracleDatabaseMgmtClient as OracleDBClient +except ImportError: + from azure.mgmt.oracledatabase import OracleDatabaseManagementClient as OracleDBClient + + +# Global declaration +importCommands: Dict[str, str] = {} + + +def pick_first_not_none(*values): + """Return the first non-None value from a list of values.""" + for v in values: + if v is not None: + return v + return None + + +def normalize_enum_token(value): + """ + Return the enum/member token expected by tfvars as a string. + For Example: + 'WorkloadType.OLTP' -> 'OLTP' + """ + if value is None: + return "" + s = str(value) + return s.split(".", 1)[1] if "." in s else s + + +def _format_rg_vnet_subnet_from_id(net_id: str) -> str: + """Return 'resourceGroup@vnet::subnet' from a subnet ARM ID.""" + if not net_id: + return "" + parts = net_id.strip("/").split("/") + try: + rg = parts[parts.index("resourceGroups") + 1] + vnet = parts[parts.index("virtualNetworks") + 1] + subnet = parts[parts.index("subnets") + 1] + return f"{rg}@{vnet}::{subnet}" + except (ValueError, IndexError): + return "" + + +def _get_rg_from_id(resource_id: str) -> str: + # ARM ID format: /subscriptions//resourceGroups//providers/.../autonomousDatabases/ + try: + parts = resource_id.split("/") + idx = parts.index("resourceGroups") + return parts[idx + 1] + except Exception: + return "" + + +def _list_adbs(client: "OracleDBClient", resource_groups: Optional[List[str]] = None): + """Yield ADB @Azure resources across provided RGs or entire subscription.""" + if resource_groups: + for rg in resource_groups: + try: + for adb in client.autonomous_databases.list_by_resource_group(rg): + yield adb + except HttpResponseError as e: + print(f"[WARN] Failed listing ADBs in RG '{rg}': {e}") + else: + for adb in client.autonomous_databases.list_by_subscription(): + yield adb + + +def print_adbs_azure(adb, values_for_column: Dict[str, List], state: Dict, tf_or_tofu: str, ): + """Populate CD3 columns for a single ADB @Azure and queue Terraform import commands.""" + props = getattr(adb, "properties", None) or adb + + # Resource names and IDs + rg_name = _get_rg_from_id(getattr(adb, "id", "")) + adb_name = getattr(adb, "name", "") + adb_location = getattr(adb, "location", "") + + # Contacts (list of objects with .email) + contacts_csv = "" + try: + contacts = getattr(props, "customer_contacts", None) + if contacts: + emails = [] + for c in contacts: + email = getattr(c, "email", None) or getattr(c, "contact", None) + if email: + emails.append(email) + contacts_csv = ",".join(emails) + except Exception: + contacts_csv = "" + + # Tags (dict) — kept as metadata only if the sheet has 'Common Tags' column(not used yet) + common_tags = azrCommonTools._flatten_tags(getattr(adb, "tags", None)) + + # Prefer subnetId to derive rg@vnet::subnet; private endpoint IDs don't contain vnet/subnet names + subnet_id = pick_first_not_none( + getattr(props, "subnet_id", None), + getattr(props, "subnetId", None), + ) + formatted_net = _format_rg_vnet_subnet_from_id(subnet_id) + + # Optional: keep raw IDs if needed elsewhere + network_details_raw = pick_first_not_none( + getattr(props, "subnet_id", None), + getattr(props, "subnetId", None), + getattr(props, "private_endpoint_id", None), + getattr(props, "privateEndpointId", None), + "", + ) + + # Whitelisted IPs (array of strings) + ips_list = pick_first_not_none( + getattr(props, "whitelisted_ips", None), # snake_case (SDK model) + getattr(props, "whitelistedIps", None), # camelCase (REST casing) + ) + whitelisted_ips = ",".join(ips_list) if isinstance(ips_list, list) else "" + + # Compute details + compute_model_raw = (getattr(props, "compute_model", None) or getattr(props, "computeModel", None) or "") + compute_model = normalize_enum_token(compute_model_raw) + + compute_count = ( + getattr(props, "compute_count", None) + or getattr(props, "computeCount", None) + or "" + ) + ocpu_cores = ( + getattr(props, "cpu_core_count", None) + or getattr(props, "ocpuCoreCount", None) + or "" + ) + + db_version = getattr(props, "db_version", None) or getattr(props, "databaseVersion", None) or "" + db_edition_raw = getattr(props, "database_edition", None) or getattr(props, "databaseEdition", None) or "" + db_edition = normalize_enum_token(db_edition_raw) + storage_tbs = getattr(props, "data_storage_size_in_tbs", None) or getattr(props, "dataStorageSizeInTbs", None) or "" + workload_raw = getattr(props, "db_workload", None) or getattr(props, "databaseWorkload", None) or "" + workload = normalize_enum_token(workload_raw) + license_model_raw = getattr(props, "license_model", None) or getattr(props, "licenseModel", None) or "" + license_model = normalize_enum_token(license_model_raw) + backup_retention_days = \ + (getattr(props, "backup_retention_period_in_days", None) or getattr(props, "backupRetentionDays", + None) or "") + # Character sets + char_set = pick_first_not_none( + getattr(props, "character_set", None), + getattr(props, "characterSet", None), + ) + nchar_set = pick_first_not_none( + getattr(props, "ncharacter_set", None), + getattr(props, "ncharacterSet", None), + ) + + # Auto-scaling flags + auto_scaling_storage = pick_first_not_none( + getattr(props, "is_auto_scaling_for_storage_enabled", None), + getattr(props, "isAutoScalingForStorageEnabled", None), + ) + auto_scaling_enabled = pick_first_not_none( + getattr(props, "is_auto_scaling_enabled", None), + getattr(props, "isAutoScalingEnabled", None), + ) + + # mTLS requirement + mtls_required = pick_first_not_none( + getattr(props, "is_mtls_connection_required", None), + getattr(props, "isMtlsConnectionRequired", None), + ) + + module_name = "adb-azure" + resource_type = "azurerm_oracle_autonomous_database" + resource_name_in_module = "autonomous_database" # Need to change if tf module uses a different name + + adb_tf_name = commonTools.check_tf_variable(adb_name) + + # module.[""].. + tf_address = f'module.{module_name}["{adb_tf_name}"].{resource_type}.{resource_name_in_module}' + + # Avoid duplicate imports by checking current state addresses + if tf_address not in state.get("resources", []): + # Wrap ADDRESS in single quotes to avoid escaping the ["] in a POSIX shell + importCommands["global"] += f"\n{tf_or_tofu} import '{tf_address}' {getattr(adb, 'id', '')}" + + # Populate CD3 columns as per provided header list (write only if column exists) + for col_header in values_for_column: + if col_header in ("Resource Group", "Resource Group", "Resource Group Name"): + values_for_column[col_header].append(rg_name) + elif col_header == "Region": + # If the sheet still has Region, fill it from Azure location (no per-region scripting) + values_for_column[col_header].append(adb_location) + elif col_header == "ADB Display Name": + values_for_column[col_header].append(adb_name) + elif col_header == "Network Details": + # Write the formatted rg@vnet::subnet if available; else leave blank or fall back to raw + values_for_column[col_header].append(formatted_net or "") + elif col_header == "Whitelisted IP Addresses": + values_for_column[col_header].append(whitelisted_ips) + elif col_header == "DB Name": + values_for_column[col_header].append("") # Not exposed in Azure UI/API + elif col_header == "DB Version": + values_for_column[col_header].append(db_version) + elif col_header == "Database Edition": + values_for_column[col_header].append(db_edition) + elif col_header == "Admin Password": + values_for_column[col_header].append("Rand0mPaswd#123") # never retrievable + elif col_header == "Compute Model": + values_for_column[col_header].append(compute_model) + elif col_header == "Compute Count": + values_for_column[col_header].append(compute_count) + elif col_header in ("OCPU Core Count", "OCPU Core Count"): + values_for_column[col_header].append(ocpu_cores) + elif col_header in ("Data Storage Size in TBs", "Data Storage Size in TB"): + values_for_column[col_header].append(storage_tbs) + elif col_header == "Database Workload": + if workload == "DW": + workload = "adw" + elif workload == "AJD": + workload = "json" + elif workload == "OLTP": + workload = "atp" + elif workload == "APEX": + workload = "apex" + values_for_column[col_header].append(workload.upper()) + elif col_header == "License Model": + values_for_column[col_header].append(license_model) + elif col_header == "Backup Retention Period In Days": + values_for_column[col_header].append(backup_retention_days) + elif col_header == 'Character Set': + values_for_column[col_header].append(char_set) + elif col_header == 'nCharacter Set': + values_for_column[col_header].append(nchar_set) + elif col_header == "Auto Scaling for Storage Enabled": + values_for_column[col_header].append(auto_scaling_storage) + elif col_header == "Auto Scaling Enabled": + values_for_column[col_header].append(auto_scaling_enabled) + elif col_header == "MTLS Connection Required": + values_for_column[col_header].append(mtls_required) + elif col_header == "Customer Contacts": + values_for_column[col_header].append(contacts_csv) + elif col_header == "Common Tags": + values_for_column[col_header].append(common_tags) + else: + values_for_column[col_header].append("") + ''' + elif col_header.lower() in azrCommonTools.tagColumns: + try: + values_for_column = commonTools.export_tags(adb, col_header, values_for_column) + except Exception: + values_for_column[col_header].append("") + + else: + # Extra/custom columns via Excel_Columns mapping + try: + oci_objs = [adb] + values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, + values_for_column) + except Exception: + values_for_column[col_header].append("") + ''' + + + +def export_adb_azure(inputfile: str, outdir: str,credentials, + export_resource_groups: Optional[List[str]] = None): + """ + Export ADB @Azure resources into CD3 (existing worksheet) and write Terraform/tofu import commands. + - No region/service_dir/export_tags/compartment scoping. + - Single import script at outdir/azure folder. + """ + global importCommands, sheet_dict + + tf_or_tofu = "terraform" + + # Validate input Excel + cd3file = inputfile + if '.xls' not in cd3file: + print("\nAcceptable cd3 format: .xlsx") + sys.exit(1) + sheetName = "ADB-Azure" + # Read CD3 + df, values_for_column = commonTools.read_cd3(cd3file, sheetName) + + # Get dict for columns from Excel_Columns + + print("\nCD3 excel file should not be opened during export process!!!") + print("Tab- ADB-Azure will be overwritten during export process!!!\n") + + # Prepare a single import commands script at outdir (subscription scope) + + resource = 'import_' + sheetName.lower() + file_name = 'import_commands_' + sheetName.lower() + '.sh' + script_file = os.path.join(outdir, file_name) + if os.path.exists(script_file): + commonTools.backup_file(outdir, resource, file_name) + os.makedirs(outdir, exist_ok=True) + importCommands["global"] = "" + + + client = OracleDBClient(credential=credentials[0], subscription_id=credentials[1]) + + print("\nFetching details of ADB @Azure...") + + # Build state resources (to avoid duplicate import lines) at outdir + state = {'path': outdir, 'resources': []} + try: + tf_state_list = [tf_or_tofu, "state", "list"] + byteOutput = sp.check_output(tf_state_list, cwd=state["path"], stderr=sp.DEVNULL) + output = byteOutput.decode('UTF-8').rstrip() + for item in output.split('\n'): + state["resources"].append(item.replace("\"", "\\\"")) + except Exception: + pass + + # Iterate ADBs in requested RGs or entire subscription + rgs = export_resource_groups if export_resource_groups else None + for adb in _list_adbs(client, rgs): + print_adbs_azure(adb, values_for_column, state, tf_or_tofu) + + # Write back to CD3 + commonTools.write_to_cd3(values_for_column, cd3file, sheetName) + # Region count if present, else any main column (e.g., ADB Display Name) + count_col = "ADB Display Name" if "ADB Display Name" in values_for_column else next(iter(values_for_column.keys())) + print("{0} ADB @Azure exported into CD3.\n".format(len(values_for_column.get(count_col, [])))) + + # Write import script + init_commands = f'\n######### Writing import for ADB @Azure #########\n\n#!/bin/bash\n{tf_or_tofu} init' + if importCommands.get("global"): + importCommands["global"] += f'\n{tf_or_tofu} plan\n' + with open(script_file, 'a', encoding='utf-8') as importCommandsfile: + importCommandsfile.write(init_commands + importCommands["global"]) \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/python/database/templates/adb-azure-template b/cd3_automation_toolkit/azurecloud/python/database/templates/adb-azure-template new file mode 100644 index 000000000..7f8a67f92 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/templates/adb-azure-template @@ -0,0 +1,94 @@ +{% if count == 0 %} +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +############################ +# ADB @Azure +# ADB @Azure - tfvars +############################ + +az_oci_adb = { + ##Add New ADB @Azure here## +} +{% else %} + + {{ display_tf_name }} = { + az_region = "{{ region }}" + resource_group_name = "{{ container_id }}" + + display_name = "{{ display_tf_name }}" + db_version = "{{ db_version }}" + license_model = "{{ license_model.split('_')|map('capitalize')|join }}" + admin_password = "{{ admin_password }}" + + network_resource_group_name = "{{ network_container_id }}" + virtual_network_id = "{{ vnet_name }}" + subnet_id = "{{ subnet_id }}" + {% if data_storage_size_in_tbs != "" and data_storage_size_in_tbs != "nan" %} + data_storage_size_in_tbs = {{ data_storage_size_in_tbs }} + {% endif %} + {% if autonomous_value == 'adw' %} + db_workload = "DW" + {% elif autonomous_value == 'atp' %} + db_workload = "OLTP" + {% elif autonomous_value == 'json' %} + db_workload = "AJD" + {% elif autonomous_value == 'apex' %} + db_workload = "APEX" + {% else %} + db_workload = "{{ autonomous_value }}" + {% endif %} + + compute_model = "ECPU" + compute_count = {{ compute_count }} + + {% if character_set != "" and character_set != "nan" %} + character_set = "{{ character_set }}" + {% endif %} + {% if ncharacter_set != "" and ncharacter_set != "nan" %} + ncharacter_set = "{{ ncharacter_set }}" + {% endif %} + + {% if customer_contacts and customer_contacts != "" and customer_contacts != "nan" %} + customer_contacts = {{ customer_contacts.split(",") | map('trim') | list | tojson }} + {% endif %} + + {% if backup_retention_period_in_days != "" and backup_retention_period_in_days != "nan" %} + backup_retention_period_in_days = {{ backup_retention_period_in_days }} + {% endif %} + + {% if auto_scaling_for_storage_enabled != "" and auto_scaling_for_storage_enabled != "nan" %} + auto_scaling_for_storage_enabled = {{ auto_scaling_for_storage_enabled }} + {% endif %} + + {% if auto_scaling_enabled != "" and auto_scaling_enabled != "nan" %} + auto_scaling_enabled = {{ auto_scaling_enabled }} + {% endif %} + + {% if mtls_connection_required != "" and mtls_connection_required != "nan" %} + mtls_connection_required = {{ mtls_connection_required }} + {% endif %} + + + {# ##Do not modify below this line## #} + {# #} + {# ###Section for adding Common Tags### #} + {% if common_tags and common_tags != 'nan' and common_tags != '' and common_tags != [['nan']] %} + {% if common_tags[0] %} + common_tags = { + {% for tags in common_tags %} + {% if not loop.last %} + "{{ tags[0] }}"= "{{ tags[1] }}" , + {% else %} + "{{ tags[0] }}"= "{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + + {# ###Section for adding Common Tags ends here### #} + }, + +{% endif %} + diff --git a/cd3_automation_toolkit/azurecloud/python/database/templates/adb-gcp-template b/cd3_automation_toolkit/azurecloud/python/database/templates/adb-gcp-template new file mode 100644 index 000000000..bd168ed1f --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/templates/adb-gcp-template @@ -0,0 +1,108 @@ +{% if count == 0 %} +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +############################ +# ADB @Azure +# ADB @Azure - tfvars +# Allowed Values: +# compartment_id and network_compartment_id can be the ocid or the name of the compartment hierarchy delimited by double hiphens "--" +# Example : compartment_id = "ocid1.compartment.oc1..aaaaaaaahwwiefb56epvdlzfic6ah6jy3xf3c" or compartment_id = "Database--Prod" where "Database" is the parent of "Prod" compartment +############################ + +az_oci_adb = { + ##Add New ADB @Azure here## +} +{% else %} + + {{ display_tf_name }} = { + az_region = "{{ azure_region }}" + resource_group_name = "{{ container_id }}" + + display_name = "{{ display_tf_name }}" + db_version = "{{ db_version }}" + license_model = "{{ license_model | replace("_","") }}" + admin_password = "{{ admin_password }}" + + virtual_network_id = "{{ virtual_network_id }}" + subnet_id = "{{ subnet_id }}" + {% if data_storage_size_in_tbs != "" and data_storage_size_in_tbs != "nan" %} + data_storage_size_in_tbs = {{ data_storage_size_in_tbs }} + {% endif %} + {% if autonomous_value == 'adw' %} + db_workload = "DW" + {% elif autonomous_value == 'atp' %} + db_workload = "OLTP" + {% elif autonomous_value == 'json' %} + db_workload = "AJD" + {% elif autonomous_value == 'apex' %} + db_workload = "APEX" + {% else %} + db_workload = "{{ autonomous_value }}" + {% endif %} + + compute_model = "ECPU" + compute_count = {{ compute_count }} + + {% if character_set != "" and character_set != "nan" %} + character_set = "{{ character_set }}" + {% endif %} + {% if ncharacter_set != "" and ncharacter_set != "nan" %} + ncharacter_set = "{{ ncharacter_set }}" + {% endif %} + + {% if customer_contacts and customer_contacts != "" and customer_contacts != "nan" %} + customer_contacts = [ {{ customer_contacts | replace("\'","\"") }} ] + {% endif %} + + {% if backup_retention_period_in_days != "" and backup_retention_period_in_days != "nan" %} + backup_retention_period_in_days = {{ backup_retention_period_in_days }} + {% endif %} + + {% if auto_scaling_for_storage_enabled != "" and auto_scaling_for_storage_enabled != "nan" %} + auto_scaling_for_storage_enabled = {{ auto_scaling_for_storage_enabled }} + {% endif %} + + {% if auto_scaling_enabled != "" and auto_scaling_enabled != "nan" %} + auto_scaling_enabled = {{ auto_scaling_enabled }} + {% endif %} + + {% if mtls_connection_required != "" and mtls_connection_required != "nan" %} + mtls_connection_required = {{ mtls_connection_required }} + {% endif %} + + + {# ##Do not modify below this line## #} + {# #} + {# ###Section for adding Defined and Freeform Tags### #} + {% if defined_tags and defined_tags != 'nan' and defined_tags != '' and defined_tags != [['nan']] %} + {% if defined_tags[0] %} + defined_tags = { + {% for tags in defined_tags %} + {% if not loop.last %} + "{{ tags[0] }}"= "{{ tags[1] }}" , + {% else %} + "{{ tags[0] }}"= "{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + {% if freeform_tags and freeform_tags != 'nan' and freeform_tags != '' and freeform_tags != [['nan']] %} + {% if freeform_tags[0] %} + freeform_tags = { + {% for tags in freeform_tags %} + {% if not loop.last %} + "{{ tags[0] }}"="{{ tags[1] }}", + {% else %} + "{{ tags[0] }}"="{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + {# ###Section for adding Defined and Freeform Tags ends here### #} + }, + +{% endif %} + diff --git a/cd3_automation_toolkit/azurecloud/python/database/templates/exa-infra-azure-template b/cd3_automation_toolkit/azurecloud/python/database/templates/exa-infra-azure-template new file mode 100644 index 000000000..ed4463a08 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/templates/exa-infra-azure-template @@ -0,0 +1,59 @@ +{% if count == 0 %} +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +############################ +# Exa Infra @Azure +# Exa Infra @Azure - tfvars +############################ + +az_oci_exa_infra = { + ##Add New Exa-Infra @Azure here## +} +{% else %} + + {{ display_tf_name }} = { + az_region = "{{ region }}" + az_zone = "{{ availability_zone}}" + resource_group_name = "{{ container_id }}" + + display_name = "{{ display_name }}" + compute_count = "{{ database_servers }}" + storage_count = "{{ storage_servers }}" + shape = "{{ shape }}" + + #database_server_type = "{{ database_server_type }}" + #storage_server_type = "{{ storage_server_type }}" + + maintenance_window = { + patching_mode="{{ maintenance_method }}" + preference="NoPreference" + } + + {% if customer_contacts and customer_contacts != "" and customer_contacts != "nan" %} + customer_contacts = {{ customer_contacts.split(",") | map('trim') | list | tojson }} + {% endif %} + + + {# ##Do not modify below this line## #} + {# #} + {# ###Section for adding Common Tags### #} + {% if common_tags and common_tags != 'nan' and common_tags != '' and common_tags != [['nan']] %} + {% if common_tags[0] %} + common_tags = { + {% for tags in common_tags %} + {% if not loop.last %} + "{{ tags[0] }}"= "{{ tags[1] }}" , + {% else %} + "{{ tags[0] }}"= "{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + + {# ###Section for adding Common Tags ends here### #} + }, + +{% endif %} + diff --git a/cd3_automation_toolkit/azurecloud/python/database/templates/exa-vmcluster-azure-template b/cd3_automation_toolkit/azurecloud/python/database/templates/exa-vmcluster-azure-template new file mode 100644 index 000000000..5bb8c4975 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/python/database/templates/exa-vmcluster-azure-template @@ -0,0 +1,113 @@ +{% if count == 0 %} +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +############################ +# Exa VM Cluster @Azure +# Exa VM Cluster @Azure - tfvars +############################ + +az_oci_exa_vmclusters = { + ##Add New Exa-VMCluster @Azure here## +} +{% else %} + + {{ display_tf_name }} = { + az_region = "{{ region }}" + resource_group_name = "{{ container_id }}" + + network_resource_group_name = "{{ network_container_id }}" + virtual_network_id = "{{ vnet_name }}" + subnet_id = "{{ subnet_id }}" + + exadata_infrastructure_name = "{{ exadata_infrastructure_name }}" + + display_name = "{{ display_name }}" + hostname = "{{ hostname }}" + gi_version = "{{ gi_version }}" + cpu_core_count = "{{ cpu_core_count }}" + license_model = "{{ license_model.split('_')|map('capitalize')|join }}" + ssh_public_keys = ["{{ ssh_public_keys }}"] + + {% if domain %} + domain = "{{ domain }}" + {% endif %} + {% if oci_zone_id %} + oci_zone_id = "{{ oci_zone_id }}" + {% endif %} + {% if backup_subnet_cidr %} + backup_subnet_cidr = "{{ backup_subnet_cidr }}" + {% endif %} + {% if cluster_name %} + cluster_name = "{{ cluster_name }}" + {% endif %} + + {% if diagnostics_events_enabled %} + diagnostics_events_enabled = {{ diagnostics_events_enabled }} + {% endif %} + {% if health_monitoring_enabled %} + health_monitoring_enabled = {{ health_monitoring_enabled }} + {% endif %} + {% if incident_logs_enabled %} + incident_logs_enabled = {{ incident_logs_enabled }} + {% endif %} + {% if data_storage_percentage %} + data_storage_percentage = {{ data_storage_percentage }} + {% endif %} + {% if data_storage_size_in_tbs %} + data_storage_size_in_tbs = {{ data_storage_size_in_tbs }} + {% endif %} + {% if db_node_storage_size_in_gbs %} + db_node_storage_size_in_gbs = {{ db_node_storage_size_in_gbs }} + {% endif %} + {% if memory_size_in_gbs %} + memory_size_in_gbs = {{ memory_size_in_gbs }} + {% endif %} + {% if time_zone %} + time_zone = "{{ time_zone }}" + {% endif %} + {% if local_backup_enabled %} + local_backup_enabled = {{ local_backup_enabled }} + {% endif %} + {% if sparse_diskgroup_enabled %} + sparse_diskgroup_enabled = {{ sparse_diskgroup_enabled }} + {% endif %} + {% if scan_listener_port_tcp %} + scan_listener_port_tcp = {{ scan_listener_port_tcp }} + {% endif %} + {% if scan_listener_port_tcp_ssl %} + scan_listener_port_tcp_ssl = {{ scan_listener_port_tcp_ssl }} + {% endif %} + {% if system_version %} + system_version = "{{ system_version }}" + {% endif %} + {% if mount_point %} + mount_point = "{{ mount_point }}" + {% endif %} + {% if size_in_gb %} + size_in_gb = {{ size_in_gb }} + {% endif %} + + + {# ##Do not modify below this line## #} + {# #} + {# ###Section for adding Common Tags### #} + {% if common_tags and common_tags != 'nan' and common_tags != '' and common_tags != [['nan']] %} + {% if common_tags[0] %} + common_tags = { + {% for tags in common_tags %} + {% if not loop.last %} + "{{ tags[0] }}"= "{{ tags[1] }}" , + {% else %} + "{{ tags[0] }}"= "{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + + {# ###Section for adding Common Tags ends here### #} + }, + +{% endif %} + diff --git a/cd3_automation_toolkit/azurecloud/terraform/adb-azure.tf b/cd3_automation_toolkit/azurecloud/terraform/adb-azure.tf new file mode 100644 index 000000000..302ebd44a --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/adb-azure.tf @@ -0,0 +1,93 @@ +#data "azurerm_resource_group" "resource_group" { +# for_each = var.azurerm_oci_adb != null ? var.azurerm_oci_adb : {} +# name = each.value.resource_group_name +#} + +data "azurerm_virtual_network" "virtual_network" { + #depends_on = [module.avm_network] + for_each = var.az_oci_adb != null ? var.az_oci_adb : {} + name = each.value.virtual_network_id + resource_group_name = each.value.network_resource_group_name +} + +data "azurerm_subnet" "subnet" { + #depends_on = [module.avm_network] + for_each = var.az_oci_adb != null ? var.az_oci_adb : {} + name = each.value.subnet_id + virtual_network_name = each.value.virtual_network_id + resource_group_name = each.value.network_resource_group_name +} + +/* +output rg { +value = data.azurerm_resource_group.resource_group["demoadb"].id +} +*/ + +# Azure VNet with delegated subnet +/* +module "avm_network" { + for_each = var.azurerm_oci_adb != null ? var.azurerm_oci_adb : {} + #count = each.value.virtual_network_address_space != "" && each.value.subnet_address_prefix != "" ? 1 : 0 + + source = "Azure/avm-res-network-virtualnetwork/azurerm" + version = "0.5.0" + + # depends_on = [ module.azure-resource-grp ] + + tags = each.value.common_tags + resource_group_name = each.value.resource_group_name + location = each.value.az_region + name = each.value.virtual_network_id + address_space = each.value.virtual_network_address_space + + subnets = { + delegated = { + name = each.value.subnet_id + address_prefixes = each.value.subnet_address_prefix + + delegation = [{ + name = "Oracle.Database/networkAttachments" + service_delegation = { + name = "Oracle.Database/networkAttachments" + actions = ["Microsoft.Network/networkinterfaces/*", "Microsoft.Network/virtualNetworks/subnets/join/action"] + + } + }] + } + } +} +*/ + +# Oracle Autonomous Database@Azure +module "adb-azure" { + for_each = var.az_oci_adb != null ? var.az_oci_adb : {} + + # depends_on = [ module.azure-resource-grp ] + source = "./modules/azurerm-oci-adb" + name = each.value.display_name + #resource_group_name = data.azurerm_resource_group.resource_group[each.key].id + virtual_network_id = data.azurerm_virtual_network.virtual_network[each.key].id + subnet_id = data.azurerm_subnet.subnet[each.key].id + #network_resource_group_name = each.value.network_resource_group_name + + resource_group_name = each.value.resource_group_name + location = each.value.az_region + display_name = each.value.display_name + db_workload = each.value.db_workload + mtls_connection_required = each.value.mtls_connection_required + backup_retention_period_in_days = each.value.backup_retention_period_in_days + compute_model = each.value.compute_model + data_storage_size_in_tbs = each.value.data_storage_size_in_tbs + auto_scaling_for_storage_enabled = each.value.auto_scaling_for_storage_enabled + + admin_password = each.value.admin_password + auto_scaling_enabled = each.value.auto_scaling_enabled + character_set = each.value.character_set + compute_count = each.value.compute_count + ncharacter_set = each.value.ncharacter_set + license_model = each.value.license_model + db_version = each.value.db_version + customer_contacts = each.value.customer_contacts + tags = each.value.common_tags +} diff --git a/cd3_automation_toolkit/azurecloud/terraform/exadata-azure.tf b/cd3_automation_toolkit/azurecloud/terraform/exadata-azure.tf new file mode 100644 index 000000000..fffc6b2f1 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/exadata-azure.tf @@ -0,0 +1,125 @@ +#data "azurerm_resource_group" "resource_group" { +# for_each = var.azurerm_oci_adb != null ? var.azurerm_oci_adb : {} +# name = each.value.resource_group_name +#} + +data "azurerm_virtual_network" "exa_vmc_virtual_networks" { + #depends_on = [module.avm_network] + for_each = var.az_oci_exa_vmclusters != null ? var.az_oci_exa_vmclusters : {} + name = each.value.virtual_network_id + resource_group_name = each.value.network_resource_group_name +} + +data "azurerm_subnet" "exa_vmc_subnets" { + #depends_on = [module.avm_network] + for_each = var.az_oci_exa_vmclusters != null ? var.az_oci_exa_vmclusters : {} + name = each.value.subnet_id + virtual_network_name = each.value.virtual_network_id + resource_group_name = each.value.network_resource_group_name +} + +data "azurerm_oracle_exadata_infrastructure" "exa_infras" { +depends_on = [ module.exa-infra-azure ] + #depends_on = [module.avm_network] + for_each = var.az_oci_exa_vmclusters != null ? var.az_oci_exa_vmclusters : {} + name = each.value.exadata_infrastructure_name + resource_group_name = each.value.resource_group_name +} + +data "azurerm_oracle_db_servers" "this" { + depends_on = [ module.exa-infra-azure] + for_each = var.az_oci_exa_vmclusters != null ? var.az_oci_exa_vmclusters : {} + resource_group_name = each.value.resource_group_name + cloud_exadata_infrastructure_name = each.value.exadata_infrastructure_name +} + +# AzureRM - Exadata Infrastructure +module "exa-infra-azure" { + for_each = var.az_oci_exa_infra != null ? var.az_oci_exa_infra : {} + source = "./modules/azurerm-oci-exa-infra" + # depends_on = [ module.azure-resource-grp ] + + # Mandatory + location = each.value.az_region + zone = each.value.az_zone + resource_group_name = each.value.resource_group_name + name = each.value.display_name + compute_count = each.value.compute_count + storage_count = each.value.storage_count + + # Optional + shape = each.value.shape + tags = each.value.common_tags + customer_contacts = each.value.customer_contacts + maintenance_window = each.value.maintenance_window + +} + + + +# Known Issue - https://docs.oracle.com/en-us/iaas/odexa/odexa-troubleshooting-and-known-issues-exadata-services.html +#resource "time_sleep" "wait_after_deletion" { +# destroy_duration = var.destroy_duration +# depends_on = [module.azurerm_exadata_infra] +#} + +# AzureRM - Exadata VM Cluster +module "exa-vmcluster-azure" { + + for_each = var.az_oci_exa_vmclusters != null ? var.az_oci_exa_vmclusters : {} + source = "./modules/azurerm-oci-exa-vmcluster" + + # VM Cluster details + resource_group_name = each.value.resource_group_name + display_name = each.value.display_name + + exadata_infrastructure_id = data.azurerm_oracle_exadata_infrastructure.exa_infras[each.key].id + exadata_infrastructure_name = each.value.exadata_infrastructure_name + db_servers = [for obj in data.azurerm_oracle_db_servers.this[each.key].db_servers : obj.ocid] + + location = each.value.az_region + cluster_name = each.value.cluster_name + hostname = each.value.hostname + time_zone = each.value.time_zone + license_model = each.value.license_model + gi_version = each.value.gi_version + system_version = each.value.system_version + ssh_public_keys = each.value.ssh_public_keys + + # Networking + vnet_id = data.azurerm_virtual_network.exa_vmc_virtual_networks[each.key].id + subnet_id = data.azurerm_subnet.exa_vmc_subnets[each.key].id + backup_subnet_cidr = each.value.backup_subnet_cidr + domain = each.value.domain + zone_id = each.value.oci_zone_id + + # VM Cluster allocation + cpu_core_count = each.value.cpu_core_count + memory_size_in_gbs = each.value.memory_size_in_gbs + dbnode_storage_size_in_gbs = each.value.db_node_storage_size_in_gbs + + # Exadata storage + data_storage_size_in_tbs = each.value.data_storage_size_in_tbs + data_storage_percentage = each.value.data_storage_percentage + is_local_backup_enabled = each.value.local_backup_enabled + is_sparse_diskgroup_enabled = each.value.sparse_diskgroup_enabled + + # Diagnostics Collection + is_diagnostic_events_enabled = each.value.diagnostics_events_enabled + is_health_monitoring_enabled = each.value.health_monitoring_enabled + is_incident_logs_enabled = each.value.incident_logs_enabled + + # Ports + scan_listener_port_tcp = each.value.scan_listener_port_tcp + scan_listener_port_tcp_ssl = each.value.scan_listener_port_tcp_ssl + + # File System Config + mount_point = each.value.mount_point + size_in_gb = each.value.size_in_gb + + + tags = each.value.common_tags + #depends_on = [time_sleep.wait_after_deletion] + # depends_on = [module.azurerm_exadata_infra] + +} diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/main.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/main.tf new file mode 100644 index 000000000..a2605b35c --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/main.tf @@ -0,0 +1,59 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Resource Block - Oracle ADB @Azure +## Create Oracle ADB @Azure +##################################### + +resource "azurerm_oracle_autonomous_database" "autonomous_database" { + name = var.name + resource_group_name = var.resource_group_name + location = var.location + subnet_id = var.subnet_id + display_name = var.display_name + db_workload = var.db_workload + mtls_connection_required = var.mtls_connection_required + backup_retention_period_in_days = var.backup_retention_period_in_days + compute_model = var.compute_model + data_storage_size_in_tbs = var.data_storage_size_in_tbs + auto_scaling_for_storage_enabled = var.auto_scaling_for_storage_enabled + virtual_network_id = var.virtual_network_id + admin_password = var.admin_password + auto_scaling_enabled = var.auto_scaling_enabled + character_set = var.character_set + compute_count = var.compute_count + national_character_set = var.ncharacter_set + license_model = var.license_model + db_version = var.db_version + customer_contacts = var.customer_contacts + tags = var.tags + lifecycle { + ignore_changes = [ + name, + display_name, + db_workload, + mtls_connection_required, + #backup_retention_period_in_days, + compute_model, + #data_storage_size_in_tbs, + #auto_scaling_for_storage_enabled, + #auto_scaling_enabled, + character_set, + admin_password, + # compute_count, + national_character_set, + license_model, + db_version, + customer_contacts + ] + } +} + +/* +data "azurerm_oracle_autonomous_database" "this" { + depends_on = [ azurerm_oracle_autonomous_database.this ] + name = azurerm_oracle_autonomous_database.this.name + resource_group_name = azurerm_oracle_autonomous_database.this.resource_group_name +} +*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/outputs.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/outputs.tf new file mode 100644 index 000000000..eaddf386e --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/outputs.tf @@ -0,0 +1,37 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Outputs Block - Oracle ADB @Azure +## Create Oracle ADB @Azure +##################################### + +# Azure info +output "resource_id" { + description = "Resource ID of Autonomous Database in Azure" + value = azurerm_oracle_autonomous_database.autonomous_database.id +} + +/* +output "resource" { + description = "Resource Object of Autonomous Database in Azure" + value = data.azurerm_oracle_autonomous_database.autonomous_database +} + + +# OCI info +output "oci_adbs_ocid" { + description = "OCID of Autonomous Database in OCI" + value = regex("(?:/adbs/)([^?&/]+)",data.azurerm_oracle_autonomous_database.this.oci_url)[0] +} + +output "oci_region" { + description = "Region of the Autonomous Database in OCI" + value = regex("(?:region=)([^?&/]+)",data.azurerm_oracle_autonomous_database.this.oci_url)[0] +} + +output "oci_compartment_ocid" { + description = "Compartment OCID of the Autonomous Database in OCI" + value = regex("(?:compartmentId=)([^?&/]+)",data.azurerm_oracle_autonomous_database.this.oci_url)[0] +} +*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/provider_req.tf similarity index 76% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf rename to cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/provider_req.tf index f1f97aaeb..f51a8c14b 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/provider_req.tf @@ -6,5 +6,9 @@ terraform { oci = { source = "oracle/oci" } + azurerm = { + source = "hashicorp/azurerm" + version = ">=4.9.0" + } } } \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/variables.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/variables.tf new file mode 100644 index 000000000..6d2c697b3 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-adb/variables.tf @@ -0,0 +1,126 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Variables Block - Oracle ADB @Azure +## Create Oracle ADB @Azure +##################################### + +variable "name" { + description = "Azure resource name which should be used for this Autonomous Database." + type = string +} + +variable "resource_group_name" { + description = "The name of Resource Group in Azure" + type = string +} + +variable "location" { + description = "The Azure Region where the Autonomous Database should exist. Changing this forces a new Autonomous Database to be created" + type = string +} + +variable "subnet_id" { + description = "The ID of the subnet the resource is associated with." + type = string +} + +variable "display_name" { + description = "The user-friendly name for the Autonomous Database in OCI. The name does not have to be unique." + type = string +} + +variable "db_workload" { + description = "The Autonomous Database workload type. The following values are valid: OLTP, DW, AJD, APEX" + type = string + default = "OLTP" +} + +variable "mtls_connection_required" { + description = "Specifies if the Autonomous Database requires mTLS connections." + type = bool + default = false +} +variable "backup_retention_period_in_days" { + description = "Retention period, in days, for backups." + type = number + default = 60 +} + +variable "compute_model" { + description = "The compute model of the Autonomous Database. This is required if using the computeCount parameter. If using cpuCoreCount then it is an error to specify computeModel to a non-null value. ECPU compute model is the recommended model and OCPU compute model is legacy." + type = string + default = "ECPU" +} + +variable "data_storage_size_in_tbs" { + description = "The maximum storage that can be allocated for the database, in terabytes." + type = number + default = 1 +} + +variable "auto_scaling_for_storage_enabled" { + description = "Indicates if auto scaling is enabled for the Autonomous Database storage. The default value is false." + type = bool + default = false +} + +variable "virtual_network_id" { + description = "The ID of the vnet associated with the Autonomous Database." + type = string +} + +variable "admin_password" { + description = "The password must be between 12 and 30characters long, and must contain at least 1 uppercase, 1 lowercase, and 1 numeric character. It cannot contain the double quote symbol or the username 'admin', regardless of casing." + type = string + sensitive = true +} + +variable "auto_scaling_enabled" { + description = " Indicates if auto scaling is enabled for the Autonomous Database CPU core count. The default value is true." + type = bool + default = true +} + +variable "character_set" { + description = "The character set for the autonomous database. The default is AL32UTF8" + type = string + default = "AL32UTF8" +} + +variable "compute_count" { + description = "The compute amount (CPUs) available to the database. Minimum and maximum values depend on the compute model and whether the database is an Autonomous Database Serverless instance or an Autonomous Database on Dedicated Exadata Infrastructure. For an Autonomous Database Serverless instance, the ECPU compute model requires a minimum value of one, for databases in the elastic resource pool and minimum value of two, otherwise. Required when using the computeModel parameter. When using cpuCoreCount parameter, it is an error to specify computeCount to a non-null value. Providing computeModel and computeCount is the preferred method for both OCPU and ECPU." + type = number + default = 2 +} + +variable "ncharacter_set" { + description = "The national character set for the autonomous database. The default is AL16UTF16. Allowed values are: AL16UTF16 or UTF8." + type = string + default = "AL16UTF16" +} + +variable "license_model" { + description = "The Oracle license model that applies to the Oracle Autonomous Database. Bring your own license (BYOL) allows you to apply your current on-premises Oracle software licenses to equivalent, highly automated Oracle services in the cloud. License Included allows you to subscribe to new Oracle Database software licenses and the Oracle Database service. Note that when provisioning an Autonomous Database on dedicated Exadata infrastructure, this attribute must be null. It is already set at the Autonomous Exadata Infrastructure level. When provisioning an Autonomous Database Serverless database, if a value is not specified, the system defaults the value to BRING_YOUR_OWN_LICENSE. Bring your own license (BYOL) also allows you to select the DB edition using the optional parameter." + type = string + default = "LicenseIncluded" +} + +variable "db_version" { + description = "A valid Oracle Database version for Autonomous Database." + type = string + default = "19c" +} + +variable "customer_contacts" { + description = "The email address used by Oracle to send notifications regarding databases and infrastructure. Provide up to 10 unique maintenance contact email addresses." + type = list(string) + default = [] +} + +variable "tags" { + description = "Resource tags for the Cloud Exadata Infrastructure" + type = map(string) + default = null +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/main.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/main.tf new file mode 100644 index 000000000..a9db112aa --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/main.tf @@ -0,0 +1,56 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Resource Block - Oracle ExaInfra @Azure +## Create Oracle ExaInfra @Azure +##################################### + +resource "azurerm_oracle_exadata_infrastructure" "exadata_infrastructure" { + # Required + resource_group_name = var.resource_group_name + location = var.location + zones = [var.zone] + + name = var.name + display_name = var.name + + shape = var.shape + compute_count = var.compute_count + storage_count = var.storage_count + + #database_server_type = var.database_server_type + #storage_server_type = var.storage_server_type + + # Optional + customer_contacts = var.customer_contacts + tags = var.tags + + maintenance_window { + patching_mode = var.maintenance_window.patching_mode + preference = var.maintenance_window.preference + lead_time_in_weeks = coalesce(var.maintenance_window.lead_time_in_weeks,1) + months = coalesce(var.maintenance_window.months,[]) + weeks_of_month = coalesce(var.maintenance_window.weeks_of_month,[]) + days_of_week = coalesce(var.maintenance_window.days_of_week,[]) + hours_of_day = coalesce(var.maintenance_window.hours_of_day,[]) + } + + lifecycle { + ignore_changes = [ + # Updatable from OCI + compute_count, + storage_count, + database_server_type, + storage_server_type, + customer_contacts, + maintenance_window + ] + } +} + +data "azurerm_oracle_exadata_infrastructure" "exadata_infrastructures" { + name = var.name + resource_group_name = var.resource_group_name + depends_on = [azurerm_oracle_exadata_infrastructure.exadata_infrastructure] +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/outputs.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/outputs.tf new file mode 100644 index 000000000..75382e5d2 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/outputs.tf @@ -0,0 +1,28 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Outputs Block - Oracle ExaInfra @Azure +## Create Oracle ExaInfra @Azure +##################################### + +output "resource_id" { + description = "Resource ID of Exadata Infrastructure in Azure" + value = azurerm_oracle_exadata_infrastructure.exadata_infrastructure.id +} + +/* +output "resource" { + description = "Resource Object of Exadata Infrastructure in Azure" + value = azurerm_oracle_exadata_infrastructure.this +} +*/ +output "oci_region" { + description = "Region of the Exadata Infrastructure in OCI" + value = regex("(?:region=)([^?&/]+)",data.azurerm_oracle_exadata_infrastructure.exadata_infrastructures.oci_url)[0] +} + +output "oci_compartment_ocid" { + description = "Compartment OCID of the Exadata Infrastructure in OCI" + value = regex("(?:compartmentId=)([^?&/]+)",data.azurerm_oracle_exadata_infrastructure.exadata_infrastructures.oci_url)[0] +} \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/oracle_provider_req.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/provider_req.tf similarity index 76% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/oracle_provider_req.tf rename to cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/provider_req.tf index f1f97aaeb..f51a8c14b 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/oracle_provider_req.tf +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/provider_req.tf @@ -6,5 +6,9 @@ terraform { oci = { source = "oracle/oci" } + azurerm = { + source = "hashicorp/azurerm" + version = ">=4.9.0" + } } } \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/variables.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/variables.tf new file mode 100644 index 000000000..dce66362a --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-infra/variables.tf @@ -0,0 +1,91 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Variables Block - Oracle ExaInfra @Azure +## Create Oracle ExaInfra @Azure +##################################### + +# Mandatory +variable "location" { + description = "The name of Azure Region where the Exadata Infrastructure should be. e.g. useast" + type = string +} + +variable "name" { + description = "The name of the Exadata Infrastructure at Azure" + type = string + default = "odaaz-infra" +} + +variable "resource_group_name" { + description = "The name of Resource Group in Azure" + type = string + default = "rg-oradb" +} + +variable "zone" { + description = "The availablty zone of the Exadata Infrastructure in Azure" + type = string +} + +variable "compute_count" { + description = "The number of compute servers for the Exadata infrastructure." + type = number + default = 2 +} + +variable "storage_count" { + description = "The number of storage servers for the Exadata infrastructure." + type = number + default = 3 +} + +variable "shape" { + description = "The shape of the Exadata infrastructure resource. e.g. Exadata.X9M" + type = string + default = "Exadata.X9M" +} +/* +variable "database_server_type" { + description = "Database Server Type" + type = string + default = "X11M" +} + +variable "storage_server_type" { + description = "Storage Server Type" + type = string + default = "X11M-HC" +} +*/ + +# Optional +variable "customer_contacts" { + description = "The email address used by Oracle to send notifications regarding databases and infrastructure. Provide up to 10 unique maintenance contact email addresses." + type = list(string) + default = [] +} + +variable "maintenance_window" { + description = "maintenanceWindow properties" + type = object({ + patching_mode = string + preference = string + lead_time_in_weeks = optional(number) + months = optional(list(number)) + weeks_of_month = optional(list(number)) + days_of_week =optional(list(number)) + hours_of_day = optional(list(number)) + }) + default = { + patching_mode = "Rolling" + preference = "NoPreference" + } +} + +variable "tags" { + description = "Resource tags for the Cloud Exadata Infrastructure" + type = map(string) + default = null +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/main.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/main.tf new file mode 100644 index 000000000..812b141e6 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/main.tf @@ -0,0 +1,97 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Resource Block - Oracle ExaVM Cluster @Azure +## Create Oracle ExaVM Cluster @Azure +##################################### + +resource "azurerm_oracle_cloud_vm_cluster" "vm_cluster" { + + # VM Cluster details + resource_group_name = var.resource_group_name + location = var.location + cloud_exadata_infrastructure_id = var.exadata_infrastructure_id + cluster_name = var.cluster_name + name = var.display_name + display_name = var.display_name + hostname = var.hostname + # hostname_actual = var.hostname_actual != null ? var.hostname_actual : null + time_zone = var.time_zone + license_model = var.license_model + gi_version = var.gi_version + system_version = var.system_version + + ssh_public_keys = var.ssh_public_keys + db_servers = var.db_servers + + # Networking + virtual_network_id = var.vnet_id + subnet_id = var.subnet_id + backup_subnet_cidr = var.backup_subnet_cidr + domain = var.domain != "" ? var.domain : null + zone_id = var.zone_id != "" ? var.zone_id : null + + # VM Cluster allocation + cpu_core_count = var.cpu_core_count + memory_size_in_gbs = var.memory_size_in_gbs + db_node_storage_size_in_gbs = var.dbnode_storage_size_in_gbs + + # Exadata storage + data_storage_size_in_tbs = var.data_storage_size_in_tbs + data_storage_percentage= var.data_storage_percentage + local_backup_enabled = var.is_local_backup_enabled + sparse_diskgroup_enabled = var.is_sparse_diskgroup_enabled + + # Diagnostics Collection + data_collection_options { + diagnostics_events_enabled = var.is_diagnostic_events_enabled + health_monitoring_enabled = var.is_health_monitoring_enabled + incident_logs_enabled = var.is_incident_logs_enabled + } + + # Ports + scan_listener_port_tcp = var.scan_listener_port_tcp + scan_listener_port_tcp_ssl = var.scan_listener_port_tcp_ssl + + file_system_configuration { + mount_point = var.mount_point + size_in_gb = var.size_in_gb + } + + tags = var.tags + + lifecycle { + ignore_changes = [ + # For Idempotency + id, + cluster_name, + hostname, + subnet_id, + backup_subnet_cidr, + gi_version, + system_version, + + # Updatable from OCI + license_model, + ssh_public_keys, + db_servers, + cpu_core_count, + memory_size_in_gbs, + db_node_storage_size_in_gbs, + data_storage_size_in_tbs, + ] + } +} + +# Lookup OCID of VM Cluster for output +resource "time_sleep" "wait_10s" { + create_duration = "10s" + depends_on = [azurerm_oracle_cloud_vm_cluster.vm_cluster] +} + +data "azurerm_oracle_cloud_vm_cluster" "vm_clusters" { + depends_on = [ time_sleep.wait_10s ] + name = azurerm_oracle_cloud_vm_cluster.vm_cluster.name + resource_group_name = var.resource_group_name +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/outputs.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/outputs.tf new file mode 100644 index 000000000..eb77042cd --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/outputs.tf @@ -0,0 +1,47 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Outputs Block - Oracle ExaVM Cluster @Azure +## Create Oracle ExaVM Cluster @Azure +##################################### + +output "resource" { + description = "Resource Object of VM Cluster in Azure" + value = data.azurerm_oracle_cloud_vm_cluster.vm_clusters +} + +output "resource_id" { + description = "Resource ID of the VM Cluster in Azure" + value = azurerm_oracle_cloud_vm_cluster.vm_cluster.id +} + +output "vm_cluster_ocid" { + description = "OCID of the VM Cluster in OCI" + value = data.azurerm_oracle_cloud_vm_cluster.vm_clusters.ocid +} + +output "vm_cluster_hostname_actual" { + description = "The actual hostname of the VM Cluster after provision" + value = data.azurerm_oracle_cloud_vm_cluster.vm_clusters.hostname_actual +} + +output "oci_region" { + description = "Region of the VM Cluster in OCI" + value = regex("(?:region=)([^?&/]+)",data.azurerm_oracle_cloud_vm_cluster.vm_clusters.oci_url)[0] +} + +output "oci_compartment_ocid" { + description = "Compartment OCID of the VM Cluster in OCI" + value = regex("(?:compartmentId=)([^?&/]+)",data.azurerm_oracle_cloud_vm_cluster.vm_clusters.oci_url)[0] +} + +output "oci_vcn_ocid" { + description = "OCID of the Virtual Cloud Network (VCN)in OCI" + value = regex("(?:networking/vcns/)([^?&/]+)",data.azurerm_oracle_cloud_vm_cluster.vm_clusters.nsg_url)[0] +} + +output "oci_nsg_ocid" { + description = "OCID of the Network Security Group (NSG) in OCI" + value = regex("(?:network-security-groups/)([^?&/]+)",data.azurerm_oracle_cloud_vm_cluster.vm_clusters.nsg_url)[0] +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/provider_req.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/provider_req.tf new file mode 100644 index 000000000..f51a8c14b --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/provider_req.tf @@ -0,0 +1,14 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + azurerm = { + source = "hashicorp/azurerm" + version = ">=4.9.0" + } + } +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/variables.tf b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/variables.tf new file mode 100644 index 000000000..84cef2e43 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/modules/azurerm-oci-exa-vmcluster/variables.tf @@ -0,0 +1,178 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +##################################### +## Variables Block - Oracle ExaVM Cluster @Azure +## Create Oracle ExaVM Cluster @Azure +##################################### + +# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/oracle_cloud_vm_cluster + +variable "resource_group_name" { + description = "The name of the Resource Group where the Cloud VM Cluster should exist" + type = string +} +variable "location" { + description = "The Azure Region where the Cloud VM Cluster should exist." + type = string +} +variable "exadata_infrastructure_id" { + description = "The OCID of the Cloud Exadata infrastructure." + type = string +} +variable "exadata_infrastructure_name" { + description = "The name of the Cloud Exadata infrastructure." + type = string +} +variable "cluster_name" { + description = "The cluster name for cloud VM cluster. The cluster name must begin with an alphabetic character, and may contain hyphens (-). Underscores (_) are not permitted. The cluster name can be no longer than 11 characters and is not case sensitive." + type = string + default = null +} +variable "display_name" { + description = "The display name for cloud VM cluster." + type = string + default = null +} +variable "hostname" { + description = "The prefix forms the first portion of the Exadata VM Cluster host name. Recommended maximum: 12 characters." + type = string + default = null +} + +variable "time_zone" { + description = "The time zone of the Cloud VM Cluster. For details, see Exadata Infrastructure Time Zones." + type = string + default = null +} +variable "license_model" { + description = "The Oracle license model that applies to the Cloud VM Cluster, either BringYourOwnLicense or LicenseIncluded." + type = string + default = "LicenseIncluded" +} +variable "gi_version" { + description = "A valid Oracle Grid Infrastructure (GI) software version." + type = string +} +variable "system_version" { + description = "Operating system version of the Exadata image." + type = string + default = null +} +variable "db_servers" { + description = "DB Serverset." + type = list(string) + default = null +} +variable "ssh_public_keys" { + description = "The public key portion of one or more key pairs used for SSH access to the Cloud VM Cluster." + type = list(string) +} +variable "tags" { + description = "A mapping of tags which should be assigned to the Cloud VM Cluster." + type = map(string) + default = null +} + +variable "vnet_id" { + description = "The ID of the Virtual Network associated with the Cloud VM Cluster." + type = string +} + +variable "subnet_id" { + description = "The ID of the subnet associated with the Cloud VM Cluster." + type = string +} + +variable "backup_subnet_cidr" { + description = "The backup subnet CIDR of the Virtual Network associated with the Cloud VM Cluster." + type = string + default = null +} + +variable "cpu_core_count" { + description = "The number of CPU cores enabled on the Cloud VM Cluster." + type = string +} + +variable "memory_size_in_gbs" { + description = "The memory to be allocated in GBs." + type = number + default = null +} + +variable "dbnode_storage_size_in_gbs" { + description = "The local node storage to be allocated in GBs." + type = number + default = null +} + +variable "data_storage_size_in_tbs" { + description = "The data disk group size to be allocated in TBs." + type = number + default = null +} +variable "data_storage_percentage" { + description = "The percentage assigned to DATA storage (user data and database files). The remaining percentage is assigned to RECO storage (database redo logs, archive logs, and recovery manager backups). Accepted values are 35, 40, 60 and 80." + type = number + default = null +} +variable "is_local_backup_enabled" { + description = "If true, database backup on local Exadata storage is configured for the Cloud VM Cluster. If false, database backup on local Exadata storage is not available in the Cloud VM Cluster." + type = bool + default = null +} +variable "is_sparse_diskgroup_enabled" { + description = "If true, the sparse disk group is configured for the Cloud VM Cluster. If false, the sparse disk group is not created." + type = bool + default = null +} +variable "is_diagnostic_events_enabled" { + description = "Indicates whether diagnostic collection is enabled for the Cloud VM Cluster. Enabling diagnostic collection allows you to receive Events service notifications for guest VM issues. Diagnostic collection also allows Oracle to provide enhanced service and proactive support for your Exadata system. You can enable diagnostic collection during VM Cluster/Cloud VM Cluster provisioning." + type = bool + default = false +} +variable "is_health_monitoring_enabled" { + description = "Indicates whether health monitoring is enabled for the Cloud VM Cluster. Enabling health monitoring allows Oracle to collect diagnostic data and share it with its operations and support personnel. You may also receive notifications for some events. Collecting health diagnostics enables Oracle to provide proactive support and enhanced service for your system. Optionally enable health monitoring while provisioning a system. " + type = bool + default = false +} +variable "is_incident_logs_enabled" { + description = "Indicates whether incident logs and trace collection are enabled for the Cloud VM Cluster. Enabling incident logs collection allows Oracle to receive Events service notifications for guest VM issues, collect incident logs and traces, and use them to diagnose issues and resolve them. Optionally enable incident logs collection while provisioning a system. " + type = bool + default = false +} +variable "domain" { + description = "The name of the existing OCI Private DNS Zone to be associated with the Cloud VM Cluster. This allow you to specify your own private domain name instead of the default OCI DNS zone (oraclevcn.com)" + type = string + default = "" +} +variable "zone_id" { + description = "The OCID of the existing OCI Private DNS Zone to be associated with the Cloud VM Cluster. This allow you to specify your own private domain name instead of the default OCI DNS zone (oraclevcn.com)" + type = string + default = "" +} + +variable "mount_point" { + description = "file mount path" + type = string + default = "" +} + +variable "size_in_gb" { + description = "file mount path size in gb" + type = string + default = "" +} + +variable "scan_listener_port_tcp" { + description = "listener port" + type = number + default = 1521 +} + +variable "scan_listener_port_tcp_ssl" { + description = "listener port ssl" + type = number + default = 2484 +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/provider.tf b/cd3_automation_toolkit/azurecloud/terraform/provider.tf new file mode 100644 index 000000000..70b6b0cc7 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/provider.tf @@ -0,0 +1,9 @@ +# Azure RM Terraform Provider +provider "azurerm" { + features {} + + subscription_id = "" + tenant_id = "" + client_id = "" + client_secret = "" +} \ No newline at end of file diff --git a/cd3_automation_toolkit/azurecloud/terraform/variables.tf b/cd3_automation_toolkit/azurecloud/terraform/variables.tf new file mode 100644 index 000000000..d25fc24c6 --- /dev/null +++ b/cd3_automation_toolkit/azurecloud/terraform/variables.tf @@ -0,0 +1,118 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +############################ +# +# Variables Block +# Azure OCI +# +############################ + + +########################### +###Oracle ADB @Azure ###### +########################### + +variable "az_oci_adb" { + type = map(object({ + display_name = string + az_region = string + resource_group_name = string + network_resource_group_name = string + virtual_network_id = string + subnet_id = string + db_workload = string + mtls_connection_required = bool + backup_retention_period_in_days = number + compute_model = string + data_storage_size_in_tbs = number + auto_scaling_for_storage_enabled = bool + admin_password = string + auto_scaling_enabled = bool + character_set = string + compute_count = number + ncharacter_set = string + license_model = string + db_version = string + customer_contacts = optional(list(string)) + common_tags = optional(map(string)) + })) + default = {} +} + + +########################### +###Oracle ExaInfra @Azure ###### +########################### + +variable "az_oci_exa_infra" { + type = map(object({ + display_name = string + az_region = string + az_zone = string + resource_group_name = string + + compute_count = number + storage_count = number + shape = string + database_server_type = optional(string) + storage_server_type = optional(string) + + maintenance_window = object({ + patching_mode = string + preference = string + lead_time_in_weeks = optional(number) + months = optional(list(number)) + weeks_of_month = optional(list(number)) + days_of_week = optional(list(number)) + hours_of_day = optional(list(number)) + }) + customer_contacts = optional(list(string)) + common_tags = optional(map(string)) + + })) + default = {} +} + + +variable "az_oci_exa_vmclusters" { + type = map(object({ + display_name = string + az_region = string + resource_group_name = string + network_resource_group_name = string + virtual_network_id = string + subnet_id = string + exadata_infrastructure_name = string + hostname = string + cpu_core_count = string + gi_version = string + license_model = string + ssh_public_keys = list(string) + gi_version = string + backup_subnet_cidr = optional(string) + cluster_name = optional(string) + domain = optional(string) + oci_zone_id = optional(string) + diagnostics_events_enabled = optional(bool) + health_monitoring_enabled = optional(bool) + incident_logs_enabled = optional(bool) + data_storage_percentage = optional(number) + data_storage_size_in_tbs = optional(number) + db_node_storage_size_in_gbs = optional(number) + local_backup_enabled = optional(bool) + sparse_diskgroup_enabled = optional(bool) + memory_size_in_gbs = optional(number) + scan_listener_port_tcp = optional(number) + scan_listener_port_tcp_ssl = optional(number) + system_version = optional(string) + time_zone = optional(string) + mount_point = optional(string) + size_in_gb = optional(number) + common_tags = optional(map(string)) + + + })) + default = {} +} + diff --git a/cd3_automation_toolkit/user-scripts/OPA/Compute/oci_restrict_instance_types.rego b/cd3_automation_toolkit/common/opa/Compute/oci_restrict_instance_types.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Compute/oci_restrict_instance_types.rego rename to cd3_automation_toolkit/common/opa/Compute/oci_restrict_instance_types.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Compute/oci_secure_vm_access.rego b/cd3_automation_toolkit/common/opa/Compute/oci_secure_vm_access.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Compute/oci_secure_vm_access.rego rename to cd3_automation_toolkit/common/opa/Compute/oci_secure_vm_access.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/deny_api_keys_admin_group.rego b/cd3_automation_toolkit/common/opa/Identity/deny_api_keys_admin_group.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/deny_api_keys_admin_group.rego rename to cd3_automation_toolkit/common/opa/Identity/deny_api_keys_admin_group.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/deny_iam_admin.rego b/cd3_automation_toolkit/common/opa/Identity/deny_iam_admin.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/deny_iam_admin.rego rename to cd3_automation_toolkit/common/opa/Identity/deny_iam_admin.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/deny_storage_admins_delete_resources.rego b/cd3_automation_toolkit/common/opa/Identity/deny_storage_admins_delete_resources.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/deny_storage_admins_delete_resources.rego rename to cd3_automation_toolkit/common/opa/Identity/deny_storage_admins_delete_resources.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/dynamic_groups_check.rego b/cd3_automation_toolkit/common/opa/Identity/dynamic_groups_check.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/dynamic_groups_check.rego rename to cd3_automation_toolkit/common/opa/Identity/dynamic_groups_check.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/enable_service_level_admins.rego b/cd3_automation_toolkit/common/opa/Identity/enable_service_level_admins.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/enable_service_level_admins.rego rename to cd3_automation_toolkit/common/opa/Identity/enable_service_level_admins.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/ensure_mfa_for_users.rego b/cd3_automation_toolkit/common/opa/Identity/ensure_mfa_for_users.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/ensure_mfa_for_users.rego rename to cd3_automation_toolkit/common/opa/Identity/ensure_mfa_for_users.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/ensure_tenancy_admins_access.rego b/cd3_automation_toolkit/common/opa/Identity/ensure_tenancy_admins_access.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/ensure_tenancy_admins_access.rego rename to cd3_automation_toolkit/common/opa/Identity/ensure_tenancy_admins_access.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/iam_email_check.rego b/cd3_automation_toolkit/common/opa/Identity/iam_email_check.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/iam_email_check.rego rename to cd3_automation_toolkit/common/opa/Identity/iam_email_check.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Identity/oci_iam_policy_checks.rego b/cd3_automation_toolkit/common/opa/Identity/oci_iam_policy_checks.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Identity/oci_iam_policy_checks.rego rename to cd3_automation_toolkit/common/opa/Identity/oci_iam_policy_checks.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/default_tags_check.rego b/cd3_automation_toolkit/common/opa/Logging_Monitoring/default_tags_check.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/default_tags_check.rego rename to cd3_automation_toolkit/common/opa/Logging_Monitoring/default_tags_check.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_bucket_write_logging_check.rego b/cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_bucket_write_logging_check.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_bucket_write_logging_check.rego rename to cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_bucket_write_logging_check.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_log_groups_checks.rego b/cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_log_groups_checks.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_log_groups_checks.rego rename to cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_log_groups_checks.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_resource_tags.rego b/cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_resource_tags.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_resource_tags.rego rename to cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_resource_tags.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_vcn_flow_logs_check.rego b/cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_vcn_flow_logs_check.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Logging_Monitoring/oci_vcn_flow_logs_check.rego rename to cd3_automation_toolkit/common/opa/Logging_Monitoring/oci_vcn_flow_logs_check.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_adb_access_restrictions.rego b/cd3_automation_toolkit/common/opa/Network/oci_adb_access_restrictions.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_adb_access_restrictions.rego rename to cd3_automation_toolkit/common/opa/Network/oci_adb_access_restrictions.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_default_sl_checks.rego b/cd3_automation_toolkit/common/opa/Network/oci_default_sl_checks.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_default_sl_checks.rego rename to cd3_automation_toolkit/common/opa/Network/oci_default_sl_checks.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_deny_ingress_for_nsg.rego b/cd3_automation_toolkit/common/opa/Network/oci_deny_ingress_for_nsg.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_deny_ingress_for_nsg.rego rename to cd3_automation_toolkit/common/opa/Network/oci_deny_ingress_for_nsg.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_deny_ingress_for_sl.rego b/cd3_automation_toolkit/common/opa/Network/oci_deny_ingress_for_sl.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_deny_ingress_for_sl.rego rename to cd3_automation_toolkit/common/opa/Network/oci_deny_ingress_for_sl.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_container_config.rego b/cd3_automation_toolkit/common/opa/Network/oci_enforce_container_config.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_container_config.rego rename to cd3_automation_toolkit/common/opa/Network/oci_enforce_container_config.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_dns_zones.rego b/cd3_automation_toolkit/common/opa/Network/oci_enforce_dns_zones.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_dns_zones.rego rename to cd3_automation_toolkit/common/opa/Network/oci_enforce_dns_zones.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_lb_config.rego b/cd3_automation_toolkit/common/opa/Network/oci_enforce_lb_config.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_lb_config.rego rename to cd3_automation_toolkit/common/opa/Network/oci_enforce_lb_config.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_network_security.rego b/cd3_automation_toolkit/common/opa/Network/oci_enforce_network_security.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_enforce_network_security.rego rename to cd3_automation_toolkit/common/opa/Network/oci_enforce_network_security.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Network/oci_oic_access_restrictions.rego b/cd3_automation_toolkit/common/opa/Network/oci_oic_access_restrictions.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Network/oci_oic_access_restrictions.rego rename to cd3_automation_toolkit/common/opa/Network/oci_oic_access_restrictions.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Risk_score/oci_check_score_constriant.rego b/cd3_automation_toolkit/common/opa/Risk_score/oci_check_score_constriant.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Risk_score/oci_check_score_constriant.rego rename to cd3_automation_toolkit/common/opa/Risk_score/oci_check_score_constriant.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Storage/oci_block_volumes.rego b/cd3_automation_toolkit/common/opa/Storage/oci_block_volumes.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Storage/oci_block_volumes.rego rename to cd3_automation_toolkit/common/opa/Storage/oci_block_volumes.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Storage/oci_deny_public_bucket.rego b/cd3_automation_toolkit/common/opa/Storage/oci_deny_public_bucket.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Storage/oci_deny_public_bucket.rego rename to cd3_automation_toolkit/common/opa/Storage/oci_deny_public_bucket.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Storage/oci_fss.rego b/cd3_automation_toolkit/common/opa/Storage/oci_fss.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Storage/oci_fss.rego rename to cd3_automation_toolkit/common/opa/Storage/oci_fss.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Storage/oci_secure_database.rego b/cd3_automation_toolkit/common/opa/Storage/oci_secure_database.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Storage/oci_secure_database.rego rename to cd3_automation_toolkit/common/opa/Storage/oci_secure_database.rego diff --git a/cd3_automation_toolkit/user-scripts/OPA/Storage/oci_secure_storage.rego b/cd3_automation_toolkit/common/opa/Storage/oci_secure_storage.rego similarity index 100% rename from cd3_automation_toolkit/user-scripts/OPA/Storage/oci_secure_storage.rego rename to cd3_automation_toolkit/common/opa/Storage/oci_secure_storage.rego diff --git a/cd3_automation_toolkit/common/python/__init__.py b/cd3_automation_toolkit/common/python/__init__.py new file mode 100644 index 000000000..ce4f0b656 --- /dev/null +++ b/cd3_automation_toolkit/common/python/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + + +from .commonTools import * + + + diff --git a/cd3_automation_toolkit/common/python/commonTools.py b/cd3_automation_toolkit/common/python/commonTools.py new file mode 100644 index 000000000..47d49c467 --- /dev/null +++ b/cd3_automation_toolkit/common/python/commonTools.py @@ -0,0 +1,322 @@ + +import re +import os +import shutil +import datetime +import pandas as pd +from openpyxl import load_workbook +from openpyxl.styles import PatternFill +from openpyxl.styles import Alignment +from openpyxl.styles import Border +from openpyxl.styles import Side +import collections +import warnings +warnings.simplefilter("ignore") +from contextlib import contextmanager + + +@contextmanager +def section(title='', header=False, padding=117): + separator = '-' if not header else '=' + # Not sure why 117 but thats how it was before. + print(f'{title:{separator}^{padding}}') + yield + if header: + print(separator * padding) + +def exit_menu(msg, exit_code=1): + print(msg) + exit(exit_code) + +class commonTools(): + endNames = {'', '', ''} + + def __init__(self): + pass + + # Read rows from CD3 + def data_frame(filename, sheetname): + + # Read the tab from excel, Drop null values, Reset index + df, col_headers = commonTools.read_cd3(filename, sheetname) + df = df.dropna(how='all') + df = df.reset_index(drop=True) + + return df + def read_cd3(cd3file, sheet_name): + df = {} + try: + df = pd.read_excel(cd3file, sheet_name=sheet_name, skiprows=1, dtype=object) + + except Exception as e: + if("Events" in str(e) or "Notifications" in str(e)): + print("\nTabs - \"Events\" or \"Notifications\" is missing in the CD3. Please make sure to use the correct input file for Events and Notifications in properties file...Exiting!!") + exit(1) + else: + print("Error occurred while reading the CD3 excel sheet: "+ str(e)) + exit(1) + + yield df + try: + book = load_workbook(cd3file) + sheet = book[sheet_name] + except KeyError as e: + if 'does not exist' in str(e): + print("\nTab - \""+sheet_name+"\" seems to be missing in the CD3. Please make sure to use the right CD3 in properties file.....Exiting!!") + exit(1) + except Exception as e: + print(str(e)) + print("Exiting!!") + exit(1) + + values_for_column = collections.OrderedDict() + # values_for_column={} + for j in range(0, sheet.max_column): + col_name = sheet.cell(row=2, column=j + 1).value + if (type(col_name) == str): + values_for_column[col_name] = [] + yield values_for_column + + #Write exported rows to cd3 + def write_to_cd3(values_for_column, cd3file, sheet_name,append=False): + try: + book = load_workbook(cd3file) + sheet = book[sheet_name] + + + except Exception as e: + print(str(e)) + print("Exiting!!") + exit(1) + if (sheet_name == "VCN Info"): + onprem_destinations = "" + ngw_destinations = "" + igw_destinations = "" + for destination in values_for_column["onprem_destinations"]: + onprem_destinations=destination+","+onprem_destinations + for destination in values_for_column["ngw_destinations"]: + ngw_destinations = destination + "," + ngw_destinations + for destination in values_for_column["igw_destinations"]: + igw_destinations = destination + "," + igw_destinations + + if (onprem_destinations != "" and onprem_destinations[-1] == ','): + onprem_destinations = onprem_destinations[:-1] + if (ngw_destinations != "" and ngw_destinations[-1] == ','): + ngw_destinations = ngw_destinations[:-1] + if (igw_destinations != "" and igw_destinations[-1] == ','): + igw_destinations = igw_destinations[:-1] + + sheet.cell(3,2).value = onprem_destinations + sheet.cell(4,2).value = ngw_destinations + sheet.cell(5,2).value = igw_destinations + try: + book.save(cd3file) + book.close() + except Exception as e: + print(str(e)) + print("Exiting!!") + exit(1) + return + + + #rows_len=len(rows) + rows_len = len(values_for_column["Region"]) + sheet_max_rows = sheet.max_row + #If no rows exported from OCI, remove the sample data as well + if(rows_len == 0) : + if not append: + print("0 rows exported; Nothing to write to CD3 excel; Tab "+sheet_name +" will be empty in CD3 excel!!") + for i in range(0, sheet.max_row): + for j in range(0, sheet.max_column): + sheet.cell(row=i + 3, column=j + 1).value = "" + try: + book.save(cd3file) + book.close() + except Exception as e: + print(str(e)) + print("Exiting!!") + exit(1) + return + + if append: + for x in range(1, sheet_max_rows): + if sheet['A'][x].value == None: + last_line = x + break + #rows_len +=last_line + large = rows_len + start = last_line+1 + + + else: + start = 3 + if (rows_len > sheet_max_rows): + large = rows_len + else: + large = sheet_max_rows + + df, values_for_column_sheet = commonTools.read_cd3(cd3file, sheet_name) + + #Put Data + j=0 + for i in range(0,large): + + for col_name in values_for_column.keys(): + + #Check if column name to be populated in present in the sheet. + if col_name not in values_for_column_sheet: + continue + # Data + if(i>=rows_len): + sheet.cell(row=i+start, column=j+1).value = "" + else: + sheet.cell(row=i+start, column=j+1).value = values_for_column[col_name][i] + sheet.cell(row=i+start, column=j+1).alignment = Alignment(wrap_text=True) + j=j+1 + j=0 + + + brdr = Border(left=Side(style='thin'), + right=Side(style='thin'), + top=Side(style='thin'), + bottom=Side(style='thin'), + ) + + for row in sheet.iter_rows(min_row=3): + for cell in row: + cell.border = brdr + + # Add color for exported sec rules and route rules + if (sheet_name == "RouteRulesinOCI" or sheet_name == "SecRulesinOCI" or sheet_name == "DRGRouteRulesinOCI"): + names = [] + # Add color coding to exported rules + for row in sheet.iter_rows(min_row=3): + c = 0 + region = "" + name = "" + for cell in row: + c = c + 1 + if (c == 1): + region = cell.value + continue + elif (c == 4): + name = cell.value + break + + vcn_name = region + "_" + name + if (vcn_name not in names): + names.append(vcn_name) + for cellnew in row: + if (len(names) % 2 == 0): + cellnew.fill = PatternFill(start_color="94AFAF", end_color="94AFAF", fill_type="solid") + cellnew.border = brdr + else: + cellnew.fill = PatternFill(start_color="E5DBBE", end_color="E5DBBE", fill_type="solid") + cellnew.border = brdr + else: + for cellnew in row: + if (len(names) % 2 == 0): + cellnew.fill = PatternFill(start_color="94AFAF", end_color="94AFAF", fill_type="solid") + cellnew.border = brdr + else: + cellnew.fill = PatternFill(start_color="E5DBBE", end_color="E5DBBE", fill_type="solid") + cellnew.border = brdr + try: + book.save(cd3file) + book.close() + except Exception as e: + print(str(e)) + print("Exiting!!") + exit(1) + + # Check value exported + # If None - replace with "" + # If list, convert to comma sepearted string + def check_exported_value(value): + if value == None: + value = "" + if ("list" in str(type(value))): + str1 = "" + if (value.__len__() == 0): + value = "" + for v in value: + str1 = v + "," + str1 + if (str1 != "" and str1[-1] == ','): + value = str1[:-1] + + return value + # Check TF variable Name + def check_tf_variable(var_name): + tfname = re.compile('[^a-zA-Z0-9_-]') + tfnamestart = re.compile('[A-Za-z]') + + var_name = tfname.sub("-", var_name) + x = tfnamestart.match(var_name) + # variable name doesnot start with letter; append with c + if (x == None): + var_name = "c" + var_name + return var_name + + # Process ColumnValues + def check_columnvalue(columnvalue): + + if str(columnvalue).lower() == 'true' or str(columnvalue).lower() == 'false': + columnvalue = str(columnvalue).lower() + + if (columnvalue.lower() == 'nan'): + columnvalue = "" + + # replace \ with \\ + if("\\" in columnvalue): + columnvalue = columnvalue.replace("\\", "\\\\") + + # replace " with \" + if("\"" in columnvalue): + columnvalue=columnvalue.replace("\"","\\\"") + + return columnvalue + + # Process column values with :: + def check_multivalues_columnvalue(columnvalue, columnname, tempdict): + columnvalue = str(columnvalue).strip() + columnname = commonTools.check_column_headers(columnname) + if "::" in columnvalue: + if ".Flex" in columnvalue or ".Micro" in columnvalue: + columnname = commonTools.check_column_headers(columnname) + multivalues = columnvalue.split("::") + multivalues = [str(part).strip() for part in multivalues if part] + tempdict = {columnname: multivalues} + elif columnname != 'Compartment Name' and "ipv6" not in columnname.lower(): + columnname = commonTools.check_column_headers(columnname) + multivalues = columnvalue.split("::") + multivalues = [str(part).strip() for part in multivalues ]#if part] + tempdict = {columnname: multivalues} + return tempdict + + # Check CD3 Column headers + def check_column_headers(var_name): + # replace special characters and spaces with '_' and convert to lowercase + # replaces multiple occurrence of '_' to just 1 + var_name = var_name.strip() + var_name = re.sub('[@!#$%^&*<>?/}{~: \n()|-]', '_', var_name).lower() + var_name = re.sub('_+', '_', var_name).lower() + return var_name + + def backup_file(src_dir, resource, pattern): + dest_dir = str(src_dir) + "/backup_" + resource + "/" + datetime.datetime.now().strftime("%d-%m-%H%M%S").replace('/', '-') + for f in os.listdir(str(src_dir)): + if f.endswith(pattern): + print("Backing up existing " + f + " to " + dest_dir) + if not os.path.exists(dest_dir): + # print("\nCreating backup dir " + dest_dir + "\n") + os.makedirs(dest_dir) + + src = os.path.join(str(src_dir), f) + #dest = os.path.join(dest_dir, f) + # print("backing up ....." + src +" to "+dest) + shutil.move(src, dest_dir) + """if (overwrite == 'yes'): + shutil.move(src, dest_dir) + elif (overwrite == 'no'): + shutil.copyfile(src, dest) + """ diff --git a/cd3_automation_toolkit/connectAzure.properties b/cd3_automation_toolkit/connectAzure.properties new file mode 100644 index 000000000..191f96d90 --- /dev/null +++ b/cd3_automation_toolkit/connectAzure.properties @@ -0,0 +1,23 @@ +[Default] + +################################################################################################################## + ## Required Parameters ## +################################################################################################################## + +# Friendly name for the Azure Subscription; The generated .auto.tfvars files will be prefixed with this +prefix= + +################################################################################################################## + ## Auth Details Parameters ## +# Leave below details empty if there is no need to run APIs against Azure portal +# This can be used to generate only terraform without applying it +################################################################################################################## + +subscription_id= + +tenant_id= + +client_id= + +client_secret= + diff --git a/cd3_automation_toolkit/connectCloud.py b/cd3_automation_toolkit/connectCloud.py new file mode 100644 index 000000000..e58f97c69 --- /dev/null +++ b/cd3_automation_toolkit/connectCloud.py @@ -0,0 +1,30 @@ +import sys +import subprocess + + +def main(): + if len(sys.argv) != 3: + print("Usage: python connectCloud.py ") + print("Example: python connectCloud.py oci tenancyconfig.properties") + print("Example: python connectCloud.py azure connectAzure.properties") + return + + cloud_provider = sys.argv[1].lower() + argument = sys.argv[2] + + if cloud_provider == 'oci': + script_name = 'user-scripts/createTenancyConfig.py' + elif cloud_provider == 'azure': + script_name = 'user-scripts/connectAzure.py' + else: + print("Invalid cloud provider. Use 'azure' or 'oci'.") + return + + try: + subprocess.run([sys.executable, script_name, argument], check=True) + except subprocess.CalledProcessError as e: + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/cd3_automation_toolkit/connectGCP.properties b/cd3_automation_toolkit/connectGCP.properties new file mode 100644 index 000000000..ec604a3fc --- /dev/null +++ b/cd3_automation_toolkit/connectGCP.properties @@ -0,0 +1,31 @@ +[Default] + +################################################################################################################## + ## Required Parameters ## +################################################################################################################## + +# Friendly name for the Customer; The generated .auto.tfvars files will be prefixed with this +prefix=new + +organization_id=378499894770 + +# Auth Mechanism for GCP APIs - api_key +# Please make sure to add IAM policies for service account before executing connectContainerToGCP.py +auth_mechanism=api_key + +# Path to JSON file having private key information for the service account; +# Defaults to /cd3user/cloud_infra/gcp/keys/gcp_api_private.json when left empty +config_file=/Users/susingla/PyCharmProjects/orahub-develop/cd3_automation_toolkit/gcp/test-api-private.json + +# The outdir_structure_file defines the grouping of the terraform auto.tf.vars for the various generated resources. +# To have all the files generated in a single directory in the corresponding region, leave this variable blank. +# To group resources into different directories within each region - specify the absolute path to the file. +# The default file is specified below. You can make changes to the grouping in the below file to suit your deployment +#outdir_structure_file= +#or +outdir_structure_file=/Users/susingla/PyCharmProjects/orahub-develop/cd3_automation_toolkit/user-scripts/outdir_structure_file.properties + +# SSH Key for launched instances; Use '\n' as the delimiter to add multiple ssh keys. +# Example: "ssh-rsa AAXXX......yhdlo\nssh-rsa AAxxskj...edfwf" +# Optional +ssh_public_key= diff --git a/cd3_automation_toolkit/connectOCI.properties b/cd3_automation_toolkit/connectOCI.properties new file mode 100644 index 000000000..2ae1c7df9 --- /dev/null +++ b/cd3_automation_toolkit/connectOCI.properties @@ -0,0 +1,94 @@ +[Default] + +################################################################################################################## + ## Required Parameters ## +################################################################################################################## + +# Friendly name for the Customer Tenancy eg: demotenancy; The generated .auto.tfvars files will be prefixed with this. +prefix= + +tenancy_ocid= + +# Example: us-phoenix-1 +region= + +# Auth Mechanism for OCI APIs - api_key,instance_principal,session_token +# Please make sure to add IAM policies for user/instance_principal before executing createTenancyConfig.py +auth_mechanism=api_key + +################################################################################################################## + ## Auth Details Parameters ## +# Required only for ${auth_mechanism} as api_key; Leave below params empty if 'instance_principal' or 'session_token' +# is used +################################################################################################################## + +user_ocid= +#Path of API Private Key (PEM Key) File; Defaults to /cd3user/tenancies/keys/oci_api_private.pem when left empty +key_path= +fingerprint= + +################################################################################################################## + ## Deployment Parameters ## +################################################################################################################## + +# The outdir_structure_file defines the grouping of the terraform auto.tf.vars for the various generated resources. +# To have all the files generated in a single directory in the corresponding region, leave this variable blank. +# To group resources into different directories within each region - specify the absolute path to the file. +# The default file is specified below. You can make changes to the grouping in the below file to suit your deployment + +#outdir_structure_file= +#or +outdir_structure_file=/cd3user/oci_tools/cd3_automation_toolkit/user-scripts/outdir_structure_file.properties + + +# IaC Tool to be configured - Terraform or OpenTofu +# Default is terraform +# To use OpenTofu, specify tofu +tf_or_tofu=terraform + +# SSH Key for launched instances; Use '\n' as the delimiter to add multiple ssh keys. +# Example: ssh-rsa AAXXX......yhdlo\nssh-rsa AAxxskj...edfwf +# Optional +ssh_public_key= + +################################################################################################################## + ## Advanced Parameters for DevOps ## +# Below OCI Objects - Remote State Bucket Name and DevOps Project/Repo and a Notification Topic will be created/fetched +# from region specified in ${region} above. +# These values are required to be set as "yes" for Jenkins Configuration. +################################################################################################################## + + +# Compartment OCID where Bucket and DevOps Project/repo will be created; defaults to root if left empty. +compartment_ocid= + +# Remote state configuration +# Enter yes if remote state needs to be configured, else tfstate will be stored on local filesystem. +use_remote_state=no + +# Specify bucket name if you want to use existing bucket else leave empty. +# If left empty, Bucket with name ${customer_name}-automation-toolkit-bucket will be created/reused in ${region}. +remote_state_bucket_name= + +# OCI DevOps GIT configuration +# Enter yes if generated terraform_files need to be stored in OCI DevOps GIT Repo else they will be stored on local +# filesystem. Will enforce 'yes' for use_remote_state in case below is set to 'yes' +use_oci_devops_git=no + +# Specify Repo name if you want to use existing OCI Devops GIT Repository else leave empty Format: +# If left empty, DevOps items with names ${customer_name}-automation-toolkit-project/repo/topic will be created/reused +# in ${region}. +oci_devops_git_repo_name= + +# User Details to perform GIT operations in OCI Devops GIT Repo and Remote Terraform State Management; Mandatory when using $(auth_mechanism) as instance_principal +# or session_token +# Customer Secret Key will be created for this user for S3 credentials of the bucket. +# When left empty, it will be fetched from $(user_ocid) for $(auth_mechanism) as api_key. +# Format: /@ eg oracleidentitycloudservice/devopsuser@oracle.com@ocitenant +# Users in Custom Domain are not supported as of now. +oci_devops_git_user= + +# When left empty, same key file from $(key_path) used for $(auth_mechanism) as api_key will be copied to +# /cd3user/tenancies// and used for GIT Operations. +oci_devops_git_key= + diff --git a/cd3_automation_toolkit/example/CD3-Azure-template.xlsx b/cd3_automation_toolkit/example/CD3-Azure-template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5a1a761a5a76c6ea1494e705e5b7bbd1049c1c6a GIT binary patch literal 62191 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 E5C78P&j0`b literal 0 HcmV?d00001 diff --git a/cd3_automation_toolkit/example/CD3-Blank-template.xlsx b/cd3_automation_toolkit/example/CD3-Blank-template.xlsx index bd05b65fe49a6983ddc945c821d400d49ec5b53a..6aad6e70ec7626e43694e85076dc6ec8c2d46acb 100644 GIT binary patch delta 87560 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

tqwFE8p^2)mP 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 delta 87336 zcmbTdby$^M6F!PaiF8Owi4xM?AdS-9CEXoTk0>EXigZbXlyrAV$EG`^yBp54(f9j& zzu!6My3YA$yY{S^Su^+CGtb)WZEX=+bRpW0hbWI~KkqHwJ%)kNjzmGBLSwdlWcCHu zpQ+3Gr;!Lpq!0=&z+=oK-(cnsXC^qRbK=CmQZcLN{VwTUW(r;KOp_ozQA*wl*3nLr z{Y^IHaL@JOPKI{S+a6as#{Eh2ix9CDz5d(VN=8PZ^J{##ffq3Q>5xOV&^2P6ux*+I zjiELDe$R6gEMHby|H{Qkl0Fd=?xC;6ZmS#R7Uh`(bmNSS00vJgvN%&*6~`8$3yYz5 z9n7OR)Aqp|v(5f=+^Jqwp9GCXN0#wzeGbG=6621`l{jVE@smkCRDwta66pRn7Hm>Q zW&2&}EgLEG{9Y&K>bi`9wK?ECyPIqc_rEOr24Q4FHW)i^SG#aE`cp6Nq zOJ8fqFV3mTNB<(#RdWmoYa)05D$3-;FV*;NOQyii1sefi;th3LIAVJ@@)SP`uh)4x zH>}_}ntmv(Yll6C+kj1eshTCnSuBJ6%$GF?qNL5_j1*6mIrG={`Duoan0`sP5w=S| z-~heTA~GPBVvEZ63DPe*)7uweI$qn;2A%kK<}O5?eHD{qvYR?eytbU0nza^VWk)tg zo`Y5?%0xGFdQ7oDMvEWf?>Ti5qIqfBz=&lO`HyXF5~WYQ);5KN2a$GOjN)^rP%sym1SSLFh?%55{YYqXwB~etC1RG+|IQxCbxg^m zYRN6EvKf&2FoBhD)KqlkP%=9sok$gZU?TO@!K3!ZYmbLjo>_Zzr{iY2C@%Ell2_PJIY8WjCMaLKd82%@R5kjU>8&bo7VyjhiM2;TvCY^zoal!`rqw4)A}~ z+15)%NTwN*8{1%_3;v*YQ4Tu&G`SbQj9f{Of^)W|&@ujvSJ;wf`(`U5dKGPFUfxY? zioW#YV3%kG4Xh;J0!$?xGN0~jU@xACY9vAP({Tg>$K3!tp|6Wc5pf+@ybNBt)F#<+ z0D1pPd>cCC@%GwP(?<*0?KE=Pig?kl&1TP6DTYwl1IgyS`SA#kMyk6+u_y|qL(t>b z1PeM_w%1v`BPAaM#7E!sdYZN^^`#hS3Rr!~=7P7t5`+2G9rDd{fxVN`!-R*P86IuP z39d9vt<791^5=uj{WS8V2U>_hGeuIz3qXf{gOGE?>QByQBihKy7w+1RKlbb^IK9?M zLlU%Fo}k{E47T{hmm`(2aVo>i`e`?}N2C2|y%4@hgp1%vZz}%dhse47Og1ZU z^o_Z<{_}Sa#bz{Va|}^|>k?ny;eAlE90_rDHih&0oSI zOCPWij+k-uZ@GK}SwmS^vmZp0N3_e^$?9|(*u5$5$KRhFv%7kt{8s)&$kqEU@^+(# zz2XsbUHmTuLZq08rS^R2W!vWWqD8+K0GNl^+Qo(#j%9{4L&qvYKXoAx!o6r2btKw{ zC_$ndtj$6+dxwM>C_UydegsuqMMB+abqF+Cpvd>9Ww<|gkq}{h9fG+iD6r|b40p$p zZ8y4W?aJ9=4M^D&X7hFJX{oo&Hg!CUjpG`v&7{@nkq?@tusfuZqE^#HI^u5*uQ6;=w9o2s(&4B@{6i`arI+s zuOKbLBz4I&f@m#M%Bwh+Q+bch#VDc7F`t-A+0YeUV&u)z0Cyh*LVBh_>fu+!C~TkE znsk(LHd3!??Zk6eQ;ADSRAB*9P58dc8U-@0#JoiQr+A}B%g^2^7^(UYl&ZC;@^$;4 z42reKM6oLKzr^E<(@_rI?CN*&_h~F5!TFiv9{%3Yp7Mdj=<*ld>qD}Do-JxOqOtHE)k0PI-&?^HBxNoKs9;e;!;Fx9hNX{p?H8MLRJ&WG5 zxdd&ZVSlRlvbc;aWeRJ|o%BfAdPDk~sijk~_`vwO^tVe;9L3Foy&gxjSf?}!(V>Bj zQsJ@H&$f4(YkCoFgOf7|498ImVA6cv<*>#n$J^DJw2b)S&=0>+_ZFWQ-aO!uX!y^4 zd!aN|pTqb4a4#jDDCLFHKC}N>u=*fl#XZsvUl&h(DOsxs-Jg2}AJ_}WAnBA2F8W0e z0wp!VE6mfWCGqSatdBb>&Kj+*f^gM>(gRMzXq6g{0gq#IXWYzkrEmx7eM>e8y9n`` zGHE~b+-0P~AsoMf@u|=SEE$9I?!|%66#1USxcF@=EkZs|78;1`9P=b84{-}W$m}P& z9_uSVChmA!@5k~aC=kx(wXwjAIaXueBqE;H*P_ndG9R2uCxrdY=s|?1<>B_Hj1G^ezF9=o^6GqZW=NG76praf(A~fa zeMs;8$oiVJ1!e=*2Dj-Ez!j6a+OWWPN$Dsfqzh zKfRZtN!;1)onHHHLYutl@}(;mN1+GYM9v(hK9J5M@ycd}_WFE=w#4K62K*lJ%fJ9$ z^u`u|i-W-j?nXQ_45qfJEuGGph=ck&HlGT6Kxf}%6&@F<4n(6cn0QYc(#8Iz^1Fx; zxv5S-hwxlCS_Hf?@-GQCQ|Ex3^lD3FHV&8keGGywz2#Kq63eInGitFmQRe30a}l&< zTfp%aztcmGJ7?B7CZMHfq*Y;|nHv^Icamfd?>6J%1LVF>Wbd%rkfIwN$$yR1XV@~k z6kft>=oVhU`|=3p3eg;x%k=8f+Qdh0d zz7RcM=Yhi%a4(Vj7*hI(t+y^I-!_xtXA?en`BNEF95=2T=4F>Mg1ihR z%lpqPqeuebNrxp5UiK)5zH*NH3B%BQZmrAJ0@ z5$&6{r>M1AlYKFHiv)$7Z&>mr=3+YVMg&J&+3eH4LJ}x8_D3L9BS^c=qYS;qd2fLd zfhQlB+T4ljpL3Vfgt3U1X#7>~riAXDnoiqJmA)3^L}`zIU(Q95)A($Kf{xWP67L5c zG5Z=Z!tIOgme59%qqh99Y4!qUCIrn^Gc|UI6?>TpAa6?oUZLJOHdP9)5^0sY>T)j` z4ct`99Uq&Sv_IMw>8t!EJMVhFrGK$;+1j=AaV5(rZZ?g#(yO6o`f$C@pQ0g*UCD~C zO3iAbmSheUcUm`TKBN)d&G2S+=#YMDp;krxc(mi(^e*z79&RZsekClN|HD^9rMra3 zun&O9W#U)x>?79e8Ku-DUFfKC*o!+Kh+trL`(R-3BYmu&l;SW5!2+4-0^e%CIH!d3 zvZT-bY<=y4w&Vb-%3UG69G0k^$bs#vr zc-?r+cz1pkY~y{I0yy1WR5spp-mNm~0au4|A+xuhRTn3%ww)jErVrLhZFO~Ryoc}h zRnGMq1^5L#&sX#sz0X%F$5Z9z1H9k8z?MXyA;Zn^Ieu{=*7#ws5mBsm^~{cW=K!D7 zmgI?nZ9qay$+GBb8@ViwEMI$Iciw?3WY>t~=yqOQu~_MW z2h?^dtsShaQQdr(HJvJ7gB);?+M7Xiz)q4 z{(S67nzZt#mkJb{58CNG%46Cth1oET(}b0QKtcs{>eZRNj_0TNf1k0Y>qS{Sh#?~y zmxG~_CO+~InH$~XB>v)6@%UfDAnvnGcErErF=fB~VZjb7qZ8L~s zD^R`^jmp71dH=S*zNW_>h_pQK#Qq13`;4sy>+;fxEBQJSx7ic_i(d7(c*yO6Z{jxJ z-$J!D?jJ}06A&Mw3(3Dy8GOf}$2(z(Hj_*KAAdg`>Uhg$ih$}^V-k|nt*|0=vnA#K z#1;+4MqK;&@3Z zI6c8S#CKYON`FY8T}pq&;JQuq4-fzpiRgP7**~&-QR+u+fzAomT{qiL|1EsaAS;8Z zK}^+h2-#ot)T(JCu7&$6*6u@pSe&aVDx@UorcWlJKq{D3EnsdtEWPW@4Vt3Db?)v&CKW#IurT|%M?td5- ztM#&(pZ4D_rCwB-z95VLixF12aA)~&e85c@W({_WVGp*;xP zkIMT=S+vHUqHghTbErq{zeRLfK|Q}M|1k_-c~{iP9*2(ezdgNs*t`2@6#g>_YxzoR z|Av?Q4A^8C_&;YC>;L*9VjkFL|BDT8`{@(@*Dx9sbpoj9UXlN1LkeGM%HM}-R2)Z| zo?`#zDR4jb$$NUD6X=ij$zCq@J&}bD@B4^NCLKyw{QiesD<(aU|1}c8Ht&nZJB9z7 z_)vF@+kbZ;bP^FT*6m{di*VYJINVeKu=sy448XArRb-r#U;IzA3P(HDuCxI0B&fP| z#|hlrbxc%&c(HW4`onHMUCZT0B02P^WV0o(_>_zUt2oHgsZGCMEV}&VwZ6aq6~?uP zqD0+GgA*(4^ZRAw3uwI^Nyg8Tj|DA$8^9{%y!f0d4!>cnlYA7+GnB&`!ZVuV7{W7|QyQW> z9AaZZqxv!kfjlqAoMw#HLNkc{b9}TzGd<51*O}c-|I4dXZlbKFtY(0#Ifpfvr#;6p zST{VlU$@^2Ho;|?FI|>xQ#xIieN#JKmczZ7gXb|1p3l4+V?4rgMq2;N&9bz9+Re7K zemZv{dY%NHGYv6_P2#(eT!|!)kuHfOuaON2#&ZeNq_vYgGs0k{a2~|m$Z(#=xsY%k z^bL5-jqTk!fv@IF{hYw2Z+bu1=GXLo?#+yJy!`aioTE$mtW2)zoYK!c^*KkMd7uI6 z$_MwW_HT*AMK4LG$-dasPLrkFv`UkussTxrE`NMTm0s+h9Ewpc=--uMeX1DDJ<|I+ z6((oZW4iOS;CGkd7(QYzih44$or$ktmiQU)a(H5^OWF;-)i7hJkZ;Z4 z;q;&p$G2ED;?znHXA&nLu%AUC~LGOqa?Ms}?1{Xg?muL0` zW&vyTj&o7$IM@V!{B#_4M`Wv0{a_WgepH_`cUg9V;v54|Vj8S9(o6GWGKJZFh>H_$ z&Kl^z7mrj3Cd@j63ZoTRv!M$OypXKP>FNQGiLz(Qr3e zY#}_uXTa5nlfv=AZY1skC%a>@5XI)5AeTfYrhBvzqtBV<9zmPIE0?S;3%S}v2 z)9z2uJ+HRyi~L$CNd8q_jSPXv#s<>z%Xlwh3L5sJQO@tNyhlr=`1;T=SPt z*kw{6`wl@55lNN)$UFvG$!9g=+nXm63CAI%Uj^-*@3xEfJr>MIIfQ< zotNG5vVpGjU8xP9OzErR%`ow0K7L|@Di)%x+&GBZ`#3FWaZiiYV|x89^p;-AA&{|s zM23Pg;($f0Fm(9}Ot-w@9V@L^5xViF{}Awva#@I7I#qg>>7_Cl`4$mdsn+qO{Hkii zK`JGMD7anDXs=5)d=d9GyPxEh1)9D5t2@?0DI z#}>~Z*(te1;=UHEINc+t%feumIWo?z>++EYsf1Z!PDigkE2PD9du1dbYK|2EIp)#9 zy1-@Jw2*kPJJ05zO9} zc5AH6mIB9{kO69?Nc$`> zT9b#ZW=bHNf*@A<`3Xu8I^Y>d7jqo(Wbo|$WR^=1gD4gv{Ely6Wutg>V?dM${g^W; z)8DX5>&00R`W0t_v0HAsr^n)^x6Vyn?b;I2P3&@SHdur_K_+`yK~DPM~~y4Nao%c4CK)xE{DIV@J=zSFm8oQf|fR=F_w^ z0(Vo#NDGp7(y#K<-kG&eC`S(E5@t267Hb(QgXM!-=2Op7{V-<|uZ|CP9A$#%2%9C` z`5vdVaMEdG8nz+e(`QY*Y%C+*YY_{ZAmI>_FxpGAe@RiDo_ums=^R|k9wFnu@wiat zh#9z5WzF8J;_#r^LLO%$QgGEUpm5_S_Bwyg5v0bNU3AQGMb~i%GOA#1>x!x}7QX%Hi`Op#9 zjL&SvVglMhm)xLT&WRwv6>pt)l^AaVbW9jV4t0WgX5kWiymzX~Myql5$civhp_g(w zmR;IM#*igmgEhMe^mtmai#@?cxtuB^E@}xT*L9M;|E)_sYp6MU~q3#(*G0bG|9 zTn?EYbsITBdu@XwyAaIT`0S}@|W_3xtr(eHju{Iu&!lr?vx>OHqx zp0RslTZ3&VsJp_9k+TlmcnloGgw8d*JJG>KuZ^xJlphNY&-ZPN;2@%J|70yEK`gRZe))~* zN=V$sa`jlKxPg>y`YqVHr=G!!90ctJ2H=PfDxQhw_S3YbDdjl5lsD1q%(02Ip9P>p zL9Y|^n8CK1~wsnXL-hto#emHsqetJ96) zs-RnYX4Vc1loZYERxETxswjE>?5*xb2R!U~#;zN|9bXfIUyg$`v~Hbn0BM*|QOwW_ zmfZ#Hqd@$WU0{O>Ee6(bgxyio03sT!%-N4hTW9r*r*^&((J-;LOVSk;oEgz?>uSN7 zVWrt!0jH^ zF$6-=Y(yA5bPP@|rUK5`Nsn42XJ!74m+qI8K;`9{9^iRv4S``XkQL|Kz8?eCO6tIju9-V;ekL<5=N(-4o#c zPJJ+m2hJI{0%7_|j7>M427!?+6+U0+^%ie~;rfHCUk$xDIPk6~&wQw3`zzr6b2p9Aa%0O&4}81xfF$dX<3kiUG@ z6fF*sp8;~axWOt;P{=b7+!BTLOk2;(Vuh#uAEx#@Cds&r9H;OU*_aSMPB>1yncI&g||4+3gD@j6BrgfrGx>cTpWqs(2eXA@UiJ{+&t!rgcJCX>3cPkGB(@hX9xs!$`#2)E^9SwG zX?rr?hx0_l`pX1K|I&mpbxBvRacj401xoue`_UB1B!-1jI#-VoAVPhAh)LK7hbicl zM`) z*Mxt(O{SAUJdmM?is_5wqyh?0ZL{jP_Il98xh!J^2#Og~oAfV@*sk!v_p8TURh~N- zZe~QCO=qstjo&x*Jxl#*7?J%CKhPA>JnP`JT>a{LF-5*7FFKckm$U?FUN=Ei(ydc{ zCnG@)c@)CEqEkY?H>j|R&BK4|>4~1WTYdul8@crS6jth)N?>sTS1K-o(p#n%99qwe z-UM^M&@G9bxGUu5^KYOoiS;tv!4Ef*eFdAvO_yAzJYD#)MihqQff43ha*q*Jt1*5dkM!){_SPO&}w#5Y0)Z%B!U^*Ha$qV%_m?ZC<%3Y(Zw*8MYpW zS5osZkwQnF`sX_i7un~qzz*66G8})~_N2#1?O`RUT7d=A z`fcAyO|VOAuFzg*OlmgjqYwC;IkR}le_u(%<+j|+8#lsupFOaYVP6?+pCYvWk&3aV zAWvpiIn9d)QCsnnXX5+v9LCcI_=xbH*(6%}(MNHD>EW#AySi~b_6+do=xj?2a!BQh+VAzY^3gb z_H=>X zE9BgZFC*2xJC|Y$)duPgy(}4fmQ3)PKBB#RFO<-X!OTzc8!v_rbCAnx81dDxZQzPH_@aBk6G%gYvCBg78$v#s<@R zI|wxsJSc1%1q~j@()?m z;rC_WyQHf-AK*c0tlBLs^3%^(uvH+tCmu&Cj1mCMObl+;R*7G=!qS*Xj`)kL=P-w#=Q9q?sPm;<%bUD}#-X%^^rj)I7iIFP9}fEfLo$43U=! ze2rnyMwIn(h)(MIsPl-r^{4uja+xYB_h*Y_{wo{l&CGc(9BP}F+I22t$eXb2uUZBN~lKjX}ps zRAs4A!8N1_%k{JPP}^*OA>hVw;&_;4swA}*_Fa`wBbLsr9gc#QP-}@g_Lp5qDPPD@ zu;^=!=0z()wC*=e;Z-eUeRwZ!-vsRyd$cz0OYJ9dYf*3xIcARSHq(j{R+G8)#U;>- z0?k$z6h&KDjTl@w0N)XO?5|&==2uAl#C%tV`&mPYglLo3Poi|1-+f$GJ%FDbIW3EW zpX3Vdc!o`3vQbt$@NDG`SfjF8D$$0mdwgpGdos$gc4QpEl;EXNUAi z!r1~9B{)tOR(YB~SqH0>g#BD$!O%zIdjMRHV@eXfKM#U?uM1ld6D+4&g!Ev`PhYNO zt6^9cwj#3am$;iA&!g*t6WuRFU+N;?6F*mzTBvcSGg3Y z4Ns_)q37x4hj?G8t-1M`1Ac9$LIcStue!5JFM6u;v#;{Za?CiRJ zDyM&XyG{De?a;wf$ULkgID}AzKHxS11y_cqIAznypj?{!MQ3rE_SdiLjJ&7W{hoEa za8q(Gzv?#JaCBHWB1H4qYf9}X>T08?zZQSAt-cUbjz!n;sCyE<&?IgFlLeEe z;YdGqqp|f{k+1D7q-m`hTEQ;(I{-6}n+Q|R@ffZ0#tHI{QP+&cG&&V~`DQon1+e9^ zflE))E&JhnvBG%=GLbpPu)Y}G2VNbCw^e{5kphd}r0Ca$ZwzU_yt_Hl;PmQ0Q)i}> zgi$vW@kk@%q2o0jU9mx=^v@c1{)TQP9HqDLgW-OzDe$XLdk}! z1(wc?xJvEM=ps9UEiPr@Iiq_vGo*rdSMbt=f6l58S|sUzP&k?#63D_{g0D0f=`<_y z*XqZ*UO`k~9C!_^!%>8BJrrE$H5BYlvcoWbo&v{j`_#Kqr>2odaydSFUs|P0h8Gr@ zHPaQ_Aj7SCb53)NgYa!xxMq*cTETl3`GPe=WyxIL&T!3H&cSKI*X^mpE=zFZisoX~ z9KHtAHSR_(GKjgkqmqVQ6CX!qi#D&a*AT68bK_-GrPIdgA%%u@Yt*P*1UI+9ahW*7$cV>^bC>g!|g1pt#~_NVF?SrojFm;55oj8%VPBv1P@ z8_vv);Sfv<9LqDEZHcw*^RmI0E_+~(rVg`&B0ywLT;FHAUc#4R8yY@9KJX)XObn(@ z{|GwHOXG|XU;!<(4@?+hmBJacuRRS=@6{P0bHORzfAbe@b=|L_Cx!+acfVc=aQ=xWkHa;Q6$i zN(z5+ET2VS1KHds&rdh-Z(B{?*LPxmbhC~_q>PvO#CUn;>t8Mw@q#e6np&HTC7(Ws zeyB-W^w&)#2~4Slson#)>t>DDrF~}cumD3nUM!E~kaG{JK4=Eb5E%lr{;Zn zV|CAr9kNCAuBTskGwdWc!n?^&zUu2ZuS;z=T#k+0RnRA#wp~5wMI%2+0|M5Uu?NXT z(0I>FakULAlvW9w>7Kjd3h$iZh{t(jVokldpm0y(;(5yf%5@wbp^;?+!F0uKpSOKPHp#>^$Z$F{ zwpzJAYkVA2?8MFN6!)bTQZAWnZp5B9=YG+&kw)rOh&k$6j!_`MbT@E+cl(-+3;2xV zu~gy1uX0%Nb^p30>ey(5sO#`?9DR)DQ#YN|#)FG^pZ3!y153km2;+ifnmkFKDtVdY zTXH24FPXl9&)TQ({*_t6_FRmMZ$7igb;EXQFiQ+s5a@)nBSuWLzy(>qJjP@sDS1}D zSEc6d;4<=1@SGy^TsCmWRRjEO*Jl9N9zw4$Xkyo)SI5B{D~#U~Z~Zfs`Q|O=6LYL=E}!KT&c?1~(~e4BYIuJY zs&=s(&mK0v$sZ@Lt?od?PQn>k0&XMXrXfOcYP)A`|tz6|L{Qc zdD%R9v-@*2^5qEqNdnk0krIqGjl^l#U>Jk(_U?eD1}BQ2=%&xrNm&}dyzqRg!}NpX zi?+}E!l!Wg0U2s!s^~gBO$XmD*atHQ7LIS?6@|BXt&={BQ<8gSAJA%scoh{uI6dn6 zRQGjcn&Px2F~krFb0`Q<#y;`<0Ad21-Erjo$drM&Uv~W9k$m3q<1IVvumb3lci?> zaMXIW1I!k#nGQ5u{kSPgI4RBhTxvRhy?hfudUrZHy?5s-=zh9=7jwIsFx_~2^|^Ad z@!eG`$KiG9$@a=;+m6RK<8GM+r*%pE)3+&S(+5C9oi>9m-`!dd-aunD>B&5)#7XJe z8Ti{SxAo7hB8@zeg!ZTaDY}m5hx5LhRO5sXh{rKu8^9GLC+xV9m+$zhRRrMTJKo$M z+yYm8e8<_~KLUKmF%kjEwrW?97kVk$hdbZPcT&7u%Nwr`X6NUE&zfen7ME68Z^ZG7 z?k*;$NPB->M7j#$9~ylJ2>j{fbXPw!nef|&4V>gT6|QU^0N)rPlhK`q-d=(x31M=3 z;U}vHu|+Mhr@oh4$2@Z1fJoi7M+3Hy*c0Y~y_VQKs72FK{`3v% z(QJaN?VUStx;;B>D=6qOYNMxPl~R2+Z_9tYy)v$MyPbD>F*$#CAb59n!)e;cb+x#S zM~Ys5b(>-1#V367Ztjy=q#Np1E1B1iF_2v`{_q&RecqObBpV%$Kxr%j(I39V*!GWFA}5oL-dJ z>$@DrszZ=v{o`%RL1$bcDuhFwdGUN%n$zE$C_mQj+CJ-G=hrdkMduz1RbzS;%#RM& zkN~}B#jFg|X6zc;FzV^mDWT;dF6!zq>Mtdt(`RoauYSQcDav>i>m)sfkvchP=Wt3EalRrHAn4a~dVX-(DOks(hhB3{qg^q;*e))p zxNJwJsx+>_E;!sYOnVQ&H?3THRo)~& ze&2I)Wpl-k2Lt-knNMe&%h)TN4_n;z(!2JahZ+&99b9?2-gu+9YPVl;&z@W{&)DPc ztvQYFb=q~R)TNZ(!MFmnm%b;<_=Qzf3vMY@cA)Zrwrit>E?s3&w0*WKFq1In;vcN{ zgfY66l;g~h>biuRdwy%jvq&(h$nR+OuIA$06OzKos67?D*jY4oxsTW5mECK}VAcsN zIhi~9m`7IqfT_}+($;r-&Oisl5W|6oPZIbT3_i0D-d|#=1xyQ6Ta5U>R|7&Fb!tZ2 zK}7JtJf#w(v~_$hmY`7F4*x-p(fT(w{~rY(mbKNOaDAV5d|+4Y4H*AHQmx`|0RUqA zk3{e*!dU~OcVnZ&Z%Fsf?j3~Yo!{Jc{|2{lUa#6)(4V((>Fml93Uhlqe5YX8IP{=U zXwoNFmSCYlKpGn>{*>_lRRH{-HldEQRp1$U4c$;C+=M`xq+K{aKk=Iy|9=H`iI&{1 z;FK)lxy|@6s6C+9Zw*ON1~B3+uX?I?t|F0z9h2@LqzXT;)>`FAp>O*D?#fv}QOK__|8Cwi&Pj!gTYxvY^GWC9IEa{g>ea6iWHm&-K56sXD=9Qka zkGUxwEg%a=nm4_)6{Vd!(s&YwU|829U-(S}l)bS{EMJmMt_Av(vu%~9J9{)}ZB{k> zztcXA^Ww8sokp;#1v_V8+NRvQ(!+|^tx9KScj3|1sL9$4N1l!q@0dXH(X*r@@1Chh zN7=J{dXZBV$j894yLVZgK#ZYa>w#tc9ew6`40p5vDlMCI#wUMVUrOvivE@(x1mb2a z5fkj8X0ZnEDLGGm`8hB9cHHlVfV+XB;I29kbQfw+|6AnX)v{?X+A8{tEl$#kRDw-A za@N%fC_+^?%aY5He#r54IbQ{$FWG4^_M=jw%z_YQPd#;mO}~_YAxAj@Pc;gXZx5f^ z#ip;tod)V5{apP}^5f~ycXOtvMt)h4_w=SU-&jy5979W0WgeRIFy`|>ok&i;GnfVq z#u0{Hb=BQM%|_Y6yN_D>9Yyo9e9DsXfU#r>O=oMe_BB7TRWOA?zKpB7r!f%$J5bkT z@W1^0mOiPRNEYWu*_ z7Y`y4`WuNhi!mp{A6e3+l#uuJ%lF5;1dmBVpreK4gFswy^=q=D`pf5=$YejD?P0S7 z(-*o=KbM{{pPY)V@Vy3+NpbZzt7rFkR^Q|41%{aQ;OeLS7ziB>V90LCgR1^E3rZ+L z$Ha0FvWRyEkzl5KIIm;g8N@-+ezn_s>iaXz6WIv1_?YE4N3*1!(+D#Snr8{) z)BNE*S2tE_oCfH#-uqwqogy7=rq^t2^Z=eU6`r+Dey6Yj?s*Za_Dw&rjh@!VYmVG1 zp3Cg{CmX83-f~!D?lVG4tkf>iw>ms&2L71w($6`vDE^4d{}G-35uH5BgJ7a!2M+$a z^xfIGCmYBtSm%3YRSOsd@T4tX!VPA))c+7q8m#&N)sxx0uc1VO?G&BTJr;tRsRp)T zW}^Tbeo&ck>l_J`NOb0Y{`LG&c6}N~M)mN3R>m$9m+oH-rv`0SGtW~?c1sS_Q`QlazRc!sS(n7}|JA)$1!?P4 zqQ;SrO{n%tk0`Xf`rEeAJ<+K=j9YoqaK{n0?D9wR!N&QVzyP+D_lN^HC8qSFWKRX= zyp9$S*`VB6kYE5$EksoXHbnN8SHQ-5C6M#Zn3Shq)86_ATBC-S@Xiz%B2CWra{Q!? zY-tDXKJyPbD-%*4C>;dLG>T9szTJ~Xz$vkOb4vfbZ`H6#zzGW3egbZMy;50;kPMzO z$h5(Grd^w`Tb{}ebtAC%#cLD&Kqoc@fgBD1bT7JkF$-!q!Uc}IT^zy2sQNY>pgS3G z->IN1%nV$W`y8jLdB3@DTIfptKPy#mHAnO1-uU;~GK8S>q3@OtH$;lA2Uo$$L049s z_aKqF8`pBD+QVmnLH2osc&!7!_xGloXRzW>E#ld$Ik;>%=XX-IJZim0PeE>z)NIw> zSWP##@;kXA%1ww=qP8KHgY=%-*^*nUd%adSFLL%P5yI~T#XSM}Xywul>;nJg@ype9 zk{T7B$*c2asvxsiNngrwDzH{;($9q>1KVU>?g@(mGM0)r&EOeke4SRLl-E9QLd~iK$l2l$tkfmgdeMa=UGtzaaEQsCcKbWu6Et6@4r&2TtEBBH)Ga7g z7uEALeslV_3><9xk3a^1v;s|j6NmyjI}EMoEdRwH6=8@z*VsQJSn@Ziz=rsLl7R!N z9hF{a43t(I|(HKG?1k2d$f&;u7fxJS;c}Y9U@7v zFr++SVLVYX(CZIdBSXFE0n3kzod4v(bZz37HI85<4}p(r{D(fRwyLG~!q)uP_m%A< zRKxhqE+`yc>rr0ozw29c?fLsekQ1N&IdLUh`VT2q5M};ZnS!g$saKbSwD^KH_hbi` zg7){FC387=k*HT|Eu7rwd2nuDSo&pUU7&`8&(isX$&lq~3``((H)NPo!-I}Z&7>F+`Jv%t$?-b^2>2i8I%`@<{1G}Z#LoEb#2PNQv zpB+o;L=|XifwZ=($6is!`qUq%rRyu9ZspA@yGLG{v;6rTSuV-k+7%1EUA_yZYNk~V z!jf9G#U8|qlrI1~jm)CiiSd5B72og<7sETA*2P1=Imgy!j`=qellS5=7eh<5f_S}5@-cNzeb=?*i57I^3R)>o-)ZBB`*|3oZ8mz!c zO|ikf?-Y;OiQ@ZAqMZ#*d0J%Nkdgl?Eh6$5gL*mK7!Q&8?d5u_qwu#ESQo=-sF%0r zkX3QCt1;mIyebwZ(q-Uir5>20HFHDP0V)phI<}EzYyTYiZ?15FM_vSW;z?@TV2a%8aA)2_lpB;>*r-%%YFGhubP!k_hn>j ztmn0C^zNL7qh&Ac(dU;V`_J}Y)7BN^Hpu*3Bx!j4nzvz6%6&1UejlZiM$FDZ5I13w zAXF)6;TMm;%-+51a2#-`Xk~qxjnmwv*E5MeV3()}M|GxDOrE^Rm5C&~oBdXTuhss| zgT%5nBHsCXMmu!Udn^%zjx)opNgs4%x%n?UqcnHjC|_?w8H8m1nbV~a3WWci^{!Jf zV=|NkAqO3DgZFv&yBR*@gW|8guvy|zD+kQ4sk6I8bH^9@A@#+e5cmE{OjH_y*4{}jZ^p8 z!IQ#x3?0ptE4RmLGM^ag554OA@+d`P{8U?l`kc0V@1Ds=R933Wa7Yw*WP3fwsZNTDiJiBoOiq=d-|!qy@?sgT9&L z(6fALiy{|%@t?ZQVnRE0>mL*MS+8g2zfW<99P}kY6djhei^P(Q?DHi9&g#t^W_c8v zH~81Qb9X!IcWe1Qr{7zn&)=%8c9JxBS0>r;x>p74fuB%3&P}LhEB17(JkAA@j-P?E z5q%z3o4RZ^-}FhiA)7c#Ww zsM6d%BzzUeNW3bqlbbn2f@&Pfj)TfjHm;p2odjx;+|zMxBOYo7Qjbc>VkugJOScmv zu@1s+-$U`V$PlT2r)np%*dHfS-X9r>IvE6HKRGgz$)7dyvp*Gr0$(#YA0os3*};8m zP=pPL;>bbMN7{&X^&UHOA-#N+lpF|u*2gW{g?2TgGLEV-uqM)NRk{!gh;? z)M@hAdkk;OguVrZaAyG_t5>B;^7RuI+Z@7Q!%6F|6BpQv8$_*Q1}mU?mmw<<8Wt64eg zVuFe_@Oil`rOoE5)@Jl}R2)ayNC+Se)MlE+&h{gTa)gMHO}?F+iOLC{5@N!B6X=Xh zPt%o~pZ?^7Fw!Voyz*6pe0jkuNpUITjwfkvBwsvIieDJd?75ohz0{8)2&2Y$C%`f{ z#IB*{if$qiNOC95V)Se~)^I5nK9Krxv?UtFQ#!XVM*TE=kdQA{g=XI8j_k9~wvL?$ zCrpJ=e}6M~(0Mn6Fy>^U$6>MOt8E?q_4_(vWU3wx^6SSVwE+12)VJSX&5;F~!2$}Q zEo3-imBV%LpI&Kci6rEx;m=jp2bsenKP@C_ z$Ogz;;6I=1X7MR)>%PpAFz0`5^*q7sz4C)e1S7m~uUDJzpTatLQlV_c@?eTmJxdAv z)mV-q1pn#0Ai7!&IW?oOgdC@Ozq^2%=7?iD6l>1VoifhewU#&nM{0aBQYcwjNhpxW zi7bq`b~qwjbm@f`--~LPYn_2{qoVm+m`Lz{ew6wKGdw`%(#ams08uDFhJH&I^UdKQ zLg{pfDEOlyGi;0(3Qa;VgMWL|>CGsa!kVu#i`q;gq7I1<{NX zm=a^9%GaymDK3(uNlG4IDD_fput>Q*dqjp3juZX{CH!ePY`BBWk4*veh1iGJJGrw+ z#A@t2GOx|xvLar6v=YWw)_$9nA%CE))a8ORpnOQ&&KdPqVv_BpMEikiDc9{6*20jO zqO*sk>*1OYkXe#HKKB3Vh_E`G!R#l_$;K zD3rs+JEv0cA9yOx19VB^y8kcIzB``kxBtIGk=;P{h{%Ytwl(u94}M7*vcJ4%lJ=ngYPfY z5ZLxIRy!*;qXKykd{?&Ali1rw)GdtcCgF3zU$X*lv#C)g@<^G!QuO^!7%9w7a3?A? z^R{+ku9RuO_iSAs$!~iX*$eABY6^rV_L>K(vy8*4N&-KIR)(I7D8x+(#B29Axe-bj z&c>p!$Vn!}9LK}-;<<@RsFpnW$(M}U=a`?F$b=4^uzr5Bum22l_k2{h-J)~}huXsl zA}6)_(Pue1?_75kcCk@8kuorRJ)X|wWk8c1F*+W&96>zLB2utU^6@4RMASt~zzM{E zL~e^I3px4zivO_B-b|qC0OpRV7894T1j1B;f*uo@0iPZ7+#-#U5_XC!7HBe2Yx5z zSrx+Rz%+xmDpG4$3sXrCf2H@$$q(Iv7pLO-{siBX1icaMb7o!k4264rUNBTmj27%9DSg*EiXrX= z7F?z8Duv&$M%tqjq_JKntT@0Q8fAan{Yd}irs(JRJ(~w@-35_psR!u+f-E5st^S$B zsylmX_91;u({pPZW48S-?H+9wc?y43-Eiq2o1&29T*w|Pjh*$P4bExtIv8D&E~%%# z);B+2aqwfO+V0>SYfg?yf%aUx$YA@8nRzaF_F1^Yi`{Z<`J$L|d(94gx+jzVK4<#* zA}(5nGirx3xv5{apxPLA^WUMC z#7zy1eKhGR_5A)(zZJ`cAL|mI@{3sMU?bb{(wKMe?JE4Vw`XoRm{2g4z1y;f`1zu? z2`;&iiTmRDBxgfQBH`B?G+(8w7G21UMk6zkg*{C_dRlaK%=+tV*zBV;$bBh^uAL!x zc!mV8jMHq&<5lUko=eLgOuv_EI$?0pUgtw&tZC>4UaAKS z-2`f9js?N_mIwa5mv8x-{pz+?LhbNMuar*Gt-n|BwZEEa&>IMG z`u>$!rkz#>sLV@%|u#^e)7dGf=xnr7e)^*f(=ZJ7Q!V3_KMw|+JJ*adZ+iUwr4O9#{UN>0j$ z@zsZN)`y9)nON0iYA_(ilY3d_xe2^8>j!ap)aM`lZMxMU*!rzET?h;vw(OHL{ zWD94Z48J5C&gy$B%hkMW|3O#StjIqwWb=Bh-LqgOAo?R%voyUmu-4dG!JeX_Rt*D= z31f$7N`6v7*BX-iGr7u9+|}^~3W}G7AK;>D-YvrLYa4dBiB6q3Q4G}vDpXIR8Tdwr zo%dDJn+4BHpPm?RW4S0#G+u^(Q>`P!hrKng-!q2{OTbuW&QORZWO4Jx`{8bVz`7bv!%^l&uy|l@JLFV_OgV}?5C0+DwM7Az0<2FJ8 ziJBiu>nL*dnmLPk&s2P49F$$>51w^~=MuX#7_a-ByNRXt>az4}CiXLtFW7J9``NHt z+Xa3;9prYBex2!p+NW~$5EQ$)I##}vz5*fJJi9Cf&AjWA+g71B>?2=OUeZ$i9(1lN zx$1IOLK>f9dBPpa8uEmNklR3cQ^2p2k#YY2@M|0x7x-n=E<40htR{ANEe5G=&S`cw$vF4h$P{lU7Bu-MHXsLvGxO!5iOeR{EGU#6 zmkpj9@&*efh`1wpOEMRQZDKT@&`^aSoS0Zf9Z}~p(4u=l+Mn5mokm#%7=PE-!ZL0CuP-& z?SzER^e$Ob-ZEL~K&(Jn3SSC%(6v`oV|l?5RFos1?hdDCsZdA$@Di%F2yVklyd=vJ z_>;o+YVU)*YKxFISfa7_e%HH(>v?IRQn%F^T{r?+&KpG`M|D}!EgsAG_qB{C^Mp#d z2L`~Z)Rj!81k{4rDb>&E{y6D#UeJe~O3nBB#Tz$9UuEl9+$t0nzk6QI_si|Y^Xb;q zZwH{r25E2kvU*ohESEuDARxx~1{Ai$c%o!W`_qKxH|!!N(r7gq|eusypay6nu* zkq~s zEaCNeI2BoDaV1AL;!!C-eEk-#3?u2sG;GCBKdzk}F7(S#lvd;szx%3Q;W|~=IU#Jk zEul3_q(*#5V!mT3tN4Mv39lY?y{%sAx=#2xc{>@!w^-KdSW9;Dc+3Tt zE`|OIzD1mr%X%sF`?F9V&%x(2YMt|vGlqW^o3I|cQ3g^JOIbP$pV@7~gB0AlPF#SZ z1i|10zK6e6ZjKG_SFgHC>SLJPf%}m!kLapzG{bVpa!RU8e6Je!3IB`JeX;n@#^cJC zvR6L!$1#`Cj_h7(SdTYB=8g2PH}vr94>~P}m_*E^$nrmqFDUcEUzOgDUMQIHTHoLH z*PG}g3C~+v?x$A}Qtyq{PbVcuuQKDhy9eufjaBD9Mc>UXR?*5vy$*gz#Qn9*3 z-&qHX(DXZW{!Xn`LngxHq=RK?f`nrn9yhebOAWjAb(~-JUUu_sm&l1$(>I87%p0<( zZxfdzp~(_@GB)`#(LDGyo-drzF#7cC==$r?(Pv&qD@a90Q-CY*#sIFW!rY3_OlY2N ze|53%!#Q~WoLxNW72zlu*@HPnqk+f1^W8=4d6%!B>**=P32!B_QN!JmA9;)&f1@vr zK;~;2t_*XhCqwu%dv3v}7mWh^9ExJDP)VuvlLv*#hbl#1KTEkwPHd2mDDhS?anZPZ zQHA$$<(TI9_4A$eqf)9FbS&zB3A5I!9BT>j#z+ zXY}`@cCk>Gzb?a09@yhPMA3b70e6CS(4Qyllc!GIW0Ogh3Rk|fyI+je&hIGsA;8qG zWGB)nbUjXTr%TLpdHr<(BR^|aMrr1E&N74YI;Wf1ij8t^0?zz|%$HKWXA3RJyiQfs z&>tY!Ti?cI+akW1=Ep5rB%p}Q>Rxyllbqh{mhLTkr}uP;5ofvSCyJ!msATx9{^SYG z2QEA~%(y04b)=z`45t_zuaiIJglWTaaZIr5$U|uv+^-Wqr77|0Y3>~nQja@*(5Dms zfS|y(AZx9x`AkiQ)33|kD)Q$_*o4C`o|{rUe-l5VF7iX_m@=PqlF+SRNmya$TA~xB z?3%GkVpk=;oD*#?4Oi(q60q3QhIzm< zKdTX}$wrQcmu=ylkj= zdi?UG2PVvoZzb4#KkzXmot_n7j{D-$^fnM5D>mpdE05zhpV98Of#=m9H72n!;?du6 zmt}dT*sOp@dS6PhU92PgwU~wuNd3*2*ViWm?%*+B9*+vwYmK7SzU5FN&em_gvC+1) zBf0t4-{rJk^M(x||YzNFl&SejiZ&-Qy?VH z=dMcdi*L;v1z5Z}r#%T2^bp-1_-dQZeNS|I>ZO_ zi`W`s7a1;W5{jaAn!b!=_$5dd+nt*C$6SjanSz0*pqO(#oJ^-7BZ|)uDwvZ z^?98_(uR8}9HNqqB_GYUIHEW>e3n=PdKm2BSo^JNrYFSA?= z`2B@lb>oBE!CITQIn(F&XR{`6a^qZkrO^05_~Um+$6zr*j2!qs1St!8lpSC>Wt5gv z2{;f?cUKXwJ3M8I8zMvuI2DdwTS-cB>0pTa_1^A2foOL%EZE^Wuilfc;q`_4&8;cE zu}pEl1ahBUnY~YfD^!Ko>@cP8FWNxUc0cr~Zub{*=a2r_G{Yy&3sSPz%V3eGT>O6dDZ+CX!{^q}_dU!@yoQ5R~C-Jn+KT!)s#?cYOjTO9$P6~YVrJWr< zAtzKx$yJu&uv6hbFyP4QKcng9{`Sk2e_i(utULdm<~;uYZUFqme_L=x^6%3|pUUXf zGk%7qW09zg$z&M*rZ3SfRH@1_f46g-zJ~<|BPN^evHL+_ukd-!M_EOjC>c6yNrbjx(9=r`lmirJoPF@=eO$CwyB`_;SwRjT$KxnX$2G z`n-!YWUS?RESG*OQCm$rh+EzGUR6}!!+gV1PO%DUsVdJyR4jIzH@V~5lnc@3f&CiD z{iBZx!gQ^{ISciD&K-t#O70TPNpNCskGKtvVhJE?;c*)J(2wOj2Tcy7J6xV&iQNDC zQq;=XK)_5AY0cIypVs%Yt*3r}qf7>N{(M)U)Duhh<|1T7ZDM9CL6>Z*NcC5Ot0Vjx zMX7?6`%9j}@>hAHehO#ZY2w}ePUIEmwR=_gavA@n338aUEsvf~3H467(IrHut5vPF z5ZmjhPIy(yz@}M>a1(WC=I+(gvgJwdzp?s#D)*Nr^S$qp-EFYkn;_4ZlX~hvna%lw zX~Zm@h{Bq41@+ZSF4sSiM}Ev9Vv`LILJH=$Kh~G}C3jB4FPJLf%)S~&$E+cnLS-IL z`bWB}JFLi@YSq2YluYB|-~%qIb2~8=r?tK$uzMikN+#V8eZ{p`RdUtj#@mx?-NVc` zZTHz|o5`1KKHj>p^z`QaOH8iG4OhJs$t~Y-nZcJHx3AVKsGFM6g@l;L!l;x-NT^yCiYer6Y|_G&~ieX6@D`C0Xg$NlI8%YVt31{PZI6re)3@MSd5-!|0JuqXOl1(1mk|~{&y-SIT z3CWf$Go71h;C}EE!8C2Qv`br{-$57ojb4x3x9RrphnExS#=xCnyvmXisXS{Qx0;2Z z;LKFZxyJH$WbY}|o?n*9lYPzD%g}qV7tZ+oEZGain`H0H{A~CG9x`xUJM(V*q2T^7 zBUwdUQcKV*UQJizkGo6b5$xf(#iZw*uV$=Z7F()@; zY~|(HqcpAFGdbtm#2B)T}}F4tdU|9$h#4JvW6uU$oE$>Fa96Yri?ADZ%9Nc+Ni zMcC3hl{k0Zu&~6-yVS()DsA{DuSA{%4~A=@C*|=?h?uc+VY#PrvBR<1o_}Z#f-JT=% z!E@g2SQ(sGq#^Z_zC%|NhttFopX=^7M?O}Yp3XejC3u*;%B5ARQ?Q!4HG5Ce?EJZ! zE^njfZ3BUy)sr@@X`1dyG$~w_A7Or>-3WhPT6-__*0-`)OCFOliLLdH-DrkHe(vFy zvFgPSNlBZPAM<~$t9$gLEGyg7`Dxn?-3&om9oU8YI-Rwtt-a1)w(Q&nzt~wP1^Ik` zQp=W||H)5jhE#TLa@=5(pElJjfhkevg=kB>{<5;?&ZK?guW@qO2O;uf)zV`m4~p57 z1RX@eIY{4{S0nJj@9cioC7*gYS@dQ>f6GLrI^qV0bEo(VTI*oi1H}4+c+}!Ai^2}G z{>&3L>(JAI2^21xe2ND@YD#2*As7u{l&GJpZCI-BWBh$*rRD|29X}TvdTvhd?S$A5 zczNt>{}41hSO~E9awzC8+gu#9KiD50MoMsu4j*JnFYHfL*XA6o*K`f;&dt?24P`VO ztnSVG?l(oOZ?MCwcb;sF3=ev^3hjqPqH_*-l_`TX4hL=z}v`rE7Uo?-kJm6#@Acz!Q1?L>jHQiUT>ub zZ&T~7NbvT1z17g3#B*OCd;9mo`fq9YRJpZ5k*$H}<+oV|v4a|U4G$y>Gf28!#7ioy zqNUa+>PTqYk-YX_ZT2h^XFQ1a85T;;vA2Z~b@VRns_wK)?M<)3AH18} zQk2YZ{Sh+L!g&Xov+78YKhetltD!T;V9_upQnBRwDhF=A;oifF&m8)v4uX8M;hNi7 zzS++Yn#)gW!7D2YT3z==_A0NBPUp;raJ4(%eJ-gzX_YM5C$IH;FW}j9;gjh7=|_fT z14#Hhk2qT;Dtc*AVtKZITEkw#o@?=U)6A1azTCP~&H-Y(yGYeX&-yQtETl|aDEeX- z))2ei;j*Y&&T{a?zrstI4rgLZh70~tY5D4WGdDD|Ph8uy%{jUuwrvVwy0e}&^MRu; zIer46hOp--csIh;n?RaAA64w`wt~eP*<12%8}xJQ9@#mt+&uuU zm!oQz6YgDV8d!U&FgpB|J*~v|u}kG=?xd1SP6grfT-~N=NhJiIGeYNocJ?b4m)wu_ zeO&NiUbDUbR3B$j3BS|Eve8VR%d>@r`RBIe?fnfCygMHZ6xS^qqoMe&%zb zp27^1bGs_I=uX4!nELfUiZiwMM-}(UgUP7Sd4uxji=K@AwwCkGKzIr7^r7B$J{Qr$ z)pU|sVe{*cn;f?GS6093p#>ylQ;Hl8Clr@NK!|%F^;(Sm{TePVhdAA*=T$J^T~r-i zSapH+rW?g2DMgqSl!v;4A2(e+g!6Zk&jt5TMcDW}17@vg`>%Mg%2}HQ49&48mGCz8 zD?lnDEO)5kHCFNE_&OgO9)$ux**A*alZxD-rWs?uc>6E$LmhOM^K_7AZF!dvJ{OWh zta6&9Nu_tBoG>(6KPou6|yi|30dFl}%4 zYU1v#XijZW>ezC+jYPTW3e4@g$!vTZ>wCZF_D+IZ+q_E(%Ps)NP8we&uf=kbV)KezHWB4}3uZn!L!YZvg@ zP8Vn1Bf+)o6V0zJr;#;Yb!Xkj&V9=c6Dwb5%#-FmPtJY*J<>e!va6-xTf8Bw7v0Te zyMT2&>1~y~y)7M;`BgU=?*c|&*4_!J6=9uH+vuW|2{QOYqL-!lbCvLBeP>AeUZBYU zx$VGb!u~C>Pc8D3wr!JeTluM%pZByAAPE@-j9HKb&tNlqX)9G=QMTaw{=U!w2<=Re z#il^g=FL7a`DNR-W!r{d@$*Kj9@OVNAud|H+tzI5*I%x?wN6w{?g%jN-rNzJT)F?) zi#ps3u)gYc^+^TMOUX6?5_P!lV|d@PTMC@({a!@po-2NfvMFW7N{;HbSA^z13v406 zbDt4b9)aAC#`36$5IIPK@5!!upW2dYlOWmJFS;ptFO;5iZY6X9sf6hkAX)alv|agp z_pJpI*OM-A2fKmC3zARISx53}eZqI#@o0TaOB)IK7_Lm8SRF~!Brd_SH$caS91X6_ z4IG@Jlf}qxA!wTTGnfd+$Z>1+2=@ATQSx%{?=(p6OsGWHB<>84m-!B7?*wC43;#TQ zCN$ty=aJn;q6yUOh?zihIDi^kx-neqRc|u18PhAdFTH3Vm8m8E#}%#%&9BxE1wA~t z50~+}o!8{Odq2qQ^h$U%AmmedLG9CrlXGvAA26R7Vm)fFC-bbTjX{ZDF-V2IHpv(qo51 z)*Qp#ItDcESegMXc}#NX4os+Fd<=z}0EmGSF(Tk|FWUAA^1b`gkV(?pzuwc^U?OGB zF~I91BV-99e5FW6vKz#8#PyEz74C2lscruAERquAGPUFu_)MVbEyW)7ei?w~C(Dk$m1Y zxt<6AcxWh`E0q3ND|~FH_?V*d9P1_FXGHymcK~1IgBDBLe_yyggD|0OmEisOZYKbp z6QhpUeIOev%%OrMQEQI-*>tygLSZAq5>o~sZ$q?0#vW^(+!o%h^n-#9j;n8f6Kxn& z?Pv z#t8jyEvR6wyTaShI-x>fn3s4&`+jBcpBVd>CR!D!VGt@PVmC;f^WcXy0o^|CM%#4+ z0j+KlR}@WWCm{B}wM@_NiHz<1!*;KaOz52Q`glan8OiQM`dM_+(Y^TF`UaL>r@!d1 zkU*5;!03emcSVEk^gOL^>@nASG7POTR0njqcj`JT{2tGX6bvUN>dm0F|x27Q&I@MSD%p-dVeVB1w9Q$G34UlN!(hHvEpIS=Hk|K6Jrks7L*&9)o(%K z4PA%wfESYo6&2SI%BwS>TVjdyadjjJZUWealM{@d35ae2*eK2M#^CVpEyQ&KmIC!KEKE>4kNU&hB9;#fVrj z^MVUgBNtnG=4AX1d#Civ<0od>`W6V^*rGn~mD1=z@@rvi&;y#aA4Quu$ADqKr*pnJHa$d^=>Mjq`UV6zP z(ez5ob?{r}=2z6_R^;q&`zEr1f@>TSOPtwg2^!EioDwzi%KRb!p@9F~oIoxO)e?b; z9CpykvNSUYO~V^9LA|98rQb8S@EZJuK5)4o-JDrCto^GIlB{7?L)0>Yo+<#ETE8HD zeIH^EanoWt0Kmf0S0&m@XbCQ20sqpp?;}KwkPR4q%XA%@88Lzs18LZX7f7IPU=N)u zISKr)_MfII)chO`L9PhYUiyl1JtF6SYHm`pa~*)^ru7L3LTiE2O+WLcrc77g4co?7 z_O9fEkYy03|Llez_dCmpHwK2(PON@zS+ekpCfIIwPUp6_%3rHv60J*o9vV3yxQ(^S_2RpDn?^&q@e{+h1Cg?& zvzMH<+=;cgzGiQnn$<5l!|iU_zb0$r-Y}DG_yUfYbG1)4lC$awz#hI~)kAP{tBp12Y=h2C9jkYyWj3$J>6(VCPqrYLKM^)-NfU1 znd%l5Rhkx4rg!bRikXVN-SbIURo=dfw{N~#-S4s}8vLzmd`XP-JTyO78$To&-en(T zXwJbYc8?(B($g;LrNKmv`>r1;=#*eNf+MCJa6YknL?ktS3JWfIoQum@pJ?b_5u=f2 z`umSm1EeA-?K31YFBGJifUy_pUY(5?5L6F!{m4wGgv(75er4(Qn>T#FVxGh|CAeO` z4Z-W`v3ccxqXw)6o!PFJ?;Umq_*c~=Z3K~W)6E9d@>DkrUgQjf`(ON)H2f17_ucif z88neMHhJlG=Nmpgb#nph(RYQ{raYNW1>**cej;63X6T_I@ePJJ<&EuMy1j^*);IcY z@tP&XqC@#+4~k1c;s}CFY?Oq#9a>~%zE_l zX-0@BwA6RXN?K`>=B-HP-FKiStQky&^p~;mZ->5@3X`yEKaQp;uBwQ*= zRF$q+j%2H+`aL1f)E+~m6uCehXrk@;U$g){rlGzVm{e(|D~>OL;lD5FU~B;q)m}Zq1s7n#7SF?Zm6h|APt>8nmjhERchyutnNL`2l z;C~$L&7PVgkX~M&IPaEvn4zS|O+$fi5FaRE^eWShNO4ChvIcL%#V@$TWhsE zjHj*&qZA7D7U8JmSBMH3jLU|9B7CS|7fB*QAlsw>eHcY?lrReT@*SM$)z58dfU?3+ z?e%&bH+BeaG?GD8piTq$v$Za+hn0E^nqXnlJR3oTUI8h@G(o5}7(Bqcz>_1Z@?Tbf zXfZ#O{$x;|a_msiNkBRZ;YtmofqPEusrFO99dN_FV;VXUzj58k{`r#y{o6ls7fMOe z-I+Q?7krBEEKPG9tTem7D;AV4Td_-3BFho1GPhFM@Jn?WIO~))vL?HEs|kRe+S`cv z8={%FSR`->#Lhy<6Rx|ZyL~MfTkVv~n!zX>442s_5iXk?&7840v`2pLnEAWARsKpWnl7mG7(i|hgDP;q0yUer7^W%Bly4&d z$FL2S3~I0Gf$WhviDA8vf9*W;p##w21{v}{AuVej-_R9Dup8`?8)58#f)HZ|l$l3P zMdx@5I-f;A5x&=w41a~dJ+#tJ8L9wBqdg26U|vB`I(QwvVb&8#l#2-wQ!RnIbaYr4 zm>)NrXTRfU9|FwHmC^*3qRp#I9|+(FSsB%Y%)R%+{S&&zZbgu1JmLNc(qBgaUU9+t zE`7lpbS!^wIbP|-{WCoQok1WwL+}1!KH~{7l;%-QVD6CJa6a#G9pNR^H+exLN5+PvCcknRr$6$Mh|(3oDc$@;q)N?!5RWifl_I z%pKTzExU0o$VDRMA;=@+v1V3&cJItx?V!6**|R@u8X75?^C^Af0niyOxt6gT9RvdM z_aHw;X(2z@0uF&3wV)u#vo*<%JHt$>LrN-ViXrbR2sHsgf(1jbP zr<)-b?fq+Y-*9@MVg&dUQkjn~avJ5Q?TNx$XijDvqhsG1- zazOD%={Q}LYyoYE7Lbzf2zdmi=CX(m zdBde1yN#iZ&L&hEL!0|YDPk}T(N>8g47>!T{iBbFXl7tJlr-oyXx){F?@%ZDl!RUm z5r>NqfI2Z&LXsfjXb|S0^9+W#|7W3x)Ex^2m=9AEy&2#LcQg1O1{el9QBa^1G1_Xd zj{qakmZ9<3gc_%f-1Sj}V4`D+HI1i3+55ol5fd?;Q2GPgKLsd|ILP`e&ib0kEIE2gJaNKm$U7h66-s(H2 zR2V9ZvbPC^3m!U}&?w+!gDqpj z5D5A!uorN=05AE*^|fa*hVAdk0=#a%qO%q(phsQH>W}ogkMMDVlxgdc zNb7SRiSz=W4%iJ<+^1KB^THJZim&axA}&=5G3xxxTROW`t1T9O0b&>McV{<$29%Pc0>sQEy~4U4IEOVA)mdLFshigu%YUOk zwk8KYFId%GP}pAPZK_*YQT9-0jTRn;Hnxs!?d%WjSlodJU^eM!Ug)V3( zJT?>VtD8QRl$pF!>@r-?ty3DIQx=i$p~N5G*@rbyzEL_>z*VMjWoXLw6p5Zp7I?=4 z?^lMmZ1Lb5cNMRdaIf^?(-pqb`Lfc71-)0S^lj4?zQP~avfUyED+apg#k!b;9mw)s zCkkpr9mpcfP$*}mYkNuY`LPvqt0YsRqSghZs85{Dy;o{h*%6Z5;0$E#^6;k}+Xv%^ zKj+^++E_!x4X1n}?f4{Q?V?t+;{b-tjNOF5vW^TP>y3AhHik3%)o;~~WcK@i@Arqq z(*~fN>DgWAA)$|fXwOvf>T2zh^G(^#|~%eqTugi z@EhR&9e8wSWydDVyx-MY#GYv-e5UAe$NLiDN3=ceD>3%TF@yBh;s`U^vfv+2V@+`F za&;Wknre-IJ6iTE&D`74i*eo+(Ud@ZrmYChPf!{SHmvawNPh_lOimj_bF1Mg|5WFaLd?oiMYPLyP(~%1plDWpY;~4SdZGe>o zowaxaUB3zc)ccr_+VAE)DY2Qd`gb~(?qwA#tWSSvheMJJ>~edZ)S4ztf1_r*l{FjC zGCZR6OX{uqWB^V1@Thpu?w8@G4f#VW&E4TzV2hx)3*~rl@`RUTMA6qzwOFsUpG-7?2{Utz4E0 z=mz*_lr@dHG5FoxHNdl52F;5SvepNfcfeIoP>5W%c}9(3J>8%Q|JM5$FN0)9K{4*0 z2{^FH@XpH8y&3KGZI+Cl3qL%>em;rXE3dcOJcKV^QE#<<*!BeNU9>6Nu_g=l?0cod z6E~a>STgp&LW7_C+Ri6fGfq)JLO>hFnn85b#$wGNqxkVyOq16ky#Gtu<4wP=ceA)E za82o}>070l9#P_z^;Y<@fU(GyTy7!lpi0Ov;6fbM3}Hx!rbNU3&`OZ;1lg$``nat9 z`*%=oP06Ez+j=+oD}qr8=Ac)p*4{&GS@}$cq!5^_C*n0as(UL1E zq`Oy{`eF3bwl`{)q&ayMF6exSuD zdk>f0q87%R&=;_EU1pvgUFx_*CX zwk(r%#~Za#oZw~HGELIF9VEUGDZbS_V6%ps7?TZ`#$ZKXp`#3A+scyA&V=?lu6c&! zvGM;p2SnmtC76Sp2p8IMJ0xYrO&C7-=E$Vl(OpmDsJ%)w1?XTrY=dB=j{~!4(U#X5 z1Izse0b$iUcaH^WZy`+hV61S|5BfkT8!8xqA%|^o!0#a*og-Q?fk@H}aWv(cxj)4D zzn_muJdAh|x_@v2*J)Ya`%?6H*Kgy>p#wq6uK%U=xP9!{LpSZAJd7QXrwPYYc0(TLL`b4xbDL(B@ApP@^xQNU0qiTe&z$ua^m; z5O`{644Sci(nK0 zr~gbr*lEPHAdCcagNd*PlAotAAI)ddGt z&tmhb&7k>-3!ddEE?-h4hEb1qzttuVEEtqZORTXWK@dyOIqiQ#qmwYyggb;CYtK*k z?S@pE+9VnTxr4FAO&h**e6e)zxQ!0AKSqG$J~rs*g7-3MYcg;TlHiY+9ipQ)kaE=i z7b)nBMgt3}?Ue)p1+~wDS_?(gF@-3^LqQlh9Mocv{w02K(nG&3-$AG+fb+P}&f9|u z;9(nGz`X;YFooi%@W?a&km}Yju_ap3YZhkyf-8CSLQ9Q{!Nf}H{%U{1;Fq;(cJTu& zt%{UIrOrj&&oL4sFAR4F;G4US@@1PHi|wC(e*7U)T|l(;!l?9Wupa`)FY6~|xwrz8 z-%{*lDg!Et&s0Ultuh-Ur5o}YS$)QB5oo$p>7s0-}30n@9En2 zMx{(Xyy%4&*1{;i1vpr^T3)Tz1d6<>f+@n2ii*pHq~rONIb6SnGB-IDa#BqvvFQ&D z&z3*==BlL7-dX%8cBzjjc6`~TW$|H|M=#ZfpB{dxPJSxwVu~$P$m-57w^^DJ-Qt~0 z{5Fzaa){x=;C?)objpVAUl$Yj9{LU}rW+&QMev1Wz=Dy(;+DC=lp+c%g#$@4)$Z*k zw7ieQ#~0YwS@6WZhGb$?}t5ABb*vrdpg9jS;VOZHqb-jO`{@26hsRO5l&w} zTJDgDk!$tQ6K4FB@PBL6&gb#v1y}{-viZSr>GPVQ#ay8$%v}dNOlV7zn-j(#p2fB3 z{-C(UwZe@Grqoez^h~}?6`qs^6e-387+seR=gY_RE3^ISfAy!Iwj$7v+0u%ZH!pmA zgtIl2SviZzk0|uo;*cS?jknQ{-Xs_i{jT3HIK?$)1;;j;P`_bm@LZz=pX<<(3bcO|K6 zN`YHVFBlbK0#MJAU|A6E=k^Y08%mM^u-C-LdI%<@j_rRa`3KhZ)5ox!+D}l0iz{at z`~6H9zY*LTI(x{4NXZHGqzB#CZ()<{ufd&a?%&H7u)JQ4Tk$Sl7TB(Ll9ZXqA|A5& z6P^%SQNKDc+6(_!`YD}v0H{taA>gPSJksKb3}3sy`uqO$pYr~z{~FaHfFV-=0Pc%; zcI*vlYRDP!wj>JJI_7}fQ<=kmoS{+1w{y+T*B!~K+ z!Xf=@cZZG%U_2=Y5zxtSM8Ji>zoOxd^q*+xib_0Y;IizWe#E;!{e|*>`n59u^vf%u z`(GG&n-Gh^H@hwr{E5eY8i;|VxTA11#0}wvLa_Tve)#x%sWvE%jiEU0{wp20Wsbwa z(@Fd|Oaks5_iJ45Cf-k_67vsFaU)H4dY$redH__An(w)ANh!gPvtPUo(?zS(^LbA~ zNs&$qfe8D23}O%#@WJY;bW;c4;L0@~>8cLBS+3^WD||$)q7Ph?6}|B#vZbH4epE)z zM}brgt3cNxk!2d47mK4JH;$uH`S-KosPH71T_HN6{m%^(*25D%{QN|z;~w+qr`o|# z1jz8Otq*+Yea@<6c@pz8?OHTTQ@L_xFDO0J)#1O|IcBg@!_MTV^*k?NT;vvBf^@4x z8y_oY5Gam}fs4|-RUzY-Kb!@0{KnV!C(W}1RGpFCRO8|328%o0}?#!q+WOvmxF z-F^(l?$E(0$cYrFhWtc9UbB-Bf_!^QJrCj7&4ZSjU>y$c>k9F#rVWN5_^);jsa{-q z*P%@}3au>Eyk;6IMH`PPj;irCtMWUyT1i0W7wj&|=_JeGd(=hAE|2U_(G^mCujt71 z9j8SOM=~r@4uCS3vD^Y2hX&>47jxF&imXt2382y8XV}C?VH~?5Ugp3>e6htfN&wlm zT-EC9;(niop58kps;1L9O_h(B{7h7_#T??_sl<#^r$d$K1c@HeTEd6c(&~^?Mm}0Y z&oaQ+1o=uL$tdvCce3r4+pIw~r*k6rZ0S9Qp3M+CwetvwMcT7WKylOKVLy);{bJb#RA#(`200O9Xc=%BeM^g!Or z9sC6Z?6j6D)PD~tfuVIkjTYFEo3?zJpwPk1_7kz>ly!xiY};;u_6_{;RHURV$;Gpvx6vr6(fN5fTv;}Bw z!l6u{Dqt{bSPU#384Mss(L^7Kpb9u^033k9C+j>W(*bp6nm%aV_& zR6wpFxG|KOXz_~^@LCM71yuZ@m;+(t{{uR2p`$1XP`CLP#C>N7;%TPR=YDfyfMSlF zzI{9@*C7!Q2jonpz)m>WPl0@$K!-an3eptAnM@#(+Cpf<+7tLZoc#RwF0hsIU1|4=ZFM+*l<5OTt>1rwA`4rR$tR69JX zr|OKQj)IXKj-Hsm4*3~f95C^hAdNvQ;qP;{85~~1+#~l+Rqwc~W|;YC1)L3@-Ur3G z4In!`I9&T2qRFlc=hszP-IY@xvC$b=bvp4UKx+pgag4^OQ$*Sy9bsT!5wXm4L?=HE zI8VX_fHW(;Ux67r!iF-lsx+}nqhF3hpL}Fv{mwV9@^vShqxpQlZA;RT4li( zB-doYEhwi9i~tdL_(F`RmV=!~sLFvp@Is8}k%Q5kLW4py%E0ImL(s&3yb!~!iTIgH zwf_p|L+b$7M^rz1_m@5YKTTkyj`a~~O6W{RD9XU35Kkds-~|UpftZzr@$!O*!*C^H zi9amb_y8mg6UeUa=tJ*Ug8krL;G!(WAF2=!Wng4*(4iyUgz=<4I3Ebj$RAC-51jg! zT;Sh~S$phDDL9AD26g>@>IRhOkQ1R)1j)jA3DRQJc~yyEP1Md6zF_Ii>&;y%gT#=w z(ZV=vxhh;$0{qDj?#S4{Eg47)XoEaVi=>`E7mck(J}#KFU_oTd!!E!h%nG2SF?VI% z$PI2f8s>fN9@7s67IHWqq_Y6X#R1H=J#Xm@Ws{xX7i_sGGur5PHK!LMaqYZLr2K3? zQ)m7kGPvx0JU^8(wR+8FM~Sa>?a5 z^B}Y!^Xkh$<~<&8@5SidU(Y*SwE%7$8^LJ+vg2p-ZCt2wA7 zM>zVZNrN&6*{8DuoixzYVd|g6;Q%<^kz834ghAw{b=Dx{CW z3QQqPKrG&ZU9fVGss2Zl{Sw8Lp?OPUOwD!y`BO)DC~uCCpULAMR4ESkHV{)%=$L|v zC0ZpWe>_0iLHPq*3W3FzE=xf$+=h`}5D#(+MlXTN+i`QDz)ThP5r(*`3d2MDWAh`F z6Nd*Y;14u0yogd&K=nse7(4WWkGQM?Yg1%tviw8um(xge0f&;N*u6dO_(H^N@@f?; z#G5XA#CRSi7_ zY_N?qks^^&7EjhOP(6^G;>tB0qr7hx-fiTGw6gAj#1yomWBe<*jGrU~-k`{-2?xpa zEflo%b6IKyR4Q?+4(#7H;TV52(nn6T%17MB(vMbuRqMp|A*r=3S({_4vcnClcTJ*)yoUDz5Heo!wL40_mb82VWr1;Pd}W2}?e zjceVAxA$S<@EZwtU*)CBac+Hx+$G=9^I5+_JokSnd+WF;yXJq~B}FMEr9exrQ^4#_jA|td_S+>KfC)nXXZUK@0oMX?zOvf z*_G&`^cc00DS9gf4&F;gPv@58mn8mJMYzp2W$5sE?QR&eELlQKrgxT+e(xEpKz@Sk zAVJ~zu{Wx3en~*ha1&{vr4N-5!E+f_TlVj~_)qCcBbFRKCNT2(40Y4FDt3Q-=sz?? zXIdUb{PGDojpfIPV`uI3igz-Ck&i3dPb5El&G1ngs#<;Ha)1;?#^eVffc)o0^j+(Pj&~!h9gqI$pGYt<`7z}4?4LA%N7QH!0*{^ z^s~cGb(aCC>$bZd{BFAv)dsF0m`^L{4V4nYdw6?2B{Na*J-ipD^%qlSbQ7E#DUKc- zWCQYP+k>%LIq?kR&_mi<^qkbzCUx3PHOOG*(gb==FW(cGzh%F5rmL{aQUzDLg7*D%s%Su5a{nm4~0W#4>ZT`KMeQW)O&43K58tPlZ<5O;(7|Ro@<@%RHzxbwBy8ok-`tZ-n00 z{G+Ry&Oj-q(xN+*6)X$}%JrHdS4XGQ#W%HQ+l$6iGYyxUo2;ydz!e)Q4=)&UQ8T%7 zoRE+WG<#gYQufbQ0Vb}LE9WTyaz4L%Q$E0|FworVbW**&GQ2o^0MLP1unuhx=UY~c zugO_CZ?4y`uXpy3PZUC{6|U9}rw1(w5KFO9_rvadFp1j<*)*w`Ugvy%W#(Rewn%R@ zL@@M0MLK%qI@R)91sI%pGy{>A4g#)7+J3D~alyk-7sKhhz zqP~!9GC$N|u(aN-0vMM%P!A1p!|j)<_lL>4ITuUqdpI;iruzqtUv2nbq)OGQQ>2Iv zOT_6F2@g3at*mbhO2lOXH5V|P6qfD+^^{Z56qow*`D+UukxeIp6vw$M)h3bwJ+ct% zW-Sr1U%h}49zT2dIAwW$e*2Nm^Kg_^y)@te@2DPwrDKYs^(j-UsLkWRc9(HrF{+w;!b#LNX&h(|6n2vsmnx@Hy{BggF@AIc#I08UoU-j z?uT6g# z=Aj>#(+3yCIw6&!0bUvbJ}%Pl#HGEL$_t2F|Kjv+^4$Mrs&DSNvH9z``F7avCc)C- zQPQ=;b#l5%(!O81^Jy}IS$vFyv75mF;=rNt73l)f@3y}g($6zyWQf{c3bShv7BrYW zn_64`cHx=6YQ2)F6c+dNXUpNAXpvljtBwXGY#Oek?<)pBJ>ax$3;Wgj7lA(FA-!{i zWUUDy6S|r%H>IV++Yvb(?%zF*p9W@#cPC{i?GU5f_rZu(mzO3cCF1W%nbWz1I@`g2 zwZUl%`zI3cClZppj_5y;DB(!Ifh2I$AN=lX97aVSZbxexbrJC8>+5AzoFPen$)VP0 z@xO<iW#|q3 z88iiTa|V$iSk^)xIDkk|R=^H*I-j8I4j@8gV$vx&ZK$XdT!|U_`u6E3#3M?X^!iVI zM{bb)rnqI$d-UR;{g{9Ho$Z+3AP{~JYHAPC5O7r(cp7^0M&B@ zk%JbYfFp>Q*7GfAqpn`V%jAR)>VKwoxK8QMLcz4m68`BkROnW5;3w4mic6&VWd#yj z&i!sE;0$^MwQ~R|K(QP_QuH$E{=Z@>FP)KV_}SL_SIWnN4>rUZ{-_8}QYf|qoC!=Q zs{{N~vXB!f9%X9no3Vfm)E&;_?IaO3SKZ~X9^wrlCd$z2IO?~PmGFNv)aML(1|@U` zy+T`+w7$87THIh&PrHEZ5bnd9rO(<3-nrws1A>+sfF4!bx`Rv+*_d3)dd&vhMu)G> z9z!mMn{Q4R=i+y7j;~Uht~T|qZ+L;LozdZZYtQrI-J8po*U)wWXnOLGL)?Qs;(D)8gp=J7bpAc5hD>G9^O z$?IkKjc>08EHOVc$-3WE49>SSxx>z`g4}^C>@`*?kp{klPeL5I9^DD!STL?ivE@}c z#?bTA{a3Czg&zGKp}Rd|P#Hd*;eXBwXU4aazmS4Vr}63dL|dwYOvMSYbx^V>n_fIht9;C5pPb}H@*eo z7-bSp(xF@7h<4&HIv>?is4w}=gs+-(X+v0wD(M)(ZhKg6Zcz$lMYe4FTEoP$FY-S>4cfEo?V7c*V?Xx2!UnwJhK3g zZ}ztN5*lZdE6#V#Poq3~&O3Nxe!E4*nIQ&^@dA+pFibtCqXU&eCC@w8qyj`DnOk?` zC@?rAwBGnRbdqRN{J%V24^q)FR~qY>%Pg3G*!1WC(=3Kd-0(}oO&%BFat1K*@tZv}BW`{$_!j{Y6F51iDVVy|BuQwBQc4T?r{ zW_`NX8|ZZcXz9|VBt9u`+H^3WIbnvXDU z&kr06U2Z-3se#on^h+aM*R&ZHUG>vvtb^zEzhZIAyc$!Vf@*yLF<>%o2f|5P;Wn!T zZc(u#KwO||C@2cVgJAs%3Wm(Ia((XEUI9 zA3(04-P-|nC~5#`{;ua~_9*z$i{vL7RQ&^p<3UivY^c_DbF$~Dlz92pi(h;^#_k5o z*Og7F7c}f~6f5OlxkD*GfOtSBzwGb+vJVvq1ii%=y_RR!x+OMU?c(3_)>un0{SmVp z*ilP!*ud!QOX%xJ(35+Y3Fi#?kTx3MXecBYG*g}W5&pUK?!h_VpCMqmc@|AT|KQ+e z4Z0r;;(;!Pf>NR22oQ4hKnMs6bhmSJIA`>Fa~;Ya4x&d{KdUv+V}SODgXXG_!r+i- zRK){uzlyVaps8>H z@irNFiYL+xdIAd>s){DE45kCO8OGEt^h(9rLhuAtw{%Kn+luh&Rkw6YS67KVbLYkG zVeJPK!BTYVH`JLFmUN(?L=Zm?PReQ6S22%tnw#u#t82U-9DXQtKMC|G<`W1XS`r6B z#rHdHZKV~-*u$R7AwW2==!du5VWb}goKBQL zy^=uE)gy86g#_||#>axz)r>r>+Z*Rk-7e=b{CQl5;sfOw$J8v;N{b8*1DP4B3MTRl zHUljgstPBH3?OaCc!DZh8l^AW`tj;jwzNvM+jj6|J#=kmZB+Isef>}UGS91lRreO? zgEY`Hq_ckY#Ojd5+lwi2DWDA`rbTx_D0%`&0a0*H8~P~)F4F1Tv``J7^aDW|l0aLa zdMH6Me17h17RsIkdWQI{=@43!4C-UKA~$j>GM9DIQ96ojrTX0eK+z2{S51b2aL{(+ zZ;YGN;QoGph;-sJM}I3jRS@(+20Z?O3=lF@u>cee^(q8SV`D8|^fa=P07Bpm78<$oE~&810;g<4Ls*lJ&*>n1pP;S^Iz(?|3#f2 z`Xd7*{NMDa|E2$5%+LK#^B4b8|1aj}{`-bFB&@g9X243|UOBPZHp_JERO%emsJGQ(Ku&N`F|pd##B}UfY8?d8 z+v+d?6I@)KVBDCr{AT+AJeP9Q3T4d&i4e?%;$Gv-0atT3*PD7bo|gl_&0+HmdG)Ju zP%Pp-Der5=fCqQ($U6SKc1BnY!be0v!-lfefhbWTVe3y)eW2=fAZEb%WM#2g1UQ4O zLKSXKFP=MFUzb~eJuc_1Z=w}az@Fz%LM*QxfRpR*9gC{h9u2*r&i*am6HZx0P;ah1 zfg0fC_~c|4-qKI_=yLnpw7My_7hNj_rmNTGGQ1~n)AjI;Tg38R>qRGzdfJok!XLWG zc=UDyuFj_i$U}J79e`r8g}s?V0o|*P`U}fC)r1|%MzRknU#siSG(s!BsP6D$!NNXb zj#3Nom4O|`OXojXHb!7!ZEt*nDy6-0&cX1P&F;q9{B)uJ$|H^ptD|uaaK{i5BNC^$ z#~vW2tGoPwwZ?_{hdkfSR{`B8e%h?fO^hj&7*yE4gsqgUn%w{voo?Hle$ArlhD{jC zgMeq~3t>{#1Ii|k zAiZuM=QwD=Mwtps*>m$y-Cs~9x#dUXp&=<)*0IY+N)(NCF@KpzAqy$*ye288n%y1j6lztSPMpZqMIOGQrqokpqd*@>A=8U z-d?-BbsT^7%~rkQ(ZoyWVbpea*yGLEE?;#ak|k z2mGQ?s>>0$pnH39s+)b2o4Rc)`3q5WdTviwbh_ij`ikzYd*UyTjlLc8e)O(tmYN2{ ze)H3vx@}E}Yzc%`{dUGEYO#7_j%?rBv$#N=-V*CqVZ$wRyuDcLSgS?7M6D3c5dDX` zNBEeo*B{aB4jp5?b^ldDx6$4D@=|mfoVrcr)lmnXo}=|3EKK7I_nIYP_4ey9A~ z6K-4e4Jb}}J^8oqzoVzwsk^W3kLoOmc@$VJ6$0+JNr%H-l;;(~>l$!cs}oo`U)oZ% zs?@9*^TVyzo%}Ro@$$v!_*otO&k2@N&6+kp+^)$_I&WUSaO}z!zzs4=CfF&UY|HnZ zTeh>rP-x3v-g2(pB#YhL0w$)Ri$UUjb3c?nlJ@z|)>*^2z&K3i>Q!L?#f z2OZs0Vd7qKt~EIsW!lvJsTRd({$ji!MZ2cLFPn^kg8tV+it!-^o45y z`P<`j*9YV`0Zovb?ddtcGOU{_&y(dt>%}o2+r#FjX$)dAd=K)|T|J&qtdzN%tDe=9 zW_bw(Pe{3LQW`PRwMi@!t zs5R6IM`TIl#57b2oz82r*x|#&*m6D^s_W?~l0a$RkQ5l>jV4Tq{E90=HTwBmHVh+} z+*+O~Q&1iZ^-508M^j~6tav?T&4^4Wa z;}aFe^sQ9{`o|(O+9%s)!rVs94$%~~&3dUI3~X33c$Jca=^{9>#LAH#w1L-GMzOi+ zJHgu?$_Z!)_9kvIt{i!4;&}R+_UiK~8XH6fojdzfv%u7%ny`Wwv73Rm0G=1IyTS47Mr1eNc{{y?g?YMy zVGo^0QX>p`j{~7&xhAj*g*+wALLh3M-1>YBbxSfsuX1{AScbC7D7hJt_xW;6%+-f= zcNfoD5lAR;T(&ig1l)K3YF%4`gDdE$k0gIhwDC=;>QRpMik!r>vz3TP48U32Bq;^q z=sCzaYKSx_M2{ez*4&K6*C>3iG6u@!T(`}e?8CZvQ;=EwZ9py9Eu2-dpOHbplD zQI34-Bjw~<5tdL3;00sm!&c1PwC?pXz-CZbR%Npgpd0#Eu0M*^+@z)2SJcmgWq;T) zS7pv!qFk72A9Ul}r&o4_0Q8VCEid7tIiN)Zq;S{3#YFp#eS-3*xNE{b1ra z6H4wc;)l(SYR z(@?u4$|UMaYVCF+YtgdomnIM%-j< z!#`;wZs17Y>!RS#co!9R&n~f*_;C)u7)uz@(9@zYd^;b9FtUe88MMmMfyM_ftY^`0 zruOWW!qQQkSF$aIdjTlT7tWKK$3Gkc)|8$cQ24dA2>Z3c4Qi~p-#>hIqgyQUMMEOg zY-=l<%31@xtm4BF#P44g@&Bhqf8VA$_=T7&Oe!1AJ%8krP9!8M1cS%uq!-mG6z##i z0JUhdd;-Ba?OoWZA$)b;x_3-Ru&`b z#2b2M6^1z^=KbzS{GQC9+^qD(kD^e`%()jeOsCXd?r#tf9)Q>%ihMVG{E;|L%DZV7 zuTS>sQ)&^RVZJo4^D#U%xG4L6-c5#p*Ev$eGY)A?dWt6*-Xyg9eh6m$VfQoqxWX7S zd}k;~GyIW2>mP6YZXA96eqvVDbx}Vfv#-dSg}g@c*>jmk06i^U zMubXuNJvBYmpsn(XL&Lh>(9+(c$K9#WLl)&XA!zMe@#ZekCDJhCHc;iny{BL+?wGC zQpEq{TAKaX>~u_mP;3O%|i- zKFUt=8)%nz$Mf-(GI(Q1$mE$s!nBx8H!Gr%HDDm;Bk}6lj{2b#_ljq~^z7u*=9fQ+ z(CD8SWhAPEJy(_x5I8^#L3LgUBv6(&lU7%jtqT`WRv-cpLR!cXUfjnBLJuN1oK;!F zvPCydcA^~W{Z97rRp;YQuF&oA>TFl5g(in+*j38tOr7o!Q$5`VX{(p{yjJN!lu%kn1D1VGZzyFlWwm9=j>%2N4W9M*xj#e zycdofeTG56&bDbXF@)80?8HXRp4e8V9H5z6=js3d4_@9hU+!!~)i+c4;5}uZXOi6E zgtEJPe0KYcL*^&rsjGXC`ql6TV)l)Ni_hE-m7jM@^XF1T0~vu14olgOuy%U!STo{B z!iq9t9H<>LlDRS_-`)`66X8F?XI;tG)YBaZ$2R4es&8j`^YBf4$Ikflun_E97FWJI z^97!k#Q?RdshV{zmJT!>;$a~5%dD2o+p7HztO0HOZa8-f+C;f2!eFIM*-cj2u znI`E^V8%rp!GuzyyIEN6ay#{FCx z?hMAb7?X3Iqmb0r3&ZyIQ2Kry791TZGTp2;>M?j_LA5LaY%8-%><{1 zrudDYD|e8KChwDUB_xaz*kJyrOdkGGCzJP=elJbv+yn?uw4nKQrL&QN6_1sYqpLhvFP4 zM>G5!o>XQK=TgHmDElN?zmCRxuX7Ij2sBR z8)@1k%WA{y=5@ZaKg)c)YCL(rRT!hf_o3C}Klj*(7a9LJLg3}0`$u_r#t+_ifbURn zawmM{yrmCUSQjOjT?IQ>IvCH>Difr;)L3tC(~a82YyHXYY8f26CS_$&nh{B z|7b47*w7xe<#uD*9lAdgpqtusZ??Y8Grmn7+4(#{oMFbs~0`U|6 zD~3OkM==fJ25v-&|8^AqSuuYt7^FW6Ci4+6>GpG%MEkiJ40}Ld{1|d@J!|nf*Y>*g zX%ekfl~d4bM*8=@{`cIEL|A2nj70iz5hp!uc?SP!NXtUoW$hz~Y-%C|mY{63ObjXj>XM1Q#T+>qb{Tii;$0|IXvP7bhSxr={c zdMxOLb>5--=Z5lgBlxc=M*Abh%~rq|c#K=>S;piV5>b7aOqgkt6s=A3{P?wGd;&FA z${tT>p~(MH*E+#!DL=QpQvJhC)-uy0*hfbkeX0ajugsZFE1web&k^#q(JPAsNh$4w!cjHdW;&`?GCj}2a+XUYc~%p z8tk^wsCOPhQl5p z#GItyb%zCco=-r482=qco+crh&X0)@H`8bq# zcimi#+k44&ZkhB-ts#BR0HH;@@@rwKP*nT~TztFP*`EBE#5fSxEj55D2T-|n5HS>g4m6A$^0@_Hpn7Kxl!gHKyzsM3t=G~F`R>m~f>`@J zXhM3rx|nM!(B6T|+3Rwkc`1zCA2)jX#M;`Lyrrk3=V}{%0jTNR*7>e~{zH-et&Flkfv(rQ$EN5k=l^@u%a}2sX7+qVnd-XCKRRR~${4^tw zVdJPKaDzYTiGpKV8f#v_lS3JEzJcNLh-`t9lnX)dwL`TP zB{aS01H$HVsz52d$C!9{rRj)xTwk=ms<K3IzKSy;4>B7~mo*fwFL0yCHF*pcb0=anc+r6K1AT zl#f&vS}9?^Y5IyHi*CyP5wa15wfD9L#;A-Z1H(ZL;7YTsRFr)cl2>ACx^a1 zG_=6gkHjBiQ%klLE>Oy)UXPdka_zuu5Y93-wFof855oXjg=w5tnV#{x51iD#8W_-% zN=#(_wHJ=1&q_(*?2iojb)7G3=L=%cnXrcvu=&MtDFR!JcO$2YJ=jzrR zAhA37mPGx*&ebu}NpfME&s{-AefF}9U@D8DuUdwm)`T1NT0K@!b=iK&Sihev;|Tyt z%JJKK4(YzqFc&bt^!o^jJpo^2i{v1mc^t7aB)&Vi8wwtHhc0C96;4p5g!01dwRRwJ z9|D*T;`y}BVq?FFkN0Djp@!HGM@iA$_kg#D|6C5>YtUBdJu>={f!tojM9p>IgZ9c5KZ@DmV?hon zwEU#ODy%luLdd?u&mqif^&lss_{A21)FVDquLnu1Z}D~N`%*1<4ROT-wrAHLcJiot zG^?mg`^kt9EvL(rhZdGLV4?ajli{@V?Rl-Wi$5N$|Pz=(QF6Pq%iRlgcs7M)IC|8v`B^T%JW>D>4|}VdD*v) zBDUw#Ix*i#`=^LM^lNk*Xm&gCnbXb}Sq#2S=s759(GC@X+ zB1i4}`kGBFF1t2kgj>Odu15gdT?3I6cb_k7`q-^sCnuC?uzV=+`%!$lS||d1%fI|M zQ1&>v>#e~@jLu>$c_L_ze*9}rA^`&>(q9z&zR4zYrvH}=wpa$AFH3Ncg1%f1LOC)N zQKrN{Bz(RsXRhvOq8iLwu*C|a|3owXWe4z?{AK9%G2D}Ri^gpjTWqvIY(awe796ah z@5^g8cS5968y>>m-E~6E+P-M>gbN zauPh~DCR#cN|F}9J%|-d-$aWy!SVqr;qrs8OKzhtvG3%L$7~aHyKf%W@u&a7aA1^3)W!mQC{{L6+&W~Fgwd;reAXK2Zw1ZJ zX$)DX+~9F{`YEAm|90Hs7j=#$Fu1cjADh}!sn_&NMhSZ*Nq9${v-#k?D~_m z#07n=Zz;IBmZ+zQ&89MO~OmmK~~1*GhUe#!6##W|gS6+Fi5QPCp| zI@_IFC*HKYE;;!r#5VCeJ6pf=di*;}?!RFhf5FNlB{`CzxWn1mMb9bs|DtPHQYzB5 z&t@=Tj-FP`E}bB@>}8`GB&SUtu0n>6nB!ahML$P~qR4FC60)c0s)(M7KZ_Fd>ELrs zo^Q3Io}R1C?Z}ufWEsTqF5X?6oY=41(FhAJKGLRG%d#!X+`u0_z6_4JM6G_Y4$?rq z*Vk@E>;=EaDJ{{@uTQ%6K&K#J(29s1TLM7dM#UB4c`yEMgbwUYr<^>*kXmtdQG@~e zUW=%-^D?c`r{8Uxv;KJH$W16&?|Ajf>hSvTWD6pgq3?8F2?z$?2v4%P3tRg)5E=u@ zljO;smk|DB%#P~)g@pu+`o2%sOYT>FPIQYY?0mscu#@XmNgS}na|pCluANCL(T@eK zP&d!D-c6ou&EC@z{CdcCqp+cFBN#JYEu%>>Iwfg_m@yB-{s7ccrbg(vFH=esgZ4Z%*WtP*qWI=0c#vVs&LKP%iuD)?&L zZ;utXM~7`@Nh>r2_-s<*484UxpP08Lg_jhuwmc=F8&MG1r5+~>*S;^K(W(AC6j8#I zF!#iN!}e=;qjDBTTc4Y9yaZ!APK$D*vRm_AL!~+~yKPEa0IvF6P`ZfxvDMuGM2UTH zElOAoA_XR{#OcyUg?VPj@v{u+xj^=d0^tQVe2L4YUWEcc#2_nn!IN>vkll&gHkEEC z!G3N6(&|M8Vd6Up{$5?blK`J>$1yy4;9vTm*|Zw#eh7RBHE^McA1)?ELKk?kGQ;~D z!hMmrK9o-p_oT1ZdJAq~r1*@r`9zz&$#oJAomP{QbP@MUXA-DQxgDdje0a&?^?ks3 z?n2YH8P8A`?t?y4;Kk&x>A$J`Whhd9bvYmF)@_qjPvesZoSAex)dm*Azs%?>_zF?121EbvO(ZOLp&5MyHzNt2=iD zlcAir2(tj|HE!!rDey|mQT6D&FX0)CcCP3eR|R#9+wWx9O7Y4R`dr0yJW+eH%x^hV z*!{uV_!Id7I|L=?)%(NuS5Ema_JDrx>OQMQaIsJIWZv~iCCP2TFK<@QJXQoPuO)NjGawT;zzJz z(KTnUwi}e3@nriwQH*~uwO{r9d>3}7shx>Ln2BujGE&T{#+O%+b<~}P`P01R!>v8^ zo+F_B<)DozE89>6RuGDansAXdHvE0cSTNmmmXqNW=iyND-0Gf({4S}{S%$d@j39oJ0Cc$zKNnO8s z;HcfgL2?e}jX4*XH}hr&%uQ}VHRdoHw%m}f);K&4A&wsZjz(-Y&Nph6hvIUo;e4LU z8q>=lsJ0buG5CT1a8eK&*{05c-M^njLmP-w+XK_VPNci&zdlfYC+re$WC;_cNteY&633sHNGeu zWiFixdhzJ!o@h_P7Id;*SO(m)B2KpH#$tYB{2_+=MJRtL1_BP%v^e^!3JS_l>ksi3 z>HU1uF_b1nV`;KZ>AhwPaOgjave}Y89cVz|?@{ zSz2*O=E65^E$4`^Ny2qgElyM^h4B8A^fli83rdy=b-P@cva0;Z;Cmozmo+Q7%UOv} zC`}T>Xpv&{SbcJOQ^&4$&$lTyXVQ*_kAHMO9-^dD+}Su`HTH2nXLi#m0j8fn&b@;I zZ&+{0wMJT9=UjNbR$!c18uvi};4kmhWGhrC+^6krG-zuppDzJ;3r@(7aVK`_D6`zb zGk@3fLxqZev zCMCfkcyiy-Oc+%#{Ok}>*dM^?PumC)N?CdOXdr=~wG=26iGMIkOg~5onauDZbv=I4 z6;u;azuiOvb8#5u3Q67X8>N0JwJ+Hk93iVb@_+1lg9VeCuo^+L~9#lk+X?utmO>`N1~`=7ryPAf3nhNByX#Jz)#W_~5ZS zLTuWz#TWx+Mtyo_u=$*q#ABMOz&9b&tF&VCYmWDUqVn^pXD5d=e8uPQ2PFz2{V$$= zR2h#AZ5Xb9E0ST9Czg(-8|q)d$@ezPeP+S|mY^2D0S?T0_1$T#EIH)S53>TC55b3# zmF4b3>Bv?mb=h3S3BVX7Gr~LW2ZHmw6I|ABJYLwkelj|A_)to+$3dD9$mqEBi5mna zo3fWZit(c02@nk5lsny4Wj6sHyCx;y*Nz+{qG8TU!i8=e`4GB)|-_}mJ+H@3-!Z#?@m~~f^kvfIabhY?Fc-=`m`|1KRx?tDbmt& z>J77L{+onK^A7oAQvs*(ozX}4x42NVEe4!teJU$hw8Yx?1$H+pc}}H**@Z@qCg=oq zQ7NSmrMg4v53j|n_h#3|H$3kAcrv-t*o2FrxqoMd;8LjtxzbnI$9`NihDQ0rQ!{Mn3_n$g1Q0b==fBZhBi zQ77G7D|6=NG+B@mtl>V&1V5)`yl%$g39~F!tgX_~-S4MN2_IE6QQY@!vu8>u7OLDX zmZ4kI@fI||B-#V89zA)sKM$@R!ISri8D^*skSq@#=Q|4B-Kpx1QW$4@clcX&h;*N!9n(ULB z-VEDDH-z0^YL^-;c5;QaP&CO((ad?Q?; z_wp5JoTp4n!`Cd6sve*$yCQ5M>H-A^bd}hW7P*3(j}u*D91+Z!KXQ)~NvuY1heas9 zgi4ov0%oNOUS7JeEpCAKz%~y~x9%U_BbLu#Dp@EOPC)CxXw7_rpDYV?L{EPkdx$Ll zW@_T=aqdccaw@`#u~$zKGBs<6*x2{O>Sv$LnB_YO(XX0A0T$8-eU+LQ%e*=^jHHdiFKecScp?fgW;z;rlnk=8G zzA}^iJ#PWR5QbtWi}!9%C-k24GM~4Zze@8r?wLTG>3DfIYQ-O-{OqMNNxMN2PFuw7 zOw9|#ALW`Yz}FP_@&i+!NvGvbexF)oi@>QbBp6^EcISNsHf~Z7 zDoR(vUi$fu1(%JwZyT>%cXZ@_gt6IzrFd4+O{T7QniN8{UyD~(vM+LVKJx8w7g30O zoXcg>%WjN39h+mevz8U6Y(cOjT5oWS?M!6|tanZh))!i8K&EVb3v_a!v&lR<=OM^S z?|UUC)WhR3>x=d(I@UOj*xU}D?GA1Sn5JZ_)SLj72_vVLtGH zu?=G?m|miC%_#T;c?c;ssIAwJ>a(NGI!%PM6=9C5woY74iCi>6B@Rf5O&XaAWVX(a#adC_J#?7#@zlGNubsPO z&P;sK#^-A_jluXdqg_i7Z_*#L`)+x8QUkT{p$qn+=&nCOhYpB7B2jdr!>w+*TZ+ z)YG(|=*~EpI}Qp)m>6V5Oi8QT`ty9GGQW&~P^z_p#v zU=F)i(ob#8d|I^9O&W^WgkPwX7ZK z859)qILjJHEZbM?IQ_PvcC2T%*^iMv=F;~nXX^1F!^oM({tG-HYF_6z?wmX1Q zeB!{0p08WZa$`#fX(7f(xA({s@h+TP*KfXF_`#i!w|Kl)G7GezO5qKgSJ*s`)!~ zJ7&qpOUZwJc2P1|U;<|1uC>5W@)u3SjPE<~KDV}>adGRi#A#-|R1r6799%IWUR|ewgfUu)erC**Hsz zp{x51Qg58Yx_g9q2EpSD#qp~amR}e2^S{4NNZk0CqP=ycbT;MBBCr*A(%7AUB6+o( zFU*6bkC*L|7e;=*f~;NT6il-_nt*uxDQA5gJyB7po7sSdhzGaqVO5Sk|03G<{dg0X z&nD|KY9v*YMN(&<2?4cZ-K|FbX&KumRWaY+s2>g&BupJzIQSg47$V&nFY^)O-_|~+ zQN0c%#ggPes1o!u5l`a_;qyv0o8U03>tiEX<3oC$TYUKCBF47;t-qO=n~7eaz&TYF z`f9uR_QilH=fb=0{*Np=TWQ42(2n zd;#}=?9M-5-@g_$x(O4eF;@uHl->vT`$emF6u#uKFH6(4W}~5FBV_NvMjBQ z;tu59-<4Ya(&Pt>ciW|pkHefwz~ZfsanNv4bOX{{$S2Z1#^3m(uqlE@N+YqdSwelE zbwZ13Kmo1XVbl-&l&b)@H*6#6xP1hQ%=adrr7cmKseuy0sx(iM$J%Mf7G<3ZSwSVz z_)F{`y*3nC#S%p@w1`u`ZJpV%gy_#*S}3F!y$j71is#m2%8K zhoMDEQhrqeE^2Un?-*!InnpkPc=r>vhn(IEp^n4BJBmf743xCvBizc;Ne_o*gH?Pc zTPdl>xq`ip0woh*KB;0K_@o^JbnRB{*DZWB_4iBZv7fzCSU;WFx?KOp{{a=@Iw1Hh za&r;kr`l3uC0~lAzBKXRdK(iWi*Tgl;Na(9X^dpGF@VMK%yrJU)v6h#TQ3tRS|>D1 zypN&_jly#*ChRH7TyX4@3n^l2EaJrL423KByQT2?g7=Bt{a)*}Te}H6jUg}wL-rlk z@1%qxl9Rg^wSd&>8d>VUlI*O57M{sfZxO>88#az)Pi8GMqD@}+sME4@$S>EXaEXJ` zOrwIefyfVCo$0}+YS$1_b0@TSFG4P-DGOLW_Zj&QYxZ*^?w+mCMi$ww+;1ma`}p!(TN+Zq=~t(BC7ppcrAJ%r3BeWbS`>=6{S~3}3vqZ~={#Qc zEiblTsZoc9+Ip|b{^ASbMBY&d5Y#YRJTH-@p3 zG4_XLZ?SGW{JUX@oQ>!L6~0rase$n;7^9K;jZVD;x!5%19+#or~Yx7KdeVs3Q-yK-bix7ysp*}|KD62=_!-kMPA?lSqs zoH~m>zy-;Qa_;nzqN08Xd-$ZI2Hya|^P`i~55_9dakj6zK6?s;=|=$dXV~r%UQ0}md7jodm%GpMKYvH~1RP)U?nQNLu`F-NC10Wk6^nH^p}q(& z+E?2?^Yy|FJO_J+qG4A0g4a*+Bbehj6bCIOoB^?j2HLwyDdKnPF82M|c;BrN-;qA{ zCI_TN*@~gu#CIge8s`}r1UTjwH3+M*hgJ-5{8R`iqBS1A34Xnxd_#h_Cp0?7^Nzp{ zjf7%Q7V6Ft9g`IjUOms#*VG}N?EN`p;Nhy3z zCiMW&aRlzDAAW&}^y#pObCaSeXlqjy-uXP$Q4@z_QJJ!x5{Uex02SXQ=;(Eeq9qi~ zh~9zb^L-UX*6rNu3wCs^d$8RyGAD;U%TAlgoht5c^qCAaLx+3y z@X#Ka8&zO}I?v@(p^Hxrl6+e{Z#wsUs_E=UBK|BU?(Lpqk^r>jsc^fI(m~D5BMTfC zKs!Q9q8_glr(W&pV|oY0gCfL~zO%OxZ`5Bm@{Okq!zL9fc-3XY$_*r_0_J?B7n~^_ zPG31lGz6V;s4r?h<*a>$NClwVYCrWadB60mB*i@bfutLeWD>=dO%2Di!K-`Q)ZVtu z*zzV@-}5dR6@?H2zwOUE<;PMi8m->{Obci>uXfGtm-$INk|^uBGoWaIGSLN5x^x+D zOlN&FjOL3tfl!j9{1PEV#8J5W>yX(S0-&cvQ>S>`auYQA__!$^;Xwy;+aoca`TcAf ztE&cfJca!RO7@lAy}4Iw3Oi=~g=*}Qil>w#S2FkMx>^oB>s@(;d`5-O&%_k2TDbw^ zD8<*y={ykWs4~A)?w7pF&g*u}JgyifV_EhKEx0zWkL4IP?j7pcEIkvbj3wk831n9$ z(xNpTIhS7FgO%-TURG%#{T3cg=YhaZYXK7ngDz zj3K;Z=g1Yd(NWWZRbb3jv9*2+b(4h)BsZ}ki+>0m_}JYt5sp4#Rv+(OpH6G#JvxR@ zGVHa3zVz)W z+pQGQH#InE*N|$WJp#(`pk4czeI8tM6yiH~;hV#uh-uvMvM*!?wcUp!oE(#_Zz z$$uXvm)Vy`lGHDUof7vY3Z=(i-e@ZCU(DL&axz7_t?WB*fbj_YQ(ZA4GIhl-xU^nJ z-WdDpD%-j~MeY)=?!0zyN>JD9@N=nZtnW-#t?v*S0yWxPdT60fpZBwcvk(_{rj-BL z1$3HY`4}IA9&Ve?^^9v}+sjYvK<=0m2!GbuDd~`m4ChJS9Ldml$~e>GUX~OMf{Lq`f{sQpqS1yhXDDn`T_QFZiPxkcTOw(b zK3`L$YZ%(xm`KVXB#e+51hWJ>uzvuF17!iJGxe#>+V+(-z9khz=wzc4)-G({R!JhW zFHn!;>6SBwwnM&02A*?KMc32}Xc?H45jSmqiF@7Hl*TU;8R^wr>?7A)A(M7P)4Rr6 zP+Y%02U4P0lWro}d1=mZQB^4tMe|0N_%*Byg>EJKpI$i5Cd4CVBzETD+ zJQkEP*#UVr-Fz9U+Ln1^QIxKgu#hqphVV4oS!Xg#nGrk4 zaBLHxeVC<1>>x)evbVty3B+hX-zzgF0o&nxg@w_#<~FQ@xNC{x+vnu+puTKoT;RLVx8ilex4m5h32~ zRo;?p=a-3Q-ofPSMX?^3>e%x7$Y@FHx2sILd#|2SYzaYVb>F6ad?4+9h6-XT$(}Yc z3|&ju|FKn&LCC(QTou?9*y{9!Wq~z;vIu*oF854&zrZ@`;kn?m1+YliXF}^ec5U&y zlbGx_`WTzApX7W8eye-n=(ptBGewoM4`Ifn>VkC_j@AHV*$5SNe`T zBgRsyMdU5V`s_#uCFBN)6O0me%i^y_zf~~hEUoHjaAi^>qkoJ#Z=W572WJVMKMEv2 zc6uT)*SCV_@g0JaIw(A#$m2(5bBG^^4u162()1;l3DPqi67rl^m_nu_v&AeeJpSVk zk&jrEzK!G)((qD-n?R+U05b#k`|L!bi=|E|@HFJADE|eCfaZz>yOMYosd%2zLLoti zc!?_?#5+u$M}Jl#@(?AnHB##YlxgUhHkaNrm4=88m&oY`i9pCbYay|Q;oYqgc~IB% z7W2|o_fGh5N!L?p=fOQx4S)L}Nt|MNq)S^#_LDqAy@sxH zP|%NX=u2rF$GURw^^=rPq?(|(plx21^)gonR(~na*R?J_yu-U25Wds)bL8vt5Iq5pkO}Sd%1bduB60+-N%)?`UHN$#{5iQ| zkpsE&Y=1}4N2l|T!9y30njwi|rz@%kv31N(xT2A}R(hg{l8Fk*CpGmXT{Tq%lY9Zj z1-=qC(5(FSZ#<#=Mn0-Cz$xCL;rE9E$R&2=C%JuTr*ier7Sk9pdG3+i`>Ta?Oq%3I z`4KH~JchE5JO;z7k|4{7aHYSMA4xYv#mSbD3xEAYsbD$p3coke-=6~)@g5aYSe+k| zPV@!f-z15|ia5obz-!3~KN9&Ja{z?Kuqm&^fbJ;%Hux_*_jfsZ+GxK_jf`vq>I3L^spP;QWt)X^+O zBijocTcds^r^9?*Cu)dlUr_WHg*WASEqgQV?-!0*CA;f8s5nxKaagX@*-G;JioROR^REByI zNd8zZvcDx!}zN<`J9>q!%`VvV~uxJ5p|U>dPz#)Q-Fj@d9&L*I}WC&$7AxqtG? ze0)7m{uX(~kvT01biGgd`EDeGD`zC@e0M{94lMCxS^Pbg_^qpa)>z~Ji0M0R@m_Au z!;v=Pzj*WJ&EbpJFZN!)c)9;-pA4nnF`0cA5!gAxSpamDV*{sTCKT6~PKNTL3QVUR zK_F7ZMS&c(BYN=dMEsyEAa%_GxPQXrC_>j-3z%P7(KBMhE2?}-WRA?{ux6+T_9F^= zzp}4Mvl+uk?W77Nj+Ny0G?1jR1hb;@bmKJClpJT$J_|A>5Nw6O{lLDlU}njDLz%v` zB$JII5)kfv@@Sco%MG{+?)UEHKk;lB#2>rN#2@D$sgDU!y3|C5(d{^s)PIa3Y8p5K z9+^2p(;cbjhf=nJRZiM7{LmZ%$;%W{)l1$wz(T`x$s;Gt_^IFMet^IqM5EF2EElk% z$g?w6KWhW^SB)#&>vIDbnOq)4I?=tu`a-^=_%@lTK15Hu*)M~NFx`YBhp2M>BW2OJ z#dzcTYs(35t0bnX51yoP?0M^z*5Sh)Md4Gk2O1X?} zOSE363*B`6{v+3!2c0S0GiS}Ah*5qkm$0Ck=JVRk%C}683<`fG+3xpxS^hi9c4@c9 zU=265#v6{Hr-Oi8hyOgj!`wgN-^VX^4FNw^RLxuLg%CD@V%@jocz^4LXq74V@U0@^ z!LK60MG^6rV zdV}{Pqgg*6w1yu?r-R;kA3pu^!XQBiWILldxMc$P)MN)jFN0a1b9Z6Ims|0)_3K?f2vDA_1=kyUWjg{N*D zM}=SiXed?w3|;qWQ$uWc*pz4bwlK5fP`RaJ|GI<%o%Gk9b&XiYyy*Z7w1!)Y zb*Gohr4kApKzh?iKw%2|xWPi^ZoV48gteWm&DhBjK{OLN24&U&elpNIq^;vOnoZiL zA-rCW_T->Z8-LceHfep&y|DpkJf|q|D3pw%x|WO3P7{U^B_Rp}x&tFN#v-d0S#r?A zu|CfLW}QEhOuHUzDN(?ajVDrA=Zie<^Dxh$+uFDAg4kj#%-@nfLuvkF=qDOOIpD9LijHS*GSB<{hFKcxDiN0h#6vVT-)7xR#`b zCIjPRPk(n{)`y|DB$UJm9J!lZ04YSI+V_w#1fE3l+L*5#F$khYl7}OGMDRUUw{L|D zQk9uRzye1p2o}=W{ja!!#QGeCe2N%Qi7sjCTuS0<5?MLYNlI_6u{E0&|2JS1d>LI4 zOW&09g}cl?RtRZ~Rn39HA34_+ZH(xu0{1nApnnZtFUg{a0ASOCYJ>0(Qc(_(qhajC z7e5-R9n{eQzp_YfP$62O58uJA7)mxnumFQth zbAM7TQ}&J!dr!vrK^^0eZVR?7VoJ!>62b`Pg99Z1{*QeqaD%{htuFcDF|;NuV3$rm zfD%zyNWLWEg7nXO5`O3QDsF34o?S=vnN2?IM@MN#q*gzdGOtHD%ccDE`(@sua@QmW zCP3svQKJx_!f1@-#ENsNP)hQgQS?)AL4TgSk@7_xe?G;tUQYWR+UVS&izzkoI(Cto~$OT5pJ50xBSSff2r8)r}&*Pp-mc=9Df05 z0BnXLy!iz{GC`K(A^19N6YHP*2s8Fre&l@eug3tG22gXDZ#=Pg_Dx^`sklDFLJ%zJ zK~2#{UT5TO2H3?IGZ;Mt|Drjmq$9Tuh3{J=zZuf1#wt|G>`dt_(INMx$!mmJ2urLn zWjvOiZGJnNU3!%e82R^Tx3-lCL4POlU1_5jk+|X@mq_;Wjd>~%)TfRZKS+);IX62vwP9`KvLmS7m`JgyQppJ=D;H~x%3ZCokG}_Z(p9Kb<2keCH=V&!BHykXVt+SIl-sNK z&tcwyoiO|Qq)pTK#THZKZeeWzFmh#okq549bf#;h^2Z5dYFo33^mYQ)17=izsxfON>ACVN}nr-%%tD|esoI8~%)Bqiq2(a@e-wYj@=0`>Db zFvgCKR`(L_r{hmB?MRZ$*EE(PR&ImgR%3yE#k|JCFCOSpmaj?GaPddjzv~f|9soSQ zfnbjWJlm1a2cVx68Go&ymnn8@MpT{76esmpgOj=-$!!A361eZpFGr%$D0MoekN6`* z5%y0Ro~#ExLg+$#0tjok z#i_Kg@BkwjS%2>Bl-L$$>j7k<+(G;`=_gkOK#&$a6LO|xINB3otIR zVFG!@FG7EJf;NSf2cGJ}mHd5T1<-LJf>#?BvEm^4*ne{gjeSCfL({v4eufOyHK6Uf z4p{tFCR=|B!Obj;4w@n89C5NA(f9K#!71|_R<_M?+Zq9PM&v5eRx zA+!%1Xm_%ry&>rXf=FP}=_pKY2*}ub-wi<_^hI)h=7Du`J}!Ye;V*x(UurHAHBsJ_ z79mN2n3`XJGD2Ea0e=f{M91GvPPrCAkUXGL8h?E(e_JGp=rMWE4!6HTG?M&XEW(eH zfbF^C+Zrc;Tth*Bd(->ovx{w;b+*xCg zC{5nbT`w3&Q`{pO=P0&D=7taN{zx^CNck|O_1GEFhNr0NAAcD1>#8`A^7%+%b5Y$& z@qfg-jvqoiQIRrXr?OxR^NLb=kfRu27^N{A9mC)ke6}n{?1zwF6u7ay(2Z)LH7AfG z(HNYDZgL28MsoJcr8JpQG76PGB40ThR~AxG96a>Q<0)k>PpuPvy93C;Bq>@z8u#o# zLSBj_Og)t)LuL<&b3lG=tU5T+*HHXd=YQJac@e5sj>1-tba8c$ah}@Vwh?qRV?451O6cusP~Cn}b&ObX4!* zsrs=>dIO5%WPzW+|^D;x8PhAPI%Qkw6_HPoo@buVFBT3%UffF;F@;9_-n1RW98uFg- zQUg9rxM8z*Nc0<028m;7R=RL!OQdVfw)=ojCAG!oR{h!X8n^O`<&3iFgsxEr-3#LY z=;ZV25N3(7>l~oc0SIg??PE%P41b8Yi3AJI4pn`@#wJ5x3*zDg$le`k3EQ!*pg0V& zJ>B@qXNb7rY8^T3JQ{#0MO!FkHICl=$N}Qah2~Wa3_doq+s)Ui#}-pCX@6h3*dI#$ zpRb7EL>$m!A8u2Q`I-!ik0^Ei#d0n_EUstsjg0TOm-@@t!;?h)n|c|i8Gl9g5HQAW zmiq@)WpLn4r`7~I!ECv5Q(~=gE5d!j4EbhqFdi@AWgAfbI$6)+m#Sd{1b55rLK3f#A*ytLfZC+Zlf;1VV z!xalSKLN-OJ?UbBxc@MlIDet}$x}7#UO!_>zR_RoE2J%YRluc9JcUBN-BQ zS_m96+&J`n^@ZG7(xpHI-qIOMuNLgi%1cT@04rhf^Aw67>F#aK7s2iGGK^ITs5Hz- z+Y&{q&zxuZncW?UYAO>j5`%-od+6~am1tyqQ#6?`!Ck4OQmLrI1QVjUbFy=~bG9Yu z?dt8Fb4Lm?0*{mjM1P{Rw98gGj(!CR2uYyQE~lCnqod?G!7~0a6LDlerX`K-3)dw*qd$wAe-$Y{Td3(77fs}G&~5?Kf&k4upPT_6DF-}l+KN^7p*AJj-l zJ|hh}C4}Oq;`;XaIUm-*FTvF*SOTd+rvXif6-N|Bn7K?uPaL z-Fc&b2Z5ixOT{T`BdRZ?6rPQ_%nm}e+GHG2Ex68{P+8QJs83zf^9IfSd+S!*H$G~! zX>>GUQ1z3G4LP!L1;{noHK+4zMcZ<&;Tuc)30i_|ZG8#rifBz(cc3Oca%1+Q&cStNRtOR}bP>1Oo@_6ym-&3q^zqK95Y4^@Qh^2PIeoY@{* zYqpgP8&xs_c7}ArT_Gb1DsY$No_|XdSe9y6T5B{su_4tMw=e|HrDPnnQyqjPg5A;l zBE4&hOCllKE?yGWm0(AuO!!$6%ktE8eSfRJsg^)9NTANPiKsPO9;Q7v9CHCuWk%(w zJhV$@pH7FX!5Lb{eQM5*@Fm0-*qI~!rXhC_Yv^^`AMX+-!Q=t(jO_DZ9oeFYgNPz= zkUKbt+zooYA?t0h%2q@X`aA1R@)p*%<%^o*I=2Yn#!qU@(D_r21b!&1)Cq7ypMSFB zZOe)7SB&%9*><_N!%Gv|*3uHDB}Om~n1U1y#r+_~!n(;Z}f zz*5-bsf_6emnwwPC&?PfsT7w7$6pWDV_{vFMdgrC2O>;i64uCQKpRt#R(}A5C-+J2 zHU{&%DC`z8t`=KcK$_S6z5N%Zy_co^z5C`j&)g?*PTAUIlD@K5Czs*flir|NuNlL{ zvwb)P7Xt4=Vr+AUtm6N3Hz`r9liKEwt7klW3L1dgtzkPd*9i;Ry=TIlOeDwmpZp!A znDwqeCm=a$7phPGj#~Q++kbcW!bC&y>7C#xQzq-WIkPW4TND2AC(nnRH-_|eP|r%s zM5e}6eRe3AU}a=((N zsh=R;&!Gg6q~(`Lb;@cMLeDA9tu>zbCappKd`$`G0@0hwT(_Nxg|}%BYIH!;M$}0c zs2gdUrQ1`^%x9u-V|&5UoQ)6>O3A0U;th>Fm(oQyU%QvQS3|2oE{+n=b_nHbrp?kj z!h-D&Mn@ASZ0S$CwSV(BM`;MRc_oP*10v}8$T1*a@qdy};q0^(Uk@1p@+_(>^pax@Is)Eft-ddn!m?P4(_9ORftVi$_-=Vc<(x(Wl@1TFg5t~EvJ!%4m?rbsd; z;)Xf9Ka0ep2hRcScI??wtC6n&_+n~gGA8CvFq!>TWRHAJC~*FWB%$~SbyzCHC)6BL z0RnhvcRn{$XnzAUz!Q_4rYYT#3rD*hh#;0bb3w$ulz~oAKKO7Vg z>;n?*&7xY6R{-s%!$Ne#~yRj<_o!mrYkn=|}`)a0hqE~xX7bg|vqP@I}b z9eDc|*a?&{+h_J|I$YmIF7q-7F!tS#9p<;c5O$sy;@)+T$}tBnOy6ZOR_;NM2K5Ep zlS1RH{(t}3`}W^7vUJ;@Po(@0Tg;X0j0}z)cX#5xjRpfrtnq_mob=4qkx&`RHaD1} zDRAOZbpQ6d*7xmQ6j0bWZBsiP&v{G?Mb)nT{2uFDt6{A;zqXy=g(wA(Dfm>9_@^wAkfB1=ZjZc%jYl8OARLB!Bm8y_(`Axek4+ry#gg2=t^ZFh>|) z*A|EQf^PIE?<+1iouD+m&2^^4)2f0tX&R!~uXE1p7%7a_Rg+t1$?^FrLH}1`Vf)4c zRn*eIdA;+?&dXnRe%k(7m`UbQUiU6gU7+N5gtAr7kRe4=s0#R9D1P*8$_cPwWj~w% zuYZ`eG;(1Bc$SZ!KEv}Ue#o9+IJ0ugc`YJlEiho#ol%nHDQJRWa%+TaR-;k8xHlsNmUk0e1z*PBoSVBRG$b6RSuS#!w z;TK*2h9ev4?V{8+^D=$is680RO3+`BsDDS;LM>+FBOo;G;f+L(A;V)%hXDx!oy1RG zXeiIN5Pvp}55Vki;K8wR%3(`2amscEJbL)|ew@yDQZBc%ho&RK{VJnAK${ za8TP)v$h6N?4U7ttjUe#&h7{4%A@AHJ7dF-*Hc4)PG-q^Dv<{ zg_A)X(S|J`z>#~_3;LfJ0ZOj#L}AR;!ryUaAXa35CMyR|SYdzH!cJE>#XlaB+9}Vu zs(XrfahknI2hXOvPj;JB|EVvhd}@Gd=^L5rD|3l=T3K%{0EyqK1GPlBd5`%4o}4wtt4zni;6XmC_1hznGYu%3FTFTEd6eK&%EcX=gxu$v2p1 zK$(V2KU(*)42uoev<(4zTZQDc*J1-1KotGcRA>CbQ67rwyzJG8TV-HURYS-*?bXP5~=$P$VL=kEgU8@vyeOyJ?WpgbLv2yOhbUogw+d#D);&)gJZp7wg zBOb?cL#X$li$cG{?u9x4sMiY5!{KlhyGB`wK1Dnpo2+6%um_)_P%^a__t?Ozq=AmY zeX`X8?Cd7DQ?#JDA%75P60pOw!7h}M%NUhsvK8vvI8NUDYaRdqs?uBN$GcWqZ)487 z2K(zZ=u@1&qEb3<}AN8He)%TR5p?fa&md7=|RC6ynn~ znl~@yjkLN8ULG<|1axBF@I|c5IJrmDQcimABy9Y#5e1Gkt$(O@{B=J_I&DQVw%O-< zj%B?wys-0y{JD0FM`3j5kW!@Aki<1jo&OS35`Gf8$*?Zgq3hA6c8Cw5DwoxIK zC+)f}Y#`~WhOxVwYOfWse(k*l7hj-!6eHbl4=P7T^@G;&$NI@Z<=;68a}53JB?AkfMJ2ZVMhoS1 z`ycB*O@A`=!}IE~>Go3>}??rIwz`R6{(md(qbnG-C%)V;v2n9#VP%^#0KCups>XHs2dkZ+#5ZdCIL2(Zv9owtqny$xnOz%LZnmPhl&LFI$ey=&qm) z2QBFKnL^~l@v~niuA$syLMI285bU{RctzgvfBL?8Y5tg1Hszq&wEg%3W~G2aGV9u> zF(DXp4XBMSp%jq;3~@;GQMWzrVcsSo`AozJ6e#Y-ig;%8WebTOL_x>w1=w5K*p_Zh zJAaMJQ#vkuMa~~KY^Dy?7Wb$`Dbv+ zIWj1sK(Rljeh{x$YK}F#{Xzm^mLh6;Mt@Tk(K?Y}LbEN<`&h}_pvT9}-K}ByL3`;1 zLg`5t;3FVTQh82!k0ssIF=oCTjfELHOJ=308{7n`!kcKUQMyFY5eskx4se3Llp`fD zlXro<)ewG~E1rU3a3yl__Ur(c%IA39sZA<@UZSXMu5Mbrv*Ff@T%rC`giHP$Du2E! zSgg9j{D%sp<;c;Q^mBd`E>5XiYifC5|3m*NCo~mz3qJ8l-9-^dWIN6eXeRs{dn@;1 zw_B!_wz=6uG1z%t{>A1dLx6%uVRPZgc;x#dESt`0r&6OR;3Q%_0aU~5?Sh@E!}A-{2w^H#C&pxMaW9ceX3fSP+`bU|vBqE4 zMR5YvKw20((Zx=atoU#;yY}SPmi5H=n@m%5r___Cd;_`$ZudxZgn(ypfqx}&4mg<; zV(st6$g>VjPM8qqHhG7eNG)#Jv1ro}t&-bHS6!QlS-=@O?T15YHMqdBmTJ0s&+;RI z+VDqYPR_d2yCDD;JZ4BDJropvkA~gRjoGhx#-pYYCz@>zu6XMUWIHF>aiTmk{474W z2hihj=(x&9Al}NwQ7WG%dVdRnXQ}h|r>Bi3YB;b+`r&ZHqj-;V3UkYx7hJD^6FC}1 zfadzdxfu9H-N~7h4;}@vW6xGq0hOW6=0Q&9ymwP$?PiVYD+hZgCJDm(<#p=0D^)*I zugl2VnyVII4Kx$bzus$lKR(2=yzZZWP`0kXeOo5lACFfdNn$hgtACLA0qceMW^RAq z^5@ihk*84L^!oJ36p-{?es;jg7}?M!GN9ZQymA<9G+|->(#>#5yG#iX4&F?U`1X)(F>x*3E-VVddbI5o zjRVHHz^tWn@;x$Jcz+6f{qGft0xYUaF8qLjuVDk3fK`bxtSp@7&xZ8;8RA$jER(>Y zPE;LAIrYe-kd^kh6%S?BBOs=MjFO*aLG-1r=60SMV(wsF{FLUdONAcCFH?Y;^b=dPT2ZPWoCiV6K+|Oef#c z$ZVT2ARt2u1b=Pd4}=vaf5?Ux^fqLewoTs-$Ma`*DJYuMV@u|gRQ=2q1O1u|eVnwk zwPF6Y!K`92U&v@M3eLztRoC6cD>&LIS?!e%aZ<~X)T_#p;fb~P@8bio`n1D7-s1{@ z_Fl;-p`x-VN~%=924R~j+U6Oo`Tepx3MmW-w|xRRl7B$m z0f7eDfi@U$Q7IBjSVB#PuD+gy0fw=6V4j&OhI~T)*;YxBi7V-T;RIFXcJ6H%y&V93 z-@OK;9SoMXB#%6b*tBu(FxyW-Vf@ADxbm+^l{o4GD1BN?feRDmljZbL{2x#rv<0En z^~t=$$$x;2O7=AgY|~(n&5UfgI_w=Sx3J@?E9*($x%XQEwn#K2&BCU*jHB%3^Mi4V z_?1Gv-B7xJ-V1~Mc-bWn({O)A)NiWN!9OrjZZJ<8<5KF_j>afi7ZNAzw$@NN*IF_- z1Sx^7IP8V+);d~C_VLiv_Du5zM%xw2!^JM*oqu4U7Pi62L)oonbPh3Sczj^tmNH5A zm_q&Nw0_b!*>Bcc_1gaF{_#<({;$)M`eD7*sGqz&J~^x$RqGiBNY0_iCtWwFUlblU z!A+s(P`L_EgA30hQBNdYX{X=6!y2nP)x>xi|@?15E^AmP#Qo+@u zP#>q&mjE(>K?%|jVQJ@es$@TawQLDjp#ikLVa|uqm3hg{64!lAe)->H=>LSnt}k2`k5C_ztMK-)h!+6-bjAT3nxG3lV6p# zU%p)UI_}Bnjmu#)zPL2FdYPBP1i<*eDsA0zb2oi3g7)UTdivd7m3D5qgL}8FpOahQ za^E5#Pma@*;{?;^M&b!Lh`Yiz7k^xkrc8}O6q%|;IUSiVN^D-xssj+xkjJ$|njpA_ z;Cthrzwu8&lL^VI345?Dk=2A!iYuGGOJMMc@Fd%B@>v!0$#HrB$LYt6BY&HFHY!)4 zu7eQg9qe#cm(_ntxI(j5s|pobZfu#-0&eaO{&N+K0PF`;u04WkQ97i6V}F5HGeH=J zqmnTIg&6_Z$xW&~7Do@6*G*lv!CMggr6?psxE(xCP8rzwayPn$%A6@IGnxpNum|sj z(}PD$(pDZbySx0zJ(O?2Pkpnx7V)N+K?Wy%OTUXD`;UjE<_O8*VAv_uUzOhW!Y>-a zcVI`Hq;SeJF4K;P+JkY-9)Cda_Ams>>t-Dt{BG}sSMZr(_{X>lIX9U)@{Zzo#^x9j zS-y>3!KxzFLa@5_yaZ(C7ceNA?iIKlbn+!yMkxkd`C9l_jS3zKn{G57wnLRUvXk{r zDo?-geTf(yMTFCY`dq|w)bYMe={zDl<&%)qpIKUg>D_x{syA`9J%3LAIX(-AKn4NY zg({m^?!-CM4BKO&-4Jv)q2l#Eute>!voXU$qVj?<)cMjJ;rgk=yiDl~+7G=G;qxLZ zSN1vq$K2SeeM!m3{TYbF4@`lD%>e?hVhSk}FoF;PQa0_&G#9>zj*2xX@O8x=#;_!z zDE^rtQb^+U9H5Zu?SBcMH-G8bI{vT8f3h=B`GRD~tw3vfX^+I}FN^&0L+LM<*WV$~ zJ1{E4#-kN6e_F>Q7`D1SFF&e}(ZGe3a;t z&ku%yWc0*6o({gE5p;7GDp9uKb4OP#ZCfHzDO=@!<Pho=hbPF$-ThkKTB9*Bz} zDO$i`n;uvg{QbyWNt36=TZH-@#}Ma>%nVN#*db#(q?KibVZPf_+KQBr6Pv|aL7BVl zVF+0Vd{Vo?K!2d}Opb&2*UZ$y(oWV&4+8ai{ODxJ4#38e-T!7S25l0;ecHb1-qv3B z_GF!gBsQ0FW*_Bz5WdwFWYWGNk(QJH^B@TEQQ4jcI|fg5dT z>aZJnv)|PFBClNy2Ekdk2bf!EN$w{1y_*Yv`lfKyMt>_SD5fDUZ|AJ>ZZ6TAKV^F3 zKwL@IJvBl63KwR1E*aJtN^@}~{+ID_B;lFlf<1A-!eB8*VHKu8oIXaT?(gkE0ZRr+s$O_LGE%g>K`@61__9oe8AIfwk`2nk zDftcFkhT*J3$;x{2f3{P$NJ5rJD@BWI zITuQrRsXVUfkin)HyEtPYme74WntccjBC*Eqky=r6IpU#8t0kc#qVG0yzF?G^`@$P z{xOCsg0g+}LvpVKNY`j>3njv6WZukE5V6%6T}mnkF1*@KT%>hv z7)7HsnjI2dMQtIX)q@BuMHr$!81q07mVe4K_-6$q5mk@&YS+2TMpzwKDl^+Hc;RG^aBG^!Zsj#HZoKI=v8Pv)BaAC`=z+qNwGA^6ZRkQQWc9?_zO4Yh0DMd050 zYMR~NHNO99_J&daKcRO_TRvl>XGV);i~aDk9SB;L?$owb*XePZ$QY=Vgvbnwi**qB zTm6@vtN2@f{87gE1nwA=-0!M&vw!>@N~xQ*)7-JaKNR^(*%88XH;LNa4oD-0@B)!( z<9i0ft|ZWqfcMAX3csPh?yV#-@Ai~+)EA@O-TYuLD%@S>g?`+MXJGH(s2;vBQ&Z{A zTiYE*#%YNs*hkFI&O0B(paN#GNn`gHyo`?(Hw6eXMx!yfQ%-LN%Y$525`V7F*qAI( zj1gUJbsUa}d|CRuNU?Rb_A1SK?Q5-mTB*LT*IFNs4?Y~$zwRBMzR%U)I1Ij+kBtva zh!hV|lH?cj#snvc(_n3C@~k=A$(BXOX0EfjQ|8{kdtztk83bI9F5h)^mv?t7wcTCj zpm5FyobMamW3y$LHtZ8mFrw_Cu;uk*k9IU6^0h z+Hv2b*b!%}6fU@W21eG^S({HsWqkvY@J<6->e*HTb{xfdF`{D%fz9Qn>;D+Z8KgnD4StYJZkOG4aTx`kUAi z>lmj3(ngW@yh1bHN$@(h5p5EqE)52LXsE|@ah^xp%yj2^$NZ8@RMo$j>H_+gZ{dGQ zUd}J-OncogvVl7CDR=2xMyP!rMy?Y4^G_)00K@B~lSFazMzr^wD$5p;5s>%6T7 z>7#;Q4utgazC6*vqYO{|3&2t={g^U21W30Is{QWO_zE$g*XDH3{6F)03oLjbxe(M8 z%1H1HhgZTCt<>4UK!qqs$TvkBmSK&L&{>)0r|v)_dFfvPR!SXy0~40g9ggN;59VXpw8Bj}d3jkP~F#v5ieGsD?f-$@aT zXA|OwA@_z$0;uQG#_B37*KXAmyT9SIB+#q;m;?%|?7qMM-5{js4pv$S$!?s^GdYkH z5V}@s2ZxOuFMl|0;QTl;C?f<(aBOhjp!*avDqf>#Ik7ZB z9vg83Pvu&~Sog06(Qu?6Mq}jNfklTF_t{vC3B4gg52?!xMquv3Nol5X4>%n(!m}>I zeyDL_Y<;n`Xg0T<9OlRjr_$bT-;y+0ivc7fg28nFU~IS&|9?;4 zioXwr7vV_HnEghxUZqKP(x^@gT}^kFNtYX_6ggiC_MpiKD<-hj33#a%IG7s zaOxE%B5^10&?|0;Cj*IoPYsrcqYp;n(_#UrQ+w|-dhQ2LCy&w||3y0y0#W z*!UmJvb;KL0aU4AOBwvx;tDjP@|#lE-Qj2)^jd=_2}FPb-46>s=ibXRP1F3~nJg)F@ZJ8vW@I63&(Y zRV(KbG@Pd1$&r`0eTMm6LkGt8>{e-?dQbT|^L*yS#c@QkhtqZ1bv6sW%H7rf|}% z@W1NS8vc<_1?VFC&$D@U5cV(NP9mdp)+OzzxBE9eU*Fa!CYw(HJxzTTGn%xbTJ7@I z_UjFU3aAaU{nO9>On;?s0J$vAJ9;(=xz+iEu9c1}dbU)}_RAg2%vUde!PMM&`Q|S= zH|Jwe%a!G zetG@o)k7Bc+*M2R00l(ZLvV^X&1n?%%s+vx>_i~4?h_Y19)Ad?ss2U&3x-iu)al@a zPjPBW?Nw4q^6_ZD3JB472t*hd^-88%du0e;LX|T8_Yt1+$qB0PF`?eRYdJ_`(+fcB zO&MH}yC46vj+{-S7ZUhs>6?ku7G}?O(4&IH5+~)O^<1?Vje+Xwy-;+JAh05!K-%Fb`oARg8%2I{3GSjELh?vV3LF(@SE@c}Q7Vsfn9VkJx)m zem;qFTL8KCzkhh~1~Af8IsDFK1IcU~1;gzd8j0?@?dw;{I>BnH`v}-*&njOifYo+q7 zp$liJc90=KCP+2CeF-#GVcYhxPb3-3m^nknluQvSNfe?C86!i<5ScQZ6Ok$Nu#+id z79pKVs3b*5l$lhLd7g*!Kik%%@BP2^eg9g&wT`o|YhU;MT=)Gvd+&3$Rh!Wzh?oBE z75!M2Ck!=knwS#PCvSEFdE!Tlxc7p$8eIC%iI5AAEI1$f+!`cP#%rM+B5XWLRP^pW zT1f76osU9J-PkSh8ShO-HlygI({A@?)fBCcOju2ekIb6f6}lCwqK>~}EkYXZYZ&H8 zy{-A4sX|qQOt5>4p1l3@4AvFt^kY5^5^f)(zSX=wdtFBAD@nwRZqQLJ z@jJGeCzM+P`~u%_b!bR`z(e+ij2@!QxU+Izx4ZoJRM4w9#RRwA5AOOD$H82Y)+4z% z`mhv}W=|g~x*GM#JjCCGKVJ4sut4pT5fg%^dXD3MzAO`Qsa9ipHpwuxOqQEgxs<7e zl9Y<7^D869mz>Pvgu1fs4p8oNH#g_~y!48KY1hQ6Fs&Tr z#BFA`Z}1Ls2o2})DJcw-u4)#%ydjhow)5cePT0t%mo9$kko^H^uFpbmTEh#X`~6{~A+EU-cn_|JV7GF2=Y0|W2WviP>h?3Uko-odf9;iRzF*6HWcM3*C_ znrlTrcos6M`=P>to04aXIp1rz**vaoJyrIicFfPTgZo)r-M(WIw1?h|Yen%@%93NI z->I|R7TY#=)s8|wOM**g#0@d&>10r#*^aP4qixYQd0y5maKGCQcb{48}ooEwM&Yl?bU$EYGy5{9}qItSX-;V=r z`_r#oM#-S_al zaL(ye?_LS+CJKe<(m=`&g9V)}S!Fb<6kE&&$D~&%EmBO(51(kUcH#Tc6sFG}kj~>Sv)s@bFB-5`??~%{u*876blgGP8 zMX5{s%!%WiC&4T@<+Yy1J zce!nY1D;Lk>Syi3X?W8>!33$;hG_qyxRY;Ac+Z=kTh4>ab47ngmB6&*e{ZG^{myvN$!U?JL7q1q%+; zSQFuE&-v|Zznx5XI$CIwK|jyyg1;+X@LuILZMxCNFU}puEv2cpJFOa8e9Xr8lrsxE z+!}Os>U{cvEYTxLU*?0v7IFcK%Xv3io0-&JVTMIJM{U)gB#pU3UMDN=1YX9x$yC#6 z)`aU)6w{+cp4IJsP0}D->+Cji`HnuWslI>i}q9nU;D-z%sX47lfNk!Q{7{paCpKO+s<56 z?EQJAB5Q|*;8ONY|F@BE};q4|vl zrr%{ft=?+l8=cB+->W`lYZbQiXx-ONW!ts?g8C9uJ*^gLkbf+>@q7(`>rG2HOSfZB z&h(D#eEscfToqJ1mwYBX?ui}GOgioHm+ns|UhIfTb0R9@Gq0Zr%{e2krZm}xXQZVY zcaeHk_tsrdRvvOrT-5NLT$x%taGm!0iMTgU+9f@gRkqfQ8|PJdwA{9M%wpJm;uWtoBNJ8G(rl(ADkHs(`%a?V)6u}3_)Gpcj?V7BZ%AF_gB zEhaCHbK_CLqSMyNjnbp^DRC3*C8zP*zj@cuXuK?ITD(T+u6FDwax_VPZ^Sbl{pr)v za*5~IE~c%=zg|eVWzKJNV1%h=(n^~Ai#pY`Y`Eo4J$sFF+0_;`0>)tl9-4lcz3drt zO2tXI8ZA@im>`QYVY!rV=OUcm@Po(sgeE#Z>UInoIa<;xL5C-&eZMW_5!aP3_bg6T zbR-{muGenbA0G^!hLXDbT}rn^rEkN|1-D!L4E3{fb)zY2hJ12o6F<1>4#=c4IP~~* zdcCM>QuQwh+-7wrkLg={d<>St%*)W-CsM|$P1=v0Uy;c_)d3w9-5>Hr6Y+Hdm;4s7KL@ zBh0w`k~E=p{%bX!rBGqzhF%q4fZ{c_l}@`}_5!iWZrI%u5|lPIv48t<$n{%fpNYr8 z4vV{932_k?({U&qwr zyr8}K$_y*~h4Q&!+)|zW+JYbRD{jXfMboECu0DG=we}P0BhYEjD=zAw=)k0U+Q?wB z73ZXW?Wo8^dR3cIq5MMc+frE`^_*F}JO>4%S~_&LnU>F;jjlF`kmTB<9A!{8^gge( zSc{5B*-4u>r&KxBMqg+>_`HpsR>7{hU<+PEW=Mbk=EvPEZ&f4jeQIcy>{2Ymbrl;^ zeMO_DuP2qnkzT&NFDiPs>is0^k;Kvw{i+DWgSnlYLp#gmtYHzu8Xns+f_KC{i;Q^|RlG5Tz zZCT!)&!*Dj8B z%TBBA(U(%C$uFtyv!|bVEmXDA5R^p|3Q9b>iY*WI1Do@R1Q`p4y&+DHI8h$dAY-X* zU0ftm$&SlzXo#KodTyOE3H! z2eEP#{WO#oH`<2!F}KreDIS!~b4zZAS#gl4z=gUK$2STXUU+tEV`5s0!+zVyM>H@y z$VjbUCbmA5+nyp|9yY>5;;z1>EuIYPUxyCB zBG(}~?N=Qa5Nr7g+iKz_W0183=6Zqd%k041g8bt86d)Fjc3ocl4P7mMJCge~v1xJa zh&%Ynbx2%`_mhUAWBQkbDNQB=yuqD=I|ptyp8VQ1;WHThwq9BFazUGfS(VB&NBcHP zR;iRz_6i4Vt2BA9tsN23v(~l7R;AOTBISI_kp-6slxR?{}9=N z!EkQFV3?!L-ZK$0LLn|lz?j;1AFW^EhY=E6!Sj9(dDZrtr00Y#V3>om2?XV1YhTVt zmzeS&FoZ|LAs&3#+ioS--g;G2v7{|O21&K62jKU|2S1owC~=$B#*Zh-1qeVEOs{M0 zif6rUcKVrpR0<$@Sst~QzUXvuk*{5RDqWJ)QbJ=9+r@pgDprHKv<|`dgvpb3o0G;T zaT{LUR`p__nU08?pu%8?L=5ulUZnBKs(th~iE4qLjS1lq&~s9%x9^^3n_@BGAF(5~ z_}DQKuEs$W5dPDXNX8g;uh1PK>|bQ#WM@a!<$t^g3GgG*yj8({V?H|OJx4v@tXJYs zL9dCk&`SDoTiNzVzs&poh+yn&wp8-d<`SAyW-;v^I;`(GkFVD4vpc8d{57$lW?y3O z=gP;_IfovJo!y=p$+Ml3nyK}nTuX?Oy7rF4OVUl-5v#EFAPK|zW7i1Z;vohyQiVf0 zT~UO!6v!FEciQi?roY)|801AlJ3cDJ6tUWK*EWmP6=qKNc7o~CkTu24Zi{t%8?qo+b&)TCGb zRx8nEh4YyKTX;x9pL8!jh#p+V#|6CC zK`-$N@8h~~N@PkHYh#5$zErd$q2y9^jz65IarN3k#VzXiIqr?&1Rqg`>#!TXt~0_J z|Fj_ZNF+dII&6Q|uu%aw+5=vl1goa0E{8|`2cgVfJ6>)<^8Apep#4>tei6?v&4y%zJSqygKIBS)M0eCj0w)Kv z>nh#J*OvikK_>)S#@TZehJTsqyHH)6`rOS)1oibq8HPq zFVvTIFQ8h+QqULE#X5M3&EHba5HJMYHI`Jcm-aIRlR2AJ`> zu>T10|F_)?39jnwj!zp#lHQK|sx~t-tPL#AKPLVE1>*m=!PS}G=ql1X^0&9Y7i8Oi z1Mz=V!c5#hzhX)~0O48+3B>RyaKhH7%Ub)m&>PH-l{^KZmy{un9{tEi@93WHtR}20} z5Wh*y?C?~Ec$J3tP{#VXI9R=|Gc!WQ^dfGLQ06g5`^QWS4OG(UzEp1DMM#%5d~#n< z;5F;{hDvjPDnk3qCuXd+ZDg#EUfi^^7A6?8FjkF9R`%G;%+=OR4`vj2F(;V})v6Ru zuBG;l=Phw!Fa+ydsD=kWp*gzOmmGuHtAfGMg3mYZwqh5|Y%eHXG`nQK*WJ$6w(CV0 zLo37azH9fMDGfJ#{hoL=)bZHYBlk{SC3}l~c=tlY9kQl3PCW`IBiZwpY<^T1QmvHh zm|xOcoYkzvc|BX~@2i^*(A0E;C%Z%H>Z_VNHOCbWt$MjFwki_WV7wljFi<$JIX=dz zC@#nq~+*6?t`baeu_Yf^%4Q6jOg!!b>%*ld z3mGKq#%4P*wzLM{v4ks{AXe<+yCztv2|5DbZGy;QnkI-8j%pFVX;KwdF{c%3XhKIGaJ8f!*uQsDZP94QKCxv#I#>R=~B0q#X1Z{exH+ z^&e1yZCW69s`Ua=TZ89-A_Ij@|68yoW>iLV2*h zzmBPn-l~o6xmmKjT$|kB+~nNMCEcQ^-1OY+3a$LRLs>&P4m*Xjp61vLF%<{rjML?1 z802UV$-NTF!5`0!SXz4^n;R;WULltsY?Bt8Jx-OEilfT&8@el$?LaAfcPVRWu=8bY z)>w|mQs#p%Ic~X06@2;5$zIDtS*KM#z{|MDcrI_Vv4C-lg@E3-(uFI{Uq?dpaD`tL zvCB}@yU3Xgj(DEI5OHxJ*0cz_C*~Z+Qt2drjb)(?@71fkZ{UQ-ffOK1J_uy$*5Wf> za}*Pk1Gp(@pM1)*wUdo|#E2iJ-v-5aD;$gf8`olzHN(?vGpHt|I*6C|!+~%rgYSK( zY7U8CyuFodb?Wh5V-7|IVfREYEP+T=?0&W=hTM}QtzI~CNS*NI6U0w~H$}cYR`-%t zD!uhga3;3AcfDJ@XR9wmH6fzQ?gc-UsujV(p~JpZiEb*&Qv)~Ob+Wksh)xre{+`Q8 z=@Q%mQ2k}@St*smexVBG$mvttbwBQMa^4aUS3RrqnySCl-`bG%fr)Pjq$*dd9_HG^ z8eH^M?({pp7pXTM=iE0}z#EM+vc6VqXPoehAl3aGe?Ga7kvYL9P~*glt@qkHbFt)M zsSs(0Tq3{V+N8&W+SSFoXO3&|tv30^YdF@}zVLLs!kNf+OTC%5{$U8+RMvv`>dc4G zT_?N8g0Vv4F9ZqCz3f6oz|-BuPd{)Gs>?;62F_E-&wn>qRjGdry3fTd--i9OuZ zv;%{w3~ID62q2p!E82>|9A??9O3_}=^#J5z zWeZt`9)nzMpco+hyrCBi;D`}EV(Gqs3Y^M{Dscvs6!-GNY z{^Kq!5S1AqG8yBn#&bY+AGGanFZ!XVEESQ7C*R=p1hTb%vi*oeWj_#^k$6kS6p-0d zZ_ain4wZ>r1u}Zh);V*~-viv6WmO65vgpH!q_F2zEG=nG-Le=J908&rqjXry1@y2S zNx|Bra2A=!cmMS8ZZ<00;tXUSClcR8f+zVt1|OFGE{~Xx%1$D(_xO`P3W1D_X0xoO z7?njKGNLGZC6W#MPqzDyQCT}8_4xggmbwmLR|5?sK|s=vKG zuSR6TTY~Q&JP%(7HAB_4XkY;nD0lTrP&o*Uq}&|1)QHMvU9e)%SPKdcxq_I_EQWpC zK+Gig@c8#&OYPBS9jtJmD_HpY+Fcw&;Ko?;KPuTCpkjn;kz59toGeRF-!S{;T!vrP zRdjAZwct-Rg1D^sXUWVDuB-GB6{!jz+ZNE$5C1e_cx+vjf~Zt?TNEXMHJ{GEdCl|B ztgF5Q)s}4m2Qe_w4YX^C27Yl3%K(eGV;R|YNvodW-;2R$g>DW`7C>cJ5t+N{VM_yW zL+}pW=Bk!;QQ1>O7TU3w1UX_IaATWGcn*lRykvKSCopJU}FS zx{)0NSclVbn+M>3gUT#{j5O?d6{9SS2b+*nFUse8fHm}W5CzjnuHTQv-kj_B1S*sD z1Tkx~u$dQ@4G!?cNu*t^p{3}NVh+FXCH-3i;_v4M()529V25OA6#C+<3y9d@`5r~+rW&j)0Gfq-Hc6x?!!C}4IU;F92qGL}BrUF_?B z`U59lRgKNpnld*i`o#;pQ(bORZT71rUCJp^?>LdnMn z+5Z>?)PVq8dIl>70!3a0Lh{0?f!KXe$#Yb(02CzBus{%29vZAc1tCE|F!>e*eL+}8 zq0QgNe^=~Y5B>G+94@+orDt9LXi0*>oQE(NaGv?&M*uz@j8%a0+hFj=ghP;PH{1}6 zRfKMRhG{|oX8exYatgtU(cBqCb354CS=u{ag^}|uTpxhl1(^>cva`_lF;s4J3)E>d zg@V)5;42>C7FZ3JXAp)LK0ON<%22>K&7q7@C-pUCc}e6`Ah^T5d61QKWQpBJOT)JGyh^J;a-F(V)=s+iv-M0_CFXr z!d%<)2h)f!^5TCmoKb+$JoE?SfG|zR|6nQ+=AhOe3{5m(UK;*lsNnO_V6kf$BMcvG z8V#EA6w&0HpbTvcI2uPxQ2_Fh!dGIzvfB^ejlmi~SIyBKzziwOAB)6YKp9||6rS}3 z6A>2+n$l;1(x5U@xC;@=S)mN5o)ngj1B|mZ%76}$!loC&ue$4?sabI#zWyS*FDwE} k29F_XAsdvTy^P%sYrHPvtxa^_j}{rH{Sj;=bE+m zs#P^c)gD!~YIYQ|aTKzi1RhS>YkV*q4h)Pog%+L;h^~^H24^DAEjyoByk4ud)JND$ zus-5vpOU}$@yPFHkHNz0on>3J1h*0>z;0#qGjl&BFE603VUNvK(pislo4XQ=n8)-8 zI%fX#eX~5!phkif!EzDLMczs`DYQ!{Gb`$gN6(axHetCg@*mjo7@iB~v!lub?1E>0f4KUDDiKPwaQ%2?Y8dlMg@s z@(X0~T2n)ur=BK%7&hURQ@*w@Zw)qp1Az$*t)Jz&;v} zqZs}eP}!nZ(dw4}V{m5-Riqtpa{{ZQImQrQ&1EFJ!Vq4cG7$>@9iEG4w#xrnhHOQX9IynwxC7O4d#YKgTa?vtm4rERD4TM!s<2Y%; zRptkqx4a;gPF}`;TVCIy|6LzJ{3TN~`_~f=A2o~ggm}j&V0NZ{q_%W82>bw}B5qK- zKQCJt8Lb0B=MPN_ z^LL#{K%oi?shJe=9q9=| zG5bC;La!kn=^!`spnWPd9-zUXSS#2qLdcsKglIpN*?}|Kk_ufHK>}1)&=VY*a1!b? zfHf)x>>0gT-Vln8bmMp3BGkCE=n_1O|Mdoxa|9`KIlEXn8l3I0DOcD(L@Z(q1Hdr^ zcmOE?31HoSz@XbR>cYB-X-+^fnt_Nek1dhd1~k(CM-dWG9Ndn; zZQ1)qj>E~c_CY`%KtV=U6PusWOOEaSiX|FY5=FOnR#U|Auv&AXltY zpugC-Jtgd^Rw!4AJ?K=CZO7922~J(VL;`Z-R-C;za6KB5KbFiLF|F0RlV zqa3%aC^6hYVQor*G2FYrr)n>iO%A&{qdG1(z&}<$5TifRst&VZE!Gsb_BE<2&r=0W zQySL##18xj!S(sc)M`&!_`9nRy%JKd2_M&fb_M(o9=Wp@_sCF)T;^nM$c zMs8e6J_*M4ioXMGH2Cj8N2OXlkQHdY;JT7n_LT%$z>z zLS-5Z<@kv=dEX`BIt9^psSE3eNtsw|#v-2)N(Xk9b)+M7Y(r|L92v*5OwHHGSeF1$ zmx}c-BRhpGns97cTX!!%WDF9fEy0($fT{E3o5V=qYEO2_w3^jaIrLPSiV;ro9W}RI z^>vV%@Pf5Gj1pD<=+C`a`KwBw@nT-PaJV89M|t9C2qq&Vl^z7|VR7YZ^`&YA=EL8; zZjrryu__T&IZOCzEPD~cBx&sg1+QC}vl4L3n9>x@^O@00*(*j4ZjGQeBovs^v^i#g~;PhG(4a)xnUJ6=wQDu{>CVNI_JC&zuhuSOWOGc(+;!l{_ zWalAy>4zQ^shC{pQqGN)t~RjHjAhgI$Ny0AvG+2{#PAu9mrO@CBH_0%hzeoXZAe_t z6XWbz$*cIddNBQ0%VB^L+>3fYBKqC-1v-&?!wdz6CEwvAm;iERr)L1EI6SKb2;$$8 zi2F9jlyXIgYL3xzOXvsc#-<)szv)DS|%`-Ki^V#)hV3LFTRTtv?Z=$_;AJ4}E1e&Lx$TUU* zzNALpfdL*~l3fqCdw)LI)Ck_{Y-83xPL6)-VN(FduFgNfz`#B~A;47RQ?h0e8~{NKgEzZ1qa@$wx9daS55twV6pZc8hbkQE1ky zl#7Znik{vwr{9I&K8(6eQw;AbWi0k48Br-B7B#E)H}AKqw71`v_sJ11QyS!A-WHc) zHvj62CQD1^95rg|FKat_ezaj}cw~&2XdR4I)o7|Yyf2?k3%}L^D^J0;j~1(Hd*yfa^+p?;XuN42cg26L{z($EgB%x{F|vagcTcD%_bj_6_ws)1s0FL>5S z0s*mBOCDjPgRUl|NFc{j*1lHT>pE6QcKnq?PQu=ZT60!DHHnky+p6H%^XeeD!K%)H zLb5lXjiiu&wY|ilpZ+Yj0 zueTS@Pgu+pkpMhkhAy;?mV`-*LNa>c*e{8n0TR+i!85as(E{$G;eCG{ttLCyeO7?OwhGkiHD62#{m__`>u0PX zoZLH`WsWJS;DA<`HZAzyfnUW$Pb%7O#&f_w~dA{fZbvfiSm7Cpf9~RuXO%=A9 zIZCY_Z4iT@O59ZrJao-*bTjnTK&@d83;8(5h(7F>o?9WExj0+Re(40v>M-jHWVDx; zG1a=1=|A(hZWt?S@&-zo=|>qx>E*LTXG}UX{>(PO-Z`hs%n6NW!LxOs_k_X2m6@bj zd;Z#qJffEanyjsoN~s%$`*_48>H23FZcFY#3w zJN3S&V`eC6crRhG0pZ1XTl|p?w)T+2J8H{b3A0Y`4&$W3j!4GnYRJ&Ro?QV$6(_eg z`@9#Q<&UZwi^?rWt@QLtp;dEpJYV}Ue-;!Vg56FMC(J|&dxn2?^~3D12E;7lPd#6C zqBVboiIMJjn?p2ul(JhXqMXWbm@>Y>BHPQS#fTykEzKXz)u&eUr4~Q*b3-X_D&32Z zc@}+kf(Bst{#C?|%jmIJqGVKibqBfA=}Q&Mua1Y_Xdp4LmZ}GNuQsSxcGhTZ=7!G# z4IBSC^c+gl4EVMs?d~5*A^ld$<And~_~)_|?|#qPjsNWORTR?ma7eEU1L}G80Vt zYh^|{7Mq>V3Yy`Cx8-g!b}nmj=SN3I!gI)N7gNko;tNOnTs!Yn${$am(9DIxY2yMm zoxJgYeghT?Y`QL%G2HI*=`*PFkHS$xVEV{fbu*7j#!s2$0fSg$Za15h{wag5Ju0PY z#~k&gCJu^Ev9@(k63B0;I)Uhm&2{gpWB-Bx`cy<6==LWud56fH`0B;xTTK3Y!_ zpL!myf~9BjME;+_Uv<^eBpmCsK)D=&@#2C=rip$=2;a*ch55@Pa*~-;Y#jd9gQe69 zx*r>9Y~z0640#_+4OqI`bK`uyjh@7DuDmv0|6uOw>q#2`l*pd&*IKiDx;pHsKf;&9kPi-nS^AuN%WNAy|Oj zaVpvWE}G*mN+qChO61jn>ov|EXw?$i@qPgySUkRqnF(^g@^eZ*MD(G#DCj321*Lr7U4cjN>dTa6P1#KS;34XjcsvkA9uh$>?Y zJs?o07sC#FGQg`Jxy#pg@J0!3pU>0DZfweMZ1nLOiI z|0;FGE+(kDv5YpNG5v#cDRn+P??ozZS0H$;-!s#MFj?x#-Nm6vm1ATOg5lzAqy9cm zC~0vXzZ^r19Tj~TeVFm>VfgHRlyz92VTATz2kZ1ez0uWH;%GiT1*(fpt7X14jA9_$ zCUn_&^(T#EJWwjgAOe9tVm)nnugn2s0bKF{aDlDKM>0sXsyf__^qqH8UNskXXKMd} zMHB(dvP}S~S4sA=$gDZWMDFOvkj#3|eR%_kYOsDPIge~y;n5#zjJ{1@J02X@ix+j> z>dcJ9v6+iQdALw}Do9(DjF@B}EP_OLatRK5UTXeo7GQHbPqM;#%6L8@E(CWC_b$>t z|2H9z)!>P-#DMR=&a&pXtlCq>C$iv7a@O)rL`7T4-Va0bF-(X%ewfUQiEHVF#h7~I z4Rl#K80t_<#-iRHyX5?J=GXGrmzh%yV{^?d*i=<TSKX%ljgR=vpYGOk;n%B;vI^IDAU0cypUG6_0tO|OG`b}M$&CWG3}p( zz+(MN=yhMz1R8BcaHRlG`up1UimD^u=f0r-`{tiNP^>S?UJYUU~Se&|` z$eyxZ&!^Cu$ua`9N5Qtvujq`X(9Q4TaRJk=@<|rZP1p>UHu<87WQptnUbwgI@E1d{ z^?1#xXz+U924yvv#`LItK+lYcqk8PDyrVM;=Hzv%I8VIRFk^W;h z2uY+9+;Gdzvc%$SP4jOphztf7u{<`Oy_FV0V|J`QF~NI%u}1xuNBGw?1e%?(03eL# zf~SskmHsL5M0rGTk~-h+a<+4#T|^mC6WvQK-wpG}{E>45+A1M+VRbu9*e{5-cf%L; z!ArD20;6za%mkgmpe*9%XjSxvf%s7eBk2iTm9~;1Qs5yK&!J+%Tmbe^guSW{DyFV{ z64}M-Edt}oKu@b$+~ok)*`BvvCXoAAMECdiU%BAo_^VUlL=p;I-`$Fd99Dwo^*4G| zgf1@foD|K^932H~E-lq9z_#b+Ye5nq^^U+@_W1oklrj%A<-bGyE|F#hWqv$91Ki;1 zd47=8cH6K7f`t9?jslVj%bS~W6-y8|Wed8vUX#vJBs8JnS3VsUpq8BXS0EcdFWt0o zY>(`gX_q*v@MC?-VW3%IGxCrHb&nMiM^#B&S;d_#v zw>eNAlUdwjo2pqJ*>js=K$S~>&by+wM`SNpCA2;)xK$ki{8L6lm!->s9eWl{gUKz0 z4BTAchGr(1v??WE^|BZ;Yt>N}GH# zXw)@6Ac^mDTK3|5tX^Ri+uY``Ix|#kK-Qe5K`a^-yrDLns`fL0cX&1RuvXJ8UZYEb zN_B;&oZ41f%l>Z2X`rJViC#>3 zmJ?F1zod4E#rg#Cv4|kw^V>*;_4UuNGKfsKA2><^M91MR(z`4@Je~dMDWx%dfQFRa z7%X_~Le-}p!8XY8)8tq_t7+*7%Y9`(kkyElQwds8wRP{AM&`7APn$qT$IJW_O3EF3 zPWV)qd7V@?uov%@LyMCmM^qGRE|*y z7NJ_!2D%1QBVBkBar9_rR&0AW%G@(4k=Xa83^jn$42~&A$+@!~w9Pk(0-+4h>^HVF z>#_NfQYW*NocG!5(6bHt}`4%&97aChsCCaqFW5LjvMS(t_C-MLel zU)yiE`Y6NCo23dDC2qh_tM@q{b=?%McW8l5_1#oHa;8)GaV)gzNE1gE?sZh}S}+u> zQ-Bfgnrp2yOhItk6xSi9NveMG%|J4FNj;IwWA~CS+y`oUD!SWYLmUKO9ti-UFvmQ8HzA7BrF0k(c?=9#1#Q* zL@CrEk0bc$5B@n<1r8NU43TCc6;j_6D_d6mxm3AYWd@{+1%Q>F-fp{2s7u-93uwY9 zzh@82;)!=tsVa`xDz*&`4bQ=|VI9#_DE*tAymcL-5s;UZX;)xXh`{6KL<%)aIB})B zU=h?~O{N(QG2*^o>{Rw)ph(ntVgz5~f5Ta!4rBn_&z2;w9HWLW6X0r}hPvncW*~YM z)~w45BH)>rIR!Q!fw-Odlm~J8n6o+z$KcW~VzoNa{}LUlw(Bi{cChLpe)C)P-#Ms> zpZB4)Z6Ew1B6pPBdxf43PD8#~9EZgTXiR>F`@1|?V}U$>>e%h!mL?~_?=GQ?;r&pd z85~lfk4N}dc?Q~BWojssJczVPaMTOL?Rt|IAGrY!&DW z?O5}t$O7V}E-UQp{r77seP{oM^PI6CstawX7g-at5mMA9z6q0g&S{V}z@5P+G{Cq1 zD9Cu2?a>>p-;POcZ2qC1MXAS_qu$E?4+Y&P^d9!19}~O*j>5l7CHa@42F4(>QfYm& z)LkYcF>|1(h;|!Hv9OOTTgQi4oV(nv4#;HbBpk40mp0%Ms4R!`kF4K2vTcWNRgpm| z$YSr@!=t^^#vU=TFMY&*byYy45E*|Cz6+l+oUonxGkH)H#~!ugoCm7R1z#j|#^sOY zT8hM*rjG7Ckso+ZN=B!g_ev-)|}|y~bzlNY~*< z4D?3=QnmaBgA9GLF{+^peY;+%ztnZc4dsdliyq`WzkvL~oHAt-ibs4LWy6DxXCCR1 z*wl}`SLJd9J~zEvApFEzgem+Tyn!N$Wfp3qqERDEajbTz9bTMn@kJ9?=YrH=q$k2e zt}3tu33-BRN~L<7V{jq`(^OIf+4 zZmmFsy~PsAPemn_&2F>=n;&d3lI#Gq1U%pxwX5#TE^N4DKB={b&V+F}l#*GjBU4{(G=t{+a74!I>Jw?L%3DsS1A*dkA(FPi|t zlSb1{B;@h&s_lsxp6M&R+C;|r>+CHm3`F-(o2hR;PP-(a<8n7$7kk3?gvveCv@RqJ zSRqr=AzRAZWI(9cJ|RLEHiRQmgirP-o%RwYiV1qR0gx`Y11Cw9lI(Il(f!h6igo6K z2J1t}1FNWYAh>Sr43T4A+8Bh1!!6CfJP`_^ zZ{H-95#HJ^%u0}tzN5LxW+DQ)nCyKu^yl-s?Hj_D#uE1Z;j37%-&W!prMgICq>QeX_gx{3!0TI&;con8!L2F~jUBn##QP!X5z_LF6>1AlsKG z+H!Kdexbh7Euk>=d*E#^lXWW)>LihIYpbrwf>JRsD)q6Zp=#c zc3ji%K41M^amAc-KD!-L$mZl4a|JV6hbL9-`>!i`M{P%jpB_RH5r6db$3*SsrkyA( zC_9I|jRy$z`{Z1QQ*udxemM^TLTdv7HiF@no5j*+2O_Mr&Fg?b_rbRBAc&?kX4VUAGgnLjqlEDUY9L+ z-z>ky$$<{e3(QCLyMwWV#gKY@!Sw`AutIa{!jmX`Ft?;W4zRes3!Yv+ZPXO&hhw;M zDUE@~$;U}nwt1j|UH<;=WIFtj(5#Fxl6V8;nHbQ^))c1UodW3OB?JnG$ykz?fAJ5& z6B`Au8PKuVN-8BDwNYMrQj>|Pq5G`~%Aaxxu#|>6EZONO&GYkt)Lbq-!6Ex{=r+EU z;sRu()E2p{2Scp42Aw776Bv^d+NWC%vRw3z#U;B<3EwI+0li9bi zGx@4)^Mq&Ibi9QKNWPW1D!H@bB-|1?F0oH_R;>Hh=w{e|tz`u(+=eP*l%tzG@n&PBP$HGaos4NBN~w zf-8)n%~gVJX6*e!$4n9kXgZn8c!%=42TTT&+E}t~LIJX9luVaV*%vFAC2_szU3yGR z5O8C#8jE1rlDNGmsg5S1wfcqJAn9D9_@SCyRWe3fV0e@0YA{P?jts{{eTG1&JRJC6 z7@TFt=Lbxt;ODvBjU zi7KlG7JAP{>RJ&gD{Ya97)*)3LN7r=8+l~=GGZ9bWh~MntQ@tJD}Zu%Oq%Jqk!iV- z%@mo6SDPNr)u~pLl>~qye+AqHc<+@#=wAFD8(U#u zKyt^{+nJDw_l!z_OWuLE*KjDX5-MPM(>v<}oZ}HBvQD;*SUgj0IryaGLgg}M( zm2!`3lGXL&4z%oZ4dXT!7wBfBI>}uZ)C+#n|xo(1LqJPHp8rGwH|R;V^Aq8(!`m1XSz; z^Vg!+5ivmi^~bPvjNv=ckEUPjC&3nSzJpM%zeF&IJdTrVSK3@G6p{iYJTV*pAYiBt z$A$ELWHSSog|y#at3SA&iiWbaUiKrM&h27;oHamDQXGly@psu%%jg|v{Z{USg@@j9f0qTou>r58g*%jM$b%v@lWVuLZ@ z#gg3lplOxF;fFP*Un@%Hg}dfVk}+enjO6KY9hm_vFSl;4xvtEzCJxo?T@PZJ*x$jH zd~?OLn*ztuBe#KJ{WEm=S+G}&#ad(iqG@i+fB;PETLyRhcPyF(Lwk-|{rfx(_^a5Z ztPNL~qB$r0Y;=nWCw4ynqNDpq<7rVe;45Z{Z2e(ds{%3bE<+abWk-Wrx(pEj z_POho{ySr`Win^@c&2(6q05d5{mPgOFDxd>tH876TKYey_I;nwFv}@b zck=|%Ys%Muhql&>CI-%`gm<@TX#8M+!gHUk66-|~K=gm+Sx;|`HQ3Yo9UG&^i>UF1Qe3t z6zA6PPT#c6+9|J>n&)K-FXz6kAl5$4lH2=6;aq#rKE+z@AwggpIMrT>6Lp-8Yc8K28-1H|hC)l@z~P0bcp!U}8S(GNwqCnVB9Q0K)>?ZT<& z43_pLG9i^(Yg)Occ0vmT7VDsmX0=TvrK5i8V*UB2h4Ze4C2@(-r#$4F9C>~qQUv_z zK=q($r~fk56YCU{FihD?wBic`r6!cq$t>g%!h}cuIhux90etx0xi37vG>T8P?GOb~ zUkCEa+4_`?QUyPfa(elvv$Fk;N{nwPQ zHJ~ISV@BRhotTGg^S^CgEh+hF!F$$M2hWvUE!!|JA2JS>rE^BI%E!hC26l!D^Q*1b z0q#EHIW}9q^xP`?-={*&8nx+*DeHNJdgACK1)6cY5s*>6WH~>Nc!V+Omn-`hw0;d> zq;~(J;X&G;V`dAKYmaqq)YS;cGH+{&(BnIrETiSOxp+w3su!V?XuR{m+6p^LD278z zrf1qw=zqh}na8e4QO&0UI;uczip^BFZNpi>=Tl>5B$o$erQeZ{Igp7e^0*_wYV7yn z*-9lVBX3xnD2DFNCk%x4oQwO;L z(^qA9Y|iZ))E6L{%OvECZ4pB1b@s?h6gjWswx(hx*A6~)LI>f2(1VqyuHN&80*5sVHO!$ z*a7}GL-&;4`Wx#&1WhKML$x*$`*+okc(d#6E6#Fe%UUIxL+AY|mq2!#(r%T)FvR!r z#mDnl(PMqJ&Wn81ELdA{Asx2gOx4eVYo04PE=rPyu4%>ldT$rvEkDp-_%$|iE!S0b zg}3LY@0{POZkqia?Lo-fG74suAvc>DT1*!$z-%;$iC%c%xj;2zPQWxZaFhDmbw0|f)4`9SH*kxC)9hj<7eDop0@0#_oHvhzi63N467c?7H(J+I(!3HA zDg_*V=4>N`>lVpns9PYr&Rcm8bW1*Mrc$^^i|gzn>9$mqcnAlV)_WkGPkSXeA#&w* z;KwQ&T-pOLRb&+dUk>&zd60YK+T>m_U*JYiYv>LO;n3~#r@(b3Pba-z_eTJCTM!BH zmT*@ohQ|2vl<1fZcn{iMCM;~?cFx$jIvl5iAr{~_QA@ZM7VT`QNc+9)EK2W-p9BMJ z7d=lb7!X zU0Xj-BZ$EHbAWn7wwOU9AQPv34hd!KpFH0rRJk|AA44Z9YrhQMXpq7K>j2Izd~4JCXv?`U zljIoCNjC}H-L520R+#Q@!<-Co6-kDbnD8Th&iVJJt{{zscCtJ1D%X3x$)&$Hd&guJ{uW?hq2Mf;m0?#hceY&zTCr=G%!_Q9%f+5g!XQM)>azdr3INo8* z*Op&c70vuJOcxh#b@~X;K09L~^5Bk7#sCfnV*GK+`_q0QO4dDqH={OW>}IxNDv888 zZqM&Y?=Ssg9gVYisIwjw|58m_?HFul6I}UcwY#DYEYG*aAu&x`QJ%`tOFiKwnk1B0 z8@%oEvkK&A{=WB#zu$hZ1+>2!>?|foMU+8-gQvE5Eg{tJZoz7MKzR*E$yQERRtCNU zQ<7$}8sSTzz~MvY>&ni+!N8iKQiS>OfUL~k4)!@IhED6GnBiA67s8~MX0a)j6BA-2~xg^$7MnBm5 z9a=Ue^ybM5HT1&FP)Y_z-z+xuXyoF2NS+jAT%EnGo)lm*g#ruAQ{9)ohO&$$%{1s_ zyFs7&K&E5zlO8dT6^0*+`#N?UC}b729b0{lm>r1DMPhQ})$U(a8Shj<>O>IWne8(6fnoM}M%lH=YW4q{2< zzxU8cOtx|&fuJQBDX)(UO13y~dyS_Rl7*iy(I1yGbOHi8@6wtDqOtt^y;QgtXEb&32|HBS94`tD$D(?1AuH%bdwqkxm=WrxSH5>n zaCy^nKIRiOC`*V+FN7(N8*`qi0YFu|eiqEIZJ1XSsw)RQ$=MmLm2hPYXixidCQ5B2 zySc={#gEq#)z0x@(r@j54?6!ECD$o6#P{^-%$9>&$VQW^RPTyiApFy-*@ud*E{dM- zP*urCX4Ff2^x~Zl<%Bj;DC*+@aNSZ`z|BMP@sz<0rxS^&WqU{5?$xp;^8taJe${lZ z#eTgh9Jyw2@vf(|m%+b?BacH4>_twCDjWwj9geW~OTFFh0( z%-QU?@70abOVZ)$$06;B$}91~ov_%C0_0$>sTCq26y8VpQ=91INiD}DQa4+H;y-y*{Xd;`FNRIve) z;FRkBm1@2ua6Fq7RvRkNGX($@gn= z<|QyN%>PyJ#iadGjQy}dX*dAX6!;QU#Qzm;7ys9rE-rure6Qrcyb>3HPx!wH>i-|_ zLFs>kyT|gdkTl_!gu9xevWf!=$NOp?!}|Z%0{}GjpBHX7Kxjl?E_OlcL;x|s94P$@z}xpy zZuW5g+bbXdF#sP>3?d}{Dvkvi{|6jFh5rE)(BXeT2t-Tr1wpzeL>L3Ns68v|}0l>h%e@*mg|7+D3a{#@Q0))V?UO|Fn00Ho7 z0BD8`Kncnt`|7(!&@>r91H1$3|7x=2UwzvF^M8$>Uk0EL^oJav45$GSQ+&ZP$dLk| m2Tp6hDv)Bd+we}gIscEsWdOn_)bwYSFG(`(NMzaP$x4aI;u3`EdzWqZVatrcEE!;VPw zR`f4eXP_lb;q>=Mx+5tpxvApWpxc#)7|ViLZr{T%i&%NI^myNS+=xZcl=g1Pl*FkX zbddI>5qV==xwi9qpAO*hf~;m|Ob-S(3qtF(Mec++9O) zEP4F#CZU(ry62$wyU?o|QmS-?MYGySfC`2!eSKG9PpxW3O?!28-I?v|IoX==I|bf{ zHO2v29PlrZXTNnDW*vFTho085oGdKHteCF%emWlzk+9e|XH2pf!N-~YUQQ0+!vn=W_4u4o|Y@ne1A~I{RjN1 zMcdsv@9m=Hz@2`6=SA8oXdKXZsQQ9eAjP9v-f)`26|9j?{aj$uoLJr@dx8OOb{DHIIipM5Ga;V@P*VZzRd3%hcj}i zJ3HTYUzQSo;oMz;=8n@E1-5&PXGO3f8Ab`AjLqamw7W)D9L z?2pD_G10CHUG4_$vj@AwvN}L5YAnoz{$Mqf4k3<@_KTX`{f>#Jz#p_c!SFx6mKBg; zp?G8nFi;ql2W+Su_5kw$GAN9Z0n8~-gIIM#)r3>TH6gJXz0i)ZB_&mr{%*AynXuj5Xq7cn9S?HUvQ8WIiE z3ipduwPQi^7ewD%hn`_R64<;7q91lT3(5^{FG%292ti_QF_R^x%(Tij`)}+35waOr zj2Vc4A^Ra|fUCC*3hcxiwrNk|pJ*c7c}4MN^q`m#vO05d=t#Ssd{Q9#UrOYOtPXal zE!?(Jo7wwqv=c&jcv%bRL1>)1-1Qo`8%AU*c%sEbEV62}y(s8}5;c>WUqB7NUWCoh zx;ehrC1Yr+HIeztZyE%zzTvV3HoUiHuG>Ua9|du;8i~=K3Sql#a##0q+rUUIHPNW@ z$TOcq0weO$gwULL>2ybt6%(0!AHcZ!m!^6={v59NdSLHQft6BT643l4=EPh`)(1?o?FyHR;tN} zDw8ySEfLhk-z+WA8?!e1H!T5=Sx4$NPIk@Gq?vGnim6>8lP_UIiL>G!9e@9sE@dR<#D(LFd!$2Qy-wJFMd9hI)cfSfaS4rX7Iz^SbxCUduz$3Ik zFT6YyZT>3m+`TWb?%G?nhD&1^>Jtz%jJ+5x)1gm-|4Id(H1(g> z04Lw9(4Le83}>TD5=-yeq;4OXeX8blJos=L`MB7RAS>}qkQe34eBjS0RmU74%P`e7 zEf57D^-Ntkad7(%G|7FmM*5^E)LS);bRn)6 zt6n>wwJ)()`QkBTr%s!GF>{Iub+5?x1~z$oGdNlHd~+tQ$7%{JkTsKgN3gc#f2+r8 z`Au2X3xH}FANkH>oja%`RpK$E5wk*o8QZ2<<&hdiqW>T<0Xe%AU^!1qaE+$?ERle$ zZJmt6!#`il0GW-oJMk{|NOx!|yb!@575-KK8gQ17N=`BdjvyxS`DHE^rhV$o>K^js;!b3CGi z7tL^^(s_MT4Kjrw#Rdygr9@uU5MtQ8o0a=c4%(X};%Fw~zodc|29ZIWMzz1zbG~wS zuVj_IUtYLAR&yDk2KJ)e4U3!DK7aYeyJ3d<%$Do$9!LniveVsBO?m zF@r9N(9AKLZ-{>8ba4OW?XQroeJO??v|rKM!eTMRr=38&pCY|QS1&QBAGXtf0{rE< zj5)N4E|DaA`GphsSF8q3;!+jHlrgR$Z@}@N!^L@@7Q4MM-<2NnyV@mQW@@ZuH>w}@ zpsgsumbJ_7TbTb*>$Y_k7x3&nkH4~I5+v2Nec61L^}BYFp92;boJHQf5m=LXXN2Z* zKg1guhwQ;?#kUkx{v$pA?rPoi{``4d_gS)ew(E{X;nFcc@NjiAoP}s#Um(-_`YOSD zcX0CVjr)47V*KaJxQfHo#_qanrY4qh^ybx zG(3XsY0|gQ#2YXD3UP=|e zN52j~`}{kTE2NC{mS!mMGRreV>JuO%mK{K*%bL+S#{0}`EuZM9U}J zr9ePKrFa=Xe3&@TN;o|P#16>lClS!k#_eDz;r>W7>ZtahDJ~7WCM|Ek zZuNl9J~TM`ORr;ubuKRKsAs3>yI+0%jF`3swpje1wAk9d@D;^+O%)2*n8euzys zwuB^T`7=)U>laMkAJ09CuDzmN-cKb*`ZYZ@bIaSyHLM`~rH8kM=evjLW8C+3MK+BX_dS>E-5O0z-}R*|#xrxCheY_udyn-vlLx}9GI3o&hJ1-NW8zvnv9g$D zvJhC@7+qK2-;7}Yu{@WWy;;JJhZ8aQ=pzCf^o`SL{IFktZCGF3TogDJdfN|GL?iCFR>9O`b>VC4;){-TXJDJe1Y zFRCV4uB;-UM{1}hj1tCLA}?$CM-$gzzMhUc8^X{i2cwpIsW8??*4LUQ%R^MW?Jz+` z4@zj2)B3uT@ZnQaGmV3mlS=yJZ2pnc?^hj^`eta449W7T4IKbbX|$yp9*C z!n>oveCu+YN$EZdU7Qd_9DxCs=<6OF^=PEz4OKp14`ds&ub_%y{~wO|^p_pSQ7t{J z9|*RIN3ln<^(u$5+)RJd%jQ!}rvx1GI|kN(5?1N_E$?Vyi}k%JTEUDE72o@8*(J9Y zFnCZ_gM)LK_M8u96QB9axEzmCRN?I52E_XYXRDLWtg|g$G&hz|O~;K+gYc2;O^YFi z10$1w%+?Al?KtiAI&SLRn0~ZoJf&-T#i!>q7B*$4AjPjKdBf=wu=BOGUr2P-YlZlO zN2SMXNr~ylb5CY#sCkoT4=MF{9t84}rAvj9#t1!B$_Yr4PEF#=+X}R|@sUC01eMg9 zqN?mHgbSwYN&Uthf~NRE#n|XQk?UEC zX*P*yrO%Bqefm(d5@QYDI29 zw{)7UbNi6AmHhJ>75Yl$A`w%TQuJsnqg3-4gN1t^KvxePNBCi#mK`$!Rx$0u9U5*< zO-5^@+%64^(KQB6#W&H#I0;@CahJaKmxH2z7zj{sTb|kRlfr2;FfhsRzA`)faFbQ$ z)_3k=hxESZnCYPFI4p0Tgh+WR<#a0GgVao_Wdu~Baz{Z@cz=n_sCzNHT_q0z%UQ8K z^B8~3S-!z2s2y(VN8A%=)WL5rCKg2i2DS}$^GGsFA$kwR2nPYoFW}W&G{-o)khnO- zfC^shtgYhI(rYr4v@~$!D9YVvS>%X8tNgYQDwU4KFn@7K zLHa8R2V1b^ASJ0PS^ProY2;@Vqy7iZT2vvUtOfCou3)@WTV|u+bFht$4%!I>28Ps>ov~kZ_x_c^?vo&bGnlQ3MOEbpni;mK1DAr-3Ygsrs=`>@f^=^3d%fwm^4=u{%q~b>75T??u$Pe(4zD0@ zMweZe&g3B?J0H4ytCm(E8@)Hogd%bWdvj;vqkz9a=_5PJvyg)+Q3;~8%%YG%pO#p* zc9zmS(yaMyW<6S^8OvUJW#}kUeG_-?a>t{2X6phRd(3c#{f{CjWc)NC>r!c#3P`kM z9w_s#05p9GcWd8ovxL;)!+d#qQKa~wNcpcCCHWKXR3`HfHHim6(cQYQMI~f$Z1JQH z_C|k(a7u1O0vKZuNDOwrU1hc(Dj$}iI+v9kdr-D1d%Y`#D&=%f6aPjs*ZEKzz9h6x zDolL+L&n<5N)#w55~u2eJ#Tl@%4Gkh(xJW4s9*q0D)7$oED`SQ{~|E5fXV+yvjvu0 zEaN$K13{?nr&qo%P%Gpb>jdwrIBCDD?EHyOc1noYO8UvZ5eik8A5C?H>bWzN*QPa578=!TVCCuqdtBSXcI!gy%by+T;C+&}yX+|Uz|B8O#Fr_D)ER;R?s z@yuk}Nv^BU;^8L3--@B^d>^|Pa&hB=JPQH6 zaDW&;F+w<#fN)A*?}uZCNZq~Rf)M0yLycc#31d$~j!tOzJ5#j~&4+9mku;Hw?K@PW z#r(bLW5Cp|Z%!E_BgKQ_W#-*Q z-WOyQaaj!jLacCG*BLeQw z6-SuO^jdqZLKGhP!E6Cvyo;cgdq34l?N|D?shJBpIzEpKAbGhd+{Td&)fwLXMHVf8 z+`jdnto)0@_Ihu0o|@H0LKt^$7!!;=c3HI zQ*~Z6UJtsQSARAI0~dd=w|5CH6z%SlHhIwUvyAV?3Kl)_tqLtf`|Xmtb{DvQdn`Vh>VslDgC0*o_NPBq9h=LYm}>j#RJTVLpV2APF>obe7WHk{8_8Uz!{ zGuFd-fElyR;?k95++8egw`3biW@hBdLkjU$D_GsZ{wmR-qt3csXKbESp0!^#vVKi# zTC++8OqLeKpw0M@D;3(RE~$-nOjrRVml7jq#lwn~KCFvdt@sAu{H|^qP~GVBb#j@c z4&>vEBcOG=Wn07KZ}1ZHvkqGL9jgJrdbOr; z+8sXPCSuFA)0B2;&eN>k5&EpFGetg`rv7=9Q!GF2EN|Qo8#lhu2zQj*+{!lCv^uEP zH^XQ3feUnhLZh%8?0B7lfK-yEC{?0*LE?n9&bSozTxU1wz>hI`=bH?Y;uo$c)YbeO zAQ@d_3dOgzhCfz1bK!nYMFg8(T1?UVHWph0B=NN+-{u%KULJ!kKH5LRq+o;poE($`8(S zVNTFPA`fseOWo)^K76Ufo8D1)H60zvK(#8^eC4tRwu{u=7!f5nI)9y57heF+|_dWurey-qKttX-3*vq%Csd*B_ zOvmbUNIX7>@5&+k<>8HShsx{2y}TG(XBvUDBXc}Cu8n`qT-XW;^$*3af2q?=1Fwne zgxh)PD|nPwlrjdXtuGwKAI%rdxN1|qv)Q^Yp>}%>cM37sL*`-)5yC;xIQy(KTN!@T zDaG;2f5#=+3qgwvBc&dE&j@F&(rvWm2Ub>{D|*|vTx7x;0M3yCAKe#hPHmny%n?b&?o+hxEzEsj0PbCgjJuc#NM#ebF} z1w59AE5n?4p>>yd7Z_JN{&S`Z5FL~NAx3cmrp-q_d6uhx$BOO3?lvFwlljL_SE_}Af;?i2rr?Cv~*+BNH=tNxf^F=h|RQ7jry*ON6|lgoR$Z$5CL?KdKAHj4YVbxP;QPQH%5@1Wvn z0YD;XHyRsZNxb07&#o0(?kq7zz=~Bm+;V^VC)jG(%Bcvwpwe3GOe1aDzPnYZz5V%i zG9Glx*>G}vbMvZ36emxm|8x6g_4Q=u=JE8=WZH)yuvr!^-mG;s#(2xw^!s!pMEB&1 zwb)7~Zyd(#!rvML1>y@PQcS;+MNnQ0F>p|pA$EiCD=swVKbcS^I2FXZE)8{o4swT@ z%>qn9)9sQUKl9{H7nLjPonwmkte>9W>$tvn1o}sS6)N*L&f$1lbg#+$*71F9X&9Q$ z18i?(rs+b`Dsl{RWxsV8!p1sjTAuQ5F{$}Q&%^4^nAcT`!MnJs=VN3c@n3K`r~m=l z(1a~s*p-7yP=D$d*W6tEg$RPvKuj>GEqIK6NA#lA>8jN_dUKV%rTplX3#S#zN(Jw> z+Bd~H4P|CLWZ1SprX82Ki3?>r<}Q?I8g%liTM38Zh;n%iBlXkw{cZGkP+}yz zC}LwFzvk_M;upDB-BQ92BS~M@YtPw5qOF8gBFMpzCm0K}J(~g@VF|O?4f&eZgswf< z@xyj0hv=S23ycTt8LH~2hOUaV!PI|(f=9F^hxzv`akLswRhyVuiK$p;^_;&)4``y~yLzAv13eWo$58{;E_;(n4l}?bJ#u33`(ANSD;aLa%O^7O;l9t21!^2SqoW=j_6{oKmU1RpVMR-6dW8*kXM*bX5S+<0e05 zwiAfJ9yPA_jVAsa&1D>8o7Wqq(!I7OMY{DWBXnZA))=!TiC>|j<8EnEli~jFFLYtq zoz)T?7=&U+Q|C-kae^IjZh5VXHv$oo-1j2Cdo)ck$EI&^a6n{+Gp?l|F^V{DFfbUy z`>@0+cj;6}kEi#eT(@=WqeHo@o^b)0_Pr@A;u~2fBDu%4t<2vPI6InsEZ7jlUVT}L zzw^P|u&*2`ZNt%MMs^AE+08?JeDD6VVmWp6@vX0fwfaeyO>EAFY_lDLlPB?G^}YC< zB5N20NKV%n6hKbM_CDd>w^0yi_Kwu9P#s~o9jif!2kDm)BT?M#PmK0nRP>>5BQVRO zj(XPs9fm0*ZE#1%kO)9+o^IlyloZAr|xfl`JuY3iU4H=RRK9Q9J|Tw5Qu`Hi zctzQ!{24PdXKZ@EvUd$Sy@<6gM!sRPoP?GTvIJUJj97>dp<_jhiO-zY9*!s8W;@PC!K4}9-q*aWr6h)39}2nQkcV&6qIpU2Pn1;J2k0rhg-#+ zsQ?2b{)~C&^T#4-X~km$lLrJ1$o^!3TR60Qu?>TxGl1e*2K$R&LuClpJ@R!_RAFF(5!j=TDx6{Z96CroMSbbuVarZ(LPTFi>t_Zx(#tXc?d^%c&q+X|(|6>6az^IXK3;VLa~PrwOw zJ$<|cx8$`8_XY7~YR6L*4|0b`NRhz9{0L@&YD?5H5PPrw?(t5eoGNJ3N?d5fXuHrt za~=-k?0B~xKBfizb!M!LkrTVVW@GD>GW4-L#UN+gDEBlzcaWnz4OtZTPnPQ?gW%L} z%-)iiF+fCb46T>Q5nwFVz%>8o0 za!L8&C^!SF8*twtc$`zo;U{;vrT3`^04@z2s+bY+NgzzH`wq^TR^Qp5Apr%~5+f6X zM1#%ecU#soY#;rz!-m)rzg(qSw6um-LiGLExJ7=lL_=?EwDX*#%j8*aL>F5prf)LW zPwI4CG!j160Alj!PCi<)gfcS|XG5laMMIRLhrxO2KJfh0yrX;M=6zMUm`v14^Y+T4 zCRd*k`#?QWhh0f!C3FH`KMb_lJ}MC2056%zEGhanGQmcPmlbv7Yam3joaqoy4#&U~mvGqQn;a$I+8+{>?18cSBV3_oDc4xlTJ= zT1lwhI;OBlPpVF%Lbb_o_BtV@c}KuHa%RFgfn=|(!e4o1^|EURXkH+E5+07LS%IKz zoiX7#-F%WtWlt?!*ujf-eEjo@#0Av;_Y-#n&(}4|SZb9A5vrk6?mlA?pkp(s(#zB) z&;H=wqWHN%{-4qu2US~qIDl`+?LK{V-gAt{&fO#;M56^)JU6s8wUB4%Uc*O@AI-&^h`IN#GOakn>%yqbMHK zV_g9wt0a%ukqBuRn)xpkuztpJvX@j}`m711uVEil`C!h{CklW4a)I{CSP{C7rR1xo zN+~W87{G-5uC|2#%_!z;|I<1AKv=w?Pu#)gjEOPrqYi>r_!9}Rel36-uLk#A5`P{6 zT>#muSQ7P=&@zI5I|D-%y1f!GGm-dUb7L}Wi|#4ynXsHu{Fb=GZ@x6rUcwPYOmIU` zPRYKud!<&#ah~(?{3MU-ESx_UaseUr6U#B^2!Qk~h%2^Un^_c68;@Iyg{>xn{Fr8w_0a`>F8kj!vcPg7dHus(k5{96$-Jc`M)wlVmX(TzxAZh)2&%{6M zEuIu!p$ciL5N=QX=mN+A;<*4Bt1NV*Ux2D!G>>b+s$)ZzDUPPv!uV59$ieYx@ zF*C!!kHTpzLS#td^`0a-nu=HJ_wjibnqN|B(ZJZm#KN ze>*8`MWwRzOZSr07^Q^iwlxZ3mRinB^W-9Zb5cC!DPq;{-uaVI^PD_tW|s#Xw(1)d z)<&uOAY{o;HU(x;>15g3x$u>0Ntrol#yf*4C!XXgf<*y+-kBJUW;Ay}23Bi%! z%cSqqpXaa{X?$PO9R`8C;Lx;hXSxHq1B0|Ti%BL!z+9Hxa!}1>%nb9?v`RV-W3f;% zu?ITph&EbP!Y>-|_aIDE;0!-1v2tA0l?J_M^+s~EU7FN&I(qQL7^(Bx#Zo zlj+cr4n%yKm%3kT)aHcteaAsBun4~%AE6GQ2w&a{D8=MAI;lzy^NQ_M5tIa8`rqI0 z?5MF5p9_K@>azzU?L=u?ec(In)Ocr!3z8X`l;9N{e^r8^<`uhvZsK+-5U{Z7Eck@X zcYa8qGx{eCmvn)tI5l==kLMocoiY_F>1M#U#W}mgtEsdU_En-?=MSpMDy|-6Y$mh~ z&Mwtzgdf;Lc+Dg&>_e#@aK&ebR6$)$tKzlz6DZAN8@vLLt#%5|jCIl{--BA!ev5f{ z4D~_Uwli@U*kLLFBepC8jE$Jy+dE|XUcGuyjk*w+lvf8AmzSsu;|S>$NC>_P_Dsa? zimantK$5Ao1V50;{EJ6SGKYo~vlP6&WfEN4D@9gHfz=b6Fs<4q)@Xpq73IVjNG?>m#X(dkp6x^l`vH zqWE4aE<6Zn^^$Nx};#%(b)j-_u`L z#&O@PbaTJT51jW7wXM8~CT%t`6&6fFE{-Ds@ zcI-^>)=SOf8Q5fb)?;<&C2bW>B{Eq&T87;X{D^ll^1Yp02Kv13@xQPBHST`z_J5Of z))m^(IGOU9Ar$bIX^8okZ-S6qrdWsKKWtf*zd%-18ajqEBre9Fl}4tFtgVCjvvV7W z>-)Y6(4-rwaQZ=-8W&29#IPl}nP)T!+xu+#y+fEb6eZcY2(2?Ui=? zL*xlQ6aII^_Yd35JnZ6Sfrvpp^a)_bo5 zN)lnPQVc!-Po>dY_OQ?G6&H%>YQZv2O~hAZhT5TZm758ef9BCR&V5=wpTh=Bq6tJQ zI>t4zT@#HrdRbT`1Wi`*T!Co?Uh7B~YHvXuobfPXkptwwsWHo8@LT^AN9j&Meg-wE zW~CF`k}|^S$6hnfRKpp)HIeW^T{(8VJM@`=NsSY434amo1((nt5y%;5 zT2T2ZUho-i8A)xj3FHd8wC0yy^-*uvE60+>K>at6cMh3kj5?d>zH#VjqU{OLxiTgt z`{$|I{rcZp!Kwv>%bTy(CY7tYUo|eRP_-?!)JC_u9>Sf1gbOVe%u})|7Oim!+DyqyTj0tz2uqMhkT+qAjDh(fDVWzmjsmx9zBtPc}Jn|Roi+Vry8W5 zOAWM9f!P$u)phB?9K#b+q+_Et1#mMTNhYo<1f`p}Bf^#r1+$8Db#aq7hO-S2E&i+A z#x1Q38-8T^$Ny`X-@Z7HdxY=+c59QTC^_QAG1OiH+JjjZ;^>{J0d=>qu3=P36?GvS zgWj)f60YxiWONeGQZKI$FDr)~=);U00}+TvR#844c?FdZr-3s6w{)=YIL^Vp+D^zz z*m;n*=l*IkQ2B$-&H8&xOS@DF49xe^51aQ>6l8ei5#MW=q8QCCOJs%EDW-b5kJp2^%b*!uz<{Ma6&nu&3C*Da{4D00V_DlT5>4$>BHuVSLp{dYA(%k`Tp zEX3UjsY4nt`yK36dTS0JJd_bBf!M&6A3C~xFM*mwwk2wNLpg_s)hE%$JRtFA4;ih+ z$hV3on6Z&XURnLU`{KB7P|~CPPwVO9!Q{*m2)=sPT36@N?D-a@D(S);X=ZWf9AoNm zm*Y)FPet`1_|uxvWqp45uNTMYEPsOc#q2g5-i+mps>>mU#P43FMFlB}=kz{58ie!m zLfBYceEX3}wYI;EVQy1u3K`d_h&+&vK-EMwROBz7ZF>bHKJM}20%Pb;!lbstIRKHqJJv%?5s5dzdIl#>E~d*LsS}*>xu7Z{x*fC8&O@;uR(x( zP+~W+teQbEJ={5)CAC#*MA-(4fycjxNZ|b9Y?AAIFWu5TSy}qx*>ooh(+YSHb?nR1 zX%{GGy`|8u-z87;mmM+)h~mxNxYG)19!8e<4VL&6_$`Jv%F{#t20Bg!$`NpxSj5X< z`h>qU$~5j@H-mQfL&7cYQIw_vQ433dQ-k~_u0lKen9q6YxnGp!Rc?U#T2v65YA3jf z%42PnRCC5&P#7_=;lNz34N`yAY53V>sx0YdMN#`w!JKTW@35;MS^eaLVhecw;#15U zFsCNXP-nT$od6@K5=N2F-9mgeYtMMw*C4QOhSyN_!SUy44y;Hkcs~8+I2ACDvC=xlb6kjCOBgL*{k#-6Fz?#$ZYWq-ONSyJE)f+U?HV^6O zE7#ml$#~k#i4ic`_;liqu|uCwD5WI6EP1p+UlKZn*{3PK(nTjavbh{!wEz9h2NJ9U z2WwkzwwZgH?gLBSYo)2#^A19{!D%=zgn>i|?JqPrg@k};f&r0##Rsypcstl3I*)?@EoF5uB5I_fs5ZBh`*61yJBJovJcd#O`(Fba!$~9*Mz5Dp3Gt;|dw_s}*hX!T$&UV}_vsMJx=`TZg2ZbzQ zH(qy-55m{kN zsAz~$KPR@i>)j|7qwSp2*UzgnK4oAMNoumd)4U|>gdTf6vma$M5A3?m;&C{aSUFF0 z^TVu3jaW;3>MwAk_9IVo@5~(*1`37pAKIpgFb%a}Q>f|Ee?T{SYFlf~RFO2lZjTp0!V;@b~joqCnol-=foP!5hg;k$L+!-f$*oQo2Ay!}z zwGacYcq)nky`- z)LTNblM05ik_-&@Ha!r9rQnZH?2)VwC-OU6xYe(Wp?!>)`#X?!iL^5$BEfCUGf{{t zT?F$i2a!Uhv_DZy*O|q3K9&A}u1R#(tyFy4KN8S-DKStEL*;pg`zum$L@Za`>G>v| z&PTSd4xS}AK24L}JLhLcm8!ZBNEQkzG0sz=RA7O;z&fy1eeAmSy8q$=V${_6#e>O? z440@B53Dx3N_Xm9J2zM1 zKYhi>L4iVI9yZLXFzd^9a??Tx(GXg8uMC5=(o(G05b#6;02<5pvtbQx!}NR`{h8tZ z;hc9aW}%D{qKLKq)wKmCgNrK7u&2wWV=;>2fchcx^`Z@IUeUl%pj@k@B_M6{RRua- z`|IhqI3v%qM-<5^PG%iln-Ntgl&Yxpj2OZ(M#Sl64wEiuT$n`9qzoeBE?z9N;rQHC z`JivGF2=fpzQEQsD4rN#Ez}M?Ibvlm=Wn5YW;Pxubi-dks4{N#7O-eU-{27%z4#Q> zUeE7Ll3#AcOJXwRo`*uxSX_qffB$rG&dDN*@i3&lYm7#}DS33bZ9JEXEpqf41YoD_ zB1Q$=_y7V(x!V7nAmdsXur)q_ z0l)(W;eSRT9RiUK;eh{sHbFv-fbj?bVt_NSE&)IsumH~Z5BkBI|3L+ql<*T$!KVL# zC%AwR@D*SVKKukoIQQz=-S`kjLO zPI1B8|9SMl2&A7Lez4*vKoVYo6G%U&1A7Br_z%x-LFc!)U>35^5Yu;{={sC758-Di z0?9t_OBFbi3_wTtzZdRPi*NF|$fN&%svim7CIg5-BEN!3$pJ!8V*mhn1`0q44kQP# z0%pN= apaT%V>y)1}a0h>(0?>ZZ#QMwu;{O6aN6YU3 diff --git a/cd3_automation_toolkit/example/CD3-CIS-template.xlsx b/cd3_automation_toolkit/example/CD3-CIS-template.xlsx index 478d13cc1122ce19a1311e269e3d8e5ef6431753..ec2334140a34ac84cea8d45c01ed818601422fbd 100644 GIT binary patch delta 141139 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

c8Vw>4sO6rkjS*Mt`}yqX6D*4@I^tX=&Y3->cz z9{Y}Yet98qs)2f{z<|=%FQIV14SU!w99Q;BHRy&hG`Hw9Nwh5eL-^`yH}armH&zIG zkJ(ucD3TSGof2kC;QYk)TgJPva^A{^|DZNmC3%O{U2;`N@Xc4jA9u+<{@ii#^!gCm z$g#~k^gxBnWiw3mxZ)ST8!gAcRNis81$=i>yWe|##*tT zSAJhVN2^W3agBIw#+8mF3(>}kU2uKvzv+I#sxP1^I!mQ*wjTLFM53@Y^FSUcB zr@TT-C$2ipY6|;T-nE;5RKL^x1ku>}?ZROFaF^57?A;)H+S5DCHs5Hg{A`lcONhn0 zOxdc?P9>j&+Y;&rl8t`)Ux7B6?P5*^`r99H*1r}bWtU#g{l)q2In!Ss4Og*pV)~73 zvGMb+A39@p#W%_Ld%j9Xr7aZGK571>_9hIi8FFwii+V+8I;wpK?u@INsDP%ZW2i1^jiu^Zn#LbMb(o zF#E!CnA}i9y_-0}o4&3makbM*Zk%(aVS8t~s=5TlNR1jOu14p#nHJBJp6ccycTAMT zTK|lqsJCrB3^cv@_TCzcCred^YCla>uQahgMRoX>cB&U6mK9-GT9a`GYUhq(xVn=MBV-%3w!RrEj?qAN?>)2(y)-kz`Xn;&&EjZT7vZi*oz6I3_noAU}C zi~|n7f1dxc5pLXixcfVqm4F(pw6p*P*4@31;=scuY254(B=4TSaX_jvttdu-qNR&u z$Ub|4B7eQ2_M}#AtqoasYm4E@5PGxf@Trf#1Df{hp1rI(pXc;c%~pi#%NbS*?#fWD z35k1#0`uo0F+v=7a;e`alf<3>F_A$pMn6iET_I|s5gaY0+z^u?@qslxMzh;XT}bRZ z(dTGJ2dqk%%yWHPy6I5@*k59kU`2mRSTKo3kY`@SD^>@iBy(Eo zS|s|Du#d!EvZP-CUbpB+bn9Pyf%ZP#Uy^5zS(^O^LvrGf;pzN)11m1_90bp=hB6a}+h&YC)9g zXNm=i8mUa5TvbgCod@R_liA@}Qf>sonGz2{2mUnp&&!+nh;oG~SF6=DD{!l)=NZH? zs#)QPs)wm&9)oobGy-8oe4Ns~c|;w;6dG^XNsSPJc*As@daiXu$yoxbNXb}x091L2 z0fC_Zr&Hie+z3!KP&7>W*?LO~0IHn!ICa_bhU=7fI2z z9>cL?*VT_47N;wY7TD69RExqH^Ya5z)FPVy-@r}UVEHVf)|J&=ztS*u(;@m6X&f#HW_b_ z&EE-U3H1h@33A4X5m?-J!3jS*z#fh6ZTN#&$_G>&?uu)}+Jm+x4=@_K4*35b`6xF? z!w*FVVIA<%(Cd335u+#0h0+JaX7+*w1~T_S2_sp(acq?jSU{V;IP4dUZTsO`RD4m? zjQ`v(e!O}%sNEMV_e4N3!FT)`;Uf@{V8j2c*7$2IZpJ!;zT|48w-3Nw&0AW zfhYko`gVMH37a`NI9NEkyB!S!6pKYMAm=(@Obcn*g~L^YKn%wooXCTPQ!h^J!ouqf zEI=W_K>_Mc<=F{+1L2|xMe^R3}TB9;@UMsPy%>OP|$r)bTK$bc8uW~4q)+W z949pH1MzMWCyHP(I)xMau+W=>1qY-N3RdskPf$=ON)rF#0)EOoJ~Q+&6!hTC7g(_4 zt~{FseDZ%?#;Gef&_4`-XV-AzEi9sTae^rvBvHeM)?-koq07JUDR6Ou!$Bb?B>!tZ z1>KBBp>b{R;kG&2f3?j}fVLE0u+|wdsDH2Z>ump`3?o3Q!ShgD1WF1&LJ$Q#9Rc0` z9)S|XC%gDZDMX@Z{@japHxlfiw4#uAB#I69LkE-tn+nyT+DMc%(%=@f6$xfM@eU*$ zg_1=UgWV+tj8s|_xI7lY76Xe-An?vZ-(ygma0M5Uj>fnKeO=U_%kxDvD5n_gH878k t0n8-WW?*3g3sEziXoAH9b6Dsizgs}6u^{(XD<~=!#dc!H1_idm{{e!eTJ-<` delta 139665 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 z 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%0A98@hIfiblDg`ts(2wcV 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


{rX`n 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%0DFns|nJ1G@$#CW#$o@yUIq$ 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

P)c?kfZk64O1{*kV^Ob!f(hXdLqncC#q*4v2WJe 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 WBLPedx&}=pppH>wT?e1M5&s8!jy6UB diff --git a/cd3_automation_toolkit/example/CD3-Firewall-template.xlsx b/cd3_automation_toolkit/example/CD3-Firewall-template.xlsx index af7a8c15d0e81fd0a052cfe7e32b9f50f8d9e498..9b04a1f56b303ea15773043895220e788f9c2538 100644 GIT binary patch literal 194533 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%0A0hl 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 literal 116032 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

  • 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 diff --git a/cd3_automation_toolkit/example/CD3-HubSpoke-template.xlsx b/cd3_automation_toolkit/example/CD3-HubSpoke-template.xlsx index 7a1471de23f4af6983dfcbdecf343d92b5a949e3..f7bee0e618915491aadd661957e3ea284559aee2 100644 GIT binary patch delta 119843 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

    ASjmG%kQu+jKTkVherl{Zx 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 z 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%0A-r+}xw(1s!qV^PY8fPxy+Qipq)EO)XD|fT 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 LyLby)r?CG5bpwuk diff --git a/cd3_automation_toolkit/example/OCI_Regions b/cd3_automation_toolkit/example/OCI_Regions deleted file mode 100644 index 69c334048..000000000 --- a/cd3_automation_toolkit/example/OCI_Regions +++ /dev/null @@ -1,42 +0,0 @@ -#Region:Region_Key -zurich:eu-zurich-1 -toronto:ca-toronto-1 -montreal:ca-montreal-1 -chuncheon:ap-chuncheon-1 -vinhedo:sa-vinhedo-1 -sydney:ap-sydney-1 -sanjose:us-sanjose-1 -singapore:ap-singapore-1 -santiago:sa-santiago-1 -queretaro:mx-queretaro-1 -phoenix:us-phoenix-1 -chicago:us-chicago-1 -tokyo:ap-tokyo-1 -jerusalem:il-jerusalem-1 -marseille:eu-marseille-1 -melbourne:ap-melbourne-1 -madrid:eu-madrid-1 -milan:eu-milan-1 -london:uk-london-1 -osaka:ap-osaka-1 -johannesburg:af-johannesburg-1 -jeddah:me-jeddah-1 -seoul:ap-seoul-1 -ashburn:us-ashburn-1 -hyderabad:ap-hyderabad-1 -saopaulo:sa-saopaulo-1 -frankfurt:eu-frankfurt-1 -dubai:me-dubai-1 -cardiff:uk-cardiff-1 -paris:eu-paris-1 -mumbai:ap-mumbai-1 -abudhabi:me-abudhabi-1 -stockholm:eu-stockholm-1 -amsterdam:eu-amsterdam-1 -langley:us-langley-1 -luke:us-luke-1 -gov-ashburn:us-gov-ashburn-1 -gov-chicago:us-gov-chicago-1 -gov-phoenix:us-gov-phoenix-1 -gov-london:uk-gov-london-1 -gov-cardiff:uk-gov-cardiff-1 \ No newline at end of file diff --git a/cd3_automation_toolkit/example/config b/cd3_automation_toolkit/example/config deleted file mode 100644 index 504536b7c..000000000 --- a/cd3_automation_toolkit/example/config +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -tenancy = -fingerprint = -user = -key_file = -region = - diff --git a/cd3_automation_toolkit/ocicloud/__init__.py b/cd3_automation_toolkit/ocicloud/__init__.py new file mode 100644 index 000000000..066c83efc --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + + diff --git a/cd3_automation_toolkit/Excel_Columns b/cd3_automation_toolkit/ocicloud/python/Excel_Columns similarity index 98% rename from cd3_automation_toolkit/Excel_Columns rename to cd3_automation_toolkit/ocicloud/python/Excel_Columns index cc0d110d8..1fa76eb0a 100644 --- a/cd3_automation_toolkit/Excel_Columns +++ b/cd3_automation_toolkit/ocicloud/python/Excel_Columns @@ -34,7 +34,9 @@ "VCNs" : { "VCN Name" : "display_name", - "CIDR Blocks" : "cidr_blocks" + "CIDR Blocks" : "cidr_blocks", + "ULA IPv6 CIDR" : "ipv6private_cidr_blocks" + }, "DRGs" : { @@ -53,7 +55,8 @@ { "CIDR Block" : "cidr_block", "Availability Domain(AD1|AD2|AD3|Regional)" : "availability_domain", - "Type(private|public)" : "prohibit_public_ip_on_vnic" + "Type(private|public)" : "prohibit_public_ip_on_vnic", + "IPv6CIDR Block" : "ipv6_cidr_blocks" }, "NSGs" : { diff --git a/cd3_automation_toolkit/OCI_Protocols b/cd3_automation_toolkit/ocicloud/python/OCI_Protocols similarity index 100% rename from cd3_automation_toolkit/OCI_Protocols rename to cd3_automation_toolkit/ocicloud/python/OCI_Protocols diff --git a/cd3_automation_toolkit/OCI_Regions b/cd3_automation_toolkit/ocicloud/python/OCI_Regions similarity index 70% rename from cd3_automation_toolkit/OCI_Regions rename to cd3_automation_toolkit/ocicloud/python/OCI_Regions index 824428a7a..04908193c 100644 --- a/cd3_automation_toolkit/OCI_Regions +++ b/cd3_automation_toolkit/ocicloud/python/OCI_Regions @@ -1,18 +1,22 @@ #Region:Region_Key abilene:us-abilene-1 -saltlake:us-saltlake-2 amsterdam:eu-amsterdam-1 stockholm:eu-stockholm-1 abudhabi:me-abudhabi-1 -saltlake:us-saltlake-1 +saltlake-1:us-saltlake-1 +saltlake-2:us-saltlake-2 bogota:sa-bogota-1 mumbai:ap-mumbai-1 paris:eu-paris-1 cardiff:uk-cardiff-1 +chennai:ap-chennai-1 dallas:us-dallas-1 +shawnee:us-shawnee-1 dubai:me-dubai-1 +quincy:us-quincy-1 tukwila:us-tukwila-4 frankfurt:eu-frankfurt-1 +kulai:ap-kulai-1 saopaulo:sa-saopaulo-1 batam:ap-batam-1 hyderabad:ap-hyderabad-1 @@ -21,28 +25,36 @@ seoul:ap-seoul-1 jeddah:me-jeddah-1 johannesburg:af-johannesburg-1 osaka:ap-osaka-1 +desmoines:us-desmoines-1 kragujevac:eu-kragujevac-1 london:uk-london-1 milan:eu-milan-1 -madrid:eu-madrid-1 melbourne:ap-melbourne-1 marseille:eu-marseille-1 monterrey:mx-monterrey-1 jerusalem:il-jerusalem-1 +boardman:us-boardman-1 +turin:eu-turin-1 tokyo:ap-tokyo-1 neom:me-neom-1 +delhi:ap-delhi-1 chicago:us-chicago-1 +madrid-3:eu-madrid-3 +madrid-1:eu-madrid-1 phoenix:us-phoenix-1 queretaro:mx-queretaro-1 riyadh:me-riyadh-1 santiago:sa-santiago-1 -singapore:ap-singapore-1 sanjose:us-sanjose-1 +riodejaneiro:sa-riodejaneiro-2 sydney:ap-sydney-1 valparaiso:sa-valparaiso-1 vinhedo:sa-vinhedo-1 -singapore:ap-singapore-2 +columbus:us-columbus-1 +singapore-2:ap-singapore-2 +singapore-1:ap-singapore-1 chuncheon:ap-chuncheon-1 montreal:ca-montreal-1 toronto:ca-toronto-1 +dublin:eu-dublin-3 zurich:eu-zurich-1 diff --git a/cd3_automation_toolkit/ocicloud/python/__init__.py b/cd3_automation_toolkit/ocicloud/python/__init__.py new file mode 100644 index 000000000..c7e18e857 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/__init__.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +from .cd3Validator import * +from .cd3FirewallValidator import * +from .cd3Services import * +from .ociCommonTools import * +from .compute import * +from .costmanagement import * +from .database import * +from .developerservices import * +from .governance import * +from .identity import * +from .managementservices import * +from .network import * +from .sddc import * +from .security import * +from .storage import * + + diff --git a/cd3_automation_toolkit/cd3FirewallValidator.py b/cd3_automation_toolkit/ocicloud/python/cd3FirewallValidator.py similarity index 87% rename from cd3_automation_toolkit/cd3FirewallValidator.py rename to cd3_automation_toolkit/ocicloud/python/cd3FirewallValidator.py index c98100a6c..0f6177441 100644 --- a/cd3_automation_toolkit/cd3FirewallValidator.py +++ b/cd3_automation_toolkit/ocicloud/python/cd3FirewallValidator.py @@ -15,7 +15,11 @@ from oci.core.virtual_network_client import VirtualNetworkClient from oci.vault import VaultsClient from oci.key_management import KmsVaultClient -from commonTools import * +import os +import sys +sys.path.append(os.getcwd()+"/..") +from ocicloud.python.ociCommonTools import * +#from ocicloud.python.commonTools import * import re """def get_vcn_ids(compartment_ids, config): @@ -148,6 +152,9 @@ def compare_values(list_to_check, value_to_check, index): elif index[1].lower() == 'nsg': value1 = index[3].split("_") log(f'ROW {index[0] + 3} : Invalid value for column "NSGs". NSG "{value1[1]}" for "{value1[0]}" does not exist in "{index[2]}".') + elif index[1].lower() == 'service': + value_to_check = value_to_check.split("&") + log(f'ROW {index[0] + 3} : Invalid value for column "{index[1]}". {index[3]} "{value_to_check[1]}" for policy "{value_to_check[0]}" does not exist in "{index[2]}" tab.') else: value_to_check = value_to_check.split("::") log(f'ROW {index[0] + 3} : Invalid value for column "{index[1]}". {index[3]} "{value_to_check[1]}" for policy "{value_to_check[0]}" does not exist in "{index[2]}" tab.') @@ -174,7 +181,7 @@ def validate_Firewall(filename,comp_ids,fwpolicy,config,signer, ct): fw_nsg_check = [] fw_policycheck = False - dffirewall = data_frame(filename, 'Firewall') + dffirewall = commonTools.data_frame(filename, 'Firewall') dfcolumns = dffirewall.columns.values.tolist() for i in dffirewall.index: @@ -264,7 +271,7 @@ def validate_FirewallPolicy(filename, ct): fwpolicy_comp_check = False fwpolicy_invalid_check = False - dffwpolicy = data_frame(filename, 'Firewall-Policy') + dffwpolicy = commonTools.data_frame(filename, 'Firewall-Policy') dfcolumns = dffwpolicy.columns.values.tolist() for i in dffwpolicy.index: @@ -323,7 +330,7 @@ def validate_FirewallPolicyApplist(filename, fwpolicy_list,ct): fwpolicyapp_check = [] fwpolicyapp_appg_length = False fwpolicyapp_appg_mistake = False - dffwpolicyapplist = data_frame(filename, 'Firewall-Policy-ApplicationList') + dffwpolicyapplist = commonTools.data_frame(filename, 'Firewall-Policy-ApplicationList') dfcolumns = dffwpolicyapplist.columns.values.tolist() for i in dffwpolicyapplist.index: @@ -403,7 +410,7 @@ def validate_FirewallPolicyServicelist(filename, fwpolicy_list,ct): fwpolicyservice_check = [] fwpolicyservice_serviceg_length = False fwpolicyservice_serviceg_mistake = False - dffwpolicyservicelist = data_frame(filename, 'Firewall-Policy-ServiceList') + dffwpolicyservicelist = commonTools.data_frame(filename, 'Firewall-Policy-ServiceList') dfcolumns = dffwpolicyservicelist.columns.values.tolist() for i in dffwpolicyservicelist.index: @@ -481,7 +488,7 @@ def validate_FirewallPolicyUrllist(filename, fwpolicy_list,ct): fwpolicyurl_check = [] fwpolicyurl_urlg_length = False fwpolicyurl_urlg_mistake = False - dffwpolicyUrllist = data_frame(filename, 'Firewall-Policy-UrlList') + dffwpolicyUrllist = commonTools.data_frame(filename, 'Firewall-Policy-UrlList') dfcolumns = dffwpolicyUrllist.columns.values.tolist() for i in dffwpolicyUrllist.index: @@ -540,7 +547,7 @@ def validate_FirewallPolicyAddress(filename, fwpolicy_list,ct): fwpolicyaddress_check = [] fwpolicyaddress_addressg_length = False fwpolicyaddress_addressg_mistake = False - dffwpolicyAddress = data_frame(filename, 'Firewall-Policy-AddressList') + dffwpolicyAddress = commonTools.data_frame(filename, 'Firewall-Policy-AddressList') dfcolumns = dffwpolicyAddress.columns.values.tolist() for i in dffwpolicyAddress.index: @@ -611,7 +618,7 @@ def validate_FirewallPolicySecrets(filename, fwpolicy_list, config,signer, ct): fwpolicysecret_secret_length = False fwpolicysecret_comp_check = False fwpolicysecret_vault_check = [] - dffwpolicysecret = data_frame(filename, 'Firewall-Policy-Secret') + dffwpolicysecret = commonTools.data_frame(filename, 'Firewall-Policy-Secret') dfcolumns = dffwpolicysecret.columns.values.tolist() for i in dffwpolicysecret.index: @@ -708,7 +715,7 @@ def validate_FirewallPolicyDecryption(filename, fwpolicy_list,ct): fwpolicydecrypt_invalid_check = False fwpolicydecrypt_check = [] fwpolicydecrypt_nameg_length = False - dffwpolicydecrypt = data_frame(filename, 'Firewall-Policy-DecryptProfile') + dffwpolicydecrypt = commonTools.data_frame(filename, 'Firewall-Policy-DecryptProfile') dfcolumns = dffwpolicydecrypt.columns.values.tolist() for i in dffwpolicydecrypt.index: @@ -779,10 +786,10 @@ def validate_FirewallPolicyDecryptionRule(filename, fwpolicy_list, fulladdreslis fwpolicydecryptruledp_check = [] fwpolicydecryptrulepost_check = [] - dffwpolicydecryptrule = data_frame(filename, 'Firewall-Policy-DecryptRule') + dffwpolicydecryptrule = commonTools.data_frame(filename, 'Firewall-Policy-DecryptRule') dfcolumns = dffwpolicydecryptrule.columns.values.tolist() - dffwdecryptrule = data_frame(filename, 'Firewall-Policy-DecryptRule') + dffwdecryptrule = commonTools.data_frame(filename, 'Firewall-Policy-DecryptRule') dffwdecryptrule_list = dffwdecryptrule['Rule Name'].astype(str) dffwdecryptrulepolicy_list = dffwdecryptrule['Firewall Policy'].astype(str) fulldecryptrulelist = dffwdecryptrulepolicy_list + '::' + dffwdecryptrule_list @@ -878,10 +885,10 @@ def validate_FirewallPolicyTunnelInspectRule(filename, fwpolicy_list, fulladdres fwpolicytunnelinspectruleda_check = [] fwpolicytunnelinspectrulepost_check = [] - dffwpolicytunnelinspectrule = data_frame(filename, 'Firewall-Policy-TunnelInspect') + dffwpolicytunnelinspectrule = commonTools.data_frame(filename, 'Firewall-Policy-TunnelInspect') dfcolumns = dffwpolicytunnelinspectrule.columns.values.tolist() - dffwtunnleinspectrule = data_frame(filename, 'Firewall-Policy-TunnelInspect') + dffwtunnleinspectrule = commonTools.data_frame(filename, 'Firewall-Policy-TunnelInspect') dffwtunnleinspectrule_list = dffwtunnleinspectrule['Rule Name'].astype(str) dffwtunnleinspectrulepolicy_list = dffwtunnleinspectrule['Firewall Policy'].astype(str) fulltunnelinspectrulelist = dffwtunnleinspectrulepolicy_list + '::' + dffwtunnleinspectrule_list @@ -961,6 +968,119 @@ def validate_FirewallPolicyTunnelInspectRule(filename, fwpolicy_list, fulladdres return True else: return False +def validate_FirewallPolicyNatRule(filename, fwpolicy_list, fulladdreslist, fullnatservicelist,ct): + fwpolicynatrule_empty_check = False + fwpolicynatrule_invalid_check = False + fwpolicynatrule_check = [] + fwpolicynatrule_nameg_length = False + fwpolicynatrulesa_check = [] + fwpolicynatruleda_check = [] + fwpolicynatrulepost_check = [] + + dffwpolicynatrule = commonTools.data_frame(filename, 'Firewall-Policy-NatRules') + dfcolumns = dffwpolicynatrule.columns.values.tolist() + + dffwnatrule = commonTools.data_frame(filename, 'Firewall-Policy-NatRules') + dffwnatrule_list = dffwnatrule['Rule Name'].astype(str) + dffwnatrulepolicy_list = dffwnatrule['Firewall Policy'].astype(str) + fullnatrulelist = dffwnatrulepolicy_list + '::' + dffwnatrule_list + + for i in dffwpolicynatrule.index: + region = str(dffwpolicynatrule.loc[i, 'Region']).strip().lower() + # Encountered + if (region in commonTools.endNames): + break + if region == 'nan': + log(f'ROW {i + 3} : Empty value at column "Region".') + fwpolicynatrule_empty_check = True + elif region not in ct.all_regions: + log(f'ROW {i + 3} : "Region" {region} is not subscribed for tenancy.') + fwpolicynatrule_invalid_check = True + for columnname in dfcolumns: + # Column value + columnvalue = str(dffwpolicynatrule.loc[i, columnname]).strip() + if (columnname == 'Firewall Policy'): + if columnvalue.lower() == 'nan': + log(f'ROW {i + 3} : Empty value at column Policy Name.') + fwpolicynatrule_empty_check = True + else: + # Cross check the Policy names in Firewall Policy sheet with OCI. + fwpolicynatrule_check.append( + compare_values(fwpolicy_list.tolist(), columnvalue, [i, 'Policy Name', 'Firewall-Policy'])) + if (columnname == 'Rule Name'): + if columnvalue.lower() == 'nan': + log(f'ROW {i + 3} : Empty value at column Rule Name.') + fwpolicynatrule_empty_check = True + if columnvalue.lower() != 'nan': + if (len(columnvalue) > 63) or (len(columnvalue) < 2): + log(f'ROW {i + 3} : Nat rule Name "{columnvalue}" has more alphanumeric characters than the allowed maximum limit of 63.') + fwpolicynatrule_nameg_length = True + if (validate_names(columnvalue) == True): + log(f'ROW {i + 3} : Only alphabets, digits, - and _ are allowed in the Tunnel inspection Rule Name') + fwpolicynatrule_invalid_check == True + if (columnname == 'Source Address'): + if columnvalue.lower() != 'nan': + sa_list = columnvalue.split(",") + for eachsa in sa_list: + fwpolicyname = str(dffwpolicynatrule.loc[i, 'Firewall Policy']).strip() + finalsalist = fwpolicyname + '::' + eachsa + fwpolicynatrulesa_check.append(compare_values(fulladdreslist.tolist(), finalsalist,[i, 'Source Address','Firewall-Policy-Address','Address list'])) + if (columnname == 'Destination Address'): + if columnvalue.lower() != 'nan': + da_list = columnvalue.split(",") + for eachda in da_list: + fwpolicyname = str(dffwpolicynatrule.loc[i, 'Firewall Policy']).strip() + finaldalist = fwpolicyname + '::' + eachda + fwpolicynatruleda_check.append(compare_values(fulladdreslist.tolist(), finaldalist,[i, 'Destination Address','Firewall-Policy-Address','Address list'])) + if (columnname == 'Service'): + if columnvalue.lower() != 'nan': + finalservice = [] + fwpolicyname = str(dffwpolicynatrule.loc[i, 'Firewall Policy']).strip() + finalservicelist = fwpolicyname + '&' + columnvalue + natserv = fullnatservicelist.tolist() + for service1 in natserv: + spolicy,snst = service1.split("&") + if snst is not "nan" and "\n" in snst: + tempservices = snst.split("\n") + for intservice in tempservices: + finalservice_value = spolicy + "&" + intservice.split("::")[0] + finalservice.append(finalservice_value) + else: + finalservice_value = spolicy + "&" + snst.split("::")[0] + finalservice.append(finalservice_value) + fwpolicynatruleda_check.append(compare_values(finalservice, finalservicelist, [i, 'Service', 'Firewall-Policy-ServiceList', 'Services'])) + if (columnname == 'Action'): + if (columnvalue not in ['DIPP_SRC_NAT', 'Dipp_Src_Nat', 'Dipp_src_nat', 'dipp_src_nat']): + log(f'ROW {i + 3} : Action "{columnvalue}" is not a valid option, it should be either DIPP_SRC_NAT/Dipp_Src_Nat/Dipp_src_nat/dipp_src_nat.') + fwpolicynatrule_invalid_check = True + if (columnname == 'Type'): + if (columnvalue not in ['NATV4', 'Natv4', 'natv4', 'NatV4']): + log(f'ROW {i + 3} : Action "{columnvalue}" is not a valid option, it should be either NATV4/Natv4/NatV4/natv4.') + fwpolicynatrule_invalid_check = True + + if (columnname == 'Position'): + if columnvalue.lower() != 'nan': + post = columnvalue.split('::') + if len(post) != 2: + log(f'ROW {i + 3} : Position value in "{post}" does not have all/correct required details') + fwpolicynatrule_invalid_check = True + else: + if (post[0] not in ['before_rule', 'after_rule']): + log(f'ROW {i + 3} : Position condition in "{post[0]}" is not a valid option, it should be either before_rule/after_rule') + if post[1].lower() != 'nan': + fwpolicyname = str(dffwpolicynatrule.loc[i, 'Firewall Policy']).strip() + finalrulepost = fwpolicyname + '::' + post[1] + fwpolicynatrulepost_check.append( + compare_values(fullnatrulelist.tolist(), finalrulepost,[i, 'Position', 'Firewall-Policy-TunnelInspect', 'Rule name'])) + + if any([fwpolicynatrule_empty_check, fwpolicynatrule_invalid_check, + fwpolicynatrule_nameg_length]) or any(fwpolicynatrule_check) or any( + fwpolicynatrulesa_check) or any(fwpolicynatruleda_check) or any( + fwpolicynatrulepost_check): + print("Null or Wrong value Check failed!!") + return True + else: + return False def validate_FirewallPolicySecurityRule(filename, fwpolicy_list, fulladdreslist, fullservicelist, fullappslist, fullurlslist,ct): fwpolicysecurityrule_empty_check = False @@ -974,10 +1094,10 @@ def validate_FirewallPolicySecurityRule(filename, fwpolicy_list, fulladdreslist, fwpolicysecurityruleul_check = [] fwpolicysecurityrule_action_mistake = False fwpolicysecurityrulepost_check = [] - dffwpolicysecurityrule = data_frame(filename, 'Firewall-Policy-SecRule') + dffwpolicysecurityrule = commonTools.data_frame(filename, 'Firewall-Policy-SecRule') dfcolumns = dffwpolicysecurityrule.columns.values.tolist() - dffwsecurityrule = data_frame(filename, 'Firewall-Policy-SecRule') + dffwsecurityrule = commonTools.data_frame(filename, 'Firewall-Policy-SecRule') dffwsecurityrule_list = dffwsecurityrule['Rule Name'].astype(str) dffwsecurityrulepolicy_list = dffwsecurityrule['Firewall Policy'].astype(str) fullsecurityrulelist = dffwsecurityrulepolicy_list + '::' + dffwsecurityrule_list @@ -1101,7 +1221,7 @@ def validate_compartments(filename,ct): comp_invalid_check = False parent_comp_check= False # Read the Compartments tab from excel - dfcomp = data_frame(filename ,'Compartments') + dfcomp = commonTools.data_frame(filename ,'Compartments') for i in dfcomp.index: region = str(dfcomp.loc[i, 'Region']).strip().lower() @@ -1170,35 +1290,38 @@ def validate_firewall_cd3(filename, var_file, prefix, outdir, config,signer,ct): print("Getting Compartments OCIDs...") ct.get_compartment_map(var_file,'Validator') - dffwpolicy = data_frame(filename, 'Firewall-Policy') + dffwpolicy = commonTools.data_frame(filename, 'Firewall-Policy') fwpolicy_list = dffwpolicy['Policy Name'].astype(str) - dffwaddress = data_frame(filename, 'Firewall-Policy-AddressList') + dffwaddress = commonTools.data_frame(filename, 'Firewall-Policy-AddressList') dffwaddress_list = dffwaddress['List Name'].astype(str) dffwaddresspolicy_list = dffwaddress['Firewall Policy'].astype(str) fulladdreslist = dffwaddresspolicy_list + '::' + dffwaddress_list - dffwservice = data_frame(filename, 'Firewall-Policy-ServiceList') + dffwservice = commonTools.data_frame(filename, 'Firewall-Policy-ServiceList') dffwservice_list = dffwservice['Service List'].astype(str) + dffwnatservice_list = dffwservice['Services'].astype(str) + #spdffwnatservice_list = dffwnatservice_list.str.split(pat="::",n=1).astype(str) dffwservicepolicy_list = dffwservice['Firewall Policy'].astype(str) fullservicelist = dffwservicepolicy_list + '::' + dffwservice_list + fullnatservicelist = dffwservicepolicy_list + '&' + dffwnatservice_list - dffwapps = data_frame(filename, 'Firewall-Policy-ApplicationList') + dffwapps = commonTools.data_frame(filename, 'Firewall-Policy-ApplicationList') dffwapps_list = dffwapps['Application List'].astype(str) dffwappspolicy_list = dffwapps['Firewall Policy'].astype(str) fullappslist = dffwappspolicy_list + '::' + dffwapps_list - dffwurls = data_frame(filename, 'Firewall-Policy-UrlList') + dffwurls = commonTools.data_frame(filename, 'Firewall-Policy-UrlList') dffwurls_list = dffwurls['List Name'].astype(str) dffwurlspolicy_list = dffwurls['Firewall Policy'].astype(str) fullurlslist = dffwurlspolicy_list + '::' + dffwurls_list - dffwsecrets = data_frame(filename, 'Firewall-Policy-Secret') + dffwsecrets = commonTools.data_frame(filename, 'Firewall-Policy-Secret') dffwsecrets_list = dffwsecrets['Secret Name'].astype(str) dffwsecrestspolicy_list = dffwsecrets['Firewall Policy'].astype(str) fullsecretslist = dffwsecrestspolicy_list + '::' + dffwsecrets_list - dffwdecrypt = data_frame(filename, 'Firewall-Policy-DecryptProfile') + dffwdecrypt = commonTools.data_frame(filename, 'Firewall-Policy-DecryptProfile') dffwdecrypt_list = dffwdecrypt['Decryption Profile Name'].astype(str) dffwdecryptpolicy_list = dffwdecrypt['Firewall Policy'].astype(str) fulldecryptlist = dffwdecryptpolicy_list + '::' + dffwdecrypt_list @@ -1233,10 +1356,14 @@ def validate_firewall_cd3(filename, var_file, prefix, outdir, config,signer,ct): log("\n============================= Verifying Firewall-Policy-SecRule Tab ==========================================\n") print("\nProcessing Firewall-Policy-Secrules Tab..") fw_policysecurityrule_check = validate_FirewallPolicySecurityRule(filename, fwpolicy_list, fulladdreslist, fullservicelist, fullappslist, fullurlslist,ct) + log("\n============================= Verifying Firewall-Policy-TunnelInspect Tab ==========================================\n") print("\nProcessing Firewall-Policy-TunnelInspect Tab..") fw_policytunnelinspect_check = validate_FirewallPolicyTunnelInspectRule(filename, fwpolicy_list, fulladdreslist, ct) + log("\n============================= Verifying Firewall-Policy-NatRules Tab ==========================================\n") + print("\nProcessing Firewall-Policy-NatRules Tab..") + fw_policynatrules_check = validate_FirewallPolicyNatRule(filename, fwpolicy_list, fulladdreslist,fullnatservicelist, ct) # Prints the final result; once the validation is complete - if any([Firewall_check, fw_policy_check, fw_policyapp_check, fw_policyurl_check, fw_policyservice_check, fw_policyaddress_check, fw_policysecrets_check, fw_policydecryption_check, fw_policydecryptionrule_check, fw_policysecurityrule_check, fw_policytunnelinspect_check]): + if any([Firewall_check, fw_policy_check, fw_policyapp_check, fw_policyurl_check, fw_policyservice_check, fw_policyaddress_check, fw_policysecrets_check, fw_policydecryption_check, fw_policydecryptionrule_check, fw_policysecurityrule_check, fw_policytunnelinspect_check, fw_policynatrules_check]): log("=======") log("Summary:") log("=======") diff --git a/cd3_automation_toolkit/ocicloud/python/cd3Services.py b/cd3_automation_toolkit/ocicloud/python/cd3Services.py new file mode 100644 index 000000000..a88dcf373 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/cd3Services.py @@ -0,0 +1,138 @@ +from oci.identity import IdentityClient +import oci +import os +import xml.etree.ElementTree as ET +import datetime +import ssl +import pathlib +import urllib +import shutil +import sys +class cd3Services(): + + #Get OCI Cloud Regions + regions_list = "" + def fetch_regions(self,config,signer): + #config = oci.config.from_file(file_location=configFileName) + idc = IdentityClient(config=config, retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY,signer=signer) + try: + regions_list = idc.list_regions().data + except Exception as e: + print(e) + if ('NotAuthenticated' in str(e)): + print("\nInvalid Credetials - check your keypair/fingerprint/region...Exiting!!!") + exit(1) + + if ("OCSWorkVM" in os.getcwd() or 'user-scripts' in os.getcwd()): + os.chdir("../") + + tempStr = '#Region:Region_Key\n' + reg_dict = {} + + for reg in regions_list: + cd3key = str(reg.name.split('-',1)[1]).lower() + + if 'dcc' in cd3key: + cd3key = str(cd3key.split('-',1)[1]).lower() + + name = str(reg.name).lower() + reg_dict[cd3key] = name + + keys = [] + new_reg_dict={} + for key,val in reg_dict.items(): + keyy = key.split("-")[0] + if keyy not in keys: + keys.append(keyy) + new_reg_dict[keyy]=val + else: + new_reg_dict[key] = val + + #replace prev + old_val = new_reg_dict[keyy] + old_val_key = str(old_val.split('-', 1)[1]).lower() + if 'dcc' in old_val_key: + old_val_key = str(old_val_key.split('-', 1)[1]).lower() + + new_reg_dict[old_val_key] = old_val + new_reg_dict.pop(keyy) + + for cd3key,name in new_reg_dict.items(): + line = cd3key + ":" + name + tempStr = tempStr + line + '\n' + + with open('OCI_Regions', 'w+') as f: + f.write(tempStr) + f.close() + print("Updated OCI_Regions file !!!\n") + + # Parse XML - Used by OCI Protocols + def parse_xml(source: str) -> ET.Element: + it = ET.iterparse(open(source)) + # strip namespaces + for _, el in it: + if "}" in el.tag: + el.tag = el.tag.split("}", 1)[1] + root = it.root # mypy: ignore + return root + + # Parse Date - Used by OCI Protocols + def parse_date(root_xml: ET.Element) -> datetime: + updated = root_xml.find("updated") + assert updated is not None and isinstance(updated.text, str) + return datetime.datetime.strptime(updated.text, "%Y-%m-%d") + + # write_protocols_file - Used for OCI Protocols + def write_protocols_file(source: str, destination: str) -> datetime: + root = cd3Services.parse_xml(source) + updated = cd3Services.parse_date(root) + destination = str(pathlib.Path.cwd())+"/"+destination + with open(destination,"w+") as dst: + dst.write("#protocol number:protocol name\n") + for r in root.iter("record"): + desc_ = r.find("description") + if desc_ is None or desc_.text is None: + desc = "" + else: + desc = desc_.text + name_ = r.find("name") + value_ = r.find("value") + if (value_ is None + or value_.text is None): + continue + if (name_ is None + or name_.text is None): + name = desc + dst.write(str(value_.text) + ":" + name + "\n") + continue + alias = name_.text.split()[0] + value = int(value_.text) + dst.write(str(value)+":"+alias+"\n") + return updated + + def download(url: str, path: str) -> None: + with open(path, "wb") as dst, urllib.request.urlopen(url) as src: + shutil.copyfileobj(src, dst) + + #Get OCI Protocols + def fetch_protocols(self) -> None: + + ssl._create_default_https_context = ssl._create_unverified_context + PROTOCOLS_URL = "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml" + PROTOCOLS_XML = "protocol-numbers.xml" + PROTOCOLS_FILE = "OCI_Protocols" + + ##### main code for oci protocols #### + protocols_xml = str(pathlib.Path.cwd()) + "/" + PROTOCOLS_XML + try: + cd3Services.download(PROTOCOLS_URL, protocols_xml) + except OSError as e: + print("Could not download iana service names and port numbers: {}".format(e), + file=sys.stderr, + ) + sys.exit(1) + cd3Services.write_protocols_file(protocols_xml, PROTOCOLS_FILE) + rem_file = pathlib.Path(protocols_xml) + rem_file.unlink() + + print("Updated OCI_Protocols file !!!\n") \ No newline at end of file diff --git a/cd3_automation_toolkit/cd3Validator.py b/cd3_automation_toolkit/ocicloud/python/cd3Validator.py similarity index 98% rename from cd3_automation_toolkit/cd3Validator.py rename to cd3_automation_toolkit/ocicloud/python/cd3Validator.py index 7045be5d7..492ff4e5c 100644 --- a/cd3_automation_toolkit/cd3Validator.py +++ b/cd3_automation_toolkit/ocicloud/python/cd3Validator.py @@ -14,8 +14,12 @@ import os from functools import partial import inspect +import sys from oci.core.virtual_network_client import VirtualNetworkClient -from commonTools import * +sys.path.append(os.getcwd()+"/..") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +#import ocicloud.python.ociCommonTools as ociCommonTools ''' def get_vcn_ids(compartment_ids, config): @@ -163,7 +167,7 @@ def validate_nsgs_column(i,region,columnvalue,subnet_name,subnetobj,vcn_nsg_list def fetch_vcn_cidrs(filename): vcn_cidrs = {} # List of the column headers - dfv = data_frame(filename, 'VCNs') + dfv = commonTools.data_frame(filename, 'VCNs') dfcolumns = dfv.columns.values.tolist() # Loop through each row @@ -204,8 +208,8 @@ def validate_subnets(filename, comp_ids, vcnobj): log("Start Null or Wrong value check in each row-----------------") - dfsub = data_frame(filename, 'SubnetsVLANs') - dfdhcp = data_frame(filename, 'DHCP') + dfsub = commonTools.data_frame(filename, 'SubnetsVLANs') + dfdhcp = commonTools.data_frame(filename, 'DHCP') # List of the column headers dfcolumns = dfsub.columns.values.tolist() @@ -316,7 +320,7 @@ def validate_subnets(filename, comp_ids, vcnobj): for j in dfsub.keys(): if (str(dfsub[j][i]).strip() == "NaN" or str(dfsub[j][i]).strip() == "nan" or str(dfsub[j][i]).strip() == ""): # only dhcp_option_name, route table name, seclist_names and dns_label columns can be empty - if j in labels or commonTools.check_column_headers(j) in commonTools.tagColumns or "ipv6" in j.lower(): + if j in labels or commonTools.check_column_headers(j) in ociCommonTools.tagColumns or "ipv6" in j.lower(): pass else: if j == "Type(private|public)" and subnet_or_vlan.lower() == "vlan": @@ -377,7 +381,7 @@ def validate_subnets(filename, comp_ids, vcnobj): def validate_vcns(filename, comp_ids, vcnobj):# config): # ,vcn_cidrs,vcn_compartment_ids): #vcn_ids = get_vcn_ids(comp_ids, config) - dfv = data_frame(filename, 'VCNs') + dfv = commonTools.data_frame(filename, 'VCNs') # Counter to fetch the row number count = 0 @@ -460,7 +464,7 @@ def validate_vcns(filename, comp_ids, vcnobj):# config): # ,vcn_cidrs,vcn_compa # Check for null values and display appropriate message for j in dfv.keys(): if (str(dfv[j][i]).strip() == "NaN" or str(dfv[j][i]).strip() == "nan" or str(dfv[j][i]).strip() == ""): - if j == 'DNS Label' or commonTools.check_column_headers(j) in commonTools.tagColumns or "ipv6" in j.lower() or "Hub/Spoke" in j: + if j == 'DNS Label' or commonTools.check_column_headers(j) in ociCommonTools.tagColumns or "ipv6" in j.lower() or "Hub/Spoke" in j: continue else: log(f'ROW {count+2} : Empty value at column "{j}".') @@ -540,7 +544,7 @@ def validate_vcns(filename, comp_ids, vcnobj):# config): # ,vcn_cidrs,vcn_compa # Checks if the fields in DHCP tab are compliant def validate_dhcp(filename, comp_ids, vcnobj): - dfdhcp = data_frame(filename, 'DHCP') + dfdhcp = commonTools.data_frame(filename, 'DHCP') empty = ['', 'Nan', 'NaN', 'nan'] dhcp_empty_check = False dhcp_wrong_check = False @@ -598,7 +602,7 @@ def validate_dhcp(filename, comp_ids, vcnobj): else: # Check if there are any field that is empty; display appropriate message if str(dfdhcp[j][i]).strip() in empty and j != 'Search Domain' and commonTools.check_column_headers( - j) not in commonTools.tagColumns: + j) not in ociCommonTools.tagColumns: log(f'ROW {count+2} : Empty value at column {j}.') dhcp_empty_check = True @@ -613,7 +617,7 @@ def validate_dhcp(filename, comp_ids, vcnobj): # Checks if the fields in DRGv2 tab are compliant def validate_drgv2(filename, comp_ids, vcnobj): - dfdrgv2 = data_frame(filename, 'DRGs') + dfdrgv2 = commonTools.data_frame(filename, 'DRGs') drgv2_empty_check = False drgv2_invalid_check = False drgv2_comp_check = False @@ -713,9 +717,9 @@ def validate_dns(filename,comp_ids): subnet_check = False nsg_check = False endpoint_type_check = False - dfdns = data_frame(filename, 'DNS-Views-Zones-Records') + dfdns = commonTools.data_frame(filename, 'DNS-Views-Zones-Records') dfdnscolumns = dfdns.columns.values.tolist() - dfres = data_frame(filename, 'DNS-Resolvers') + dfres = commonTools.data_frame(filename, 'DNS-Resolvers') dfrescolumns = dfres.columns.values.tolist() log(f'Checking for DNS-Views-Zones-Records') for i in dfdns.index: @@ -841,7 +845,7 @@ def validate_instances(filename,comp_ids,subnetobj,vcn_subnet_list,vcn_nsg_list) vcn_subnet_check = False vcn_nsg_check= False - dfinst = data_frame(filename, 'Instances') + dfinst = commonTools.data_frame(filename, 'Instances') dfcolumns = dfinst.columns.values.tolist() for i in dfinst.index: @@ -959,8 +963,8 @@ def validate_blockvols(filename,comp_ids): instance_name_check = False bv_ad_check = False ADS = ["AD1","AD2","AD3"] - dfvol = data_frame(filename, 'BlockVolumes') - dfinst = data_frame(filename, 'Instances') + dfvol = commonTools.data_frame(filename, 'BlockVolumes') + dfinst = commonTools.data_frame(filename, 'Instances') values_list = dfinst['Display Name'].tolist() inst_ad_list = dfinst['Display Name']+'_'+dfinst['Availability Domain(AD1|AD2|AD3)'] dfcolumns = dfvol.columns.values.tolist() @@ -1112,7 +1116,7 @@ def validate_fss(filename,comp_ids,subnetobj,vcn_subnet_list,vcn_nsg_list): vcn_subnet_check = False vcn_nsg_check= False - df_fss = data_frame(filename, 'FSS') + df_fss = commonTools.data_frame(filename, 'FSS') dfcolumns = df_fss.columns.values.tolist() for i in df_fss.index: @@ -1180,7 +1184,7 @@ def validate_compartments(filename): comp_invalid_check = False parent_comp_check= False # Read the Compartments tab from excel - dfcomp = data_frame(filename,'Compartments') + dfcomp = commonTools.data_frame(filename,'Compartments') for i in dfcomp.index: region = str(dfcomp.loc[i, 'Region']).strip().lower() @@ -1213,7 +1217,7 @@ def validate_groups(filename): groups_empty_check = False groups_invalid_check = False # Read the Groups tab from excel - dfg = data_frame(filename, 'Groups') + dfg = commonTools.data_frame(filename, 'Groups') for i in dfg.index: region = str(dfg.loc[i, 'Region']).strip().lower() @@ -1241,7 +1245,7 @@ def validate_policies(filename,comp_ids): policies_invalid_check = False # Read the Policies tab from excel - dfp = data_frame(filename,'Policies') + dfp = commonTools.data_frame(filename,'Policies') for i in dfp.index: region = str(dfp.loc[i, 'Region']).strip().lower() @@ -1333,7 +1337,7 @@ def validate_tags(filename,comp_ids): tag_comp_check = False # Read the Compartments tab from excel - dftag = data_frame(filename,'Tags') + dftag = commonTools.data_frame(filename,'Tags') for i in dftag.index: region = str(dftag.loc[i, 'Region']).strip().lower() @@ -1415,7 +1419,7 @@ def validate_budgets(filename,comp_ids): # Read the Compartments tab from excel - dfbudget = data_frame(filename, 'Budgets') + dfbudget = commonTools.data_frame(filename, 'Budgets') for i in dfbudget.index: region = str(dfbudget.loc[i, 'Region']).strip().lower() @@ -1474,7 +1478,7 @@ def validate_buckets(filename, comp_ids): bucket_name_check = False # Read the Compartments tab from excel - dfbuckets = data_frame(filename, 'Buckets') + dfbuckets = commonTools.data_frame(filename, 'Buckets') for i in dfbuckets.index: region = str(dfbuckets.loc[i, 'Region']).strip().lower() @@ -1734,7 +1738,7 @@ def validate_buckets(filename, comp_ids): #validate_kms def validate_kms(filename,comp_ids): - dfkms = data_frame(filename, 'KMS') + dfkms = commonTools.data_frame(filename, 'KMS') kms_invalid_check = False prev_vault_type = "" @@ -1951,12 +1955,11 @@ def validate_cd3(choices, filename, var_file, prefix, outdir, ct1): #config1, si vcnobj = parseVCNs(filename) subnetobj = parseSubnets(filename) - dfsub = data_frame(filename, 'SubnetsVLANs') + dfsub = commonTools.data_frame(filename, 'SubnetsVLANs') vcn_subnet_list = dfsub['VCN Name'].astype(str)+'_'+dfsub['Display Name'] - dfnsg = data_frame(filename, 'NSGs') + dfnsg = commonTools.data_frame(filename, 'NSGs') vcn_nsg_list = dfnsg['Region'].astype(str).str.lower() + '_' + dfnsg['VCN Name'].astype(str) + '_' + dfnsg['NSG Name'] - val_net=False for options in choices: if ('Validate Compartments' in options[0]): diff --git a/cd3_automation_toolkit/Compute/__init__.py b/cd3_automation_toolkit/ocicloud/python/compute/__init__.py similarity index 100% rename from cd3_automation_toolkit/Compute/__init__.py rename to cd3_automation_toolkit/ocicloud/python/compute/__init__.py diff --git a/cd3_automation_toolkit/Compute/create_terraform_dedicatedhosts.py b/cd3_automation_toolkit/ocicloud/python/compute/create_terraform_dedicatedhosts.py similarity index 94% rename from cd3_automation_toolkit/Compute/create_terraform_dedicatedhosts.py rename to cd3_automation_toolkit/ocicloud/python/compute/create_terraform_dedicatedhosts.py index 95b04ba64..13c534637 100644 --- a/cd3_automation_toolkit/Compute/create_terraform_dedicatedhosts.py +++ b/cd3_automation_toolkit/ocicloud/python/compute/create_terraform_dedicatedhosts.py @@ -14,8 +14,9 @@ from oci.config import DEFAULT_LOCATION from pathlib import Path -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader @@ -92,8 +93,8 @@ def create_terraform_dedicatedhosts(inputfile, outdir, service_dir,prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Display Name': columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/Compute/create_terraform_instances.py b/cd3_automation_toolkit/ocicloud/python/compute/create_terraform_instances.py similarity index 97% rename from cd3_automation_toolkit/Compute/create_terraform_instances.py rename to cd3_automation_toolkit/ocicloud/python/compute/create_terraform_instances.py index e94057b2b..0503cc7fc 100755 --- a/cd3_automation_toolkit/Compute/create_terraform_instances.py +++ b/cd3_automation_toolkit/ocicloud/python/compute/create_terraform_instances.py @@ -14,9 +14,9 @@ import fnmatch from oci.config import DEFAULT_LOCATION from pathlib import Path - -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader @@ -115,8 +115,8 @@ def create_terraform_instances(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname in plugin_column: columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/Compute/export_dedicatedvmhosts_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/compute/export_dedicatedvmhosts_nonGreenField.py similarity index 91% rename from cd3_automation_toolkit/Compute/export_dedicatedvmhosts_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/compute/export_dedicatedvmhosts_nonGreenField.py index b21412fb5..5cb2488c2 100644 --- a/cd3_automation_toolkit/Compute/export_dedicatedvmhosts_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/compute/export_dedicatedvmhosts_nonGreenField.py @@ -9,17 +9,18 @@ # import oci -import os +import os, sys import subprocess as sp from oci.config import DEFAULT_LOCATION -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * importCommands = {} oci_obj_names = {} -def print_dedicatedvmhosts(region, dedicatedvmhost, values_for_column, ntk_compartment_name,export_tags, state): +def print_dedicatedvmhosts(region, dedicatedvmhost, values_for_column, ntk_compartment_name,export_compartments, export_regions, export_tags, state): # Tags filter defined_tags = dedicatedvmhost.defined_tags @@ -58,11 +59,11 @@ def print_dedicatedvmhosts(region, dedicatedvmhost, values_for_column, ntk_compa elif ("AD-3" in value or "ad-3" in value): ad = "AD3" values_for_column[col_header].append(ad) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(dedicatedvmhost, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(dedicatedvmhost, col_header, values_for_column) else: oci_objs = [dedicatedvmhost] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # Execution of the code begins here def export_dedicatedvmhosts(inputfile, outdir, service_dir, config, signer, ct, export_compartments=[], export_regions=[],export_tags=[]): diff --git a/cd3_automation_toolkit/Compute/export_instances_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/compute/export_instances_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Compute/export_instances_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/compute/export_instances_nonGreenField.py index f04f23403..74502df66 100644 --- a/cd3_automation_toolkit/Compute/export_instances_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/compute/export_instances_nonGreenField.py @@ -8,9 +8,9 @@ import oci import os import subprocess as sp -sys.path.append(os.getcwd() + "/..") -from commonTools import * - +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def adding_columns_values(region, ad, fd, vs, publicip, privateip, os_dname, shape, key_name, c_name, bkp_policy_name, nsgs, d_host, instance_data, values_for_column_instances, bdet, @@ -68,12 +68,12 @@ def adding_columns_values(region, ad, fd, vs, publicip, privateip, os_dname, sha values_for_column_instances[col_header].append(d_host.data.display_name) elif (col_header == "Custom Policy Compartment Name"): values_for_column_instances[col_header].append(cpcn) - elif str(col_header).lower() in commonTools.tagColumns: - values_for_column_instances = commonTools.export_tags(instance_data, col_header, + elif str(col_header).lower() in ociCommonTools.tagColumns: + values_for_column_instances = ociCommonTools.export_tags(instance_data, col_header, values_for_column_instances) else: oci_objs = [instance_data, bdet, shape_config, vnic_info, d_host, launch_options, avail_config, ins_options, platform_config] - values_for_column_instances = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_instances, + values_for_column_instances = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_instances, values_for_column_instances) diff --git a/cd3_automation_toolkit/Compute/templates/dedicatedvmhosts-template b/cd3_automation_toolkit/ocicloud/python/compute/templates/dedicatedvmhosts-template similarity index 100% rename from cd3_automation_toolkit/Compute/templates/dedicatedvmhosts-template rename to cd3_automation_toolkit/ocicloud/python/compute/templates/dedicatedvmhosts-template diff --git a/cd3_automation_toolkit/Compute/templates/instances-template b/cd3_automation_toolkit/ocicloud/python/compute/templates/instances-template similarity index 100% rename from cd3_automation_toolkit/Compute/templates/instances-template rename to cd3_automation_toolkit/ocicloud/python/compute/templates/instances-template diff --git a/cd3_automation_toolkit/ocicloud/python/costmanagement/__init__.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/__init__.py new file mode 100644 index 000000000..4c3a5c86d --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/costmanagement/__init__.py @@ -0,0 +1 @@ +from .budget import * \ No newline at end of file diff --git a/cd3_automation_toolkit/CostManagement/Budget/__init__.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/__init__.py similarity index 100% rename from cd3_automation_toolkit/CostManagement/Budget/__init__.py rename to cd3_automation_toolkit/ocicloud/python/costmanagement/budget/__init__.py diff --git a/cd3_automation_toolkit/CostManagement/Budget/create_terraform_budget.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py similarity index 95% rename from cd3_automation_toolkit/CostManagement/Budget/create_terraform_budget.py rename to cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py index 4170c90fb..0497c10d7 100644 --- a/cd3_automation_toolkit/CostManagement/Budget/create_terraform_budget.py +++ b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py @@ -12,8 +12,10 @@ from oci.config import DEFAULT_LOCATION from pathlib import Path from jinja2 import Environment, FileSystemLoader -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools + ###### # Required Inputs-CD3 excel file, Config file, prefix AND outdir @@ -37,7 +39,7 @@ def create_terraform_budgets(inputfile, outdir, service_dir, prefix,ct): budget_alert_template = env.get_template('budget-alert-rule-template') # Read CD3 - df = data_frame(filename, sheetName) + df = commonTools.data_frame(filename, sheetName) regions = df['Region'] regions.dropna() @@ -119,8 +121,8 @@ def create_terraform_budgets(inputfile, outdir, service_dir, prefix,ct): tempdict = {'description': columnvalue} # Process Freeform Tags and Defined Tags - elif columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + elif columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) elif columnname == "Scope": tempdict = {'target_type': columnvalue.upper().strip()} diff --git a/cd3_automation_toolkit/CostManagement/Budget/export_budgets_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py similarity index 96% rename from cd3_automation_toolkit/CostManagement/Budget/export_budgets_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py index 44c0faac3..46978ae2b 100644 --- a/cd3_automation_toolkit/CostManagement/Budget/export_budgets_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py @@ -11,7 +11,9 @@ import os import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools sys.path.append(os.getcwd()+"/..") @@ -76,14 +78,14 @@ def print_budgets(values_for_columns, region, budget,budget_name,budget_alert_ru values_for_columns[col_header].append(budget_end_date) - elif col_header.lower() in commonTools.tagColumns: + elif col_header.lower() in ociCommonTools.tagColumns: if budget: - values_for_columns = commonTools.export_tags(budget, col_header, values_for_columns) + values_for_columns = ociCommonTools.export_tags(budget, col_header, values_for_columns) else: values_for_columns[col_header].append("") - if (col_header == "Alert Rules"): + elif (col_header == "Alert Rules"): alert_rule = "" if budget_alert_rule: alert_rule = str(budget_alert_rule.type)+"::"+str(budget_alert_rule.threshold) @@ -103,6 +105,7 @@ def print_budgets(values_for_columns, region, budget,budget_name,budget_alert_ru + # Execution of the code begins here def export_budgets_nongreenfield(inputfile, outdir, service_dir, config, signer, ct,export_regions=[],export_tags=[]): global importCommands diff --git a/cd3_automation_toolkit/CostManagement/Budget/templates/budget-alert-rule-template b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/templates/budget-alert-rule-template similarity index 100% rename from cd3_automation_toolkit/CostManagement/Budget/templates/budget-alert-rule-template rename to cd3_automation_toolkit/ocicloud/python/costmanagement/budget/templates/budget-alert-rule-template diff --git a/cd3_automation_toolkit/CostManagement/Budget/templates/budget-template b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/templates/budget-template similarity index 100% rename from cd3_automation_toolkit/CostManagement/Budget/templates/budget-template rename to cd3_automation_toolkit/ocicloud/python/costmanagement/budget/templates/budget-template diff --git a/cd3_automation_toolkit/Database/__init__.py b/cd3_automation_toolkit/ocicloud/python/database/__init__.py similarity index 100% rename from cd3_automation_toolkit/Database/__init__.py rename to cd3_automation_toolkit/ocicloud/python/database/__init__.py diff --git a/cd3_automation_toolkit/Database/create_terraform_adb.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py similarity index 96% rename from cd3_automation_toolkit/Database/create_terraform_adb.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py index 0ea9ac644..b1212f650 100644 --- a/cd3_automation_toolkit/Database/create_terraform_adb.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py @@ -8,11 +8,13 @@ # Oracle Consulting # Modified (TF Upgrade): Divya Das # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -96,8 +98,8 @@ def create_terraform_adb(inputfile, outdir, service_dir, prefix, ct): tempdict = {columnname: columnvalue} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "ADB Display Name": display_tf_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Database/create_terraform_dbsystems_vm_bm.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_dbsystems_vm_bm.py similarity index 97% rename from cd3_automation_toolkit/Database/create_terraform_dbsystems_vm_bm.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_dbsystems_vm_bm.py index 2d8595924..58a98caa3 100644 --- a/cd3_automation_toolkit/Database/create_terraform_dbsystems_vm_bm.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_dbsystems_vm_bm.py @@ -8,12 +8,13 @@ # Oracle Consulting # -import sys -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -135,8 +136,8 @@ def create_terraform_dbsystems_vm_bm(inputfile, outdir, service_dir, prefix, ct) tempdict = {columnname: columnvalue} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "DB System Display Name": display_tf_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Database/create_terraform_exa_infra.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_infra.py similarity index 94% rename from cd3_automation_toolkit/Database/create_terraform_exa_infra.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_infra.py index a2deb9963..ba99ecfab 100644 --- a/cd3_automation_toolkit/Database/create_terraform_exa_infra.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_infra.py @@ -8,11 +8,13 @@ # Oracle Consulting # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -104,8 +106,8 @@ def create_terraform_exa_infra(inputfile, outdir, service_dir, prefix, ct): tempdict = {columnname: columnvalue} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Exadata Infra Display Name": display_tf_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Database/create_terraform_exa_vmclusters.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_vmclusters.py similarity index 97% rename from cd3_automation_toolkit/Database/create_terraform_exa_vmclusters.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_vmclusters.py index 737261a6f..7b6f00216 100644 --- a/cd3_automation_toolkit/Database/create_terraform_exa_vmclusters.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_exa_vmclusters.py @@ -8,11 +8,13 @@ # Oracle Consulting # Modified (TF Upgrade): Kartikey Rajput # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -114,8 +116,8 @@ def create_terraform_exa_vmclusters(inputfile, outdir, service_dir, prefix, ct): tempdict = {columnname: columnvalue} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "VM Cluster Display Name": display_tf_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Database/create_terraform_mysql_configuration.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_configuration.py similarity index 97% rename from cd3_automation_toolkit/Database/create_terraform_mysql_configuration.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_configuration.py index 3ca3504bb..ad9a79f94 100644 --- a/cd3_automation_toolkit/Database/create_terraform_mysql_configuration.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_configuration.py @@ -8,12 +8,14 @@ # Oracle Consulting # -import os +import os, sys import re from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def create_terraform_mysql_configuration(inputfile, outdir, service_dir, prefix, ct): filename = inputfile diff --git a/cd3_automation_toolkit/Database/create_terraform_mysql_db.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_db.py similarity index 99% rename from cd3_automation_toolkit/Database/create_terraform_mysql_db.py rename to cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_db.py index 35cd3fced..a5e73efae 100644 --- a/cd3_automation_toolkit/Database/create_terraform_mysql_db.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_mysql_db.py @@ -13,7 +13,9 @@ from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def create_terraform_mysql_db(inputfile, outdir, service_dir, prefix, ct): ADS = ["AD1", "AD2", "AD3"] diff --git a/cd3_automation_toolkit/Database/export_adb_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py similarity index 95% rename from cd3_automation_toolkit/Database/export_adb_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py index 5691602fa..16cf5a94d 100644 --- a/cd3_automation_toolkit/Database/export_adb_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py @@ -7,9 +7,11 @@ # Oracle Consulting # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from oci.config import DEFAULT_LOCATION importCommands = {} @@ -110,11 +112,11 @@ def print_adbs(region, vnc_client, adb, values_for_column, ntk_compartment_name, values_for_column[col_header].append(customer_emails.lstrip(',')) elif col_header == "NSGs": values_for_column[col_header].append(nsg_names) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(adb, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(adb, col_header, values_for_column) else: oci_objs = [adb] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # Execution of the code begins here def export_adbs(inputfile, outdir, service_dir, config, signer, ct, export_compartments=[],export_regions=[],export_tags=[]): diff --git a/cd3_automation_toolkit/Database/export_dbsystems_vm_bm_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_dbsystems_vm_bm_nonGreenField.py similarity index 96% rename from cd3_automation_toolkit/Database/export_dbsystems_vm_bm_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_dbsystems_vm_bm_nonGreenField.py index d29b33caa..5b9b2ebc2 100644 --- a/cd3_automation_toolkit/Database/export_dbsystems_vm_bm_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_dbsystems_vm_bm_nonGreenField.py @@ -8,9 +8,11 @@ # Oracle Consulting # import oci -import os +import os, sys from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader import json import re @@ -97,11 +99,11 @@ def print_dbsystem_vm_bm(region, db_system_vm_bm, count,db_home, database ,vnc_c values_for_column[col_header].append(ad) elif (col_header == "NSGs"): values_for_column[col_header].append(nsg_names) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(db_system_vm_bm, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(db_system_vm_bm, col_header, values_for_column) else: oci_objs = [db_system_vm_bm,db_system_options,maintenance_window,db_home,database,db_backup_config,connection_strings,database_management_config] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # Execution of the code begins here diff --git a/cd3_automation_toolkit/Database/export_exa_infra_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_exa_infra_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Database/export_exa_infra_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_exa_infra_nonGreenField.py index 20656d825..95575faca 100644 --- a/cd3_automation_toolkit/Database/export_exa_infra_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_exa_infra_nonGreenField.py @@ -9,9 +9,11 @@ # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} diff --git a/cd3_automation_toolkit/Database/export_exa_vmclusters_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_exa_vmclusters_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Database/export_exa_vmclusters_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_exa_vmclusters_nonGreenField.py index ca260a2fd..c68ec4e39 100644 --- a/cd3_automation_toolkit/Database/export_exa_vmclusters_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_exa_vmclusters_nonGreenField.py @@ -9,12 +9,14 @@ # import oci -import os +import os, sys import json import re import subprocess as sp from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader importCommands = {} @@ -89,8 +91,8 @@ def print_exa_vmcluster(region, vnc_client,exa_infra, exa_vmcluster, key_name,va values_for_column[col_header].append(backup_nsg_names) elif (col_header == "DB Servers"): values_for_column[col_header].append(db_servers) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(exa_vmcluster, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(exa_vmcluster, col_header, values_for_column) else: oci_objs = [exa_vmcluster,exa_infra] values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) diff --git a/cd3_automation_toolkit/Database/export_mysql_configuration_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_mysql_configuration_nonGreenField.py similarity index 99% rename from cd3_automation_toolkit/Database/export_mysql_configuration_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_mysql_configuration_nonGreenField.py index f2de93436..a48308e78 100644 --- a/cd3_automation_toolkit/Database/export_mysql_configuration_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_mysql_configuration_nonGreenField.py @@ -8,8 +8,10 @@ # import oci -import os -from commonTools import * +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from oci.exceptions import ServiceError def export_mysql_configurations(inputfile, outdir, service_dir, config, signer, ct, export_regions=[], export_compartments=[]): diff --git a/cd3_automation_toolkit/Database/export_mysql_db_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_mysql_db_nonGreenField.py similarity index 96% rename from cd3_automation_toolkit/Database/export_mysql_db_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/database/export_mysql_db_nonGreenField.py index 3abec6b91..4a2c5a74f 100644 --- a/cd3_automation_toolkit/Database/export_mysql_db_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_mysql_db_nonGreenField.py @@ -7,9 +7,11 @@ # Oracle Consulting # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from oci.config import DEFAULT_LOCATION importCommands = {} @@ -158,11 +160,11 @@ def print_mysql(region, vnc_client, mysql_db, values_for_column, ntk_compartment values_for_column[col_header].append(mysql_db.maintenance.window_start_time if mysql_db.maintenance else "") elif col_header == 'Database Management is Enabled': values_for_column[col_header].append(mysql_db.database_management if mysql_db.database_management else "DISABLED") - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(mysql_db, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(mysql_db, col_header, values_for_column) else: oci_objs = [mysql_db] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) def export_mysql_db(inputfile, outdir, service_dir, config, signer, ct, export_compartments=[], export_regions=[],export_tags=[]): global tf_import_cmd diff --git a/cd3_automation_toolkit/Database/templates/adb-template b/cd3_automation_toolkit/ocicloud/python/database/templates/adb-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/adb-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/adb-template diff --git a/cd3_automation_toolkit/Database/templates/dbsystems-vm-bm-template b/cd3_automation_toolkit/ocicloud/python/database/templates/dbsystems-vm-bm-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/dbsystems-vm-bm-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/dbsystems-vm-bm-template diff --git a/cd3_automation_toolkit/Database/templates/exa-infra-template b/cd3_automation_toolkit/ocicloud/python/database/templates/exa-infra-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/exa-infra-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/exa-infra-template diff --git a/cd3_automation_toolkit/Database/templates/exa-vmclusters-template b/cd3_automation_toolkit/ocicloud/python/database/templates/exa-vmclusters-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/exa-vmclusters-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/exa-vmclusters-template diff --git a/cd3_automation_toolkit/Database/templates/mysql-configuration-template b/cd3_automation_toolkit/ocicloud/python/database/templates/mysql-configuration-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/mysql-configuration-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/mysql-configuration-template diff --git a/cd3_automation_toolkit/Database/templates/mysql-template b/cd3_automation_toolkit/ocicloud/python/database/templates/mysql-template similarity index 100% rename from cd3_automation_toolkit/Database/templates/mysql-template rename to cd3_automation_toolkit/ocicloud/python/database/templates/mysql-template diff --git a/cd3_automation_toolkit/ocicloud/python/developerservices/__init__.py b/cd3_automation_toolkit/ocicloud/python/developerservices/__init__.py new file mode 100644 index 000000000..7fddee9e4 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/__init__.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from .resourcemanager import * +from .oke import * + diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/__init__.py b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/__init__.py similarity index 100% rename from cd3_automation_toolkit/DeveloperServices/OKE/__init__.py rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/__init__.py diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/create_terraform_oke.py b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/create_terraform_oke.py similarity index 98% rename from cd3_automation_toolkit/DeveloperServices/OKE/create_terraform_oke.py rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/create_terraform_oke.py index 30e95fc11..405ea1dc3 100644 --- a/cd3_automation_toolkit/DeveloperServices/OKE/create_terraform_oke.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/create_terraform_oke.py @@ -7,13 +7,14 @@ # Author: Divya Das # Oracle Consulting # -import os +import os, sys import json import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -import commonTools -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader @@ -175,8 +176,8 @@ def create_terraform_oke(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Availability Domain(AD1|AD2|AD3)': columnname = 'availability_domain' diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/export_oke_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py similarity index 95% rename from cd3_automation_toolkit/DeveloperServices/OKE/export_oke_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py index 2988e240b..a541a7075 100644 --- a/cd3_automation_toolkit/DeveloperServices/OKE/export_oke_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py @@ -15,7 +15,9 @@ from oci.core.virtual_network_client import VirtualNetworkClient from oci.container_engine import ContainerEngineClient from oci.config import DEFAULT_LOCATION -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools sys.path.append(os.getcwd() + "/..") @@ -354,29 +356,29 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod values_for_column_oke[col_header].append(val) # Process the Node Label Columns - elif 'oke labels' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'oke labels' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): - values_for_column_oke = commonTools.export_tags(nodepool_info, col_header,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_tags(nodepool_info, col_header,values_for_column_oke) else: values_for_column_oke[col_header].append(None) - elif 'nodepool defined tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'nodepool defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): - values_for_column_oke = commonTools.export_tags(nodepool_info, col_header,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_tags(nodepool_info, col_header,values_for_column_oke) else: values_for_column_oke[col_header].append(None) - elif 'nodepool freeform tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'nodepool freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): values_for_column_oke = commonTools.export_tags(nodepool_info, col_header,values_for_column_oke) else: values_for_column_oke[col_header].append(None) - elif 'node defined tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'node defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): if nodepool_type=='managed': - values_for_column_oke = commonTools.export_tags(nodepool_info.node_config_details, col_header,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_tags(nodepool_info.node_config_details, col_header,values_for_column_oke) elif (nodepool_type=='virtual' and nodepool_info.virtual_node_tags!=None): - values_for_column_oke = commonTools.export_tags(nodepool_info.virtual_node_tags , col_header, + values_for_column_oke = ociCommonTools.export_tags(nodepool_info.virtual_node_tags , col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) @@ -384,12 +386,12 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod values_for_column_oke[col_header].append(None) - elif 'node freeform tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'node freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): if nodepool_type == 'managed': - values_for_column_oke = commonTools.export_tags(nodepool_info.node_config_details, col_header,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_tags(nodepool_info.node_config_details, col_header,values_for_column_oke) elif (nodepool_type == 'virtual' and nodepool_info.virtual_node_tags!=None): - values_for_column_oke = commonTools.export_tags(nodepool_info.virtual_node_tags, col_header, + values_for_column_oke = ociCommonTools.export_tags(nodepool_info.virtual_node_tags, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) @@ -397,21 +399,21 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod else: values_for_column_oke[col_header].append(None) - elif 'lb defined tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'lb defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): values_for_column_oke = commonTools.export_tags(cluster_info.options.service_lb_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) - elif 'lb freeform tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'lb freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): values_for_column_oke = commonTools.export_tags(cluster_info.options.service_lb_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) - elif 'volume defined tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'volume defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): values_for_column_oke = commonTools.export_tags(cluster_info.options.persistent_volume_config, col_header, values_for_column_oke) @@ -419,16 +421,16 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod values_for_column_oke[col_header].append(None) - elif 'volume freeform tags' in col_header.lower() and col_header.lower() in commonTools.tagColumns: + elif 'volume freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): - values_for_column_oke = commonTools.export_tags(cluster_info.options.persistent_volume_config, + values_for_column_oke = ociCommonTools.export_tags(cluster_info.options.persistent_volume_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) # Process tag columns - elif col_header.lower() in commonTools.tagColumns: - values_for_column_oke = commonTools.export_tags(cluster_info, col_header, values_for_column_oke) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_oke = ociCommonTools.export_tags(cluster_info, col_header, values_for_column_oke) else: oci_objs = [cluster_info,image_policy_config, nodepool_info] values_for_column_oke = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_oke,values_for_column_oke) diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/templates/cluster-template b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/cluster-template similarity index 100% rename from cd3_automation_toolkit/DeveloperServices/OKE/templates/cluster-template rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/cluster-template diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/templates/nodepool-template b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/nodepool-template similarity index 100% rename from cd3_automation_toolkit/DeveloperServices/OKE/templates/nodepool-template rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/nodepool-template diff --git a/cd3_automation_toolkit/DeveloperServices/OKE/templates/virtual-nodepool-template b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/virtual-nodepool-template similarity index 100% rename from cd3_automation_toolkit/DeveloperServices/OKE/templates/virtual-nodepool-template rename to cd3_automation_toolkit/ocicloud/python/developerservices/oke/templates/virtual-nodepool-template diff --git a/cd3_automation_toolkit/DeveloperServices/ResourceManager/__init__.py b/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/__init__.py similarity index 100% rename from cd3_automation_toolkit/DeveloperServices/ResourceManager/__init__.py rename to cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/__init__.py diff --git a/cd3_automation_toolkit/DeveloperServices/ResourceManager/create_resource_manager_stack.py b/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py similarity index 99% rename from cd3_automation_toolkit/DeveloperServices/ResourceManager/create_resource_manager_stack.py rename to cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py index ee4397138..8db79fceb 100644 --- a/cd3_automation_toolkit/DeveloperServices/ResourceManager/create_resource_manager_stack.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py @@ -7,14 +7,14 @@ # Author: Shruthi Subramanian # -import argparse -import os +import os, sys from zipfile import ZipFile import shutil import time import csv import base64 -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * from oci.config import DEFAULT_LOCATION from oci.resource_manager.models import CreateStackDetails from oci.resource_manager.models import UpdateStackDetails diff --git a/cd3_automation_toolkit/ocicloud/python/governance/__init__.py b/cd3_automation_toolkit/ocicloud/python/governance/__init__.py new file mode 100644 index 000000000..3204e8908 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/governance/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + + +from .tagging import * +from .quota import * + diff --git a/cd3_automation_toolkit/Governance/Quota/__init__.py b/cd3_automation_toolkit/ocicloud/python/governance/quota/__init__.py similarity index 100% rename from cd3_automation_toolkit/Governance/Quota/__init__.py rename to cd3_automation_toolkit/ocicloud/python/governance/quota/__init__.py diff --git a/cd3_automation_toolkit/Governance/Quota/create_terraform_quotas.py b/cd3_automation_toolkit/ocicloud/python/governance/quota/create_terraform_quotas.py similarity index 94% rename from cd3_automation_toolkit/Governance/Quota/create_terraform_quotas.py rename to cd3_automation_toolkit/ocicloud/python/governance/quota/create_terraform_quotas.py index bbe55bae7..8d1a9fcb2 100644 --- a/cd3_automation_toolkit/Governance/Quota/create_terraform_quotas.py +++ b/cd3_automation_toolkit/ocicloud/python/governance/quota/create_terraform_quotas.py @@ -6,11 +6,13 @@ # Author: Bhanu P. Lohumi # Oracle Consulting # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -90,8 +92,8 @@ def create_terraform_quotas(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Name': columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/Governance/Quota/export_quotas_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py similarity index 88% rename from cd3_automation_toolkit/Governance/Quota/export_quotas_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py index 3c8b14ab1..ebc08ef90 100644 --- a/cd3_automation_toolkit/Governance/Quota/export_quotas_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py @@ -10,9 +10,9 @@ import oci import os import subprocess as sp -from commonTools import * - -sys.path.append(os.getcwd()+"/..") +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools compartment_ids={} importCommands={} @@ -28,10 +28,15 @@ def print_quotas(values_for_columns,region, quota,quota_policy): values_for_columns[col_header].append(quota.description) elif (col_header == "Quota Policy"): values_for_columns[col_header].append(quota_policy) - elif col_header.lower() in commonTools.tagColumns: - values_for_columns = commonTools.export_tags(quota, col_header, values_for_columns) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_columns = ociCommonTools.export_tags(quota, col_header, values_for_columns) + else: + oci_objs = [quota] + values_for_columns = ociCommonTools.export_extra_columns(oci_objs, col_header, + sheet_dict_quotas,values_for_columns) + -# Execution of the code begins here + # Execution of the code begins here def export_quotas_nongreenfield(inputfile, outdir, service_dir, config, signer, ct,export_tags): global tf_import_cmd global values_for_column_quotas diff --git a/cd3_automation_toolkit/Governance/Quota/templates/quota-template b/cd3_automation_toolkit/ocicloud/python/governance/quota/templates/quota-template similarity index 100% rename from cd3_automation_toolkit/Governance/Quota/templates/quota-template rename to cd3_automation_toolkit/ocicloud/python/governance/quota/templates/quota-template diff --git a/cd3_automation_toolkit/Governance/Tagging/__init__.py b/cd3_automation_toolkit/ocicloud/python/governance/tagging/__init__.py similarity index 100% rename from cd3_automation_toolkit/Governance/Tagging/__init__.py rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/__init__.py diff --git a/cd3_automation_toolkit/Governance/Tagging/create_terraform_tags.py b/cd3_automation_toolkit/ocicloud/python/governance/tagging/create_terraform_tags.py similarity index 97% rename from cd3_automation_toolkit/Governance/Tagging/create_terraform_tags.py rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/create_terraform_tags.py index f2a97d348..3365a4399 100644 --- a/cd3_automation_toolkit/Governance/Tagging/create_terraform_tags.py +++ b/cd3_automation_toolkit/ocicloud/python/governance/tagging/create_terraform_tags.py @@ -13,8 +13,9 @@ import pandas as pd import os from pathlib import Path -sys.path.append(os.getcwd()+"/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader ###### @@ -133,8 +134,8 @@ def create_terraform_tags(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnvalue = str(columnvalue).strip() diff --git a/cd3_automation_toolkit/Governance/Tagging/export_tags_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/governance/tagging/export_tags_nonGreenField.py similarity index 96% rename from cd3_automation_toolkit/Governance/Tagging/export_tags_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/export_tags_nonGreenField.py index 003e27372..126fdaa2a 100644 --- a/cd3_automation_toolkit/Governance/Tagging/export_tags_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/governance/tagging/export_tags_nonGreenField.py @@ -12,9 +12,9 @@ from oci.identity import IdentityClient import os import subprocess as sp -from commonTools import * - -sys.path.append(os.getcwd()+"/..") +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools compartment_ids={} tf_name_namespace_list = [] @@ -76,11 +76,11 @@ def print_tags(values_for_column_tags,region, ntk_compartment_name, tag, tag_ke else: values_for_column_tags[col_header].append('') - elif col_header.lower() in commonTools.tagColumns: - values_for_column_tags = commonTools.export_tags(tag, col_header, values_for_column_tags) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_tags = ociCommonTools.export_tags(tag, col_header, values_for_column_tags) else: oci_objs = [tag,tag_key]#,tag_default] - values_for_column_tags = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_tags,values_for_column_tags) + values_for_column_tags = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_tags,values_for_column_tags) tf_name_namespace = commonTools.check_tf_variable(tagname) tf_name_key = commonTools.check_tf_variable(tag_key_name) diff --git a/cd3_automation_toolkit/Governance/Tagging/templates/tags-defaults-template b/cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-defaults-template similarity index 100% rename from cd3_automation_toolkit/Governance/Tagging/templates/tags-defaults-template rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-defaults-template diff --git a/cd3_automation_toolkit/Governance/Tagging/templates/tags-keys-template b/cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-keys-template similarity index 100% rename from cd3_automation_toolkit/Governance/Tagging/templates/tags-keys-template rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-keys-template diff --git a/cd3_automation_toolkit/Governance/Tagging/templates/tags-namespaces-template b/cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-namespaces-template similarity index 100% rename from cd3_automation_toolkit/Governance/Tagging/templates/tags-namespaces-template rename to cd3_automation_toolkit/ocicloud/python/governance/tagging/templates/tags-namespaces-template diff --git a/cd3_automation_toolkit/ocicloud/python/identity/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/__init__.py new file mode 100644 index 000000000..ff94f3eb2 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/identity/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +from .compartments import * +from .users import * +from .groups import * +from .policies import * +from .export_identity_nonGreenField import * +from .networksources import * diff --git a/cd3_automation_toolkit/Identity/Compartments/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/compartments/__init__.py similarity index 100% rename from cd3_automation_toolkit/Identity/Compartments/__init__.py rename to cd3_automation_toolkit/ocicloud/python/identity/compartments/__init__.py diff --git a/cd3_automation_toolkit/Identity/Compartments/create_terraform_compartments.py b/cd3_automation_toolkit/ocicloud/python/identity/compartments/create_terraform_compartments.py similarity index 97% rename from cd3_automation_toolkit/Identity/Compartments/create_terraform_compartments.py rename to cd3_automation_toolkit/ocicloud/python/identity/compartments/create_terraform_compartments.py index 1a89d0cab..c65465a62 100644 --- a/cd3_automation_toolkit/Identity/Compartments/create_terraform_compartments.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/compartments/create_terraform_compartments.py @@ -9,11 +9,13 @@ # Modified (TF if (columnvalue not in ckeys):Upgrade): Shruthi Subramanian # -import os +import os, sys from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools import oci ###### @@ -127,8 +129,8 @@ def travel(parent, keys, values, c): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Parent Compartment": columnname = commonTools.check_column_headers(columnname) diff --git a/cd3_automation_toolkit/Identity/Compartments/templates/compartments-template b/cd3_automation_toolkit/ocicloud/python/identity/compartments/templates/compartments-template similarity index 100% rename from cd3_automation_toolkit/Identity/Compartments/templates/compartments-template rename to cd3_automation_toolkit/ocicloud/python/identity/compartments/templates/compartments-template diff --git a/cd3_automation_toolkit/Identity/export_identity_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/identity/export_identity_nonGreenField.py similarity index 96% rename from cd3_automation_toolkit/Identity/export_identity_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/identity/export_identity_nonGreenField.py index be2266c59..b9c16ea24 100644 --- a/cd3_automation_toolkit/Identity/export_identity_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/export_identity_nonGreenField.py @@ -14,8 +14,9 @@ from oci.identity import IdentityClient import os import subprocess as sp -sys.path.append(os.getcwd()+"/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools # Execution of the code begins here def export_identity(inputfile, outdir, service_dir,resource, config, signer, ct, export_compartments=[],export_domains={}): @@ -132,13 +133,13 @@ def export_identity(inputfile, outdir, service_dir,resource, config, signer, ct, values_for_column_comps[col_header].append(comp_display_name) elif (col_header == "Parent Compartment"): values_for_column_comps[col_header].append(comp_parent_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_comps = commonTools.export_tags(c_details, col_header, + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_comps = ociCommonTools.export_tags(c_details, col_header, values_for_column_comps ) else: oci_objs = [c_details] - values_for_column_comps = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_comps = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_comps, values_for_column_comps ) @@ -233,13 +234,13 @@ def export_identity(inputfile, outdir, service_dir,resource, config, signer, ct, values_for_column_policies[col_header].append("") elif (col_header == "Policy Statements"): values_for_column_policies[col_header].append(stmt) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_policies = commonTools.export_tags(policy, col_header, + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_policies = ociCommonTools.export_tags(policy, col_header, values_for_column_policies ) else: oci_objs = [policy] - values_for_column_policies = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_policies = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_policies, values_for_column_policies ) @@ -347,10 +348,10 @@ def process_group(grp_info, members_list,membership_id_list, domain_name, is_dyn grp_defined_tags = ";".join(grp_defined_tags) values_for_column_groups[col_header].append(grp_defined_tags if grp_defined_tags else "") elif col_header == "Defined Tags" and non_domain: - values_for_column_groups = commonTools.export_tags(grp_info, col_header, values_for_column_groups) + values_for_column_groups = ociCommonTools.export_tags(grp_info, col_header, values_for_column_groups) else: oci_objs = [grp_info] - values_for_column_groups = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_groups, values_for_column_groups) + values_for_column_groups = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_groups, values_for_column_groups) return importCommands, values_for_column_groups diff --git a/cd3_automation_toolkit/Identity/Groups/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/groups/__init__.py similarity index 100% rename from cd3_automation_toolkit/Identity/Groups/__init__.py rename to cd3_automation_toolkit/ocicloud/python/identity/groups/__init__.py diff --git a/cd3_automation_toolkit/Identity/Groups/create_terraform_groups.py b/cd3_automation_toolkit/ocicloud/python/identity/groups/create_terraform_groups.py similarity index 93% rename from cd3_automation_toolkit/Identity/Groups/create_terraform_groups.py rename to cd3_automation_toolkit/ocicloud/python/identity/groups/create_terraform_groups.py index cc8e0f3a0..e691979d1 100644 --- a/cd3_automation_toolkit/Identity/Groups/create_terraform_groups.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/groups/create_terraform_groups.py @@ -8,11 +8,13 @@ # Oracle Consulting # Modified by: Ranjini Rajendran # -import os +import os, sys from pathlib import Path from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -118,8 +120,8 @@ def create_terraform_groups(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Name': group_tf_name = f"{domain}_{commonTools.check_tf_variable(columnvalue)}" @@ -135,11 +137,11 @@ def create_terraform_groups(inputfile, outdir, service_dir, prefix, ct): tempdict = {'members': members} # Process Defined and Freeform Tags based on columnname and 'Domain Name' - if columnname.lower() in commonTools.tagColumns: + if columnname.lower() in ociCommonTools.tagColumns: # for IDCS tenancies if not ct.identity_domain_enabled: # Process tags using the existing code - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) else: if columnname == 'Defined Tags': defined_tags = columnvalue.strip() diff --git a/cd3_automation_toolkit/Identity/Groups/templates/groups-template b/cd3_automation_toolkit/ocicloud/python/identity/groups/templates/groups-template similarity index 100% rename from cd3_automation_toolkit/Identity/Groups/templates/groups-template rename to cd3_automation_toolkit/ocicloud/python/identity/groups/templates/groups-template diff --git a/cd3_automation_toolkit/Identity/Groups/templates/identity-domain-groups-template b/cd3_automation_toolkit/ocicloud/python/identity/groups/templates/identity-domain-groups-template similarity index 100% rename from cd3_automation_toolkit/Identity/Groups/templates/identity-domain-groups-template rename to cd3_automation_toolkit/ocicloud/python/identity/groups/templates/identity-domain-groups-template diff --git a/cd3_automation_toolkit/Identity/NetworkSources/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/networksources/__init__.py similarity index 100% rename from cd3_automation_toolkit/Identity/NetworkSources/__init__.py rename to cd3_automation_toolkit/ocicloud/python/identity/networksources/__init__.py diff --git a/cd3_automation_toolkit/Identity/NetworkSources/create_terraform_networkSources.py b/cd3_automation_toolkit/ocicloud/python/identity/networksources/create_terraform_networkSources.py similarity index 95% rename from cd3_automation_toolkit/Identity/NetworkSources/create_terraform_networkSources.py rename to cd3_automation_toolkit/ocicloud/python/identity/networksources/create_terraform_networkSources.py index cc6113a60..bab23048c 100644 --- a/cd3_automation_toolkit/Identity/NetworkSources/create_terraform_networkSources.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/networksources/create_terraform_networkSources.py @@ -7,11 +7,13 @@ # Author: Gaurav Goyal # Oracle Consulting # -import os +import os, sys from pathlib import Path from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -134,8 +136,8 @@ def create_terraform_networkSources(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) # Check for boolean/null in column values diff --git a/cd3_automation_toolkit/Identity/NetworkSources/export_networkSources_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/identity/networksources/export_networkSources_nonGreenField.py similarity index 94% rename from cd3_automation_toolkit/Identity/NetworkSources/export_networkSources_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/identity/networksources/export_networkSources_nonGreenField.py index 352be8894..744e37cab 100644 --- a/cd3_automation_toolkit/Identity/NetworkSources/export_networkSources_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/networksources/export_networkSources_nonGreenField.py @@ -14,7 +14,9 @@ import os import subprocess as sp sys.path.append(os.getcwd()+"/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools # Execution of the code begins here def export_networkSources(inputfile, outdir, service_dir, config, signer, ct): @@ -110,7 +112,8 @@ def export_networkSources(inputfile, outdir, service_dir, config, signer, ct): values_for_column_networkSources[col_header].append(strIPRange) elif (col_header == "Defined Tags"): - values_for_column_networkSources = commonTools.export_tags(network_source_info, col_header, values_for_column_networkSources) + values_for_column_networkSources = ociCommonTools.export_tags(network_source_info, col_header, values_for_column_networkSources) + commonTools.write_to_cd3(values_for_column_networkSources, cd3file, sheetName) print("{0} Network Sources exported into CD3.\n".format(total_resource)) diff --git a/cd3_automation_toolkit/Identity/NetworkSources/templates/network-sources-template b/cd3_automation_toolkit/ocicloud/python/identity/networksources/templates/network-sources-template similarity index 100% rename from cd3_automation_toolkit/Identity/NetworkSources/templates/network-sources-template rename to cd3_automation_toolkit/ocicloud/python/identity/networksources/templates/network-sources-template diff --git a/cd3_automation_toolkit/Identity/Policies/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/policies/__init__.py similarity index 100% rename from cd3_automation_toolkit/Identity/Policies/__init__.py rename to cd3_automation_toolkit/ocicloud/python/identity/policies/__init__.py diff --git a/cd3_automation_toolkit/Identity/Policies/create_terraform_policies.py b/cd3_automation_toolkit/ocicloud/python/identity/policies/create_terraform_policies.py similarity index 96% rename from cd3_automation_toolkit/Identity/Policies/create_terraform_policies.py rename to cd3_automation_toolkit/ocicloud/python/identity/policies/create_terraform_policies.py index c3326539b..3c95fdce3 100644 --- a/cd3_automation_toolkit/Identity/Policies/create_terraform_policies.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/policies/create_terraform_policies.py @@ -9,11 +9,13 @@ # Modified (TF Upgrade): Shruthi Subramanian # -import os +import os, sys from pathlib import Path from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -38,7 +40,7 @@ def create_terraform_policies(inputfile, outdir, service_dir, prefix, ct): policies_template = env.get_template('policies-template') # Read CD3 - df = data_frame(filename, sheetName) + df = commonTools.data_frame(filename, sheetName) regions = df['Region'] regions.dropna() @@ -85,8 +87,8 @@ def create_terraform_policies(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = commonTools.check_column_headers(columnname) diff --git a/cd3_automation_toolkit/Identity/Policies/templates/policies-template b/cd3_automation_toolkit/ocicloud/python/identity/policies/templates/policies-template similarity index 100% rename from cd3_automation_toolkit/Identity/Policies/templates/policies-template rename to cd3_automation_toolkit/ocicloud/python/identity/policies/templates/policies-template diff --git a/cd3_automation_toolkit/Identity/Users/__init__.py b/cd3_automation_toolkit/ocicloud/python/identity/users/__init__.py similarity index 100% rename from cd3_automation_toolkit/Identity/Users/__init__.py rename to cd3_automation_toolkit/ocicloud/python/identity/users/__init__.py diff --git a/cd3_automation_toolkit/Identity/Users/create_terraform_users.py b/cd3_automation_toolkit/ocicloud/python/identity/users/create_terraform_users.py similarity index 94% rename from cd3_automation_toolkit/Identity/Users/create_terraform_users.py rename to cd3_automation_toolkit/ocicloud/python/identity/users/create_terraform_users.py index 5ae39550f..0af79096d 100644 --- a/cd3_automation_toolkit/Identity/Users/create_terraform_users.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/users/create_terraform_users.py @@ -8,11 +8,13 @@ # Oracle Consulting # Modified by: Ranjini Rajendran -import os +import os, sys from pathlib import Path from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -117,8 +119,8 @@ def create_terraform_users(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'User Name': columnvalue = columnvalue.strip() @@ -140,10 +142,10 @@ def create_terraform_users(inputfile, outdir, service_dir, prefix, ct): tempStr.update(tempdict) # Process Defined and Freeform Tags based on columnname and 'Domain Name' - if columnname.lower() in commonTools.tagColumns: + if columnname.lower() in ociCommonTools.tagColumns: if not ct.identity_domain_enabled: # Process tags using the existing code - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) else: # When 'Domain Name' is not 'nan', process 'Defined Tags' differently if columnname == 'Defined Tags': diff --git a/cd3_automation_toolkit/Identity/Users/export_users_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/identity/users/export_users_nonGreenField.py similarity index 93% rename from cd3_automation_toolkit/Identity/Users/export_users_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/identity/users/export_users_nonGreenField.py index df9319079..949d6f74f 100644 --- a/cd3_automation_toolkit/Identity/Users/export_users_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/identity/users/export_users_nonGreenField.py @@ -13,8 +13,9 @@ from oci.identity import IdentityClient import os import subprocess as sp -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def append_user_info(values_for_column_users,sheet_dict_users, ct, user_info, username, family_name, given_name, recovery_email, display_name, description, email, domain_key, user_defined_tags): def add_capabilities(user_info): capabilities = [] @@ -138,7 +139,8 @@ def export_users(inputfile, outdir, service_dir, config, signer, ct,export_domai user_defined_tags = ";".join(user_defined_tags) if user_defined_tags else "" user_info = user - if user_info.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_user.is_federated_user != "True" and user_info.active !="False": + #if user_info.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_user.is_federated_user != "True" and user_info.active !="False": + if (user_info.active != "False" and (user_info.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_user is None or user_info.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_user.is_federated_user != "True")): username = user_info.user_name family_name = user_info.name.family_name given_name = user_info.name.given_name @@ -194,8 +196,8 @@ def export_users(inputfile, outdir, service_dir, config, signer, ct,export_domai importCommands += f'\n{tf_or_tofu} import "{tf_resource}" capabilities/{user_info.id}' for col_header in values_for_column_users.keys(): - if col_header.lower() in commonTools.tagColumns: - values_for_column_users = commonTools.export_tags(user, col_header, values_for_column_users) + if col_header.lower() in ociCommonTools.tagColumns: + values_for_column_users = ociCommonTools.export_tags(user, col_header, values_for_column_users) max_list_length = max(len(lst) for lst in values_for_column_users.values()) for col_name in values_for_column_users: diff --git a/cd3_automation_toolkit/Identity/Users/templates/identity-domain-users-template b/cd3_automation_toolkit/ocicloud/python/identity/users/templates/identity-domain-users-template similarity index 100% rename from cd3_automation_toolkit/Identity/Users/templates/identity-domain-users-template rename to cd3_automation_toolkit/ocicloud/python/identity/users/templates/identity-domain-users-template diff --git a/cd3_automation_toolkit/Identity/Users/templates/users-template b/cd3_automation_toolkit/ocicloud/python/identity/users/templates/users-template similarity index 100% rename from cd3_automation_toolkit/Identity/Users/templates/users-template rename to cd3_automation_toolkit/ocicloud/python/identity/users/templates/users-template diff --git a/cd3_automation_toolkit/ocicloud/python/managementservices/__init__.py b/cd3_automation_toolkit/ocicloud/python/managementservices/__init__.py new file mode 100755 index 000000000..25e351456 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/__init__.py @@ -0,0 +1,4 @@ +from .eventsnotifications import * +from .monitoring import * +from .logging import * +from .serviceconnectorhub import * \ No newline at end of file diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/__init__.py b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/__init__.py similarity index 100% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/__init__.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/__init__.py diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_events.py b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_events.py similarity index 97% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_events.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_events.py index b790488c7..e41b25662 100644 --- a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_events.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_events.py @@ -9,11 +9,14 @@ # Modified (TF Upgrade): Shravanthi Lingam # +import os, sys import json -from commonTools import * from oci.config import DEFAULT_LOCATION from pathlib import Path from jinja2 import Environment, FileSystemLoader +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools #Method to extend conditions with resources def extend_event(service_name, resources, listeventid): @@ -109,8 +112,8 @@ def create_terraform_events(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": compartmentVarName = columnvalue.strip() diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_notifications.py b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_notifications.py similarity index 70% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_notifications.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_notifications.py index a9ca8c708..463b65eb0 100644 --- a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/create_terraform_notifications.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/create_terraform_notifications.py @@ -9,11 +9,15 @@ #shravanthi.lingam@oracle.com # Modified (TF Upgrade): Shravanthi Lingam # +import os, sys import datetime from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +from copy import deepcopy +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -25,23 +29,21 @@ def create_terraform_notifications(inputfile, outdir, service_dir, prefix, ct): outdir = outdir sheetName="Notifications" topics_auto_tfvars_filename = '_' + sheetName.lower() + '-topics.auto.tfvars' - subs_auto_tfvars_filename = '_' + sheetName.lower() + '-subscriptions.auto.tfvars' x = datetime.datetime.now() date = x.strftime("%f").strip() tempStr={} tfStr={} + topic_dict = {} tfStr1 = {} outfile={} oname={} Notifications_names={} - Subscriptions_names={} # Load the template file file_loader = FileSystemLoader(f'{Path(__file__).parent}/templates') env = Environment(loader=file_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True) - notifications_template = env.get_template('notifications-topics-template') - subscriptions_template = env.get_template('notifications-subscriptions-template') + notifications_template = env.get_template('notifications-template') # Read cd3 using pandas dataframe df, col_headers = commonTools.read_cd3(filename, sheetName) @@ -58,13 +60,11 @@ def create_terraform_notifications(inputfile, outdir, service_dir, prefix, ct): tfStr[eachregion] = '' tfStr1[eachregion] = '' Notifications_names[eachregion]=[] - Subscriptions_names[eachregion]=[] # Take backup of files resource = sheetName.lower() srcdir = outdir + "/" + eachregion + "/" + service_dir + "/" commonTools.backup_file(srcdir, resource, topics_auto_tfvars_filename) - commonTools.backup_file(srcdir, resource, subs_auto_tfvars_filename) # Iterate over rows count = 1 @@ -103,8 +103,8 @@ def create_terraform_notifications(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": compartmentVarName = commonTools.check_tf_variable(columnvalue) @@ -134,30 +134,30 @@ def create_terraform_notifications(inputfile, outdir, service_dir, prefix, ct): tempStr[columnname] = str(columnvalue).strip() tempStr.update(tempdict) - if(topic in Notifications_names[region]): - count = count + 1 - if(topic not in Notifications_names[region]): - count = 1 - Notifications_names[region].append(topic) - # Write all info to TF string - tfStr[region]=tfStr[region][:-1] + notifications_template.render(tempStr) + subscription = [] + if (str(df.loc[i, 'Protocol']).lower() != 'nan' and str(df.loc[i, 'Endpoint']).lower() != 'nan'): + subscription = [{ + 'protocol': protocol, + 'endpoint': endpoint.split("::")[-1] + }] - #Empty Topic - if(str(df.loc[i, 'Protocol']).lower() == 'nan' and str(df.loc[i, 'Endpoint']).lower() == 'nan'): - continue - - subscription = tf_name_topic + "_sub" + str(count) - tempdict = {'subscription_tf_name': subscription} + tempdict = {'subscriptions': subscription} tempStr.update(tempdict) - if(subscription.strip() not in Subscriptions_names[region]): - Subscriptions_names[region].append(subscription.strip()) - if ( protocol in "ORACLE_FUNCTIONS" ): - endpoint = endpoint.split("::") - endpoint = endpoint[1] - tempdict = {'endpoint': endpoint} - tempStr.update(tempdict) - tfStr1[region]=tfStr1[region][:-1] + subscriptions_template.render(tempStr) + topic_key = f'{region}_{topic}' + + if topic_key in topic_dict: + topic_dict[topic_key]['subscriptions'].extend(subscription) + else: + topic_dict[topic_key] = deepcopy(tempStr) + + for key in topic_dict: + reg_key = key.split("_")[0] + + # Write all info to TF string + tfStr[reg_key]=tfStr[reg_key][:-1] + notifications_template.render(topic_dict[key]) + + #Empty Topic # Write to output for reg in ct.all_regions: reg_out_dir = outdir + "/" + reg + "/" + service_dir @@ -171,13 +171,3 @@ def create_terraform_notifications(inputfile, outdir, service_dir, prefix, ct): oname[reg].close() print(outfile[reg] + " for Notifications_Topics has been created for region " + reg) - if (tfStr1[reg] != ''): - outfile[reg] = reg_out_dir + "/" + prefix + subs_auto_tfvars_filename - srcStr = "##Add New Subscriptions for "+str(reg).lower()+" here##" - tfStr1[reg] = subscriptions_template.render(skeleton=True, region=reg).replace(srcStr,tfStr1[reg] + "\n" + srcStr) - tfStr1[reg] = "".join([s for s in tfStr1[reg].strip().splitlines(True) if s.strip("\r\n").strip()]) - oname[reg] = open(outfile[reg], 'w+') - oname[reg].write(tfStr1[reg]) - oname[reg].close() - print(outfile[reg] + " for Notifications_Subscriptions has been created for region " + reg) - diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/export_events_notifications_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py similarity index 95% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/export_events_notifications_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py index 34131f2f3..55de2574d 100644 --- a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/export_events_notifications_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py @@ -17,8 +17,9 @@ from oci.ons import NotificationDataPlaneClient from oci.functions import FunctionsManagementClient from oci.config import DEFAULT_LOCATION -from commonTools import * -sys.path.append(os.getcwd() + "/..") +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools compartment_ids={} importCommands={} @@ -57,18 +58,18 @@ def print_notifications(values_for_column_notifications,region, ntk_compartment values_for_column_notifications[col_header].append("") else: values_for_column_notifications = commonTools.export_tags(sbpn, col_header, values_for_column_notifications) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_notifications = commonTools.export_tags(nftn_info, col_header, values_for_column_notifications) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_notifications = ociCommonTools.export_tags(nftn_info, col_header, values_for_column_notifications) else: oci_objs = [nftn_info,sbpn] - values_for_column_notifications = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_notifications,values_for_column_notifications) - tf_resource = f'module.notifications-topics[\\"{tf_name_nftn}\\"].oci_ons_notification_topic.topic' + values_for_column_notifications = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_notifications,values_for_column_notifications) + tf_resource = f'module.notifications[\\"{tf_name_nftn}\\"].oci_ons_notification_topic.topic' if (i ==0 or i == 1) and tf_resource not in state["resources"]: importCommands[region.lower()] += f'\n{tf_or_tofu} import "{tf_resource}" {str(nftn_info.topic_id)}' - tf_resource = f'module.notifications-subscriptions[\\"{tf_name_sbpn}\\"].oci_ons_subscription.subscription' + tf_resource = f'module.notifications[\\"{tf_name_nftn}\\"].oci_ons_subscription.subscription' if(i!=0) and tf_resource not in state["resources"]: - importCommands[region.lower()] += f'\n{tf_or_tofu} import "{tf_resource}" {str(sbpn.id)}' + importCommands[region.lower()] += f'\n{tf_or_tofu} import "{tf_resource}[{i-1}]" {str(sbpn.id)}' def print_events(values_for_column_events, region, ntk_compartment_name, event, event_info, ncpc, fun,state): @@ -92,9 +93,11 @@ def print_events(values_for_column_events, region, ntk_compartment_name, event, action_type = action.action_type action_is_enabled = str(action.is_enabled) if (action_type == "OSS"): - print("Ignoring Event "+event_name +" because action is OSS") - action_name = "" - continue + action_info = {} + action_id = action.stream_id + #print("Ignoring Event "+event_name +" because action is OSS") + action_name = action_id + action_comp = "" if ( action_type == "FAAS" ): action_id = action.function_id try: diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/actions-template b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/actions-template similarity index 100% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/actions-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/actions-template diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/events-template b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/events-template similarity index 100% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/events-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/events-template diff --git a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-topics-template b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/notifications-template similarity index 82% rename from cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-topics-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/notifications-template index a813356fd..7d242495b 100644 --- a/cd3_automation_toolkit/ManagementServices/EventsAndNotifications/templates/notifications-topics-template +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/templates/notifications-template @@ -4,13 +4,13 @@ # ############################ # ManagementServices -# Notifications_Topics - tfvars +# Notifications - tfvars # Allowed Values: # compartment_id can be the ocid or the name of the compartment hierarchy delimited by double hiphens "--" # Example : compartment_id = "ocid1.compartment.oc1..aaaaaaaahwwiefb56epvdlzfic6ah6jy3xf3c" or compartment_id = "Security--Prod" where "Security" is the parent of "Prod" compartment ############################ -notifications_topics = { +notifications = { ##Add New Topics for {{ region|lower }} here## } {% else %} @@ -18,7 +18,18 @@ notifications_topics = { compartment_id = "{{ compartment_tf_name }}" description = "{{ description }}" topic_name = "{{ topic }}" - + subscriptions = [ + {% for sub in subscriptions %} + { + {% if '::' in sub.endpoint %} + endpoint = "{{ sub.endpoint.split('::')[1] }}" + {% else %} + endpoint = "{{ sub.endpoint }}" + {% endif %} + protocol = "{{ sub.protocol }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + ] {# ##Do not modify below this line## #} {# #} {# ###Section for adding Defined and Freeform Tags### #} diff --git a/cd3_automation_toolkit/ManagementServices/Logging/__init__.py b/cd3_automation_toolkit/ocicloud/python/managementservices/logging/__init__.py similarity index 100% rename from cd3_automation_toolkit/ManagementServices/Logging/__init__.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/logging/__init__.py diff --git a/cd3_automation_toolkit/ManagementServices/Logging/enable_terraform_logging.py b/cd3_automation_toolkit/ocicloud/python/managementservices/logging/enable_terraform_logging.py similarity index 95% rename from cd3_automation_toolkit/ManagementServices/Logging/enable_terraform_logging.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/logging/enable_terraform_logging.py index 9cbc1a528..63934d7fd 100644 --- a/cd3_automation_toolkit/ManagementServices/Logging/enable_terraform_logging.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/logging/enable_terraform_logging.py @@ -9,11 +9,13 @@ # Modified (TF Upgrade): Shruthi Subramanian # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from pathlib import Path from oci.config import DEFAULT_LOCATION -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- Config file, prefix AND outdir @@ -135,10 +137,10 @@ def enable_service_logging(filename, outdir, prefix, ct, service_dir, option='') loggroup_tf_name = commonTools.check_tf_variable(obj_name) + "_" + "flow-log-group" for columnname in dfcolumns: - if columnname.lower() in commonTools.tagColumns: + if columnname.lower() in ociCommonTools.tagColumns: columnvalue = str(df[columnname][i]).strip() if columnvalue != 'nan' and columnvalue != '': - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) tempStr.update(tempdict) tempStr['compartment_tf_name'] = commonTools.check_tf_variable(compartment_name) diff --git a/cd3_automation_toolkit/ManagementServices/Logging/templates/logging-template b/cd3_automation_toolkit/ocicloud/python/managementservices/logging/templates/logging-template similarity index 100% rename from cd3_automation_toolkit/ManagementServices/Logging/templates/logging-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/logging/templates/logging-template diff --git a/cd3_automation_toolkit/ManagementServices/Monitoring/__init__.py b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/__init__.py similarity index 100% rename from cd3_automation_toolkit/ManagementServices/Monitoring/__init__.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/__init__.py diff --git a/cd3_automation_toolkit/ManagementServices/Monitoring/create_terraform_alarms.py b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/create_terraform_alarms.py similarity index 95% rename from cd3_automation_toolkit/ManagementServices/Monitoring/create_terraform_alarms.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/create_terraform_alarms.py index aa1ce0cbf..9c0a4332a 100644 --- a/cd3_automation_toolkit/ManagementServices/Monitoring/create_terraform_alarms.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/create_terraform_alarms.py @@ -9,10 +9,13 @@ # import datetime -from commonTools import * +import os, sys from oci.config import DEFAULT_LOCATION from pathlib import Path from jinja2 import Environment, FileSystemLoader +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools # Execution of the code begins here @@ -106,8 +109,8 @@ def create_terraform_alarms(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": compartmentVarName = commonTools.check_tf_variable(columnvalue) diff --git a/cd3_automation_toolkit/ManagementServices/Monitoring/export_alarms_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/export_alarms_nonGreenField.py similarity index 93% rename from cd3_automation_toolkit/ManagementServices/Monitoring/export_alarms_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/export_alarms_nonGreenField.py index d470d0033..7fa69492a 100644 --- a/cd3_automation_toolkit/ManagementServices/Monitoring/export_alarms_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/export_alarms_nonGreenField.py @@ -9,9 +9,11 @@ # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from oci.config import DEFAULT_LOCATION @@ -60,11 +62,11 @@ def print_alarms(region, alarm, ncpclient,values_for_column, ntk_compartment_nam if (topic_name == "Not_Found"): skip_row=1 values_for_column[col_header].append(topic_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(alarm, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(alarm, col_header, values_for_column) else: oci_objs = [alarm,suppression] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) tf_resource = f'module.alarms[\\"{comp_tf_name}_{alarm_tf_name}\\"].oci_monitoring_alarm.alarm' if skip_row == 0 and tf_resource not in state["resources"]: diff --git a/cd3_automation_toolkit/ManagementServices/Monitoring/templates/alarms-template b/cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/templates/alarms-template similarity index 100% rename from cd3_automation_toolkit/ManagementServices/Monitoring/templates/alarms-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/monitoring/templates/alarms-template diff --git a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/__init__.py b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/__init__.py similarity index 100% rename from cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/__init__.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/__init__.py diff --git a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/create_terraform_service_connectors.py b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/create_terraform_service_connectors.py similarity index 97% rename from cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/create_terraform_service_connectors.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/create_terraform_service_connectors.py index af2741d6f..cb93f1d3e 100644 --- a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/create_terraform_service_connectors.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/create_terraform_service_connectors.py @@ -10,9 +10,9 @@ import sys import os from pathlib import Path - -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader # Execution of the code begins here @@ -95,8 +95,8 @@ def create_service_connectors(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Display Name': # columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/export_sch_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/export_sch_nonGreenField.py similarity index 98% rename from cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/export_sch_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/export_sch_nonGreenField.py index e93e3b67f..b0a5ad22c 100755 --- a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/export_sch_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/export_sch_nonGreenField.py @@ -9,9 +9,11 @@ # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -306,11 +308,11 @@ def get_comp_details(comp_data): # elif col_header == 'Stream Partitions' and target_kind == "streaming": # stream_partitions = getattr(target_data, 'stream_partitions') # values_for_column[col_header].append(stream_partitions) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(schs, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(schs, col_header, values_for_column) else: oci_objs = [schs] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) diff --git a/cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/templates/service-connectors-template b/cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/templates/service-connectors-template similarity index 100% rename from cd3_automation_toolkit/ManagementServices/ServiceConnectorHub/templates/service-connectors-template rename to cd3_automation_toolkit/ocicloud/python/managementservices/serviceconnectorhub/templates/service-connectors-template diff --git a/cd3_automation_toolkit/Network/Global/__init__.py b/cd3_automation_toolkit/ocicloud/python/network/Global/__init__.py similarity index 100% rename from cd3_automation_toolkit/Network/Global/__init__.py rename to cd3_automation_toolkit/ocicloud/python/network/Global/__init__.py diff --git a/cd3_automation_toolkit/Network/Global/create_rpc_resources.py b/cd3_automation_toolkit/ocicloud/python/network/Global/create_rpc_resources.py similarity index 95% rename from cd3_automation_toolkit/Network/Global/create_rpc_resources.py rename to cd3_automation_toolkit/ocicloud/python/network/Global/create_rpc_resources.py index 23f1ed6d7..622e21361 100755 --- a/cd3_automation_toolkit/Network/Global/create_rpc_resources.py +++ b/cd3_automation_toolkit/ocicloud/python/network/Global/create_rpc_resources.py @@ -13,9 +13,9 @@ import sys import os from pathlib import Path - -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader # Setting current working dir. @@ -61,9 +61,14 @@ def find_subscribed_regions(inputfile, outdir, service_dir, prefix, config, sign os.makedirs(Path(f"{srcdir}/modules/rpc")) # to save the results + if "user-scripts" in os.getcwd(): + path=f"{owd}/../ocicloud/python/network/Global/templates/rpc-module/rpc-variables-terraform-template" + else: + path=f"{owd}/ocicloud/python/network/Global/templates/rpc-module/rpc-variables-terraform-template" shutil.copyfile( - Path(f"{owd}/Network/Global/templates/rpc-module/rpc-variables-terraform-template"), + Path(path), Path(f"{srcdir}/modules/rpc/variables.tf")) + os.chdir(Path(rf"{srcdir}/rpc/")) with open("rpc.tf", "w") as fh: fh.write(output) @@ -213,8 +218,8 @@ def create_rpc_resource(inputfile, outdir, service_dir, prefix, auth_mechanism, tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'RPC Display Name': columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/Network/Global/templates/rpc-module-template b/cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module-template similarity index 100% rename from cd3_automation_toolkit/Network/Global/templates/rpc-module-template rename to cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module-template diff --git a/cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-provider-terraform-template b/cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-provider-terraform-template similarity index 100% rename from cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-provider-terraform-template rename to cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-provider-terraform-template diff --git a/cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-source-destination-terraform-template b/cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-source-destination-terraform-template similarity index 100% rename from cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-source-destination-terraform-template rename to cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-source-destination-terraform-template diff --git a/cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-variables-terraform-template b/cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-variables-terraform-template similarity index 100% rename from cd3_automation_toolkit/Network/Global/templates/rpc-module/rpc-variables-terraform-template rename to cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-module/rpc-variables-terraform-template diff --git a/cd3_automation_toolkit/Network/Global/templates/rpc-root-terraform-template b/cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-root-terraform-template similarity index 100% rename from cd3_automation_toolkit/Network/Global/templates/rpc-root-terraform-template rename to cd3_automation_toolkit/ocicloud/python/network/Global/templates/rpc-root-terraform-template diff --git a/cd3_automation_toolkit/ocicloud/python/network/__init__.py b/cd3_automation_toolkit/ocicloud/python/network/__init__.py new file mode 100644 index 000000000..4fb6c107a --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/network/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +from .basenetwork import * +from .loadbalancers import * +from .dns import * +from .Global import * +#from .IPManagement import * \ No newline at end of file diff --git a/cd3_automation_toolkit/Network/BaseNetwork/__init__.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/__init__.py similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/__init__.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/__init__.py diff --git a/cd3_automation_toolkit/Network/BaseNetwork/cd3parser.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/cd3parser.py similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/cd3parser.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/cd3parser.py diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_all_tf_objects.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_all_tf_objects.py similarity index 94% rename from cd3_automation_toolkit/Network/BaseNetwork/create_all_tf_objects.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_all_tf_objects.py index 4cde85d72..471986fc3 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_all_tf_objects.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_all_tf_objects.py @@ -9,8 +9,10 @@ # Modified (TF Upgrade): Shruthi Subramanian # Modified Rework: Stefen Ramirez (stefen.ramirez@oracle.com) -import os -from commonTools import section +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from .create_major_objects import create_major_objects from .create_terraform_defaults import create_terraform_defaults from .create_terraform_dhcp_options import create_terraform_dhcp_options @@ -19,6 +21,8 @@ from .create_terraform_seclist import create_terraform_seclist from .create_terraform_subnet_vlan import create_terraform_subnet_vlan + + # Execution starts here def create_all_tf_objects(inputfile, outdir, service_dir,prefix, ct, non_gf_tenancy, modify_network=False,network_vlan_in_setupoci="network",network_connectivity_in_setupoci='network'): if not os.path.exists(outdir): diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_major_objects.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_major_objects.py similarity index 97% rename from cd3_automation_toolkit/Network/BaseNetwork/create_major_objects.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_major_objects.py index 4b1e9840e..8f92ee4da 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_major_objects.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_major_objects.py @@ -9,12 +9,14 @@ # Modified (TF Upgrade): Shruthi Subramanian # import re -import os +import os, sys import json from pathlib import Path from jinja2 import Environment, FileSystemLoader -#sys.path.append(os.getcwd() + "/../../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Files @@ -135,7 +137,7 @@ def create_drg_and_attachments(inputfile, outdir): #prevline = line drg_versions[region,drg] = drg_version if (drg_version == "DRGv2"): - for drg_auto_rt_name in commonTools.drg_auto_RTs: + for drg_auto_rt_name in ociCommonTools.drg_auto_RTs: temp = {} drg_auto_rt_tf_name = commonTools.check_tf_variable(drg + "_" + drg_auto_rt_name) temp['drg_auto_rt_tf_name'] = drg_auto_rt_tf_name @@ -143,7 +145,7 @@ def create_drg_and_attachments(inputfile, outdir): temp['drg_tf_name'] = commonTools.check_tf_variable(drg) drg_rt_data[region] = drg_rt_data[region] + drg_datasource_template.render(temp) - for drg_auto_rd_name in commonTools.drg_auto_RDs: + for drg_auto_rd_name in ociCommonTools.drg_auto_RDs: temp = {} drg_auto_rd_tf_name = commonTools.check_tf_variable(drg + "_" + drg_auto_rd_name) temp['drg_auto_rd_tf_name'] = drg_auto_rd_tf_name @@ -233,8 +235,8 @@ def create_drg_and_attachments(inputfile, outdir): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined Tags and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Compartment Name': compartment_var_name = columnvalue.strip() @@ -328,7 +330,7 @@ def create_drg_and_attachments(inputfile, outdir): if columnname == 'DRG RT Name': #if it is Auto Generated RT(during export) dont attach any RT to DRG attachment - if(columnvalue in commonTools.drg_auto_RTs): + if(columnvalue in ociCommonTools.drg_auto_RTs): drg_rt_tf_name = '' elif("ocid1.drgroutetable.oc" in columnvalue): drg_rt_tf_name = columnvalue @@ -623,8 +625,8 @@ def processVCN(tempStr): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined Tags and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Compartment Name': compartment_var_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_defaults.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_defaults.py similarity index 98% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_defaults.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_defaults.py index 49674e763..34d8f06e1 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_defaults.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_defaults.py @@ -10,7 +10,10 @@ import json from pathlib import Path from jinja2 import Environment, FileSystemLoader -from commonTools import * +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Files @@ -100,8 +103,8 @@ def generate_route_table_string(region_rt_name, region, routetableStr, tempStr, tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) tempStr.update(tempdict) if columnname == 'Compartment Name': diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_dhcp_options.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_dhcp_options.py similarity index 97% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_dhcp_options.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_dhcp_options.py index 1c3df843d..2daf9f35f 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_dhcp_options.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_dhcp_options.py @@ -13,9 +13,11 @@ import datetime import os from pathlib import Path -sys.path.append(os.getcwd() + "/../../..") from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Files @@ -128,8 +130,8 @@ def processDHCP(tempStr, template, defaultdhcp): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": compartment_var_name = columnvalue.strip() diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_nsg.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_nsg.py similarity index 96% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_nsg.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_nsg.py index bd31aff7c..cbb957951 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_nsg.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_nsg.py @@ -11,7 +11,10 @@ from pathlib import Path from oci.config import DEFAULT_LOCATION from jinja2 import Environment, FileSystemLoader -from commonTools import * +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -67,7 +70,7 @@ def getProtocolNumber(protocol): if protocol.lower() == 'all': return "all" else: - protocol_dict = commonTools().protocol_dict + protocol_dict = ociCommonTools().protocol_dict for k, v in protocol_dict.items(): if (protocol).lower() == v.lower(): return k @@ -204,8 +207,8 @@ def create_terraform_nsg(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'NSG Name': columnvalue = columnvalue.strip() diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_route.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_route.py similarity index 98% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_route.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_route.py index 0083caedc..d47925b7b 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_route.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_route.py @@ -13,10 +13,11 @@ import re import os from pathlib import Path -sys.path.append(os.getcwd() + "/../../..") -from commonTools import * from jinja2 import Environment, FileSystemLoader - +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file, Modify Network AND outdir @@ -216,7 +217,7 @@ def create_terraform_drg_route(inputfile, outdir, service_dir, prefix, ct, non_g continue # Dont create any route table or route distribution name if using Auto Generated ones - if (DRG_RT in commonTools.drg_auto_RTs and DRG_RD in commonTools.drg_auto_RDs): + if (DRG_RT in ociCommonTools.drg_auto_RTs and DRG_RD in ociCommonTools.drg_auto_RDs): continue # Dont create any oute table or route distribution name if OCID is goven in DRG RT Name if ("ocid1.drgroutetable.oc" in DRG_RT): @@ -240,8 +241,8 @@ def create_terraform_drg_route(inputfile, outdir, service_dir, prefix, ct, non_g columnvalue = commonTools.check_columnvalue(columnvalue) # Process Freeform and Defined Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "DRG Name": drg_name = columnvalue @@ -285,10 +286,10 @@ def create_terraform_drg_route(inputfile, outdir, service_dir, prefix, ct, non_g region_rt_name = "#"+region.lower() + "_" + tempStr['drg_rt_tf_name']+"#" tempStr['region_rt_name'] = region_rt_name - if (DRG_RT != 'nan' and DRG_RT not in commonTools.drg_auto_RTs and region_rt_name not in common_rt): + if (DRG_RT != 'nan' and DRG_RT not in ociCommonTools.drg_auto_RTs and region_rt_name not in common_rt): drg_rt[region] = drg_rt[region] + drg_rt_template.render(tempStr) - if (DRG_RD.lower() != 'nan' and DRG_RD not in commonTools.drg_auto_RDs): + if (DRG_RD.lower() != 'nan' and DRG_RD not in ociCommonTools.drg_auto_RDs): drg_rd[region] = drg_rd[region] + drg_rd_template.render(tempStr) if region_rt_name not in common_rt: @@ -1122,8 +1123,8 @@ def processSubnet(tempStr): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Freeform and Defined Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Availability Domain(AD1|AD2|AD3|Regional)': columnname = 'availability_domain' diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_seclist.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_seclist.py similarity index 97% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_seclist.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_seclist.py index 5ac2b2c55..d12ce4425 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_seclist.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_seclist.py @@ -14,8 +14,11 @@ import os from pathlib import Path from jinja2 import Environment, FileSystemLoader -sys.path.append(os.getcwd() + '/../../..') -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * + +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file, Modify Network AND outdir @@ -244,8 +247,8 @@ def processSubnet(tempStr, service_dir): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process the Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Compartment Name': compartment_var_name = columnvalue diff --git a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_subnet_vlan.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_subnet_vlan.py similarity index 98% rename from cd3_automation_toolkit/Network/BaseNetwork/create_terraform_subnet_vlan.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_subnet_vlan.py index 8fdbf0b11..44456c650 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/create_terraform_subnet_vlan.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/create_terraform_subnet_vlan.py @@ -12,10 +12,12 @@ import sys import re import os -sys.path.append(os.getcwd()+"/../../..") from pathlib import Path from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file, prefix AND outdir @@ -220,8 +222,8 @@ def processVlan(tempStr): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process the Freefrorm and Defined Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Compartment Name': compartment_var_name = columnvalue diff --git a/cd3_automation_toolkit/Network/BaseNetwork/exportNSG.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportNSG.py similarity index 93% rename from cd3_automation_toolkit/Network/BaseNetwork/exportNSG.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportNSG.py index 950941c2a..91c556951 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/exportNSG.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportNSG.py @@ -5,8 +5,9 @@ from oci.core.virtual_network_client import VirtualNetworkClient import os import subprocess as sp -sys.path.append(os.getcwd()+"/../../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def convertNullToNothing(input): EMPTY_STRING = "" @@ -90,7 +91,7 @@ def print_nsgsl(values_for_column_nsgs,vnc,region, comp_name, vcn_name, nsg, nsg icmpcode = nsgsl.icmp_options.code if nsgsl.protocol.lower()!="all": - protocol = str(commonTools().protocol_dict[nsgsl.protocol].lower()) + protocol = str(ociCommonTools().protocol_dict[nsgsl.protocol].lower()) else: protocol="all" for col_header in values_for_column_nsgs.keys(): @@ -127,11 +128,11 @@ def print_nsgsl(values_for_column_nsgs,vnc,region, comp_name, vcn_name, nsg, nsg if str(is_stateless).lower() == 'none': is_stateless = "false" values_for_column_nsgs[col_header].append(str(is_stateless)) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_nsgs = commonTools.export_tags(nsg, col_header, values_for_column_nsgs) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_nsgs = ociCommonTools.export_tags(nsg, col_header, values_for_column_nsgs) else: oci_objs = [nsg,nsgsl] - values_for_column_nsgs = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_nsgs,values_for_column_nsgs) + values_for_column_nsgs = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_nsgs,values_for_column_nsgs) nsg_rule_tf_name = tf_name + "_security_rule" + str(i) tf_resource = f'module.nsg-rules[\\"{nsg_rule_tf_name}\\"].oci_core_network_security_group_security_rule.nsg_rule' @@ -151,11 +152,11 @@ def print_nsg(values_for_column_nsgs,region, comp_name, vcn_name, nsg,state): values_for_column_nsgs[col_header].append(comp_name) elif (col_header == "VCN Name"): values_for_column_nsgs[col_header].append(vcn_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_nsgs = commonTools.export_tags(nsg, col_header, values_for_column_nsgs) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_nsgs = ociCommonTools.export_tags(nsg, col_header, values_for_column_nsgs) else: oci_objs = [nsg] - values_for_column_nsgs = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_nsgs,values_for_column_nsgs) + values_for_column_nsgs = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_nsgs,values_for_column_nsgs) tf_resource = f'module.nsgs[\\"{tf_name}\\"].oci_core_network_security_group.network_security_group' if tf_import_cmd and tf_resource not in state["resources"]: importCommands[region.lower()] += f'\n{tf_or_tofu} import "{tf_resource}" {str(nsg.id)}' @@ -197,7 +198,7 @@ def export_nsg(inputfile, outdir, service_dir,config,signer, ct, export_compartm for reg in export_regions: - config.__setitem__("region", commonTools().region_dict[reg]) + config.__setitem__("region", ociCommonTools().region_dict[reg]) state = {'path': f'{outdir}/{reg}/{service_dir}', 'resources': []} try: byteOutput = sp.check_output(tf_state_list, cwd=state["path"],stderr=sp.DEVNULL) diff --git a/cd3_automation_toolkit/Network/BaseNetwork/exportRoutetable.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportRoutetable.py similarity index 96% rename from cd3_automation_toolkit/Network/BaseNetwork/exportRoutetable.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportRoutetable.py index 4e1e3b9f2..b847ee36b 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/exportRoutetable.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportRoutetable.py @@ -5,8 +5,10 @@ from oci.core.virtual_network_client import VirtualNetworkClient import os import subprocess as sp -sys.path.append(os.getcwd()+"/../../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def get_network_entity_name(config,signer,network_identity_id,export_tags): vcn1 = VirtualNetworkClient(config=config, retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY,signer=signer) @@ -204,8 +206,8 @@ def insert_values(routetable,values_for_column,region,comp_name,name,routerule,e values_for_column[col_header].append(comp_name) elif (col_header == "VCN Name"): values_for_column[col_header].append(name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(routetable, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(routetable, col_header, values_for_column) elif (routerule != None and col_header == 'Route Destination Object'): network_entity_id = routerule.network_entity_id @@ -226,7 +228,7 @@ def insert_values(routetable,values_for_column,region,comp_name,name,routerule,e values_for_vcninfo['onprem_destinations'].append(routerule.destination) else: oci_objs = [routetable,routerule] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) def insert_values_drg(routetable,import_drg_route_distribution_name,values_for_column_drg,region,comp_name,name,routerule,export_tags): @@ -239,8 +241,8 @@ def insert_values_drg(routetable,import_drg_route_distribution_name,values_for_c values_for_column_drg[col_header].append(name) elif (col_header == "Import DRG Route Distribution Name"): values_for_column_drg[col_header].append(import_drg_route_distribution_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_drg = commonTools.export_tags(routetable, col_header, values_for_column_drg) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_drg = ociCommonTools.export_tags(routetable, col_header, values_for_column_drg) elif (routerule != None and col_header == 'Next Hop Attachment'): next_hop_attachment_id=routerule.next_hop_drg_attachment_id @@ -253,7 +255,7 @@ def insert_values_drg(routetable,import_drg_route_distribution_name,values_for_c else: oci_objs = [routetable,routerule] - values_for_column_drg = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_drg,values_for_column_drg) + values_for_column_drg = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_drg,values_for_column_drg) @@ -373,7 +375,7 @@ def export_drg_routetable(inputfile, outdir, service_dir,config1,signer1, ct, ex drgv2=parseDRGs(cd3file) for reg in export_regions: - config.__setitem__("region", commonTools().region_dict[reg]) + config.__setitem__("region", ociCommonTools().region_dict[reg]) state = {'path': f'{outdir}/{reg}/{service_dir}', 'resources': []} try: byteOutput = sp.check_output(tf_state_list, cwd=state["path"],stderr=sp.DEVNULL) @@ -473,7 +475,7 @@ def export_drg_routetable(inputfile, outdir, service_dir,config1,signer1, ct, ex drg_rt_name = drg_display_name + "_" + drg_route_table_name drg_rt_tf_name = commonTools.check_tf_variable(drg_rt_name) if tf_import_cmd_drg: - if drg_route_table_name not in commonTools.drg_auto_RTs: + if drg_route_table_name not in ociCommonTools.drg_auto_RTs: tf_resource = f'module.drg-route-tables[\\"{drg_rt_tf_name}\\"].oci_core_drg_route_table.drg_route_table' if tf_resource not in state["resources"]: importCommands_drg[reg] += f'\n{tf_or_tofu} import "{tf_resource}" {drg_route_table_id}' @@ -552,7 +554,7 @@ def export_routetable(inputfile, outdir, service_dir,config1,signer1, ct, export export_compartment_ids.append(ct.ntk_compartment_ids[comp]) for reg in export_regions: - config.__setitem__("region", commonTools().region_dict[reg]) + config.__setitem__("region", ociCommonTools().region_dict[reg]) state = {'path': f'{outdir}/{reg}/{service_dir}', 'resources': []} try: byteOutput = sp.check_output(tf_state_list, cwd=state["path"],stderr=sp.DEVNULL) diff --git a/cd3_automation_toolkit/Network/BaseNetwork/exportSeclist.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportSeclist.py similarity index 93% rename from cd3_automation_toolkit/Network/BaseNetwork/exportSeclist.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportSeclist.py index a53685440..eeb7466af 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/exportSeclist.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/exportSeclist.py @@ -5,8 +5,10 @@ from oci.core.virtual_network_client import VirtualNetworkClient import os import subprocess as sp -sys.path.append(os.getcwd()+"/../../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def convertNullToNothing(input): EMPTY_STRING = "" @@ -39,10 +41,10 @@ def insert_values(values_for_column,oci_objs, region, comp_name, vcn_name, rulet values_for_column[col_header].append(icmptype) elif (col_header == "ICMPCode"): values_for_column[col_header].append(icmpcode) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(oci_objs[0], col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(oci_objs[0], col_header, values_for_column) else: - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) def print_secrules(seclists,region,vcn_name,comp_name,export_tags,state): @@ -193,6 +195,16 @@ def print_secrules(seclists,region,vcn_name,comp_name,export_tags,state): printstr= (dn + ",ingress,icmp," + str(rule.is_stateless) + "," + rule.source + ",,,,,," + type + "," + code+","+desc) insert_values(values_for_column,oci_objs,region, comp_name, vcn_name, 'ingress', 'icmp', '', '','', '', type, code) + elif rule.protocol == "58": + if rule.icmp_options is None: + printstr= (dn + ",ingress,ipv6-icmp," + str(rule.is_stateless) + "," + rule.source + ",,,,,,,,"+desc) + insert_values(values_for_column,oci_objs,region, comp_name, vcn_name, 'ingress', 'ipv6-icmp','', '', '','', '', '') + else: + code = convertNullToNothing(rule.icmp_options.code) + type = convertNullToNothing(rule.icmp_options.type) + printstr= (dn + ",ingress,ipv6-icmp," + str(rule.is_stateless) + "," + rule.source + ",,,,,," + type + "," + code+","+desc) + insert_values(values_for_column,oci_objs,region, comp_name, vcn_name, 'ingress', 'ipv6-icmp', '', '','', '', type, code) + elif rule.protocol == "17": if rule.udp_options is None: printstr= (dn + ",ingress,udp," + str(rule.is_stateless) + "," + rule.source + ",,,,,,,,"+desc) @@ -266,7 +278,7 @@ def export_seclist(inputfile, outdir, service_dir,config,signer, ct, export_comp vcns_check = parseVCNs(cd3file) for reg in export_regions: - config.__setitem__("region", commonTools().region_dict[reg]) + config.__setitem__("region", ociCommonTools().region_dict[reg]) state = {'path': f'{outdir}/{reg}/{service_dir}', 'resources': []} try: byteOutput = sp.check_output(tf_state_list, cwd=state["path"],stderr=sp.DEVNULL) diff --git a/cd3_automation_toolkit/Network/BaseNetwork/export_network_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/export_network_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Network/BaseNetwork/export_network_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/export_network_nonGreenField.py index 49fdf86be..e0bbfd5b0 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/export_network_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/export_network_nonGreenField.py @@ -11,8 +11,9 @@ import subprocess as sp from pathlib import Path -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} importCommands_dhcp = {} @@ -93,11 +94,11 @@ def print_drgv2(values_for_column_drgv2, region, comp_name, vcn_info, drg_info, else: statement_val = statement_val + "\n" + "ALL::::" + str(priority) + "\n" values_for_column_drgv2[col_header].append(statement_val) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_drgv2 = commonTools.export_tags(drg_info, col_header, values_for_column_drgv2) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_drgv2 = ociCommonTools.export_tags(drg_info, col_header, values_for_column_drgv2) else: oci_objs = [drg_info, drg_attachment_info, drg_rt_info, import_drg_route_distribution_info] - values_for_column_drgv2 = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_drgv2, + values_for_column_drgv2 = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_drgv2, values_for_column_drgv2) @@ -173,11 +174,11 @@ def print_vcns(values_for_column_vcns, region, comp_name, vnc, vcn_info, drg_att values_for_column_vcns[col_header].append(value) elif (col_header == "Hub/Spoke/Peer/None"): values_for_column_vcns[col_header].append("exported") - elif col_header.lower() in commonTools.tagColumns: - values_for_column_vcns = commonTools.export_tags(vcn_info, col_header, values_for_column_vcns) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_vcns = ociCommonTools.export_tags(vcn_info, col_header, values_for_column_vcns) else: oci_objs = [vcn_info, drg_info, igw_info, ngw_info, sgw_info] - values_for_column_vcns = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_vcns, + values_for_column_vcns = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_vcns, values_for_column_vcns) tf_name = commonTools.check_tf_variable(vcn_info.display_name) @@ -221,10 +222,10 @@ def print_dhcp(values_for_column_dhcp, region, comp_name, vcn_name, dhcp_info, s values_for_column_dhcp[col_header].append(search_domain_names_str) elif (col_header == "Custom DNS Server"): values_for_column_dhcp[col_header].append(custom_dns_servers_str) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_dhcp = commonTools.export_tags(dhcp_info, col_header, values_for_column_dhcp) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_dhcp = ociCommonTools.export_tags(dhcp_info, col_header, values_for_column_dhcp) else: - values_for_column_dhcp = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_dhcp, + values_for_column_dhcp = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_dhcp, values_for_column_dhcp) if ("Default DHCP Options for " in dhcp_info.display_name): tf_resource = f'module.default-dhcps[\\"{tf_name}\\"].oci_core_default_dhcp_options.default_dhcp_option' @@ -323,12 +324,12 @@ def print_subnets_vlans(values_for_column_subnets_vlans, region, comp_name, vcn_ values_for_column_subnets_vlans[col_header].append(value) elif subnet_vlan_in_excel == 'VLAN': values_for_column_subnets_vlans[col_header].append("") - elif col_header.lower() in commonTools.tagColumns: - values_for_column_subnets_vlans = commonTools.export_tags(subnet_vlan_info, col_header, + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_subnets_vlans = ociCommonTools.export_tags(subnet_vlan_info, col_header, values_for_column_subnets_vlans) else: oci_objs = [subnet_vlan_info] - values_for_column_subnets_vlans = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_subnets_vlans = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_subnets_vlans, values_for_column_subnets_vlans) @@ -536,12 +537,12 @@ def get_comp_details(comp_data): statement_val = statement_val + "\n" + "ALL::::" + str(priority) + "\n" values_for_column[col_header].append(statement_val) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(drg_info, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(drg_info, col_header, values_for_column) else: oci_objs = [new_rpc, drg_info, drg_attachment_info, src_drg_rt_dist, src_drg_rt_dist_info] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # add target region entries to xl.should be ignored during create cal. @@ -586,13 +587,13 @@ def get_comp_details(comp_data): statement_val = statement_val + "\n" + "ALL::::" + str(priority) + "\n" values_for_column[col_header].append(statement_val) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(dest_drg_info, col_header, + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(dest_drg_info, col_header, values_for_column) else: oci_objs = [new_rpc, dest_drg_info, dest_drg_rt_dist, dest_drg_rt_dist_info] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # print(values_for_column) @@ -811,7 +812,7 @@ def export_major_objects(inputfile, outdir, service_dir, config, signer, ct, exp tf_name = commonTools.check_tf_variable( drg_display_name + "_" + import_drg_route_distribution_info.display_name) if ( - import_drg_route_distribution_info.display_name not in commonTools.drg_auto_RDs and "ocid1.drg.oc" not in drg_display_name): + import_drg_route_distribution_info.display_name not in ociCommonTools.drg_auto_RDs and "ocid1.drg.oc" not in drg_display_name): tf_resource = f'module.drg-route-distributions[\\"{tf_name}\\"].oci_core_drg_route_distribution.drg_route_distribution' if tf_resource not in state["resources"]: importCommands[reg].write( @@ -853,7 +854,7 @@ def export_major_objects(inputfile, outdir, service_dir, config, signer, ct, exp tf_name = commonTools.check_tf_variable( drg_display_name + "_" + import_drg_route_distribution_info.display_name) if ( - import_drg_route_distribution_info.display_name not in commonTools.drg_auto_RDs and write_drg_ocids == False): + import_drg_route_distribution_info.display_name not in ociCommonTools.drg_auto_RDs and write_drg_ocids == False): tf_resource = f'module.drg-route-distributions[\\"{tf_name}\\"].oci_core_drg_route_distribution.drg_route_distribution' if tf_resource not in state["resources"]: importCommands[reg].write( @@ -923,7 +924,7 @@ def export_major_objects(inputfile, outdir, service_dir, config, signer, ct, exp tf_name = commonTools.check_tf_variable( drg_display_name + "_" + import_drg_route_distribution_info.display_name) - if (import_drg_route_distribution_info.display_name not in commonTools.drg_auto_RDs): + if (import_drg_route_distribution_info.display_name not in ociCommonTools.drg_auto_RDs): tf_resource = f'module.drg-route-distributions[\\"{tf_name}\\"].oci_core_drg_route_distribution.drg_route_distribution' if tf_resource not in state["resources"]: importCommands[reg].write( diff --git a/cd3_automation_toolkit/Network/BaseNetwork/export_seclist_to_tf.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/export_seclist_to_tf.py similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/export_seclist_to_tf.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/export_seclist_to_tf.py diff --git a/cd3_automation_toolkit/Network/BaseNetwork/modify_routerules_tf.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_routerules_tf.py similarity index 96% rename from cd3_automation_toolkit/Network/BaseNetwork/modify_routerules_tf.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_routerules_tf.py index 5b92a9e00..2b1d733d6 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/modify_routerules_tf.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_routerules_tf.py @@ -13,9 +13,11 @@ import os from oci.config import DEFAULT_LOCATION from pathlib import Path -sys.path.append(os.getcwd()+"/../../..") -from commonTools import * from jinja2 import Environment, FileSystemLoader +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Takes in input CD3 excel which contains routerules to be updated for the subnet and updates the routes tf file created using BaseNetwork TF generation. @@ -105,7 +107,7 @@ def modify_terraform_drg_routerules(inputfile, outdir, service_dir,prefix, ct, n continue # Process RTs only for those Import DRG Route Distribution Names which are present in cd3(and have been created via TF) - if (DRG_RD_Name not in drgv2.drg_rds[DRG_Name,region] and DRG_RD_Name.lower()!='nan' and DRG_RD_Name not in commonTools.drg_auto_RDs): + if (DRG_RD_Name not in drgv2.drg_rds[DRG_Name,region] and DRG_RD_Name.lower()!='nan' and DRG_RD_Name not in ociCommonTools.drg_auto_RDs): print("skipping DRG route table: " + str(df.loc[i, 'DRG RT Name']) + " as either its DRG is not part of DRGv2 tab in cd3 or its Import Route Distribution Name is not attached to DRG "+ DRG_Name+" as per DRGv2 tab in cd3") continue @@ -132,8 +134,8 @@ def modify_terraform_drg_routerules(inputfile, outdir, service_dir,prefix, ct, n tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) tempStr.update(tempdict) @@ -151,7 +153,7 @@ def modify_terraform_drg_routerules(inputfile, outdir, service_dir,prefix, ct, n if(columnname == "Import DRG Route Distribution Name"): - if columnvalue in commonTools.drg_auto_RDs: + if columnvalue in ociCommonTools.drg_auto_RDs: drg_rt_dstrb_tf_name = commonTools.check_tf_variable(drg_name + "_" + columnvalue) drg_rt_dstrb_res_name = drg_rt_dstrb_tf_name elif columnvalue!='': @@ -187,7 +189,7 @@ def modify_terraform_drg_routerules(inputfile, outdir, service_dir,prefix, ct, n if(len(rts_done[region])==0): k=1 #Create RT resource only if it is not Auto Generated one - if (DRG_RT not in commonTools.drg_auto_RTs): + if (DRG_RT not in ociCommonTools.drg_auto_RTs): tfStrRT[region] = tfStrRT[region] + routetable_drg.render(tempStr) rts_done[region].append(drg_rt_tf_name) @@ -195,7 +197,7 @@ def modify_terraform_drg_routerules(inputfile, outdir, service_dir,prefix, ct, n rts_done[region].append(drg_rt_tf_name) # Create RT resource only if it is not Auto Generated one - if (DRG_RT not in commonTools.drg_auto_RTs): + if (DRG_RT not in ociCommonTools.drg_auto_RTs): tfStrRT[region] = tfStrRT[region] + routetable_drg.render(tempStr) k=1 @@ -392,7 +394,11 @@ def generate_route_table_string(region_rt_name,region,routetableStr,tempStr,comm for columnname in dfcolumns: # Column value - columnvalue = str(df[columnname][i]).strip() + if (columnname != 'Rule Description'): + columnvalue = str(df[columnname][i]).strip() + else: + columnvalue = str(df[columnname][i]) + # Check for boolean/null in column values columnvalue = commonTools.check_columnvalue(columnvalue) @@ -401,8 +407,8 @@ def generate_route_table_string(region_rt_name,region,routetableStr,tempStr,comm tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) tempStr.update(tempdict) if columnname == 'Compartment Name': @@ -434,7 +440,7 @@ def generate_route_table_string(region_rt_name,region,routetableStr,tempStr,comm tempStr.update(tempdict) if columnname == 'Rule Description': - description = columnvalue.strip() + description = columnvalue if description == 'nan': description = "" tempdict = {'description': description} diff --git a/cd3_automation_toolkit/Network/BaseNetwork/modify_secrules_tf.py b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_secrules_tf.py similarity index 96% rename from cd3_automation_toolkit/Network/BaseNetwork/modify_secrules_tf.py rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_secrules_tf.py index 4ce712ce5..9e5226cd3 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/modify_secrules_tf.py +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/modify_secrules_tf.py @@ -15,8 +15,11 @@ from oci.config import DEFAULT_LOCATION from pathlib import Path from jinja2 import Environment, FileSystemLoader -sys.path.append(os.getcwd() + "/../../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +from ocicloud.python.ociCommonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools + # Execution of the code begins here def modify_terraform_secrules(inputfile, outdir, service_dir,prefix, ct, non_gf_tenancy): @@ -164,8 +167,8 @@ def generate_security_rules(region_seclist_name,processed_seclist,tfStr,region,t tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'SecList Name': display_name = columnvalue.strip() @@ -221,4 +224,5 @@ def generate_security_rules(region_seclist_name,processed_seclist,tfStr,region,t print(default_outfile + " for default seclist has been created for region " + reg) - os.remove('out.csv') + if os.path.exists('out.csv'): + os.remove('out.csv') diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/custom-dhcp-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/custom-dhcp-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/custom-dhcp-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/custom-dhcp-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/default-route-table-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/default-route-table-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/default-route-table-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/default-route-table-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/default-seclist-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/default-seclist-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/default-seclist-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/default-seclist-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/drg-data-source-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-data-source-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/drg-data-source-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-data-source-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-distribution-statement-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-distribution-statement-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-distribution-statement-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-distribution-statement-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-distribution-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-distribution-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-distribution-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-distribution-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-rule-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-rule-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-rule-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-rule-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-table-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-table-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/drg-route-table-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/drg-route-table-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-default-dhcp-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-default-dhcp-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-default-dhcp-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-default-dhcp-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-drg-attachments-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-drg-attachments-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-drg-attachments-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-drg-attachments-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-drgs-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-drgs-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-drgs-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-drgs-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-igws-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-igws-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-igws-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-igws-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-lpgs-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-lpgs-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-lpgs-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-lpgs-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-ngws-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-ngws-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-ngws-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-ngws-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-sgws-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-sgws-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-sgws-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-sgws-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-vcns-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-vcns-template similarity index 88% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-vcns-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-vcns-template index cc99e8415..3febe5d07 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/templates/major-objects-vcns-template +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/major-objects-vcns-template @@ -33,14 +33,20 @@ vcns = { {% endif %} {% if byoipv6cidr_details and byoipv6cidr_details != [] %} - byoipv6cidr_details = [{ - byoipv6range_id = "{{ byoipv6range_id }}" - ipv6cidr_block = "{{ ipv6cidr_block }}" - }] + byoipv6cidr_details = [ + {% for item in byoipv6cidr_details %} + {% set last_index = item.rfind('@') %} + {% if last_index != -1 %} + { + byoipv6range_data = item[:last_index] + ipv6cidr_block = item[last_index+1:] + } + {% endif %} + {% endfor %}] {% endif %} {% if ipv6private_cidr_blocks and ipv6private_cidr_blocks != [] %} - ipv6private_cidr_blocks = [ "{{ ipv6private_cidr_blocks }}" ] + ipv6private_cidr_blocks = {{ ipv6private_cidr_blocks }} {% endif %} {% if is_oracle_gua_allocation_enabled and is_oracle_gua_allocation_enabled != "" %} diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/nsg-rule-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/nsg-rule-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/nsg-rule-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/nsg-rule-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/nsg-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/nsg-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/nsg-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/nsg-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/route-rule-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/route-rule-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/route-rule-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/route-rule-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/route-table-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/route-table-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/route-table-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/route-table-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/sec-rule-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/sec-rule-template similarity index 99% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/sec-rule-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/sec-rule-template index f0a04c83b..9654612a3 100644 --- a/cd3_automation_toolkit/Network/BaseNetwork/templates/sec-rule-template +++ b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/sec-rule-template @@ -20,7 +20,7 @@ {% if protocol.lower() == "all" %} all = [] - {% elif protocol.lower() == 'icmp' %} + {% elif 'icmp' in protocol.lower() %} {% if icmptype != '' or icmpcode != '' %} icmp = [{ {% if icmptype != '' %} diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/seclist-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/seclist-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/seclist-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/seclist-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/subnet-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/subnet-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/subnet-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/subnet-template diff --git a/cd3_automation_toolkit/Network/BaseNetwork/templates/vlan-template b/cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/vlan-template similarity index 100% rename from cd3_automation_toolkit/Network/BaseNetwork/templates/vlan-template rename to cd3_automation_toolkit/ocicloud/python/network/basenetwork/templates/vlan-template diff --git a/cd3_automation_toolkit/Network/DNS/__init__.py b/cd3_automation_toolkit/ocicloud/python/network/dns/__init__.py similarity index 100% rename from cd3_automation_toolkit/Network/DNS/__init__.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/__init__.py diff --git a/cd3_automation_toolkit/Network/DNS/create_dns_resolvers.py b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_resolvers.py similarity index 97% rename from cd3_automation_toolkit/Network/DNS/create_dns_resolvers.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_resolvers.py index 3f7e70fe0..bb743d4be 100644 --- a/cd3_automation_toolkit/Network/DNS/create_dns_resolvers.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_resolvers.py @@ -5,11 +5,13 @@ # DNS-Resolvers # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -285,8 +287,8 @@ def create_terraform_dns_resolvers(inputfile, outdir, service_dir, prefix, ct): tempdict = {'res_resolver_rules': res_rules} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) columnname = commonTools.check_column_headers(columnname) tempStr[columnname] = str(columnvalue).strip() diff --git a/cd3_automation_toolkit/Network/DNS/create_dns_rrsets.py b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_rrsets.py similarity index 97% rename from cd3_automation_toolkit/Network/DNS/create_dns_rrsets.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_rrsets.py index 5fb822620..2f72d1ee9 100644 --- a/cd3_automation_toolkit/Network/DNS/create_dns_rrsets.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_rrsets.py @@ -5,11 +5,13 @@ # DNS-RRset # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### diff --git a/cd3_automation_toolkit/Network/DNS/create_dns_views.py b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_views.py similarity index 94% rename from cd3_automation_toolkit/Network/DNS/create_dns_views.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_views.py index 4532df824..eaab6f006 100644 --- a/cd3_automation_toolkit/Network/DNS/create_dns_views.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_views.py @@ -4,11 +4,13 @@ # This script will produce a Terraform file that will be used to set up OCI core components # DNS-Views # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -104,8 +106,8 @@ def create_terraform_dns_views(inputfile, outdir, service_dir, prefix, ct): tempdict = {'view_display_name': display_tf_name} # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) columnname = commonTools.check_column_headers(columnname) tempStr[columnname] = str(columnvalue).strip() diff --git a/cd3_automation_toolkit/Network/DNS/create_dns_zones.py b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_zones.py similarity index 94% rename from cd3_automation_toolkit/Network/DNS/create_dns_zones.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_zones.py index 54af6b0b7..e09cc3d52 100644 --- a/cd3_automation_toolkit/Network/DNS/create_dns_zones.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/create_dns_zones.py @@ -4,11 +4,13 @@ # This script will produce a Terraform file that will be used to set up OCI core components # DNS-Zones # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -99,8 +101,8 @@ def create_terraform_dns_zones(inputfile, outdir, service_dir, prefix, ct): tempdict = {'zone_compartment_name': columnvalue}""" # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Zone': tempdict = {'display_name': zone_name} diff --git a/cd3_automation_toolkit/Network/DNS/export_dns_resolvers.py b/cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_resolvers.py similarity index 97% rename from cd3_automation_toolkit/Network/DNS/export_dns_resolvers.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_resolvers.py index da22d814d..2a3c481a9 100644 --- a/cd3_automation_toolkit/Network/DNS/export_dns_resolvers.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_resolvers.py @@ -5,15 +5,15 @@ # Export DNS Resolvers # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools + importCommands = {} oci_obj_names = {} - - - # Create map for each endpoint def get_e_map(region, dns_client, vnc_client, ct, resolver, ntk_compartment_name): vcn_name = vnc_client.get_vcn(resolver.attached_vcn_id).data.display_name @@ -133,8 +133,10 @@ def print_resolvers(resolver_tf_name, resolver, values_for_column,state, **value values_for_column[col_header].append(endpoint_value['e_nsgs']) elif col_header == 'Rules': values_for_column[col_header].append(endpoint_value['res_rule_detail']) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(resolver, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(resolver, col_header, values_for_column) + + # Execution of the code begins here def export_dns_resolvers(inputfile, outdir, service_dir, config, signer, ct, export_compartments=[], export_regions=[],export_tags=[]): diff --git a/cd3_automation_toolkit/Network/DNS/export_dns_views_zones_records.py b/cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_views_zones_records.py similarity index 94% rename from cd3_automation_toolkit/Network/DNS/export_dns_views_zones_records.py rename to cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_views_zones_records.py index 961dff9d7..5ad3e1844 100644 --- a/cd3_automation_toolkit/Network/DNS/export_dns_views_zones_records.py +++ b/cd3_automation_toolkit/ocicloud/python/network/dns/export_dns_views_zones_records.py @@ -5,9 +5,11 @@ # Export DNS views-zones-rrsets # import oci -import os +import os, sys import subprocess as sp -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -71,8 +73,8 @@ def print_data(region, ntk_compartment_name, rrset, zone_data, view_data, values values_for_column[col_header].append(rrset['rdata']) elif col_header == 'TTL': values_for_column[col_header].append(rrset['ttl']) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(view_data, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(view_data, col_header, values_for_column) def print_empty_view(region, ntk_compartment_name, view_data, values_for_column,zone_name=""): @@ -94,8 +96,8 @@ def print_empty_view(region, ntk_compartment_name, view_data, values_for_column, values_for_column[col_header].append("") elif col_header == 'TTL': values_for_column[col_header].append("") - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(view_data, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(view_data, col_header, values_for_column) # Execution of the code begins here def export_dns_views_zones_rrsets(inputfile, outdir, service_dir, config, signer, ct, dns_filter, export_compartments=[], export_regions=[],export_tags=[]): @@ -225,8 +227,8 @@ def export_dns_views_zones_rrsets(inputfile, outdir, service_dir, config, signer else: print_empty_view(region, ntk_compartment_name, view_data, values_for_column) - if print_zone==False: - print_empty_view(region, ntk_compartment_name, view_data, values_for_column) + # if print_zone==False: + # print_empty_view(region, ntk_compartment_name, view_data, values_for_column) tf_resource = f'module.dns-views[\\"{view_tf_name}\\"].oci_dns_view.view' if tf_resource not in state["resources"]: diff --git a/cd3_automation_toolkit/Network/DNS/templates/dns-records-template b/cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-records-template similarity index 100% rename from cd3_automation_toolkit/Network/DNS/templates/dns-records-template rename to cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-records-template diff --git a/cd3_automation_toolkit/Network/DNS/templates/dns-resolvers-template b/cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-resolvers-template similarity index 100% rename from cd3_automation_toolkit/Network/DNS/templates/dns-resolvers-template rename to cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-resolvers-template diff --git a/cd3_automation_toolkit/Network/DNS/templates/dns-views-template b/cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-views-template similarity index 100% rename from cd3_automation_toolkit/Network/DNS/templates/dns-views-template rename to cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-views-template diff --git a/cd3_automation_toolkit/Network/DNS/templates/dns-zones-template b/cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-zones-template similarity index 100% rename from cd3_automation_toolkit/Network/DNS/templates/dns-zones-template rename to cd3_automation_toolkit/ocicloud/python/network/dns/templates/dns-zones-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/__init__.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/__init__.py similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/__init__.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/__init__.py diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_backendset_backendservers.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_backendset_backendservers.py similarity index 97% rename from cd3_automation_toolkit/Network/LoadBalancers/create_backendset_backendservers.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_backendset_backendservers.py index ae6bf8e0a..ca5f95b31 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_backendset_backendservers.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_backendset_backendservers.py @@ -11,8 +11,11 @@ import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -105,8 +108,8 @@ def create_backendset_backendservers(inputfile, outdir, service_dir, prefix, ct) tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = "compartment_tf_name" diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_listener.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_listener.py similarity index 96% rename from cd3_automation_toolkit/Network/LoadBalancers/create_listener.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_listener.py index 5568b75e9..897346011 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_listener.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_listener.py @@ -11,8 +11,11 @@ import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -101,8 +104,8 @@ def create_listener(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "LBR Name": lbr_tf_name = commonTools.check_tf_variable(columnvalue) diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_nlb_backendset_backendservers.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_nlb_backendset_backendservers.py similarity index 94% rename from cd3_automation_toolkit/Network/LoadBalancers/create_nlb_backendset_backendservers.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_nlb_backendset_backendservers.py index 3a957137b..c304874d4 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_nlb_backendset_backendservers.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_nlb_backendset_backendservers.py @@ -9,8 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -81,8 +84,8 @@ def create_nlb_backendset_backendservers(inputfile, outdir, service_dir, prefix, backend_set_tf_name = '' #Check if mandatory field is empty - if (str(df.loc[i,'Backend Set Name']).lower() == 'nan' or str(df.loc[i,'Backend HealthCheck Port']).lower() == 'nan'): - print("\nColumn Backend Set Name or Backend HealthCheck Port cannot be left empty.....Exiting!") + if (str(df.loc[i,'Backend Set Name']).lower() == 'nan'): + print("\nColumn Backend Set Name cannot be left empty.....Exiting!") exit(1) # Fetch data; loop through columns @@ -98,8 +101,8 @@ def create_nlb_backendset_backendservers(inputfile, outdir, service_dir, prefix, tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = "compartment_tf_name" diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_path_route_set.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_path_route_set.py similarity index 95% rename from cd3_automation_toolkit/Network/LoadBalancers/create_path_route_set.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_path_route_set.py index f84290270..3a186d685 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_path_route_set.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_path_route_set.py @@ -10,8 +10,11 @@ import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -101,8 +104,8 @@ def create_path_route_set(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "LBR Name": lbr_tf_name = commonTools.check_tf_variable(columnvalue) diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_routing_policy.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_routing_policy.py similarity index 94% rename from cd3_automation_toolkit/Network/LoadBalancers/create_routing_policy.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_routing_policy.py index 09851538f..b6fac148f 100755 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_routing_policy.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_routing_policy.py @@ -11,7 +11,10 @@ import pandas as pd from jinja2 import Environment, FileSystemLoader from pathlib import Path -from commonTools import * +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools @@ -93,8 +96,8 @@ def create_lb_routing_policy(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "LBR Name": lbr_tf_name = commonTools.check_tf_variable(columnvalue) diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_ruleset.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_ruleset.py similarity index 97% rename from cd3_automation_toolkit/Network/LoadBalancers/create_ruleset.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_ruleset.py index 55133f6f3..7fa339596 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_ruleset.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_ruleset.py @@ -12,8 +12,11 @@ import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -190,8 +193,8 @@ def add_rules(df,rs_str,tempStr,control_access): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'Allow Invalid Characters (TRUE|FALSE)': columnname = 'allow_invalid_characters' diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_terraform_lbr_hostname_certs.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_lbr_hostname_certs.py similarity index 97% rename from cd3_automation_toolkit/Network/LoadBalancers/create_terraform_lbr_hostname_certs.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_lbr_hostname_certs.py index e320c3765..4f405bd8f 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_terraform_lbr_hostname_certs.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_lbr_hostname_certs.py @@ -14,8 +14,11 @@ import pandas as pd from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -110,8 +113,8 @@ def certificate_templates(dfcert): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "LBR Name": lbr_tf_name = commonTools.check_tf_variable(columnvalue) @@ -221,8 +224,8 @@ def certificate_templates(dfcert): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Is Private(True|False)": columnname = 'is_private' diff --git a/cd3_automation_toolkit/Network/LoadBalancers/create_terraform_nlb_listener.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_nlb_listener.py similarity index 97% rename from cd3_automation_toolkit/Network/LoadBalancers/create_terraform_nlb_listener.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_nlb_listener.py index d6d5406ff..2cb3ea257 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/create_terraform_nlb_listener.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/create_terraform_nlb_listener.py @@ -9,8 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -111,8 +114,8 @@ def create_terraform_nlb_listener(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = "compartment_tf_name" diff --git a/cd3_automation_toolkit/Network/LoadBalancers/export_lbr_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_lbr_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Network/LoadBalancers/export_lbr_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_lbr_nonGreenField.py index c31fc16b0..129df2e87 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/export_lbr_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_lbr_nonGreenField.py @@ -16,8 +16,9 @@ from oci.core.virtual_network_client import VirtualNetworkClient from oci.load_balancer.load_balancer_client import LoadBalancerClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -135,10 +136,10 @@ def insert_values(values_for_column, oci_objs, sheet_dict, region, comp_name, di values_for_column[col_header].append(minimum_bandwidth_in_mbps) elif col_header == 'Maximum Bandwidth In Mbps (Flexible shapes only)': values_for_column[col_header].append(maximum_bandwidth_in_mbps) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(oci_objs[0], col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(oci_objs[0], col_header, values_for_column) else: - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) def print_lbr_hostname_certs(region, ct, outdir, values_for_column_lhc, lbr, LBRs, lbr_compartment_name, export_tags, network, @@ -523,8 +524,8 @@ def print_backendset_backendserver(region, ct, values_for_column_bss, lbr, LBRs, sheet_dict_common, lbr_compartment_name) # Process the Tag Columns - elif headers_lower in commonTools.tagColumns: - values_for_column_bss = commonTools.export_tags(eachlbr, col_headers, values_for_column_bss) + elif headers_lower in ociCommonTools.tagColumns: + values_for_column_bss = ociCommonTools.export_tags(eachlbr, col_headers, values_for_column_bss) elif col_headers == 'SSL Protocols': protocols_list = '' @@ -595,14 +596,14 @@ def print_backendset_backendserver(region, ct, values_for_column_bss, lbr, LBRs, else: oci_objs = [backendset_details, eachlbr, hc, certificate_list] - values_for_column_bss = commonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_bss, + values_for_column_bss = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_bss, values_for_column_bss) else: if "Cookie" not in col_headers: # Process the remaining Columns oci_objs = [backendset_details, eachlbr, hc, certificate_list] - values_for_column_bss = commonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_bss, + values_for_column_bss = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_bss, values_for_column_bss) return values_for_column_bss @@ -696,8 +697,8 @@ def print_listener(region, ct, values_for_column_lis, LBRs, lbr_compartment_name sheet_dict_common, lbr_compartment_name) # Process the Tag Columns - elif headers_lower in commonTools.tagColumns: - values_for_column_lis = commonTools.export_tags(eachlbr, col_headers, values_for_column_lis) + elif headers_lower in ociCommonTools.tagColumns: + values_for_column_lis = ociCommonTools.export_tags(eachlbr, col_headers, values_for_column_lis) # Process the Listerner Columns elif col_headers in sheet_dict_lis.keys(): @@ -732,12 +733,12 @@ def print_listener(region, ct, values_for_column_lis, LBRs, lbr_compartment_name else: oci_objs = [values, eachlbr, sslcerts] - values_for_column_lis = commonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_lis, + values_for_column_lis = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_lis, values_for_column_lis) else: oci_objs = [eachlbr, values, sslcerts] - values_for_column_lis = commonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_lis, + values_for_column_lis = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_lis, values_for_column_lis) return values_for_column_lis @@ -869,7 +870,7 @@ def print_rule(region, ct, values_for_column_rule, LBRs, lbr_compartment_name,ex pass else: oci_objs = [eachlbr, eachitem] - values_for_column_rule = commonTools.export_extra_columns(oci_objs, col_headers, + values_for_column_rule = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_rule, values_for_column_rule) @@ -933,7 +934,7 @@ def print_prs(region, ct, values_for_column_prs, LBRs, lbr_compartment_name,expo else: # Process the remaining Columns oci_objs = [eachlbr, values, path_routes] - values_for_column_prs = commonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_prs, + values_for_column_prs = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_prs, values_for_column_prs) return values_for_column_prs @@ -1015,7 +1016,7 @@ def print_routing_policies(region, ct, values_for_column_rp, LBRs, lbr_compartme else: # Process the remaining Columns oci_objs = [eachlbr, values] - values_for_column_rp = commonTools.export_extra_columns(oci_objs, col_headers, + values_for_column_rp = ociCommonTools.export_extra_columns(oci_objs, col_headers, sheet_dict_rp, values_for_column_rp) diff --git a/cd3_automation_toolkit/Network/LoadBalancers/export_nlb_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_nlb_nonGreenField.py similarity index 94% rename from cd3_automation_toolkit/Network/LoadBalancers/export_nlb_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_nlb_nonGreenField.py index df038c384..3e63a031d 100644 --- a/cd3_automation_toolkit/Network/LoadBalancers/export_nlb_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/export_nlb_nonGreenField.py @@ -15,8 +15,9 @@ from oci.core.virtual_network_client import VirtualNetworkClient from oci.network_load_balancer import NetworkLoadBalancerClient from oci.core.compute_client import ComputeClient -sys.path.append(os.getcwd()+"/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -136,9 +137,9 @@ def print_nlb_backendset_backendserver(region, values_for_column_bss,NLBs, nlb_c values_for_column_bss[col_header].append('') # Process the Tag Columns - elif col_header.lower() in commonTools.tagColumns: + elif col_header.lower() in ociCommonTools.tagColumns: if cnt_bss == 1: - values_for_column_bss = commonTools.export_tags(eachnlb, col_header, values_for_column_bss) + values_for_column_bss = ociCommonTools.export_tags(eachnlb, col_header, values_for_column_bss) else: values_for_column_bss[col_header].append('') @@ -156,7 +157,7 @@ def print_nlb_backendset_backendserver(region, values_for_column_bss,NLBs, nlb_c values_for_column_bss[col_header].append(backendsets) else: oci_objs = [eachnlb,backendset_details,hc,dns] - values_for_column_bss = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_bss,values_for_column_bss) + values_for_column_bss = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_bss,values_for_column_bss) return values_for_column_bss @@ -284,14 +285,14 @@ def print_nlb_listener(region, outdir, values_for_column_lis, NLBs, nlb_compartm values_for_column_lis[col_header].append("") # Process the Tag Columns - elif col_header.lower() in commonTools.tagColumns: + elif col_header.lower() in ociCommonTools.tagColumns: if cnt_lsnr == 1: - values_for_column_lis = commonTools.export_tags(eachnlb, col_header, values_for_column_lis) + values_for_column_lis = ociCommonTools.export_tags(eachnlb, col_header, values_for_column_lis) else: values_for_column_lis[col_header].append("") else: oci_objs = [values,eachnlb,ips] - values_for_column_lis = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_lis, values_for_column_lis) + values_for_column_lis = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_lis, values_for_column_lis) if cnt_lsnr == 0: for col_header in values_for_column_lis.keys(): @@ -310,11 +311,11 @@ def print_nlb_listener(region, outdir, values_for_column_lis, NLBs, nlb_compartm elif (col_header == "Is Private(True|False)"): values_for_column_lis[col_header].append(not(is_public)) # Process the Tag Columns - elif col_header.lower() in commonTools.tagColumns: - values_for_column_lis = commonTools.export_tags(eachnlb, col_header, values_for_column_lis) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_lis = ociCommonTools.export_tags(eachnlb, col_header, values_for_column_lis) else: oci_objs = [eachnlb,ips] - values_for_column_lis = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_lis,values_for_column_lis) + values_for_column_lis = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_lis,values_for_column_lis) return values_for_column_lis diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/access-control-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/access-control-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/access-control-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/access-control-rules-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/access-method-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/access-method-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/access-method-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/access-method-rules-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/backend-set-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/backend-set-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/backend-set-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/backend-set-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/backends-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/backends-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/backends-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/backends-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/certificate-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/certificate-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/certificate-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/certificate-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/cipher-suite-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/cipher-suite-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/cipher-suite-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/cipher-suite-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/hostname-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/hostname-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/hostname-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/hostname-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/http-header-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/http-header-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/http-header-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/http-header-rules-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/lb-routing-policy-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lb-routing-policy-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/lb-routing-policy-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lb-routing-policy-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/lbr-reserved-ips-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lbr-reserved-ips-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/lbr-reserved-ips-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lbr-reserved-ips-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/lbr-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lbr-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/lbr-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/lbr-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/listener-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/listener-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/listener-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/listener-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-backend-set-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-backend-set-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-backend-set-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-backend-set-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-backends-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-backends-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-backends-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-backends-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-listener-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-listener-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-listener-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-listener-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-reserved-ips-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-reserved-ips-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-reserved-ips-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-reserved-ips-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/nlb-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/nlb-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/path-route-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/path-route-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/path-route-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/path-route-rules-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/path-route-set-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/path-route-set-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/path-route-set-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/path-route-set-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/request-response-header-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/request-response-header-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/request-response-header-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/request-response-header-rules-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/rule-set-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/rule-set-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/rule-set-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/rule-set-template diff --git a/cd3_automation_toolkit/Network/LoadBalancers/templates/uri-redirect-rules-template b/cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/uri-redirect-rules-template similarity index 100% rename from cd3_automation_toolkit/Network/LoadBalancers/templates/uri-redirect-rules-template rename to cd3_automation_toolkit/ocicloud/python/network/loadbalancers/templates/uri-redirect-rules-template diff --git a/cd3_automation_toolkit/commonTools.py b/cd3_automation_toolkit/ocicloud/python/ociCommonTools.py similarity index 71% rename from cd3_automation_toolkit/commonTools.py rename to cd3_automation_toolkit/ocicloud/python/ociCommonTools.py index 8f35569b4..580ed0000 100644 --- a/cd3_automation_toolkit/commonTools.py +++ b/cd3_automation_toolkit/ocicloud/python/ociCommonTools.py @@ -2,40 +2,19 @@ import os import shutil import datetime -import ssl -import sys -import pathlib -import urllib.request import oci from copy import deepcopy from oci.identity import IdentityClient from oci.config import DEFAULT_LOCATION -from openpyxl import load_workbook -from openpyxl.styles import PatternFill -from openpyxl.styles import Alignment -from openpyxl.styles import Border -from openpyxl.styles import Side -from contextlib import contextmanager -import xml.etree.ElementTree as ET -import collections +from common.python.commonTools import * import re import json as simplejson import warnings -import threading warnings.simplefilter("ignore") -def data_frame(filename,sheetname): - # Read the tab from excel, Drop null values, Reset index - df, col_headers = commonTools.read_cd3(filename, sheetname) - df = df.dropna(how='all') - df = df.reset_index(drop=True) +class ociCommonTools(): - return df - - -class commonTools(): - endNames = {'', '', ''} tagColumns = {'freeform tags', 'freeform_tags', 'defined_tags', 'defined tags', 'vnic defined tags','vnic_defined_tags', 'vnic freeform tags', 'vnic_freeform_tags', 'oke_labels', 'oke labels', 'nodepool defined tags', 'nodepool_defined_tags', 'node defined tags', @@ -111,6 +90,9 @@ def __init__(self): dir=os.getcwd() if ("OCSWorkVM" in os.getcwd() or 'user-scripts' in os.getcwd()): os.chdir("../") + dir = os.getcwd() + if("ocicloud/python" not in dir): + os.chdir("ocicloud/python") regionFileName="OCI_Regions" protocolFileName="OCI_Protocols" excelColumnName="Excel_Columns" @@ -470,7 +452,6 @@ def identity_domain_check(self,config, signer): def get_identity_domain_data(self,config, signer, resource,var_file): - config.__setitem__("region",self.region_dict[self.home_region]) selected_domains_data = {} idc = IdentityClient(config=config, retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY, signer=signer) @@ -500,23 +481,6 @@ def get_identity_domain_data(self,config, signer, resource,var_file): return self.domain_data - #Check value exported - #If None - replace with "" - #If list, convert to comma sepearted string - def check_exported_value(value): - if value == None: - value = "" - if ("list" in str(type(value))): - str1 = "" - if(value.__len__()==0): - value="" - for v in value: - str1 = v + "," + str1 - if (str1 != "" and str1[-1] == ','): - value = str1[:-1] - - return value - # Export Tag fields - common code - Defined and Freeform Tags # header - individual headers/column name # values_for_column - list of columns from read_cd3 function @@ -608,68 +572,13 @@ def export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column): return values_for_column - # Check CD3 Column headers - def check_column_headers(var_name): - # replace special characters and spaces with '_' and convert to lowercase - # replaces multiple occurrence of '_' to just 1 - var_name = var_name.strip() - var_name = re.sub('[@!#$%^&*<>?/}{~: \n()|-]', '_', var_name).lower() - var_name = re.sub('_+', '_', var_name).lower() - return var_name - - #Check TF variable Name - def check_tf_variable(var_name): - tfname = re.compile('[^a-zA-Z0-9_-]') - tfnamestart = re.compile('[A-Za-z]') - - var_name = tfname.sub("-", var_name) - x = tfnamestart.match(var_name) - # variable name doesnot start with letter; append with c - if (x == None): - var_name = "c" + var_name - return var_name - - # Process ColumnValues - def check_columnvalue(columnvalue): - - if str(columnvalue).lower() == 'true' or str(columnvalue).lower() == 'false': - columnvalue = str(columnvalue).lower() - - if (columnvalue.lower() == 'nan'): - columnvalue = "" - - # replace \ with \\ - if("\\" in columnvalue): - columnvalue = columnvalue.replace("\\", "\\\\") - - # replace " with \" - if("\"" in columnvalue): - columnvalue=columnvalue.replace("\"","\\\"") - - return columnvalue - - # Process column values with :: - def check_multivalues_columnvalue(columnvalue, columnname, tempdict): - columnvalue = str(columnvalue).strip() - columnname = commonTools.check_column_headers(columnname) - if "::" in columnvalue: - if ".Flex" in columnvalue or ".Micro" in columnvalue: - columnname = commonTools.check_column_headers(columnname) - multivalues = columnvalue.split("::") - multivalues = [str(part).strip() for part in multivalues if part] - tempdict = {columnname: multivalues} - elif columnname != 'Compartment Name' and "ipv6" not in columnname.lower(): - columnname = commonTools.check_column_headers(columnname) - multivalues = columnvalue.split("::") - multivalues = [str(part).strip() for part in multivalues ]#if part] - tempdict = {columnname: multivalues} - return tempdict # Split values for tagging def split_tag_values(columnname, columnvalue, tempdict): columnvalue = columnvalue.replace("\n", "") if ";" in columnvalue: # If there are more than one tag; split them by ";" and "=" + columnname = commonTools.check_column_headers(columnname) multivalues = columnvalue.split(";") multivalues = [part.split("=") for part in multivalues if part] @@ -692,208 +601,8 @@ def split_tag_values(columnname, columnvalue, tempdict): tempdict = {columnname: [multivalues]} return tempdict - # Read rows from CD3 - def read_cd3(cd3file, sheet_name): - df = {} - try: - df = pd.read_excel(cd3file, sheet_name=sheet_name, skiprows=1, dtype=object) - - except Exception as e: - if("Events" in str(e) or "Notifications" in str(e)): - print("\nTabs - \"Events\" or \"Notifications\" is missing in the CD3. Please make sure to use the correct input file for Events and Notifications in properties file...Exiting!!") - exit(1) - else: - print("Error occurred while reading the CD3 excel sheet: "+ str(e)) - exit(1) - - yield df - try: - book = load_workbook(cd3file) - sheet = book[sheet_name] - except KeyError as e: - if 'does not exist' in str(e): - print("\nTab - \""+sheet_name+"\" seems to be missing in the CD3. Please make sure to use the right CD3 in properties file.....Exiting!!") - exit(1) - except Exception as e: - print(str(e)) - print("Exiting!!") - exit(1) - - values_for_column = collections.OrderedDict() - # values_for_column={} - for j in range(0, sheet.max_column): - col_name = sheet.cell(row=2, column=j + 1).value - if (type(col_name) == str): - values_for_column[col_name] = [] - yield values_for_column - - #Write exported rows to cd3 - def write_to_cd3(values_for_column, cd3file, sheet_name,append=False): - try: - book = load_workbook(cd3file) - sheet = book[sheet_name] - except Exception as e: - print(str(e)) - print("Exiting!!") - exit(1) - if (sheet_name == "VCN Info"): - onprem_destinations = "" - ngw_destinations = "" - igw_destinations = "" - for destination in values_for_column["onprem_destinations"]: - onprem_destinations=destination+","+onprem_destinations - for destination in values_for_column["ngw_destinations"]: - ngw_destinations = destination + "," + ngw_destinations - for destination in values_for_column["igw_destinations"]: - igw_destinations = destination + "," + igw_destinations - - if (onprem_destinations != "" and onprem_destinations[-1] == ','): - onprem_destinations = onprem_destinations[:-1] - if (ngw_destinations != "" and ngw_destinations[-1] == ','): - ngw_destinations = ngw_destinations[:-1] - if (igw_destinations != "" and igw_destinations[-1] == ','): - igw_destinations = igw_destinations[:-1] - - sheet.cell(3,2).value = onprem_destinations - sheet.cell(4,2).value = ngw_destinations - sheet.cell(5,2).value = igw_destinations - try: - book.save(cd3file) - book.close() - except Exception as e: - print(str(e)) - print("Exiting!!") - exit(1) - return - - - #rows_len=len(rows) - rows_len = len(values_for_column["Region"]) - sheet_max_rows = sheet.max_row - #If no rows exported from OCI, remove the sample data as well - if(rows_len == 0) : - if not append: - print("0 rows exported; Nothing to write to CD3 excel; Tab "+sheet_name +" will be empty in CD3 excel!!") - for i in range(0, sheet.max_row): - for j in range(0, sheet.max_column): - sheet.cell(row=i + 3, column=j + 1).value = "" - try: - book.save(cd3file) - book.close() - except Exception as e: - print(str(e)) - print("Exiting!!") - exit(1) - return - - if append: - for x in range(1, sheet_max_rows): - if sheet['A'][x].value == None: - last_line = x - break - #rows_len +=last_line - large = rows_len - start = last_line+1 - - - else: - start = 3 - if (rows_len > sheet_max_rows): - large = rows_len - else: - large = sheet_max_rows - - df, values_for_column_sheet = commonTools.read_cd3(cd3file, sheet_name) - - #Put Data - j=0 - for i in range(0,large): - for col_name in values_for_column.keys(): - #Check if column name to be populated in present in the sheet. - if col_name not in values_for_column_sheet: - continue - # Data - if(i>=rows_len): - sheet.cell(row=i+start, column=j+1).value = "" - else: - sheet.cell(row=i+start, column=j+1).value = values_for_column[col_name][i] - sheet.cell(row=i+start, column=j+1).alignment = Alignment(wrap_text=True) - j=j+1 - j=0 - - - brdr = Border(left=Side(style='thin'), - right=Side(style='thin'), - top=Side(style='thin'), - bottom=Side(style='thin'), - ) - - for row in sheet.iter_rows(min_row=3): - for cell in row: - cell.border = brdr - - # Add color for exported sec rules and route rules - if (sheet_name == "RouteRulesinOCI" or sheet_name == "SecRulesinOCI" or sheet_name == "DRGRouteRulesinOCI"): - names = [] - # Add color coding to exported rules - for row in sheet.iter_rows(min_row=3): - c = 0 - region = "" - name = "" - for cell in row: - c = c + 1 - if (c == 1): - region = cell.value - continue - elif (c == 4): - name = cell.value - break - - vcn_name = region + "_" + name - if (vcn_name not in names): - names.append(vcn_name) - for cellnew in row: - if (len(names) % 2 == 0): - cellnew.fill = PatternFill(start_color="94AFAF", end_color="94AFAF", fill_type="solid") - cellnew.border = brdr - else: - cellnew.fill = PatternFill(start_color="E5DBBE", end_color="E5DBBE", fill_type="solid") - cellnew.border = brdr - else: - for cellnew in row: - if (len(names) % 2 == 0): - cellnew.fill = PatternFill(start_color="94AFAF", end_color="94AFAF", fill_type="solid") - cellnew.border = brdr - else: - cellnew.fill = PatternFill(start_color="E5DBBE", end_color="E5DBBE", fill_type="solid") - cellnew.border = brdr - try: - book.save(cd3file) - book.close() - except Exception as e: - print(str(e)) - print("Exiting!!") - exit(1) # def backup_file(src_dir, pattern, overwrite): - def backup_file(src_dir, resource, pattern): - dest_dir = str(src_dir) + "/backup_" + resource + "/" + datetime.datetime.now().strftime("%d-%m-%H%M%S").replace('/', '-') - for f in os.listdir(str(src_dir)): - if f.endswith(pattern): - print("Backing up existing " + f + " to " + dest_dir) - if not os.path.exists(dest_dir): - # print("\nCreating backup dir " + dest_dir + "\n") - os.makedirs(dest_dir) - - src = os.path.join(str(src_dir), f) - #dest = os.path.join(dest_dir, f) - # print("backing up ....." + src +" to "+dest) - shutil.move(src, dest_dir) - """if (overwrite == 'yes'): - shutil.move(src, dest_dir) - elif (overwrite == 'no'): - shutil.copyfile(src, dest) - """ # def backup_file(src_dir, pattern, overwrite): def copy_file(src_dir, resource, pattern): @@ -946,7 +655,7 @@ def get_protocol(strprotocol): if str(strprotocol).lower() == "all": return "all" else: - protocol_dict = commonTools().protocol_dict + protocol_dict = ociCommonTools().protocol_dict for k, v in protocol_dict.items(): if (strprotocol).lower() == v.lower(): return k @@ -970,7 +679,7 @@ def create_ingress_rule_string(self, secrule, tempStr, ingress_rule, tempdict2, tempdict2 = {'source_type' : source_type} tempStr.update(tempdict2) - tempdict2 = {'protocol_code': commonTools.get_protocol(protocol),'isstateless':isstateless} + tempdict2 = {'protocol_code': ociCommonTools.get_protocol(protocol),'isstateless':isstateless} tempStr.update(tempdict2) ingress_rule = ingress_rule + secrule.render(tempStr) @@ -997,7 +706,7 @@ def create_egress_rule_string(self, secrule, tempStr, egress_rule, tempdict2, re tempdict2 = {'destination_type': destination_type} tempStr.update(tempdict2) - tempDict2 = {'protocol_code': commonTools.get_protocol(protocol),'isstateless':isstateless} + tempDict2 = {'protocol_code': ociCommonTools.get_protocol(protocol),'isstateless':isstateless} tempStr.update(tempDict2) egress_rule = egress_rule + secrule.render(tempStr) @@ -1213,20 +922,6 @@ def __init__(self, filename): v = v[:-1] self.peering_dict[k] = v -@contextmanager -def section(title='', header=False, padding=117): - separator = '-' if not header else '=' - # Not sure why 117 but thats how it was before. - print(f'{title:{separator}^{padding}}') - yield - if header: - print(separator * padding) - - -def exit_menu(msg, exit_code=1): - print(msg) - exit(exit_code) - class parseVCNInfo(): # all_regions = [] @@ -1294,132 +989,3 @@ def __init__(self, filename): value = df_subnet.loc[i,'Compartment Name'].strip(), df_subnet.loc[i,'VCN Name'].strip(), df_subnet.loc[i,'Display Name'].strip() self.vcn_subnet_map[key] = value -class cd3Services(): - - - #Get OCI Cloud Regions - regions_list = "" - def fetch_regions(self,config,signer): - #config = oci.config.from_file(file_location=configFileName) - idc = IdentityClient(config=config, retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY,signer=signer) - try: - regions_list = idc.list_regions().data - except Exception as e: - print(e) - if ('NotAuthenticated' in str(e)): - print("\nInvalid Credetials - check your keypair/fingerprint/region...Exiting!!!") - exit(1) - - if ("OCSWorkVM" in os.getcwd() or 'user-scripts' in os.getcwd()): - os.chdir("../") - - tempStr = '#Region:Region_Key\n' - reg_dict = {} - - for reg in regions_list: - cd3key = str(reg.name.split('-',1)[1]).lower() - - if 'dcc' in cd3key: - cd3key = str(cd3key.split('-',1)[1]).lower() - - name = str(reg.name).lower() - reg_dict[cd3key] = name - - keys = [] - new_reg_dict={} - for key,val in reg_dict.items(): - keyy = key.split("-")[0] - if keyy not in keys: - keys.append(keyy) - new_reg_dict[keyy]=val - else: - new_reg_dict[key] = val - - #replace prev - old_val = new_reg_dict[keyy] - old_val_key = str(old_val.split('-', 1)[1]).lower() - if 'dcc' in old_val_key: - old_val_key = str(old_val_key.split('-', 1)[1]).lower() - - new_reg_dict[old_val_key] = old_val - new_reg_dict.pop(keyy) - - for cd3key,name in new_reg_dict.items(): - line = cd3key + ":" + name - tempStr = tempStr + line + '\n' - - with open('OCI_Regions', 'w+') as f: - f.write(tempStr) - f.close() - print("Updated OCI_Regions file !!!\n") - - # Parse XML - Used by OCI Protocols - def parse_xml(source: str) -> ET.Element: - it = ET.iterparse(open(source)) - # strip namespaces - for _, el in it: - if "}" in el.tag: - el.tag = el.tag.split("}", 1)[1] - root = it.root # mypy: ignore - return root - - # Parse Date - Used by OCI Protocols - def parse_date(root_xml: ET.Element) -> datetime: - updated = root_xml.find("updated") - assert updated is not None and isinstance(updated.text, str) - return datetime.datetime.strptime(updated.text, "%Y-%m-%d") - - # write_protocols_file - Used for OCI Protocols - def write_protocols_file(source: str, destination: str) -> datetime: - root = cd3Services.parse_xml(source) - updated = cd3Services.parse_date(root) - destination = str(pathlib.Path.cwd())+"/"+destination - with open(destination,"w+") as dst: - dst.write("#protocol number:protocol name\n") - for r in root.iter("record"): - desc_ = r.find("description") - if desc_ is None or desc_.text is None: - desc = "" - else: - desc = desc_.text - name_ = r.find("name") - value_ = r.find("value") - if (value_ is None - or value_.text is None): - continue - if (name_ is None - or name_.text is None): - name = desc - dst.write(str(value_.text) + ":" + name + "\n") - continue - alias = name_.text.split()[0] - value = int(value_.text) - dst.write(str(value)+":"+alias+"\n") - return updated - - def download(url: str, path: str) -> None: - with open(path, "wb") as dst, urllib.request.urlopen(url) as src: - shutil.copyfileobj(src, dst) - - #Get OCI Protocols - def fetch_protocols(self) -> None: - - ssl._create_default_https_context = ssl._create_unverified_context - PROTOCOLS_URL = "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml" - PROTOCOLS_XML = "protocol-numbers.xml" - PROTOCOLS_FILE = "OCI_Protocols" - - ##### main code for oci protocols #### - protocols_xml = str(pathlib.Path.cwd()) + "/" + PROTOCOLS_XML - try: - cd3Services.download(PROTOCOLS_URL, protocols_xml) - except OSError as e: - print("Could not download iana service names and port numbers: {}".format(e), - file=sys.stderr, - ) - sys.exit(1) - cd3Services.write_protocols_file(protocols_xml, PROTOCOLS_FILE) - rem_file = pathlib.Path(protocols_xml) - rem_file.unlink() - - print("Updated OCI_Protocols file !!!\n") \ No newline at end of file diff --git a/cd3_automation_toolkit/SDDC/__init__.py b/cd3_automation_toolkit/ocicloud/python/sddc/__init__.py similarity index 100% rename from cd3_automation_toolkit/SDDC/__init__.py rename to cd3_automation_toolkit/ocicloud/python/sddc/__init__.py diff --git a/cd3_automation_toolkit/SDDC/create_terraform_sddc.py b/cd3_automation_toolkit/ocicloud/python/sddc/create_terraform_sddc.py similarity index 96% rename from cd3_automation_toolkit/SDDC/create_terraform_sddc.py rename to cd3_automation_toolkit/ocicloud/python/sddc/create_terraform_sddc.py index 456f5dbe6..d1f65eaf1 100755 --- a/cd3_automation_toolkit/SDDC/create_terraform_sddc.py +++ b/cd3_automation_toolkit/ocicloud/python/sddc/create_terraform_sddc.py @@ -3,9 +3,11 @@ # This script will produce a Terraform file that will be used to set up OCI core components # SDDC management cluster and workload clusters from pathlib import Path -import os -from commonTools import * +import os, sys from jinja2 import Environment, FileSystemLoader +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools # Function to pre-process the data def data_process(filename, sheetName): @@ -80,8 +82,8 @@ def create_terraform_sddc_cluster(inputfile, outdir, service_dir, prefix, ct, sd columnvalue = commonTools.check_columnvalue(str(df[columnname][i]).strip()) # Check for multivalued columns tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == 'SDDC Name': sddc_name = columnvalue.strip() sddc_display_name,sddc_cluster_display_name = sddc_name.split("::") diff --git a/cd3_automation_toolkit/SDDC/export_sddc_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/sddc/export_sddc_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/SDDC/export_sddc_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/sddc/export_sddc_nonGreenField.py index 034a9d9ff..3b88fdb4f 100644 --- a/cd3_automation_toolkit/SDDC/export_sddc_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/sddc/export_sddc_nonGreenField.py @@ -11,8 +11,9 @@ from oci.core.blockstorage_client import BlockstorageClient import os import subprocess as sp -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools def get_volume_data(bvol, volume_id, ct): @@ -241,15 +242,15 @@ def export_sddc(inputfile, outdir, service_dir,config,signer, ct, export_compart elif col_header == "Provisioning Net VLAN": vlan_id = sddc_network.provisioning_vlan_id values_for_column_sddc[col_header].append(vnc.get_vlan(vlan_id).data.display_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_sddc = commonTools.export_tags( + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_sddc = ociCommonTools.export_tags( sddc if sddc_cluster.vsphere_type == "MANAGEMENT" else sddc_cluster, col_header, values_for_column_sddc) else: oci_objs = [sddc, sddc_init_config, sddc_network, sddc_datastores] if sddc_cluster.vsphere_type == "MANAGEMENT" else [ sddc_cluster, sddc_cluster_data, sddc_network, sddc_datastores] - values_for_column_sddc = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_sddc = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_sddc, values_for_column_sddc) diff --git a/cd3_automation_toolkit/SDDC/templates/sddc-cluster-template b/cd3_automation_toolkit/ocicloud/python/sddc/templates/sddc-cluster-template similarity index 100% rename from cd3_automation_toolkit/SDDC/templates/sddc-cluster-template rename to cd3_automation_toolkit/ocicloud/python/sddc/templates/sddc-cluster-template diff --git a/cd3_automation_toolkit/SDDC/templates/sddc-template b/cd3_automation_toolkit/ocicloud/python/sddc/templates/sddc-template similarity index 100% rename from cd3_automation_toolkit/SDDC/templates/sddc-template rename to cd3_automation_toolkit/ocicloud/python/sddc/templates/sddc-template diff --git a/cd3_automation_toolkit/ocicloud/python/security/__init__.py b/cd3_automation_toolkit/ocicloud/python/security/__init__.py new file mode 100644 index 000000000..43ce62703 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/security/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +from .cloudguard import * +from .keyvault import * +from .firewall import * + diff --git a/cd3_automation_toolkit/Security/CloudGuard/__init__.py b/cd3_automation_toolkit/ocicloud/python/security/cloudguard/__init__.py similarity index 100% rename from cd3_automation_toolkit/Security/CloudGuard/__init__.py rename to cd3_automation_toolkit/ocicloud/python/security/cloudguard/__init__.py diff --git a/cd3_automation_toolkit/Security/CloudGuard/enable_terraform_cloudguard.py b/cd3_automation_toolkit/ocicloud/python/security/cloudguard/enable_terraform_cloudguard.py similarity index 95% rename from cd3_automation_toolkit/Security/CloudGuard/enable_terraform_cloudguard.py rename to cd3_automation_toolkit/ocicloud/python/security/cloudguard/enable_terraform_cloudguard.py index 4e3c20f8a..01cb4f089 100644 --- a/cd3_automation_toolkit/Security/CloudGuard/enable_terraform_cloudguard.py +++ b/cd3_automation_toolkit/ocicloud/python/security/cloudguard/enable_terraform_cloudguard.py @@ -8,11 +8,13 @@ # Oracle Consulting # Modified (TF Upgrade): Shruthi Subramanian # -import os +import os, sys from jinja2 import Environment, FileSystemLoader from pathlib import Path from oci.config import DEFAULT_LOCATION -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- Config file, prefix AND outdir diff --git a/cd3_automation_toolkit/Security/CloudGuard/templates/cloud-guard-config-template b/cd3_automation_toolkit/ocicloud/python/security/cloudguard/templates/cloud-guard-config-template similarity index 100% rename from cd3_automation_toolkit/Security/CloudGuard/templates/cloud-guard-config-template rename to cd3_automation_toolkit/ocicloud/python/security/cloudguard/templates/cloud-guard-config-template diff --git a/cd3_automation_toolkit/Security/CloudGuard/templates/cloud-guard-target-template b/cd3_automation_toolkit/ocicloud/python/security/cloudguard/templates/cloud-guard-target-template similarity index 100% rename from cd3_automation_toolkit/Security/CloudGuard/templates/cloud-guard-target-template rename to cd3_automation_toolkit/ocicloud/python/security/cloudguard/templates/cloud-guard-target-template diff --git a/cd3_automation_toolkit/Security/Firewall/__init__.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/__init__.py similarity index 94% rename from cd3_automation_toolkit/Security/Firewall/__init__.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/__init__.py index 8c79bf942..d4b63f67f 100644 --- a/cd3_automation_toolkit/Security/Firewall/__init__.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/__init__.py @@ -16,3 +16,4 @@ from .cloneexport_firewallpolicy_nonGreenField import cloneexport_firewallpolicy from .delete_firewallpolicy import delete_firewallpolicy from .fwpolicy_create_tunnelinspection import fwpolicy_create_tunnelinspect +from .fwpolicy_create_natrules import fwpolicy_create_natrules diff --git a/cd3_automation_toolkit/Security/Firewall/clone_firewallpolicy.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/clone_firewallpolicy.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/clone_firewallpolicy.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/clone_firewallpolicy.py index 12bb64253..94ddeb964 100644 --- a/cd3_automation_toolkit/Security/Firewall/clone_firewallpolicy.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/clone_firewallpolicy.py @@ -11,15 +11,15 @@ import oci import os import datetime -import Security import numpy as np from oci.network_firewall import NetworkFirewallClient from oci.vault import VaultsClient from oci.identity import IdentityClient from oci.network_load_balancer import NetworkLoadBalancerClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} diff --git a/cd3_automation_toolkit/Security/Firewall/cloneexport_firewallpolicy_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/cloneexport_firewallpolicy_nonGreenField.py similarity index 95% rename from cd3_automation_toolkit/Security/Firewall/cloneexport_firewallpolicy_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/cloneexport_firewallpolicy_nonGreenField.py index f6ea2ec02..af791628d 100644 --- a/cd3_automation_toolkit/Security/Firewall/cloneexport_firewallpolicy_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/cloneexport_firewallpolicy_nonGreenField.py @@ -17,8 +17,9 @@ from oci.key_management import KmsVaultClient from oci.network_load_balancer import NetworkLoadBalancerClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -43,8 +44,8 @@ def print_firewall_policy(region, ct, values_for_column_fwpolicy, fwpolicies, fw elif col_header == 'Policy Name': values_for_column_fwpolicy[col_header].append(fwpolicy_display_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwpolicy = commonTools.export_tags(eachfwpolicy, col_header, values_for_column_fwpolicy) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwpolicy = ociociCommonTools.export_tags(eachfwpolicy, col_header, values_for_column_fwpolicy) return values_for_column_fwpolicy @@ -85,8 +86,8 @@ def print_firewall_address(region, ct, values_for_column_fwaddress, fwpolicies, values_for_column_fwaddress[col_header].append(add.type) elif col_header == 'Address List': values_for_column_fwaddress[col_header].append(address_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwaddress = commonTools.export_tags(policy, col_header, values_for_column_fwaddress) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwaddress = ociociCommonTools.export_tags(policy, col_header, values_for_column_fwaddress) return values_for_column_fwaddress @@ -122,8 +123,8 @@ def print_firewall_urllist(region, ct, values_for_column_fwurllist, fwpolicies, values_for_column_fwurllist[col_header].append(url_display_name) elif col_header == 'URL List': values_for_column_fwurllist[col_header].append(url_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwurllist = commonTools.export_tags(urlpolicy, col_header,values_for_column_fwurllist) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwurllist = ociociCommonTools.export_tags(urlpolicy, col_header,values_for_column_fwurllist) return values_for_column_fwurllist @@ -173,8 +174,8 @@ def print_firewall_servicelist(region, ct, values_for_column_fwservicelist, fwpo values_for_column_fwservicelist[col_header].append(service_display_name) elif col_header == 'Services': values_for_column_fwservicelist[col_header].append(service_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwservicelist = commonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwservicelist = ociociCommonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) return values_for_column_fwservicelist @@ -220,8 +221,8 @@ def print_firewall_applist(region, ct, values_for_column_fwapplist, fwpolicies, values_for_column_fwapplist[col_header].append(application_display_name) elif col_header == 'Applications': values_for_column_fwapplist[col_header].append(application_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwapplist = commonTools.export_tags(applistpolicy, col_header,values_for_column_fwapplist) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwapplist = ociociCommonTools.export_tags(applistpolicy, col_header,values_for_column_fwapplist) return values_for_column_fwapplist @@ -309,8 +310,8 @@ def print_firewall_secrules(region, ct, values_for_column_fwsecrules, fwpolicies values_for_column_fwsecrules[col_header].append(raction) elif col_header == 'Position': values_for_column_fwsecrules[col_header].append(rposition) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwsecrules = commonTools.export_tags(applistpolicy, col_header,values_for_column_fwsecrules) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwsecrules = ociCommonTools.export_tags(applistpolicy, col_header,values_for_column_fwsecrules) return values_for_column_fwsecrules def print_firewall_secret(region, ct, values_for_column_fwsecret, fwpolicies, fwpolicy, vault, compartment, policy_detail,kmsvault): @@ -350,8 +351,8 @@ def print_firewall_secret(region, ct, values_for_column_fwsecret, fwpolicies, fw values_for_column_fwsecret[col_header].append(vault_secret_name) elif col_header == 'Version Number': values_for_column_fwsecret[col_header].append(key_info.version_number) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwsecret = commonTools.export_tags(secretpolicy, col_header,values_for_column_fwsecret) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwsecret = ociociCommonTools.export_tags(secretpolicy, col_header,values_for_column_fwsecret) return values_for_column_fwsecret @@ -413,8 +414,8 @@ def print_firewall_decryptprofile(region, ct, values_for_column_fwdecryptprofile elif col_header == 'is untrusted issuer blocked': values_for_column_fwdecryptprofile[col_header].append(key_info1_is_untrusted_issuer_blocked) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwdecryptprofile = commonTools.export_tags(decryptionprofile, col_header,values_for_column_fwdecryptprofile) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwdecryptprofile = ociociCommonTools.export_tags(decryptionprofile, col_header,values_for_column_fwdecryptprofile) return values_for_column_fwdecryptprofile def print_firewall_decryptrule(region, ct, values_for_column_fwdecryptrule, fwpolicies, fwpolicy, policy_detail): @@ -473,8 +474,8 @@ def print_firewall_decryptrule(region, ct, values_for_column_fwdecryptrule, fwpo values_for_column_fwdecryptrule[col_header].append(drule_info.action) elif col_header == 'Position': values_for_column_fwdecryptrule[col_header].append(dposition) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwdecryptrule = commonTools.export_tags(applistpolicy, col_header,values_for_column_fwdecryptrule) + elif col_header.lower() in ociociCommonTools.tagColumns: + values_for_column_fwdecryptrule = ociociCommonTools.export_tags(applistpolicy, col_header,values_for_column_fwdecryptrule) return values_for_column_fwdecryptrule # Execution of the code begins here def cloneexport_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, export_compartments, export_regions, policy_detail): diff --git a/cd3_automation_toolkit/Security/Firewall/delete_firewallpolicy.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/delete_firewallpolicy.py similarity index 95% rename from cd3_automation_toolkit/Security/Firewall/delete_firewallpolicy.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/delete_firewallpolicy.py index c055756cb..ec828f7db 100644 --- a/cd3_automation_toolkit/Security/Firewall/delete_firewallpolicy.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/delete_firewallpolicy.py @@ -10,10 +10,10 @@ import sys import oci import os -import Security from oci.network_firewall import NetworkFirewallClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} diff --git a/cd3_automation_toolkit/Security/Firewall/export_firewall_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewall_nonGreenField.py similarity index 92% rename from cd3_automation_toolkit/Security/Firewall/export_firewall_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewall_nonGreenField.py index cc40abb32..336a9b9cf 100644 --- a/cd3_automation_toolkit/Security/Firewall/export_firewall_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewall_nonGreenField.py @@ -15,8 +15,9 @@ from oci.network_firewall import NetworkFirewallClient from oci.core.virtual_network_client import VirtualNetworkClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -60,7 +61,11 @@ def print_firewall(region, export_tags, ct, values_for_column_fw, fws, fw_compar net_cmp_name = comp_name comp_done_ids.append(net_cmp_id) subnet_detail = vcn_name + "::" + subnet_name + #if eachfw.nat_configuration == null: + enable_private_nat ="" + if eachfw.nat_configuration is not None: + enable_private_nat = eachfw.nat_configuration.must_enable_private_nat # Fetch policy policy_ocid = eachfw.network_firewall_policy_id policy_info = fw.get_network_firewall_policy(policy_ocid).data @@ -105,6 +110,9 @@ def print_firewall(region, export_tags, ct, values_for_column_fw, fws, fw_compar elif col_header == 'NSGs': values_for_column_fw[col_header].append(nsg_detail) + elif col_header == 'Enable Private NAT(True/False)': + values_for_column_fw[col_header].append(enable_private_nat) + elif col_header == 'Availability Domain(AD1|AD2|AD3|Regional)': if (eachfw.availability_domain == None): value_of_ad = "Regional" @@ -112,8 +120,8 @@ def print_firewall(region, export_tags, ct, values_for_column_fw, fws, fw_compar value_of_ad = AD(eachfw.availability_domain) values_for_column_fw[col_header].append(value_of_ad) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fw = commonTools.export_tags(eachfw, col_header, values_for_column_fw) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fw = ociCommonTools.export_tags(eachfw, col_header, values_for_column_fw) return values_for_column_fw diff --git a/cd3_automation_toolkit/Security/Firewall/export_firewallpolicy_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewallpolicy_nonGreenField.py similarity index 87% rename from cd3_automation_toolkit/Security/Firewall/export_firewallpolicy_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewallpolicy_nonGreenField.py index 8d0c226b5..ae71be332 100644 --- a/cd3_automation_toolkit/Security/Firewall/export_firewallpolicy_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/export_firewallpolicy_nonGreenField.py @@ -19,10 +19,11 @@ import subprocess as sp from oci.network_load_balancer import NetworkLoadBalancerClient -sys.path.append(os.getcwd() + "/..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools -importCommands,importCommands_nfp,importCommands_nfao,importCommands_ulo,importCommands_slo,importCommands_alo,importCommands_sro,importCommands_mso,importCommands_dpo,importCommands_dro,importCommands_fpo,importCommands_tio = {},{},{},{},{},{},{},{},{},{},{},{} +importCommands,importCommands_nfp,importCommands_nfao,importCommands_ulo,importCommands_slo,importCommands_alo,importCommands_sro,importCommands_mso,importCommands_dpo,importCommands_dro,importCommands_fpo,importCommands_tio,importCommands_nato = {},{},{},{},{},{},{},{},{},{},{},{},{} oci_obj_names = {} @@ -65,8 +66,8 @@ def print_firewall_policy(region, ct, values_for_column_fwpolicy, fwpolicies, fw elif col_header == 'Policy Name': values_for_column_fwpolicy[col_header].append(fwpolicy_display_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwpolicy = commonTools.export_tags(eachfwpolicy, col_header, values_for_column_fwpolicy) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwpolicy = ociCommonTools.export_tags(eachfwpolicy, col_header, values_for_column_fwpolicy) return values_for_column_fwpolicy @@ -126,8 +127,8 @@ def print_firewall_address(region, ct, values_for_column_fwaddress, fwpolicies, values_for_column_fwaddress[col_header].append(add.type) elif col_header == 'Address List': values_for_column_fwaddress[col_header].append(address_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwaddress = commonTools.export_tags(policy, col_header, values_for_column_fwaddress) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwaddress = ociCommonTools.export_tags(policy, col_header, values_for_column_fwaddress) return values_for_column_fwaddress @@ -182,8 +183,8 @@ def print_firewall_urllist(region, ct, values_for_column_fwurllist, fwpolicies, values_for_column_fwurllist[col_header].append(url_display_name) elif col_header == 'URL List': values_for_column_fwurllist[col_header].append(url_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwurllist = commonTools.export_tags(urlpolicy, col_header,values_for_column_fwurllist) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwurllist = ociCommonTools.export_tags(urlpolicy, col_header,values_for_column_fwurllist) return values_for_column_fwurllist @@ -259,8 +260,8 @@ def print_firewall_servicelist(region, ct, values_for_column_fwservicelist, fwpo values_for_column_fwservicelist[col_header].append(service_display_name) elif col_header == 'Services': values_for_column_fwservicelist[col_header].append(service_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwservicelist = commonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwservicelist = ociCommonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) ## Fetch services without Lists fwservices = oci.pagination.list_call_get_all_results(fwclient.list_services,servicelistpolicy_id) @@ -299,8 +300,8 @@ def print_firewall_servicelist(region, ct, values_for_column_fwservicelist, fwpo values_for_column_fwservicelist[col_header].append("") elif col_header == 'Services': values_for_column_fwservicelist[col_header].append(service_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwservicelist = commonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwservicelist = ociCommonTools.export_tags(servicelistpolicy, col_header,values_for_column_fwservicelist) return values_for_column_fwservicelist @@ -374,8 +375,8 @@ def print_firewall_applist(region, ct, values_for_column_fwapplist, fwpolicies, values_for_column_fwapplist[col_header].append(application_display_name) elif col_header == 'Applications': values_for_column_fwapplist[col_header].append(application_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwapplist = commonTools.export_tags(applistpolicy, col_header,values_for_column_fwapplist) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwapplist = ociCommonTools.export_tags(applistpolicy, col_header,values_for_column_fwapplist) ## Fetch apps without Lists fwapps = oci.pagination.list_call_get_all_results(fwclient.list_applications, applistpolicy_id) @@ -411,8 +412,8 @@ def print_firewall_applist(region, ct, values_for_column_fwapplist, fwpolicies, values_for_column_fwapplist[col_header].append("") elif col_header == 'Applications': values_for_column_fwapplist[col_header].append(application_detail) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwapplist = commonTools.export_tags(applistpolicy, col_header, + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwapplist = ociCommonTools.export_tags(applistpolicy, col_header, values_for_column_fwapplist) return values_for_column_fwapplist @@ -522,8 +523,8 @@ def print_firewall_secrules(region, ct, values_for_column_fwsecrules, fwpolicies values_for_column_fwsecrules[col_header].append(raction) elif col_header == 'Position': values_for_column_fwsecrules[col_header].append(rposition) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwsecrules = commonTools.export_tags(secrulespolicy, col_header,values_for_column_fwsecrules) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwsecrules = ociCommonTools.export_tags(secrulespolicy, col_header,values_for_column_fwsecrules) return values_for_column_fwsecrules def print_firewall_secret(region, ct, values_for_column_fwsecret, fwpolicies, fwclient, vault, compartment, export_tags,kmsvault,state): @@ -584,8 +585,8 @@ def print_firewall_secret(region, ct, values_for_column_fwsecret, fwpolicies, fw values_for_column_fwsecret[col_header].append(vault_secret_name) elif col_header == 'Version Number': values_for_column_fwsecret[col_header].append(key_info.version_number) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwsecret = commonTools.export_tags(secretpolicy, col_header,values_for_column_fwsecret) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwsecret = ociCommonTools.export_tags(secretpolicy, col_header,values_for_column_fwsecret) return values_for_column_fwsecret @@ -668,8 +669,8 @@ def print_firewall_decryptprofile(region, ct, values_for_column_fwdecryptprofile elif col_header == 'is untrusted issuer blocked': values_for_column_fwdecryptprofile[col_header].append(key_info1_is_untrusted_issuer_blocked) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwdecryptprofile = commonTools.export_tags(decryptionprofile, col_header,values_for_column_fwdecryptprofile) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwdecryptprofile = ociCommonTools.export_tags(decryptionprofile, col_header,values_for_column_fwdecryptprofile) return values_for_column_fwdecryptprofile def print_firewall_decryptrule(region, ct, values_for_column_fwdecryptrule, fwpolicies, fwclient,export_tags,state): @@ -749,8 +750,8 @@ def print_firewall_decryptrule(region, ct, values_for_column_fwdecryptrule, fwpo values_for_column_fwdecryptrule[col_header].append(drule_info.action) elif col_header == 'Position': values_for_column_fwdecryptrule[col_header].append(dposition) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwdecryptrule = commonTools.export_tags(decryptrulepolicy, col_header,values_for_column_fwdecryptrule) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwdecryptrule = ociCommonTools.export_tags(decryptrulepolicy, col_header,values_for_column_fwdecryptrule) return values_for_column_fwdecryptrule def print_firewall_tunnelinspect(region, ct, values_for_column_fwtunnelinspect, fwpolicies, fwclient,export_tags,state): @@ -827,17 +828,102 @@ def print_firewall_tunnelinspect(region, ct, values_for_column_fwtunnelinspect, values_for_column_fwtunnelinspect[col_header].append(tirule_info.action) elif col_header == 'Position': values_for_column_fwtunnelinspect[col_header].append(dposition) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_fwtunnelinspect = commonTools.export_tags(tunnelinspectrulepolicy, col_header,values_for_column_fwtunnelinspect) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwtunnelinspect = ociCommonTools.export_tags(tunnelinspectrulepolicy, col_header,values_for_column_fwtunnelinspect) return values_for_column_fwtunnelinspect +def print_firewall_nat(region, ct, values_for_column_fwnat, fwpolicies, fwclient, export_tags, state): + if not clone: + print("Exporting Nat rules details " + region) + for natrulepolicy in fwpolicies: + + # Tags filter + defined_tags = natrulepolicy.defined_tags + tags_list = [] + if defined_tags: + for tkey, tval in defined_tags.items(): + for kk, vv in tval.items(): + tag = tkey + "." + kk + "=" + vv + tags_list.append(tag) + + if export_tags == []: + check = True + else: + check = any(e in tags_list for e in export_tags) + # None of Tags from export_tags exist on this instance; Dont export this instance + if check == False: + continue + + natrulepolicy_id = natrulepolicy.id + natrulepolicy_display_name = natrulepolicy.display_name + if clone: + natrulepolicy_display_name = target_pol[src_pol.index(natrulepolicy_display_name)] + natrulepolicy_tf_name = commonTools.check_tf_variable(natrulepolicy_display_name) + fwnatrules = oci.pagination.list_call_get_all_results(fwclient.list_nat_rules, natrulepolicy_id) + natrule_info = fwnatrules.data + for nirules in natrule_info: + nirule_info = fwclient.get_nat_rule(nirules.parent_resource_id, nirules.name).data + nirules_display_name = nirules.name + nirules_tf_name = commonTools.check_tf_variable(nirules_display_name) + tf_resource = f'module.nat_rules[\\"{str(natrulepolicy_tf_name)}_{str(nirules_tf_name)}\\"].oci_network_firewall_network_firewall_policy_nat_rule.network_firewall_policy_nat_rule' + if not clone and tf_resource not in state["resources"]: + importCommands_nato[reg] += f'\n{tf_or_tofu} import "{tf_resource}" networkFirewallPolicies/{natrulepolicy_id}/natRules/{nirules_display_name}' + + rsrc_detail = "" + rdst_detail = "" + if nirule_info.condition.source_address != None: + for rsrc in nirule_info.condition.source_address: + rsrc_detail = rsrc_detail + "," + rsrc + if (rsrc_detail != ""): + rsrc_detail = rsrc_detail[1:] + if nirule_info.condition.destination_address != None: + for rdst in nirule_info.condition.destination_address: + rdst_detail = rdst_detail + "," + rdst + if (rdst_detail != ""): + rdst_detail = rdst_detail[1:] + + if nirule_info.position.after_rule == None and nirule_info.position.before_rule == None: + dposition = None + elif nirule_info.position.after_rule == None: + dposition = None + elif nirule_info.position.before_rule == None: + dposition = "after_rule::" + nirule_info.position.after_rule + else: + dposition = "after_rule::" + nirule_info.position.after_rule + + for col_header in values_for_column_fwnat: + if col_header == 'Region': + values_for_column_fwnat[col_header].append(region) + elif col_header == 'Firewall Policy': + values_for_column_fwnat[col_header].append(natrulepolicy_display_name) + elif col_header == 'Rule Name': + values_for_column_fwnat[col_header].append(nirules_display_name) + elif col_header == 'Source Address': + values_for_column_fwnat[col_header].append(rsrc_detail) + elif col_header == 'Destination Address': + values_for_column_fwnat[col_header].append(rdst_detail) + elif col_header == 'Action': + values_for_column_fwnat[col_header].append(nirule_info.action) + elif col_header == 'Type': + values_for_column_fwnat[col_header].append(nirule_info.type) + elif col_header == 'Service': + values_for_column_fwnat[col_header].append(nirule_info.condition.service) + elif col_header == 'Description': + values_for_column_fwnat[col_header].append(nirule_info.description) + elif col_header == 'Position': + values_for_column_fwnat[col_header].append(dposition) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_fwnat = ociCommonTools.export_tags(natrulepolicy, col_header, + values_for_column_fwnat) + return values_for_column_fwnat + # Execution of the code begins here -def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, export_compartments, export_regions, export_tags, export_policies,target_policies=[],attached_policy_only="",clone_policy=False): +def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, export_compartments, export_regions=[], export_tags=[], export_policies=[],target_policies=[],attached_policy_only="",clone_policy=False): global tf_import_cmd global sheet_dict - global importCommands,importCommands_nfp,importCommands_nfao,importCommands_ulo,importCommands_slo,importCommands_alo,importCommands_sro,importCommands_mso,importCommands_dpo,importCommands_dro,importCommands_fpo,importCommands_tio + global importCommands,importCommands_nfp,importCommands_nfao,importCommands_ulo,importCommands_slo,importCommands_alo,importCommands_sro,importCommands_mso,importCommands_dpo,importCommands_dro,importCommands_fpo,importCommands_tio,importCommands_nato global values_for_vcninfo global cd3file global reg @@ -890,6 +976,7 @@ def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, e df, values_for_column_fwdecryptprofile = commonTools.read_cd3(cd3file, "Firewall-Policy-DecryptProfile") df, values_for_column_fwdecryptrule = commonTools.read_cd3(cd3file, "Firewall-Policy-DecryptRule") df, values_for_column_fwtunnelinspect = commonTools.read_cd3(cd3file, "Firewall-Policy-TunnelInspect") + df, values_for_column_fwnat = commonTools.read_cd3(cd3file, "Firewall-Policy-NatRules") # Get dict for columns from Excel_Columns #sheet_dict_fwpolicy = ct.sheet_dict[sheetname] #sheet_dict_fwaddress = ct.sheet_dict["Firewall-Policy-Address"] @@ -906,8 +993,7 @@ def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, e commonTools.backup_file(outdir + "/" + reg + "/" + service_dir, resource, "import_commands_firewallpolicy.sh") importCommands[reg], importCommands_nfp[reg], importCommands_nfao[reg], importCommands_ulo[reg], \ importCommands_slo[reg], importCommands_alo[reg], importCommands_sro[reg], importCommands_mso[reg], \ - importCommands_dpo[reg], importCommands_dro[reg], importCommands_fpo[ - reg], importCommands_tio[reg]= "", "", "", "", "", "", "", "", "", "", "", "" + importCommands_dpo[reg], importCommands_dro[reg], importCommands_fpo[reg], importCommands_tio[reg], importCommands_nato[reg] = "", "", "", "", "", "", "", "", "", "", "", "","" # Fetch Network firewall Policy Details @@ -980,6 +1066,7 @@ def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, e values_for_column_fwdecryptprofile = print_firewall_decryptprofile(region, ct,values_for_column_fwdecryptprofile,fwpolicies, fwclient,export_tags,state) values_for_column_fwdecryptrule = print_firewall_decryptrule(region, ct, values_for_column_fwdecryptrule,fwpolicies, fwclient,export_tags,state) values_for_column_fwtunnelinspect = print_firewall_tunnelinspect(region, ct, values_for_column_fwtunnelinspect,fwpolicies,fwclient,export_tags,state) + values_for_column_fwnat = print_firewall_nat(region, ct, values_for_column_fwnat,fwpolicies, fwclient, export_tags, state) if clone: commonTools.write_to_cd3(values_for_column_fwpolicy, cd3file, "Firewall-Policy",append=True) commonTools.write_to_cd3(values_for_column_fwaddress, cd3file, "Firewall-Policy-AddressList",append=True) @@ -991,6 +1078,7 @@ def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, e commonTools.write_to_cd3(values_for_column_fwdecryptprofile, cd3file, "Firewall-Policy-DecryptProfile",append=True) commonTools.write_to_cd3(values_for_column_fwdecryptrule, cd3file, "Firewall-Policy-DecryptRule",append=True) commonTools.write_to_cd3(values_for_column_fwtunnelinspect, cd3file, "Firewall-Policy-TunnelInspect", append=True) + commonTools.write_to_cd3(values_for_column_fwnat, cd3file, "Firewall-Policy-NatRules", append=True) else: commonTools.write_to_cd3(values_for_column_fwpolicy, cd3file, "Firewall-Policy") commonTools.write_to_cd3(values_for_column_fwaddress, cd3file, "Firewall-Policy-AddressList") @@ -1002,16 +1090,17 @@ def export_firewallpolicy(inputfile, _outdir, service_dir, config, signer, ct, e commonTools.write_to_cd3(values_for_column_fwdecryptprofile, cd3file, "Firewall-Policy-DecryptProfile") commonTools.write_to_cd3(values_for_column_fwdecryptrule, cd3file, "Firewall-Policy-DecryptRule") commonTools.write_to_cd3(values_for_column_fwtunnelinspect, cd3file, "Firewall-Policy-TunnelInspect") + commonTools.write_to_cd3(values_for_column_fwnat, cd3file, "Firewall-Policy-NatRules") print("Firewall Policies exported to CD3\n") # writing data init_commands = f'\n######### Writing import for Network firewall policy Objects #########\n\n#!/bin/bash\n{tf_or_tofu} init' - importCommands_message = ["Policy","Address Objects","url list Objects","service list Objects","application list Objects","Security Rules Objects","Mapped Secret Objects","Decrypt profile Objects","decryption Rules Objects","policy Objects","Tunnel Inspect Objects"] + importCommands_message = ["Policy","Address Objects","url list Objects","service list Objects","application list Objects","Security Rules Objects","Mapped Secret Objects","Decrypt profile Objects","decryption Rules Objects","policy Objects","Tunnel Inspect Objects","Nat Rules Objects"] for reg in export_regions: count = 0 all_importCommands = [importCommands_nfp[reg], importCommands_nfao[reg], importCommands_ulo[reg], importCommands_slo[reg], importCommands_alo[reg], importCommands_sro[reg], importCommands_mso[reg], importCommands_dpo[reg], - importCommands_dro[reg], importCommands_fpo[reg], importCommands_tio[reg]] + importCommands_dro[reg], importCommands_fpo[reg], importCommands_tio[reg], importCommands_nato[reg]] for item in all_importCommands: if item != "": importCommands[reg] += f'\n\n######### Writing import for Network firewall {importCommands_message[count]} #########\n\n' diff --git a/cd3_automation_toolkit/Security/Firewall/fw_create.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fw_create.py similarity index 92% rename from cd3_automation_toolkit/Security/Firewall/fw_create.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fw_create.py index b1d178d07..2a0d7996f 100644 --- a/cd3_automation_toolkit/Security/Firewall/fw_create.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fw_create.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -94,8 +96,8 @@ def fw_create(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = "compartment_tf_name" @@ -116,6 +118,11 @@ def fw_create(inputfile, outdir, service_dir, prefix, ct): columnvalue = commonTools.check_tf_variable(columnvalue) tempdict = {'subnet_compartment_tf_name': columnvalue} + if columnname == "Enable Private NAT(True/False)": + columnname = "must_enable_private_nat" + columnvalue = columnvalue.lower() + tempdict = {'must_enable_private_nat': columnvalue} + if columnname == 'Subnet Name': subnet_tf_name = str(columnvalue).strip() if subnet_tf_name == 'nan' or subnet_tf_name == '': diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create.py similarity index 93% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create.py index 18f97d618..e28905566 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create.py @@ -9,9 +9,12 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys + +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -87,8 +90,8 @@ def firewallpolicy_create(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Compartment Name": columnname = "compartment_tf_name" diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_address.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_address.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_address.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_address.py index a7e90e0dc..d307b809f 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_address.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_address.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_applicationlist.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_applicationlist.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_applicationlist.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_applicationlist.py index 441b8a4df..debc77dd6 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_applicationlist.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_applicationlist.py @@ -9,9 +9,12 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys + +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_apps.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_apps.py similarity index 98% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_apps.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_apps.py index b8811c288..f8f56a253 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_apps.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_apps.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptionprofile.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptionprofile.py similarity index 93% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptionprofile.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptionprofile.py index 5e6f61c06..c43f3d93e 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptionprofile.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptionprofile.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir @@ -87,8 +89,8 @@ def fwpolicy_create_decryptionprofile(inputfile, outdir, service_dir, prefix, ct tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptrules.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptrules.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptrules.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptrules.py index cb5e22e1f..b6c6cde2f 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_decryptrules.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_decryptrules.py @@ -9,9 +9,12 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys + +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_natrules.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_natrules.py new file mode 100644 index 000000000..95abd59f5 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_natrules.py @@ -0,0 +1,185 @@ +#!/usr/bin/python3 +# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# +# This script will produce a Terraform file that will be used to set up OCI core components +# firewall, Listeners +# +# Author: Suruchi Singla +# Oracle Consulting +# +from oci.config import DEFAULT_LOCATION +from pathlib import Path +from jinja2 import Environment, FileSystemLoader +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools + +###### +# Required Inputs-CD3 excel file, Config file AND outdir +###### + +# Execution of the code begins here +def fwpolicy_create_natrules(inputfile, outdir, service_dir, prefix, ct): + # Load the template file + file_loader = FileSystemLoader(f'{Path(__file__).parent}/templates') + env = Environment(loader=file_loader, keep_trailing_newline=True) + natrules = env.get_template('policy-natrules-template') + + + sheetName = "Firewall-Policy-NatRules" + natrules_auto_tfvars_filename = prefix + "_"+sheetName.lower()+".auto.tfvars" + + filename = inputfile + + outfile = {} + oname = {} + natrules_str = {} + natrules_names = {} + + + # Read cd3 using pandas dataframe + df, col_headers = commonTools.read_cd3(filename, sheetName) + + df = df.dropna(how='all') + df = df.reset_index(drop=True) + + + for reg in ct.all_regions: + natrules_str[reg] = '' + natrules_names[reg] = [] + reg_out_dir = outdir + "/" + reg + "/" + service_dir + resource = sheetName.lower() + commonTools.backup_file(reg_out_dir, resource, natrules_auto_tfvars_filename) + + + # List of the column headers + dfcolumns = df.columns.values.tolist() + + region_seen_so_far = [] + region_list = [] + + for i in df.index: + region = str(df.loc[i, 'Region']) + region = region.strip().lower() + if region.lower() != 'nan' and region in ct.all_regions: + region = region.strip().lower() + if region not in region_seen_so_far: + region_list.append(region) + region_seen_so_far.append(region) + if region in commonTools.endNames: + break + if region != 'nan' and region not in ct.all_regions: + print("\nInvalid Region; It should be one of the regions tenancy is subscribed to...Exiting!!") + exit() + + + + + # temporary dictionaries + tempStr= {} + tempdict= {} + dst_id = '' + src_id = '' + + + + # Fetch data; loop through columns + for columnname in dfcolumns: + + # Column value + columnvalue = str(df[columnname][i]).strip() + + # Check for boolean/null in column values + columnvalue = commonTools.check_columnvalue(columnvalue) + + # Check for multivalued columns + tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) + + + if columnname == "Firewall Policy": + policy_tf_name = commonTools.check_tf_variable(columnvalue) + tempdict = {'policy_tf_name': policy_tf_name} + + if columnname == "Rule Name": + rule_tf_name = commonTools.check_tf_variable(columnvalue) + tempdict = {'rule_tf_name': rule_tf_name,'rule_name':columnvalue} + + if columnname == "Source Address": + if columnvalue != '': + srcaddrs = str(columnvalue).strip().split(",") + if len(srcaddrs) == 1: + for src in srcaddrs: + src_id = "\"" + src.strip() + "\"" + + elif len(srcaddrs) >= 2: + c = 1 + for src in srcaddrs: + data = "\"" + src.strip() + "\"" + + if c == len(srcaddrs): + src_id = src_id + data + else: + src_id = src_id + data + "," + c += 1 + columnvalue = src_id + tempdict = {'src_address': src_id} + + if columnname == "Destination Address": + if columnvalue != '': + dstaddrs = str(columnvalue).strip().split(",") + if len(dstaddrs) == 1: + for dst in dstaddrs: + dst_id = "\"" + dst.strip() + "\"" + + elif len(dstaddrs) >= 2: + c = 1 + for dst in dstaddrs: + data = "\"" + dst.strip() + "\"" + + if c == len(dstaddrs): + dst_id = dst_id + data + else: + dst_id = dst_id + data + "," + c += 1 + columnvalue = dst_id + tempdict = {'dst_address': dst_id} + + if columnname == "Action": + tempdict = {'action': columnvalue} + + if columnname == "Type": + tempdict = {'type': columnvalue} + + if columnname == "Description": + tempdict = {'description': columnvalue} + + if columnname == "Position": + if columnvalue != '': + position = str(columnvalue).strip().split("::") + placement = position[0] + rule_place = position[1] + tempdict = {'placement': placement, 'rule_place': rule_place} + + columnname = commonTools.check_column_headers(columnname) + tempStr[columnname] = str(columnvalue).strip() + tempStr.update(tempdict) + + + natrules_str[region] = natrules_str[region] + natrules.render(tempStr) + + for reg in region_list: + reg_out_dir = outdir + "/" + reg + "/" + service_dir + if not os.path.exists(reg_out_dir): + os.makedirs(reg_out_dir) + outfile[reg] = reg_out_dir + "/" + natrules_auto_tfvars_filename + if natrules_str[reg] != '': + # Generate Final String + src = "##Add New Nat rules for " + reg.lower() + " here##" + natrules_str[reg] = natrules.render(count=0, region=reg).replace(src, natrules_str[reg] + "\n" + src) + natrules_str[reg] = "".join([s for s in natrules_str[reg].strip().splitlines(True) if s.strip("\r\n").strip()]) + natrules_str[reg] = "\n\n" + natrules_str[reg] + oname[reg] = open(outfile[reg], 'a') + oname[reg].write(natrules_str[reg]) + oname[reg].close() + print(outfile[reg] + " containing TF for Firewall Policy Nat rules has been updated for region " + reg) diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secret.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secret.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secret.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secret.py index cf2247a8d..e6b74aa84 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secret.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secret.py @@ -9,9 +9,12 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys + +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secrules.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secrules.py similarity index 98% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secrules.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secrules.py index da479500d..763f9a7ec 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_secrules.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_secrules.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_service.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_service.py similarity index 98% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_service.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_service.py index aa1d20735..0b65993b4 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_service.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_service.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_servicelist.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_servicelist.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_servicelist.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_servicelist.py index 5e39aefa9..746392cbb 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_servicelist.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_servicelist.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_tunnelinspection.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_tunnelinspection.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_tunnelinspection.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_tunnelinspection.py index aa9689dd6..662f218cb 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_tunnelinspection.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_tunnelinspection.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_urllist.py b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_urllist.py similarity index 97% rename from cd3_automation_toolkit/Security/Firewall/fwpolicy_create_urllist.py rename to cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_urllist.py index 2d860db4a..3f4c2bb95 100644 --- a/cd3_automation_toolkit/Security/Firewall/fwpolicy_create_urllist.py +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/fwpolicy_create_urllist.py @@ -9,9 +9,11 @@ # from oci.config import DEFAULT_LOCATION from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -import os +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file AND outdir diff --git a/cd3_automation_toolkit/Security/Firewall/templates/firewall-policies-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/firewall-policies-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/firewall-policies-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/firewall-policies-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/firewalls-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/firewalls-template similarity index 96% rename from cd3_automation_toolkit/Security/Firewall/templates/firewalls-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/firewalls-template index edd380251..4e2de174d 100644 --- a/cd3_automation_toolkit/Security/Firewall/templates/firewalls-template +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/firewalls-template @@ -36,6 +36,9 @@ firewalls = { {% if nsgs %} nsg_id= [{{ nsgs }}] {% endif %} + {% if must_enable_private_nat %} + must_enable_private_nat= "{{ must_enable_private_nat }}" + {% endif %} {# ##Do not modify below this line## #} {# #} {# ###Section for adding Defined and Freeform Tags### #} diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-addresslists-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-addresslists-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-addresslists-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-addresslists-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-applicationlists-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-applicationlists-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-applicationlists-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-applicationlists-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-apps-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-apps-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-apps-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-apps-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-decryptionprofiles-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-decryptionprofiles-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-decryptionprofiles-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-decryptionprofiles-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-decryptrules-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-decryptrules-template similarity index 98% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-decryptrules-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-decryptrules-template index ffdf17331..2745102d0 100644 --- a/cd3_automation_toolkit/Security/Firewall/templates/policy-decryptrules-template +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-decryptrules-template @@ -8,7 +8,7 @@ # network_firewall_policy_id can be the ocid or the name of the firewall Policy that needs to be attached to the Firewall # action can be NO_DECRYPT or DECRYPT # Sample import command for Firewall Policy Decryption Rules: -# terraform import "module.decryption_rules[\"<>\"].oci_network_firewall_network_firewall_policy_decryption_rule.network_firewall_policy_decryption_rule\" networkFirewallPolicies/<>/decryptionRules/<> +# terraform import "module.decryption_rules[\"<>\"].oci_network_firewall_network_firewall_policy_decryption_rule.network_firewall_policy_decryption_rule\" networkFirewallPolicies/<>/decryptionRules/<> ############################ decryption_rules = { diff --git a/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-natrules-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-natrules-template new file mode 100644 index 000000000..23c22a89e --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-natrules-template @@ -0,0 +1,39 @@ +{% if count == 0 %} +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +############################# +# Firewall Policy NAT Rules +# Firewall Policy NAT Rule - tfvars +# Allowed Values: +# network_firewall_policy_id can be the ocid or the name of the firewall Policy that needs to be attached to the Firewall +# action can only be DIPP_SRC_NAT +# Sample import command for Firewall Policy NAT Rules: +# terraform import "module.nat_rules[\"<>\"].oci_network_firewall_network_firewall_policy_nat_rule.test_network_firewall_policy_nat_rule" networkFirewallPolicies/<>/natRules/<> +############################ + +nat_rules = { + ##Add New Nat rules for {{ region|lower }} here## +} +{% else %} + {% if rule_name != "" and rule_name != "nan" and rule_name != null %} + {{ policy_tf_name }}_{{rule_tf_name}} = { + rule_name = "{{ rule_name }}" + action = "{{ action }}" + type = "{{ type }}" + description = "{{ description }}" + network_firewall_policy_id = "{{ policy_tf_name }}" + condition = [{ + {% if source_address != '' %} + source_address = [{{ src_address }}] + {% endif %} + {% if destination_address != '' %} + destination_address = [{{ dst_address }}] + {% endif %} + service = "{{ service }}" + }] + {% if position != '' %} + {{placement}} = "{{ rule_place }}" + {% endif %} + }, + {% endif %} +{% endif %} diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-secrets-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-secrets-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-secrets-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-secrets-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-secrules-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-secrules-template similarity index 99% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-secrules-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-secrules-template index e9af9b785..ad99cfed8 100644 --- a/cd3_automation_toolkit/Security/Firewall/templates/policy-secrules-template +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-secrules-template @@ -9,7 +9,7 @@ # action can be ALLOW, DROP, REJECT, INSPECT # inspection can be INTRUSION_DETECTION, INTRUSION_PREVENTION # Sample import command for Firewall Policy Security Rule: -# terraform import "module.security_rules[\"<>\"].oci_network_firewall_network_firewall_policy_security_rule.network_firewall_policy_security_rule\" networkFirewallPolicies/<>/securityRules/<> +# terraform import "module.security_rules[\"<>\"].oci_network_firewall_network_firewall_policy_security_rule.network_firewall_policy_security_rule\" networkFirewallPolicies/<>/securityRules/<> ############################ security_rules = { diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-servicelists-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-servicelists-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-servicelists-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-servicelists-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-services-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-services-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-services-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-services-template diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-tunnelinspect-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-tunnelinspect-template similarity index 81% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-tunnelinspect-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-tunnelinspect-template index c6d4b5879..9da03d915 100644 --- a/cd3_automation_toolkit/Security/Firewall/templates/policy-tunnelinspect-template +++ b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-tunnelinspect-template @@ -8,7 +8,7 @@ # network_firewall_policy_id can be the ocid or the name of the firewall Policy that needs to be attached to the Firewall # action can be INSPECT_AND_CAPTURE_LOG or INSPECT # Sample import command for Firewall Policy Tunnel inspection Rules: -# terraform import "module.decryption_rules[\"<>\"].oci_network_firewall_network_firewall_policy_tunnel_inspection_rule.network_firewall_policy_tunnel_inspection_rule\" networkFirewallPolicies/<>/tunnelInspectionRules/<> +# terraform import "module.tunnelinspect_rules[\"<>\"].oci_network_firewall_network_firewall_policy_tunnel_inspection_rule.network_firewall_policy_tunnel_inspection_rule\" networkFirewallPolicies/<>/tunnelInspectionRules/<> ############################ tunnelinspect_rules = { diff --git a/cd3_automation_toolkit/Security/Firewall/templates/policy-urllists-template b/cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-urllists-template similarity index 100% rename from cd3_automation_toolkit/Security/Firewall/templates/policy-urllists-template rename to cd3_automation_toolkit/ocicloud/python/security/firewall/templates/policy-urllists-template diff --git a/cd3_automation_toolkit/Security/KeyVault/__init__.py b/cd3_automation_toolkit/ocicloud/python/security/keyvault/__init__.py similarity index 100% rename from cd3_automation_toolkit/Security/KeyVault/__init__.py rename to cd3_automation_toolkit/ocicloud/python/security/keyvault/__init__.py diff --git a/cd3_automation_toolkit/Security/KeyVault/create_terraform_keyvaults.py b/cd3_automation_toolkit/ocicloud/python/security/keyvault/create_terraform_keyvaults.py similarity index 97% rename from cd3_automation_toolkit/Security/KeyVault/create_terraform_keyvaults.py rename to cd3_automation_toolkit/ocicloud/python/security/keyvault/create_terraform_keyvaults.py index 143066369..43270fd41 100644 --- a/cd3_automation_toolkit/Security/KeyVault/create_terraform_keyvaults.py +++ b/cd3_automation_toolkit/ocicloud/python/security/keyvault/create_terraform_keyvaults.py @@ -12,7 +12,10 @@ from pathlib import Path import math from oci.config import DEFAULT_LOCATION -from commonTools import * +import os, sys +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### @@ -121,7 +124,7 @@ def create_terraform_keyvaults(inputfile, outdir, service_dir, prefix, ct): # Process Defined and Freeform Tags if str(columnname).lower() in ["vault defined tags", "vault freeform tags"]: - tempdict_vault = commonTools.split_tag_values(columnname, columnvalue, tempdict_vault) + tempdict_vault = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict_vault) elif columnname == "Vault Compartment Name": vault_compartment_var_name = columnvalue.strip() @@ -174,7 +177,7 @@ def create_terraform_keyvaults(inputfile, outdir, service_dir, prefix, ct): else: # Process Defined and Freeform Tags for keys if str(columnname).lower() in ["key defined tags", "key freeform tags"]: - tempdict_keys = commonTools.split_tag_values(columnname, columnvalue, tempdict_keys) + tempdict_keys = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict_keys) elif columnname == "Key Compartment Name": if columnvalue != '' and columnvalue.lower() != 'nan': diff --git a/cd3_automation_toolkit/Security/KeyVault/export_keyvaults_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py similarity index 99% rename from cd3_automation_toolkit/Security/KeyVault/export_keyvaults_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py index a42bc2031..4860abf4b 100644 --- a/cd3_automation_toolkit/Security/KeyVault/export_keyvaults_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py @@ -12,10 +12,11 @@ from oci.key_management import KmsVaultClient import os import subprocess as sp -sys.path.append(os.getcwd() + "/..") -from commonTools import * from oci.exceptions import TransientServiceError +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools # Execution of the code begins here def export_keyvaults(inputfile, outdir, service_dir, config, signer, ct, export_regions=[], export_compartments=[],export_tags=[]): global values_for_column_kms diff --git a/cd3_automation_toolkit/Security/KeyVault/templates/keys-template b/cd3_automation_toolkit/ocicloud/python/security/keyvault/templates/keys-template similarity index 100% rename from cd3_automation_toolkit/Security/KeyVault/templates/keys-template rename to cd3_automation_toolkit/ocicloud/python/security/keyvault/templates/keys-template diff --git a/cd3_automation_toolkit/Security/KeyVault/templates/vaults-template b/cd3_automation_toolkit/ocicloud/python/security/keyvault/templates/vaults-template similarity index 100% rename from cd3_automation_toolkit/Security/KeyVault/templates/vaults-template rename to cd3_automation_toolkit/ocicloud/python/security/keyvault/templates/vaults-template diff --git a/cd3_automation_toolkit/ocicloud/python/storage/__init__.py b/cd3_automation_toolkit/ocicloud/python/storage/__init__.py new file mode 100644 index 000000000..6529b967d --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/python/storage/__init__.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from .blockvolume import * +from .filesystem import * +from .objectstorage import * \ No newline at end of file diff --git a/cd3_automation_toolkit/Storage/BlockVolume/__init__.py b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/__init__.py similarity index 100% rename from cd3_automation_toolkit/Storage/BlockVolume/__init__.py rename to cd3_automation_toolkit/ocicloud/python/storage/blockvolume/__init__.py diff --git a/cd3_automation_toolkit/Storage/BlockVolume/create_terraform_block_volumes.py b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/create_terraform_block_volumes.py similarity index 98% rename from cd3_automation_toolkit/Storage/BlockVolume/create_terraform_block_volumes.py rename to cd3_automation_toolkit/ocicloud/python/storage/blockvolume/create_terraform_block_volumes.py index 2d1f5c489..4cc92b270 100644 --- a/cd3_automation_toolkit/Storage/BlockVolume/create_terraform_block_volumes.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/create_terraform_block_volumes.py @@ -14,8 +14,9 @@ from oci.config import DEFAULT_LOCATION from pathlib import Path from jinja2 import Environment, FileSystemLoader -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs-CD3 excel file, Config file, prefix AND outdir @@ -110,8 +111,8 @@ def create_terraform_block_volumes(inputfile, outdir, service_dir, prefix,ct): # Process Freeform Tags and Defined Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) if columnname == "Availability Domain(AD1|AD2|AD3)": columnname = "availability_domain" diff --git a/cd3_automation_toolkit/Storage/BlockVolume/export_blockvolumes_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/export_blockvolumes_nonGreenField.py similarity index 97% rename from cd3_automation_toolkit/Storage/BlockVolume/export_blockvolumes_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/storage/blockvolume/export_blockvolumes_nonGreenField.py index c6291fd02..929dbea07 100644 --- a/cd3_automation_toolkit/Storage/BlockVolume/export_blockvolumes_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/export_blockvolumes_nonGreenField.py @@ -10,11 +10,13 @@ import re import oci -import os +import os, sys from oci.core.blockstorage_client import BlockstorageClient from oci.core.compute_client import ComputeClient -from commonTools import * import subprocess as sp +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} oci_obj_names = {} @@ -208,11 +210,11 @@ def print_blockvolumes(region, BVOLS, bvol, compute, ct, values_for_column, ntk_ values_for_column[col_header].append(autotune_type) elif col_header == 'Max VPUS Per GB': values_for_column[col_header].append(max_vpus_per_gb) - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(blockvols, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(blockvols, col_header, values_for_column) else: oci_objs = [blockvols,attachments] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict, values_for_column) # Execution of the code begins here def export_blockvolumes(inputfile, outdir, service_dir, config, signer, ct, export_compartments=[], export_regions=[], export_tags=[],display_names = [], ad_names = []): diff --git a/cd3_automation_toolkit/Storage/BlockVolume/templates/blockvolumes-template b/cd3_automation_toolkit/ocicloud/python/storage/blockvolume/templates/blockvolumes-template similarity index 100% rename from cd3_automation_toolkit/Storage/BlockVolume/templates/blockvolumes-template rename to cd3_automation_toolkit/ocicloud/python/storage/blockvolume/templates/blockvolumes-template diff --git a/cd3_automation_toolkit/Storage/FileSystem/__init__.py b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/__init__.py similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/__init__.py rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/__init__.py diff --git a/cd3_automation_toolkit/Storage/FileSystem/create_terraform_fss.py b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/create_terraform_fss.py similarity index 98% rename from cd3_automation_toolkit/Storage/FileSystem/create_terraform_fss.py rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/create_terraform_fss.py index e3108eb47..2a44ed284 100644 --- a/cd3_automation_toolkit/Storage/FileSystem/create_terraform_fss.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/create_terraform_fss.py @@ -13,8 +13,9 @@ import os from pathlib import Path -sys.path.append(os.getcwd() + "/../..") -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools from jinja2 import Environment, FileSystemLoader @@ -213,8 +214,8 @@ def fss_exports(i, df, tempStr): tempdict = commonTools.check_multivalues_columnvalue(columnvalue, columnname, tempdict) # Process Defined Tags and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) tempStr.update(tempdict) if columnname == 'Compartment Name': diff --git a/cd3_automation_toolkit/Storage/FileSystem/export_fss_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/export_fss_nonGreenField.py similarity index 98% rename from cd3_automation_toolkit/Storage/FileSystem/export_fss_nonGreenField.py rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/export_fss_nonGreenField.py index 640b28d6f..b75de40d2 100644 --- a/cd3_automation_toolkit/Storage/FileSystem/export_fss_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/export_fss_nonGreenField.py @@ -5,11 +5,13 @@ # Oracle Consulting. import oci -import os +import os, sys import re from oci.config import DEFAULT_LOCATION -from commonTools import * import subprocess as sp +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools fs_source_snapshots = {} fss_all_dict = {} @@ -83,11 +85,11 @@ def add_column_data(reg, cname, AD_name, mt_display_name, vplussubnet, mnt_p_ip, values_for_column_fss[col_header].append(tmp_auth) else: values_for_column_fss[col_header].append('') - elif str(col_header).lower() in commonTools.tagColumns: - values_for_column_fss = commonTools.export_tags(fsinfo.data, col_header, values_for_column_fss) + elif str(col_header).lower() in ociCommonTools.tagColumns: + values_for_column_fss = ociCommonTools.export_tags(fsinfo.data, col_header, values_for_column_fss) else: oci_objs = [fsinfo.data, mnt_info1,einfo_path] - values_for_column_fss = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_instances, + values_for_column_fss = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_instances, values_for_column_fss) diff --git a/cd3_automation_toolkit/Storage/FileSystem/templates/export-options-template b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/export-options-template similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/templates/export-options-template rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/export-options-template diff --git a/cd3_automation_toolkit/Storage/FileSystem/templates/export-resource-template b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/export-resource-template similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/templates/export-resource-template rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/export-resource-template diff --git a/cd3_automation_toolkit/Storage/FileSystem/templates/fss-replication-template b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/fss-replication-template similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/templates/fss-replication-template rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/fss-replication-template diff --git a/cd3_automation_toolkit/Storage/FileSystem/templates/fss-template b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/fss-template similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/templates/fss-template rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/fss-template diff --git a/cd3_automation_toolkit/Storage/FileSystem/templates/mount-target-template b/cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/mount-target-template similarity index 100% rename from cd3_automation_toolkit/Storage/FileSystem/templates/mount-target-template rename to cd3_automation_toolkit/ocicloud/python/storage/filesystem/templates/mount-target-template diff --git a/cd3_automation_toolkit/Storage/ObjectStorage/__init__.py b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/__init__.py similarity index 100% rename from cd3_automation_toolkit/Storage/ObjectStorage/__init__.py rename to cd3_automation_toolkit/ocicloud/python/storage/objectstorage/__init__.py diff --git a/cd3_automation_toolkit/Storage/ObjectStorage/create_terraform_oss.py b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/create_terraform_oss.py similarity index 98% rename from cd3_automation_toolkit/Storage/ObjectStorage/create_terraform_oss.py rename to cd3_automation_toolkit/ocicloud/python/storage/objectstorage/create_terraform_oss.py index 3faa39b5c..37a65d12b 100644 --- a/cd3_automation_toolkit/Storage/ObjectStorage/create_terraform_oss.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/create_terraform_oss.py @@ -8,10 +8,12 @@ # Oracle Consulting # Modified (TF Upgrade):Ranjini Rajendran # -import os +import os, sys from pathlib import Path from jinja2 import Environment, FileSystemLoader -from commonTools import * +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir @@ -195,8 +197,8 @@ def create_terraform_oss(inputfile, outdir, service_dir, prefix, ct): tempdict = commonTools.check_multivalues_columnvalue(columnvalue,columnname,tempdict) # Process Defined and Freeform Tags - if columnname.lower() in commonTools.tagColumns: - tempdict = commonTools.split_tag_values(columnname, columnvalue, tempdict) + if columnname.lower() in ociCommonTools.tagColumns: + tempdict = ociCommonTools.split_tag_values(columnname, columnvalue, tempdict) #Compartment name if columnname == "Compartment Name": diff --git a/cd3_automation_toolkit/Storage/ObjectStorage/export_terraform_oss.py b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/export_terraform_oss.py similarity index 96% rename from cd3_automation_toolkit/Storage/ObjectStorage/export_terraform_oss.py rename to cd3_automation_toolkit/ocicloud/python/storage/objectstorage/export_terraform_oss.py index 02aa205f9..e3ed8c8c3 100644 --- a/cd3_automation_toolkit/Storage/ObjectStorage/export_terraform_oss.py +++ b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/export_terraform_oss.py @@ -14,12 +14,12 @@ from oci.object_storage import ObjectStorageClient import os from pathlib import Path -from commonTools import * from jinja2 import Environment, FileSystemLoader -sys.path.append(os.getcwd()+"/..") -from commonTools import * from dateutil import parser import subprocess as sp +sys.path.append(os.getcwd() + "../") +from common.python.commonTools import * +import ocicloud.python.ociCommonTools as ociCommonTools importCommands = {} @@ -69,8 +69,8 @@ def print_buckets(region, outdir, service_dir,state, bucket_data, values_for_col values_for_column[col_header].append('Private') else: values_for_column[col_header].append('Public') - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(bucket_data, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(bucket_data, col_header, values_for_column) elif col_header == 'Retention Rules': values_for_column[col_header].append(retention_rule_data) elif col_header == 'Replication Policy': @@ -140,15 +140,15 @@ def print_buckets(region, outdir, service_dir,state, bucket_data, values_for_col values_for_column[col_header].append('Private') else: values_for_column[col_header].append('Public') - elif col_header.lower() in commonTools.tagColumns: - values_for_column = commonTools.export_tags(bucket_data, col_header, values_for_column) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column = ociCommonTools.export_tags(bucket_data, col_header, values_for_column) elif col_header == 'Retention Rules': values_for_column[col_header].append(retention_rule_data) elif col_header == 'Replication Policy': values_for_column[col_header].append(rp_details) else: oci_objs = [bucket_data] - values_for_column = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) + values_for_column = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict,values_for_column) ###### # Required Inputs- CD3 excel file, Config file, prefix AND outdir diff --git a/cd3_automation_toolkit/Storage/ObjectStorage/templates/oss-template b/cd3_automation_toolkit/ocicloud/python/storage/objectstorage/templates/oss-template similarity index 100% rename from cd3_automation_toolkit/Storage/ObjectStorage/templates/oss-template rename to cd3_automation_toolkit/ocicloud/python/storage/objectstorage/templates/oss-template diff --git a/cd3_automation_toolkit/user-scripts/terraform/README.md b/cd3_automation_toolkit/ocicloud/terraform/README.md similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/README.md rename to cd3_automation_toolkit/ocicloud/terraform/README.md diff --git a/cd3_automation_toolkit/user-scripts/terraform/adb.tf b/cd3_automation_toolkit/ocicloud/terraform/adb.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/adb.tf rename to cd3_automation_toolkit/ocicloud/terraform/adb.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/backend.tf b/cd3_automation_toolkit/ocicloud/terraform/backend.tf similarity index 96% rename from cd3_automation_toolkit/user-scripts/terraform/backend.tf rename to cd3_automation_toolkit/ocicloud/terraform/backend.tf index 72183ffbe..6dbd0f147 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/backend.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/backend.tf @@ -18,7 +18,7 @@ terraform { skip_region_validation = true skip_credentials_validation = true skip_metadata_api_check = true - force_path_style = true + force_path_style = true } } This line will be removed when using remote state*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/block-volume.tf b/cd3_automation_toolkit/ocicloud/terraform/block-volume.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/block-volume.tf rename to cd3_automation_toolkit/ocicloud/terraform/block-volume.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/budget.tf b/cd3_automation_toolkit/ocicloud/terraform/budget.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/budget.tf rename to cd3_automation_toolkit/ocicloud/terraform/budget.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/cloud-guard.tf b/cd3_automation_toolkit/ocicloud/terraform/cloud-guard.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/cloud-guard.tf rename to cd3_automation_toolkit/ocicloud/terraform/cloud-guard.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/database-exacs.tf b/cd3_automation_toolkit/ocicloud/terraform/database-exacs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/database-exacs.tf rename to cd3_automation_toolkit/ocicloud/terraform/database-exacs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/dbsystem-vm-bm.tf b/cd3_automation_toolkit/ocicloud/terraform/dbsystem-vm-bm.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/dbsystem-vm-bm.tf rename to cd3_automation_toolkit/ocicloud/terraform/dbsystem-vm-bm.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/dedicated-vm-host.tf b/cd3_automation_toolkit/ocicloud/terraform/dedicated-vm-host.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/dedicated-vm-host.tf rename to cd3_automation_toolkit/ocicloud/terraform/dedicated-vm-host.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/dns.tf b/cd3_automation_toolkit/ocicloud/terraform/dns.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/dns.tf rename to cd3_automation_toolkit/ocicloud/terraform/dns.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/firewall.tf b/cd3_automation_toolkit/ocicloud/terraform/firewall.tf similarity index 87% rename from cd3_automation_toolkit/user-scripts/terraform/firewall.tf rename to cd3_automation_toolkit/ocicloud/terraform/firewall.tf index e97acf31c..27ebda9fc 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/firewall.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/firewall.tf @@ -12,6 +12,21 @@ data "oci_core_subnets" "firewall_subnets" { display_name = each.value.subnet_id vcn_id = data.oci_core_vcns.firewall_vcns[each.key].virtual_networks.*.id[0] } +data "oci_kms_vaults" "fw_vault" { + for_each = var.secrets + compartment_id = each.value.vault_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.vault_compartment_id)) > 0 ? each.value.vault_compartment_id : var.compartment_ocids[each.value.vault_compartment_id]) : var.compartment_ocids[each.value.vault_compartment_id] + filter { + name = "display_name" + values = [each.value.vault_name] + } +} + +data "oci_vault_secrets" "fw_secret" { + for_each = var.secrets + compartment_id = each.value.vault_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.vault_compartment_id)) > 0 ? each.value.vault_compartment_id : var.compartment_ocids[each.value.vault_compartment_id]) : var.compartment_ocids[each.value.vault_compartment_id] + name = each.value.vault_secret_id + vault_id = data.oci_kms_vaults.fw_vault[each.key].vaults.*.id[0] +} module "firewalls" { source = "./modules/security/firewall/firewall" @@ -28,6 +43,7 @@ module "firewalls" { vcn_name = each.value.vcn_name defined_tags = each.value.defined_tags freeform_tags = each.value.freeform_tags + must_enable_private_nat = each.value.must_enable_private_nat } @@ -129,9 +145,7 @@ module "secrets" { network_firewall_policy_id = length(regexall("ocid1.networkfirewallpolicy.oc*", each.value.network_firewall_policy_id)) > 0 ? each.value.network_firewall_policy_id : merge(module.policies.*...)[each.value.network_firewall_policy_id]["policy_tf_id"] secret_source = each.value.secret_source secret_type = each.value.secret_type - vault_secret_id = each.value.vault_secret_id - vault_name = each.value.vault_name - compartment_id = each.value.vault_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.vault_compartment_id)) > 0 ? each.value.vault_compartment_id : var.compartment_ocids[each.value.vault_compartment_id]) : var.compartment_ocids[each.value.vault_compartment_id] + vault_secret_id = length(regexall("ocid1.vaultsecret.oc*", each.value.vault_secret_id)) > 0 ? each.value.vault_secret_id : data.oci_vault_secrets.fw_secret[each.key].secrets.*.id[0] version_number = each.value.version_number } @@ -182,6 +196,21 @@ module "tunnelinspect_rules" { protocol = each.value.protocol } +module "nat_rules" { + source = "./modules/security/firewall/nat-rules" + for_each = var.nat_rules != null ? var.nat_rules : {} + depends_on = [module.policies, module.address_lists, module.service_lists] + action = each.value.action + rule_name = each.value.rule_name + description = each.value.description + type = each.value.type + network_firewall_policy_id = length(regexall("ocid1.networkfirewallpolicy.oc*", each.value.network_firewall_policy_id)) > 0 ? each.value.network_firewall_policy_id : merge(module.policies.*...)[each.value.network_firewall_policy_id]["policy_tf_id"] + source_address = each.value.condition[0].source_address != null ? each.value.condition[0].source_address : [] + destination_address = each.value.condition[0].destination_address != null ? each.value.condition[0].destination_address : [] + service = each.value.condition[0].service != null ? each.value.condition[0].service : "" + after_rule = each.value.after_rule + before_rule = each.value.before_rule +} ############################# # Module Block - Network Firewall Logging @@ -237,4 +266,4 @@ module "fw-logs" { output "vcn_logs_id" { value = [ for k,v in merge(module.vcn-logs.*...) : v.log_tf_id] } -*/ \ No newline at end of file +*/ diff --git a/cd3_automation_toolkit/user-scripts/terraform/fss.tf b/cd3_automation_toolkit/ocicloud/terraform/fss.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/fss.tf rename to cd3_automation_toolkit/ocicloud/terraform/fss.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/identity.tf b/cd3_automation_toolkit/ocicloud/terraform/identity.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/identity.tf rename to cd3_automation_toolkit/ocicloud/terraform/identity.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/instance.tf b/cd3_automation_toolkit/ocicloud/terraform/instance.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/instance.tf rename to cd3_automation_toolkit/ocicloud/terraform/instance.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/kms.tf b/cd3_automation_toolkit/ocicloud/terraform/kms.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/kms.tf rename to cd3_automation_toolkit/ocicloud/terraform/kms.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/loadbalancer.tf b/cd3_automation_toolkit/ocicloud/terraform/loadbalancer.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/loadbalancer.tf rename to cd3_automation_toolkit/ocicloud/terraform/loadbalancer.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/managementservices.tf b/cd3_automation_toolkit/ocicloud/terraform/managementservices.tf similarity index 84% rename from cd3_automation_toolkit/user-scripts/terraform/managementservices.tf rename to cd3_automation_toolkit/ocicloud/terraform/managementservices.tf index 3347b3532..001567519 100755 --- a/cd3_automation_toolkit/user-scripts/terraform/managementservices.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/managementservices.tf @@ -9,12 +9,12 @@ module "alarms" { source = "./modules/managementservices/alarm" - depends_on = [module.notifications-topics] + depends_on = [module.notifications] for_each = var.alarms != null ? var.alarms : {} alarm_name = each.value.alarm_name compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null - destinations = [for tn in each.value.destinations : (length(regexall("ocid1.onstopic.oc*", tn)) > 0 ? tn : merge(module.notifications-topics.*...)[tn]["topic_tf_id"])] + destinations = [for tn in each.value.destinations : (length(regexall("ocid1.onstopic.oc*", tn)) > 0 ? tn : merge(module.notifications.*...)[tn]["topic_tf_id"])] is_enabled = each.value.is_enabled metric_compartment_id = each.value.metric_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.metric_compartment_id)) > 0 ? each.value.metric_compartment_id : var.compartment_ocids[each.value.metric_compartment_id]) : null namespace = each.value.namespace @@ -43,7 +43,7 @@ output "alarms_id" { module "events" { source = "./modules/managementservices/event" - depends_on = [module.notifications-topics] + depends_on = [module.notifications] for_each = var.events != null ? var.events : {} event_name = each.value.event_name @@ -53,7 +53,7 @@ module "events" { condition = each.value.condition actions = var.events key_name = each.key - topic_name = merge(module.notifications-topics.*...) + topic_name = merge(module.notifications.*...) #Optional defined_tags = each.value.defined_tags @@ -71,28 +71,14 @@ output "events_id" { # Create Notifications ############################ -module "notifications-topics" { - source = "./modules/managementservices/notification-topic" - for_each = var.notifications_topics != null ? var.notifications_topics : {} +module "notifications" { + source = "./modules/managementservices/notification" + for_each = var.notifications != null ? var.notifications : {} compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null description = each.value.description topic_name = each.value.topic_name - - #Optional - defined_tags = each.value.defined_tags - freeform_tags = each.value.freeform_tags -} - -module "notifications-subscriptions" { - source = "./modules/managementservices/notification-subscription" - for_each = var.notifications_subscriptions != null ? var.notifications_subscriptions : {} - - depends_on = [module.notifications-topics] - compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null - endpoint = each.value.endpoint - protocol = each.value.protocol - topic_id = length(regexall("ocid1.onstopic.oc*", each.value.topic_id)) > 0 ? each.value.topic_id : merge(module.notifications-topics.*...)[each.value.topic_id]["topic_tf_id"] + subscriptions = each.value.subscriptions != null ? each.value.subscriptions : [] #Optional defined_tags = each.value.defined_tags freeform_tags = each.value.freeform_tags diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget-alert-rule/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/compute/instance/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/costmanagement/budget/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget-alert-rule/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/costmanagement/budget/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/dbsystem-vm-bm/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/adb/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-infra/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/dbsystem-vm-bm/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/exa-vmcluster/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-infra/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-configuration/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/exa-vmcluster/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/database/mysql-dbsystem/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-configuration/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/quota-policy/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/database/mysql-dbsystem/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-default/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/quota-policy/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-key/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-default/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/governance/tagging/tag-namespace/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-key/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-compartment/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/governance/tagging/tag-namespace/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-group/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-compartment/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-network-sources/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-group/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-policy/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-network-sources/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/iam-user/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-policy/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-group/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/iam-user/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/identity/identity-domain-user/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-group/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/public-ip-pool/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/identity/identity-domain-user/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/reserved-public-ip/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/public-ip-pool/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/ip/secondary-private-ip/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/reserved-public-ip/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend-set/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/ip/secondary-private-ip/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-backend/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend-set/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-certificate/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-backend/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-cipher-suite/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-certificate/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-hostname/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-cipher-suite/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-listener/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-hostname/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-load-balancer/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-listener/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-path-route-set/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/oracle_provider_req.tf old mode 100644 new mode 100755 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-load-balancer/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-routing-policy/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-path-route-set/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/loadbalancer/lb-rule-set/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/oracle_provider_req.tf old mode 100755 new mode 100644 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-routing-policy/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/alarm/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/loadbalancer/lb-rule-set/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/event/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/alarm/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log-group/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/event/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/log/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/main.tf similarity index 54% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/main.tf index b471cc175..dcde61369 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/main.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/main.tf @@ -18,3 +18,20 @@ resource "oci_ons_notification_topic" "topic" { freeform_tags = var.freeform_tags } + +resource "oci_ons_subscription" "subscription" { + + count = length(var.subscriptions) + #Required + compartment_id = var.compartment_id + endpoint = var.subscriptions[count.index].endpoint + protocol = var.subscriptions[count.index].protocol + topic_id = oci_ons_notification_topic.topic.id + + #Optional + defined_tags = var.defined_tags + freeform_tags = var.freeform_tags + lifecycle { + ignore_changes = [defined_tags,freeform_tags] + } +} \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log-group/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/variables.tf similarity index 91% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/variables.tf index 47d1f8ddb..c1498caf7 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/variables.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/notification/variables.tf @@ -13,6 +13,10 @@ variable "compartment_id" { variable "topic_name" { type = string } +variable "subscriptions" { +type = list(map(any)) +default = [] +} variable "description" { type = string } diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/oracle_provider_req.tf old mode 100644 new mode 100755 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/log/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/managementservices/service-connector/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/custom-dhcp/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-topic/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/default-dhcp/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/oracle_provider_req.tf old mode 100755 new mode 100644 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/service-connector/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/dns_resolver/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/custom-dhcp/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/rrset/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/default-dhcp/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/view/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/dns_resolver/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/dns/zone/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/rrset/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-attachment/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/view/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution-statement/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/dns/zone/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-distribution/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-attachment/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-rule/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution-statement/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg-route-table/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-distribution/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/drg/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-rule/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/igw/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg-route-table/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/lpg/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/drg/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/ngw/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/igw/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg-rule/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/lpg/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/nsg/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/ngw/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/route-table/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg-rule/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sec-list/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/nsg/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/sgw/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/main.tf similarity index 90% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/main.tf index f822ae0c4..d9ae8f16d 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/main.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/main.tf @@ -24,6 +24,7 @@ resource "oci_core_subnet" "subnet" { prohibit_internet_ingress = var.prohibit_internet_ingress prohibit_public_ip_on_vnic = var.prohibit_public_ip_on_vnic route_table_id = var.route_table_id - security_list_ids = var.security_list_ids != [] ? [for sl in var.security_list_ids : (length(regexall("ocid1.securitylist.oc*", sl)) > 0 ? sl : (sl == "" ? var.vcn_default_security_list_id : var.custom_security_list_id[sl]["seclist_tf_id"]))] : [] + security_list_ids = var.security_list_ids != [] ? [for sl in var.security_list_ids : (length(regexall("ocid1.securitylist.oc*", sl)) > 0 ? sl : (sl == "" ? var.vcn_default_security_list_id : (contains(keys(var.custom_security_list_id), sl) ? var.custom_security_list_id[sl]["seclist_tf_id"] : sl +)))] : [] } \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/route-table/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/subnet/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sec-list/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vcn/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/sgw/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/network/vlan/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/subnet/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backend/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vcn/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-backendset/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/network/vlan/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb-listener/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backend/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/networkloadbalancer/nlb/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-backendset/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/cluster/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb-listener/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/nodepool/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/networkloadbalancer/nlb/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/oke/virtual-nodepool/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/oracle_provider_req.tf old mode 100644 new mode 100755 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/cluster/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc-cluster/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/oracle_provider_req.tf old mode 100644 new mode 100755 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/nodepool/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/sddc/sddc/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/oke/virtual-nodepool/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-configuration/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/oracle_provider_req.tf old mode 100755 new mode 100644 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc-cluster/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/cloud-guard-target/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/oracle_provider_req.tf old mode 100755 new mode 100644 similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/sddc/sddc/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/address-list/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-configuration/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application-group/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/cloud-guard-target/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/application/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/address-list/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-profile/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application-group/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/decryption-rules/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/application/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall-policy/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/main.tf similarity index 90% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/main.tf index ebfd7ba4e..834e37d5b 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/main.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/main.tf @@ -12,6 +12,9 @@ resource "oci_network_firewall_network_firewall" "network_firewall" { network_security_group_ids = var.nsg_id != null ? (local.nsg_id == [] ? ["INVALID NSG Name"] : local.nsg_id) : null defined_tags = var.defined_tags freeform_tags = var.freeform_tags + nat_configuration { + must_enable_private_nat = var.must_enable_private_nat + } lifecycle { ignore_changes = [defined_tags["Oracle-Tags.CreatedOn"], defined_tags["Oracle-Tags.CreatedBy"], defined_tags["SE_Details.SE_Name"]] } diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-profile/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/variable.tf similarity index 94% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/variable.tf index 602ee82ea..7389e6ecb 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/variable.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/firewall/variable.tf @@ -71,11 +71,17 @@ variable "name" { default = null } +variable "must_enable_private_nat" { + type = string + default = null +} + variable "defined_tags" { type = map(any) default = {} } + variable "freeform_tags" { type = map(any) default = {} diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/data.tf diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/main.tf new file mode 100644 index 000000000..50a3ecfec --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/main.tf @@ -0,0 +1,22 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +resource "oci_network_firewall_network_firewall_policy_nat_rule" "network_firewall_policy_nat_rule" { + lifecycle { + ignore_changes = [position] + } + name = var.rule_name + action = var.action + type = var.type + description = var.description + network_firewall_policy_id = var.network_firewall_policy_id + condition { + destination_address = var.destination_address + source_address = var.source_address + service = var.service + } + position { + after_rule = var.after_rule + before_rule = var.before_rule + } +} diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/decryption-rules/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/output.tf new file mode 100755 index 000000000..a618e41e4 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/output.tf @@ -0,0 +1,6 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +output "nat_rules_tf_id" { + value = oci_network_firewall_network_firewall_policy_nat_rule.network_firewall_policy_nat_rule.id +} \ No newline at end of file diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/variable.tf new file mode 100644 index 000000000..7963d3131 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/nat-rules/variable.tf @@ -0,0 +1,155 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +variable "compartment_id" { + type = string + default = null +} +variable "subnet_name" { + type = string + default = null +} + +variable "vcn_name" { + type = string + default = null +} +variable "network_firewall_policy_id" { + type = string + default = null +} + +variable "display_name" { + type = string + default = null +} + +variable "ipv4address" { + type = string + default = null +} + +variable "icmp_type" { + type = number + default = null + +} + +variable "icmp_code" { + type = number + default = null +} +variable "minimum_port" { + type = number + default = null +} + +variable "maximum_port" { + type = number + default = null +} + +variable "service_name" { + type = string + default = null +} + +variable "service_type" { + type = string + default = null +} + +variable "region" { + type = string + default = "us-ashburn-1" +} + +variable "type" { + type = string + default = null +} + +variable "name" { + type = string + default = null +} + +variable "policy" { + type = map(any) + default = {} +} + +variable "service_port_ranges" { + type = map(any) + default = {} +} + +variable "key_name" { + type = string + default = null +} + +variable "rule_condition" { + type = map(any) + default = {} +} +variable "rule_position" { + type = map(any) + default = {} +} +variable "key_name1" { + type = string + default = null +} + +variable "key_name2" { + type = string + default = null +} + +variable "rule_name" { + type = string + default = null +} + +variable "action" { + type = string + default = null +} + +variable "service" { + type = string + default = null +} + +variable "description" { + type = string + default = null +} + +variable "destination_address" { + type = list(string) + default = [] +} +variable "source_address" { + type = list(string) + default = [] +} + + +variable "after_rule" { + type = string + default = null +} +variable "before_rule" { + type = string + default = null +} + +variable "protocol" { + type = string + default = null +} + + + diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/data.tf similarity index 94% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/data.tf index 272cd2a8b..81f4234d3 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/data.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/data.tf @@ -1,7 +1,7 @@ # Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. # -data "oci_kms_vaults" "fw_vault" { +/*data "oci_kms_vaults" "fw_vault" { compartment_id = var.compartment_id != null ? var.compartment_id : var.compartment_id filter { name = "display_name" @@ -18,4 +18,4 @@ data "oci_vault_secrets" "fw_secret" { locals { secret_ocid = tostring(data.oci_vault_secrets.fw_secret.secrets[0].id) -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/main.tf similarity index 92% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/main.tf index 8744045b2..e87e848cc 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/main.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/main.tf @@ -7,6 +7,6 @@ resource "oci_network_firewall_network_firewall_policy_mapped_secret" "network_f network_firewall_policy_id = var.network_firewall_policy_id source = var.secret_source type = var.secret_type - vault_secret_id = local.secret_ocid + vault_secret_id = var.vault_secret_id version_number = var.version_number } \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall-policy/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/secret/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/firewall/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/security-rules/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/secret/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service-list/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/security-rules/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/service/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service-list/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/tunnel-inspect/variable.tf diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/data.tf new file mode 100644 index 000000000..84adb07b0 --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/data.tf @@ -0,0 +1,11 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +/*locals { + policy_ocid = data.oci_network_firewall_network_firewall_policies.fw-policy.network_firewall_policy_summary_collection[*].id + +} +data "oci_network_firewall_network_firewall_policies" "fw-policy" { + compartment_id = var.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", var.compartment_id)) > 0 ? var.compartment_id : var.compartment_ocids[var.compartment_id]) : var.compartment_ocids[var.compartment_id] + display_name = var.network_firewall_policy_id +*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/service/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/output.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/output.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/output.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/output.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/variable.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/variable.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/variable.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/firewall/url-list/variable.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/key/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/key/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/key/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/key/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/key/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/tunnel-inspect/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/key/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/key/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/key/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/key/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/key/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/key/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/key/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/key/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/key/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/firewall/url-list/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/security/vault/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/key/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/key/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/block-volume/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/security/vault/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/export-option/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/block-volume/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss-replication/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/export-option/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/fss/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/data.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss-replication/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/mount-target/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/file-storage/mount-target/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/main.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/main.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/main.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/oracle_provider_req.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/file-storage/fss/oracle_provider_req.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/oracle_provider_req.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/outputs.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/outputs.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/outputs.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/outputs.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/variables.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/modules/storage/object-storage/variables.tf rename to cd3_automation_toolkit/ocicloud/terraform/modules/storage/object-storage/variables.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/mysql-dbsystem.tf b/cd3_automation_toolkit/ocicloud/terraform/mysql-dbsystem.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/mysql-dbsystem.tf rename to cd3_automation_toolkit/ocicloud/terraform/mysql-dbsystem.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/network.tf b/cd3_automation_toolkit/ocicloud/terraform/network.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/network.tf rename to cd3_automation_toolkit/ocicloud/terraform/network.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/networkloadbalancer.tf b/cd3_automation_toolkit/ocicloud/terraform/networkloadbalancer.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/networkloadbalancer.tf rename to cd3_automation_toolkit/ocicloud/terraform/networkloadbalancer.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/nsg.tf b/cd3_automation_toolkit/ocicloud/terraform/nsg.tf similarity index 93% rename from cd3_automation_toolkit/user-scripts/terraform/nsg.tf rename to cd3_automation_toolkit/ocicloud/terraform/nsg.tf index b9554b7c8..31898e855 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/nsg.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/nsg.tf @@ -21,7 +21,7 @@ module "nsgs" { #Required compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null - vcn_id = flatten(data.oci_core_vcns.oci_vcns_nsgs[each.key].virtual_networks.*.id)[0] + vcn_id = length(regexall("ocid1.vcn.oc*", each.value.vcn_name)) > 0 ? each.value.vcn_name :flatten(data.oci_core_vcns.oci_vcns_nsgs[each.key].virtual_networks.*.id)[0] defined_tags = each.value.defined_tags display_name = each.value.display_name freeform_tags = each.value.freeform_tags diff --git a/cd3_automation_toolkit/user-scripts/terraform/object-storage.tf b/cd3_automation_toolkit/ocicloud/terraform/object-storage.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/object-storage.tf rename to cd3_automation_toolkit/ocicloud/terraform/object-storage.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/oci-data.tf b/cd3_automation_toolkit/ocicloud/terraform/oci-data.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/oci-data.tf rename to cd3_automation_toolkit/ocicloud/terraform/oci-data.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/oke.tf b/cd3_automation_toolkit/ocicloud/terraform/oke.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/oke.tf rename to cd3_automation_toolkit/ocicloud/terraform/oke.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/provider.tf b/cd3_automation_toolkit/ocicloud/terraform/provider.tf similarity index 96% rename from cd3_automation_toolkit/user-scripts/terraform/provider.tf rename to cd3_automation_toolkit/ocicloud/terraform/provider.tf index 34c1879f0..209d3428c 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/provider.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/provider.tf @@ -19,7 +19,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = "7.8.0" + version = "7.18.0" } } } diff --git a/cd3_automation_toolkit/user-scripts/terraform/quota.tf b/cd3_automation_toolkit/ocicloud/terraform/quota.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/quota.tf rename to cd3_automation_toolkit/ocicloud/terraform/quota.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/scripts/bastion-ssh-key b/cd3_automation_toolkit/ocicloud/terraform/scripts/bastion-ssh-key similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/scripts/bastion-ssh-key rename to cd3_automation_toolkit/ocicloud/terraform/scripts/bastion-ssh-key diff --git a/cd3_automation_toolkit/user-scripts/terraform/scripts/default.sh b/cd3_automation_toolkit/ocicloud/terraform/scripts/default.sh similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/scripts/default.sh rename to cd3_automation_toolkit/ocicloud/terraform/scripts/default.sh diff --git a/cd3_automation_toolkit/user-scripts/terraform/scripts/default.yaml b/cd3_automation_toolkit/ocicloud/terraform/scripts/default.yaml similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/scripts/default.yaml rename to cd3_automation_toolkit/ocicloud/terraform/scripts/default.yaml diff --git a/cd3_automation_toolkit/user-scripts/terraform/scripts/server-ssh-key b/cd3_automation_toolkit/ocicloud/terraform/scripts/server-ssh-key similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/scripts/server-ssh-key rename to cd3_automation_toolkit/ocicloud/terraform/scripts/server-ssh-key diff --git a/cd3_automation_toolkit/user-scripts/terraform/sddc.tf b/cd3_automation_toolkit/ocicloud/terraform/sddc.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/sddc.tf rename to cd3_automation_toolkit/ocicloud/terraform/sddc.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/tagging.tf b/cd3_automation_toolkit/ocicloud/terraform/tagging.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/tagging.tf rename to cd3_automation_toolkit/ocicloud/terraform/tagging.tf diff --git a/cd3_automation_toolkit/user-scripts/terraform/variables_example.tf b/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf similarity index 99% rename from cd3_automation_toolkit/user-scripts/terraform/variables_example.tf rename to cd3_automation_toolkit/ocicloud/terraform/variables_example.tf index f788d1086..0e3aea4b1 100644 --- a/cd3_automation_toolkit/user-scripts/terraform/variables_example.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf @@ -1721,10 +1721,11 @@ variable "events" { default = {} } -variable "notifications_topics" { +variable "notifications" { type = map(object({ compartment_id = string topic_name = string + subscriptions = optional (list(map(any))) description = optional(string) defined_tags = optional(map(any)) freeform_tags = optional(map(any)) @@ -1732,17 +1733,6 @@ variable "notifications_topics" { default = {} } -variable "notifications_subscriptions" { - type = map(object({ - compartment_id = string - endpoint = string - protocol = string - topic_id = string - defined_tags = optional(map(any)) - freeform_tags = optional(map(any)) - })) - default = {} -} variable "service_connectors" { type = any @@ -2081,6 +2071,7 @@ variable "firewalls" { availability_domain = optional(string) defined_tags = optional(map(any)) freeform_tags = optional(map(any)) + must_enable_private_nat = optional(string) })) default = {} } @@ -2215,11 +2206,8 @@ variable "decryption_rules" { rule_name = string network_firewall_policy_id = string condition = optional(list(object({ - - destination_address = optional(list(string)) - - source_address = optional(list(string)) - + destination_address = optional(list(string)) + source_address = optional(list(string)) }))) decryption_profile = optional(string) secret = optional(string) @@ -2245,6 +2233,24 @@ variable "tunnelinspect_rules" { })) default = {} } + +variable "nat_rules" { + type = map(object({ + action = string + type = string + rule_name = string + network_firewall_policy_id = string + condition = optional(list(object({ + destination_address = optional(list(string)) + source_address = optional(list(string)) + service = string + }))) + description = optional(string) + after_rule = optional(string) + before_rule = optional(string) + })) + default = {} +} ######################### ####### Firewall Logs ######## ######################### diff --git a/cd3_automation_toolkit/user-scripts/terraform/vlan.tf b/cd3_automation_toolkit/ocicloud/terraform/vlan.tf similarity index 100% rename from cd3_automation_toolkit/user-scripts/terraform/vlan.tf rename to cd3_automation_toolkit/ocicloud/terraform/vlan.tf diff --git a/cd3_automation_toolkit/setUpAzure.properties b/cd3_automation_toolkit/setUpAzure.properties new file mode 100644 index 000000000..8391c2dbf --- /dev/null +++ b/cd3_automation_toolkit/setUpAzure.properties @@ -0,0 +1,25 @@ +[Default] + +#Input variables required to run setUpAzure script + +#path to output directory where terraform files will be generated. eg. /cd3user/azure//terraform_files +outdir= + +#prefix for output terraform files eg demo +prefix= + +# Auth Params +subscription_id= + +tenant_id= + +client_id= + +client_secret= + +#path to cd3 excel eg /cd3user/azure//CD3-Customer.xlsx +cd3file= + +#specify create_resources to create new resources in Azure(greenfield workflow) +#specify export_resources to export resources from Azure(non-greenfield workflow) +workflow_type=create_resources \ No newline at end of file diff --git a/cd3_automation_toolkit/setUpCloud.py b/cd3_automation_toolkit/setUpCloud.py new file mode 100644 index 000000000..b32919603 --- /dev/null +++ b/cd3_automation_toolkit/setUpCloud.py @@ -0,0 +1,30 @@ +import sys +import subprocess + + +def main(): + if len(sys.argv) != 3: + print("Usage: python setUpCloud.py ") + print("Example: python setUpCloud.py azure setUpAzure.properties") + print("Example: python setUpCloud.py oci setUpOCI.properties") + return + + cloud_provider = sys.argv[1].lower() + argument = sys.argv[2] + + if cloud_provider == 'oci': + script_name = 'setUpOCI.py' + elif cloud_provider == 'azure': + script_name = 'user-scripts/setUpAzure.py' + else: + print("Invalid cloud provider. Use 'azure' or 'oci'.") + return + + try: + subprocess.run([sys.executable, script_name, argument], check=True) + except subprocess.CalledProcessError as e: + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/cd3_automation_toolkit/setUpOCI.properties b/cd3_automation_toolkit/setUpOCI.properties index 1a0e8e52b..405ea2390 100644 --- a/cd3_automation_toolkit/setUpOCI.properties +++ b/cd3_automation_toolkit/setUpOCI.properties @@ -2,16 +2,16 @@ #Input variables required to run setUpOCI script -#path to output directory where terraform files will be generated. eg. /cd3user/tenancies//terraform_files +#path to output directory where terraform files will be generated. eg. /cd3user/tenancies//terraform_files outdir= -#prefix for output terraform files eg like demo +#prefix for output terraform files eg like demo prefix= # auth mechanism for OCI APIs - api_key,instance_principal,session_token auth_mechanism= -#input config file for Python API communication with OCI eg /cd3user/tenancies//.config_files/_config; +#input config file for Python API communication with OCI eg /cd3user/tenancies//.config_files/_config; config_file= # Leave it blank if you want single outdir or specify outdir_structure_file.properties containing directory structure for OCI services. @@ -20,7 +20,7 @@ outdir_structure_file= # IaC Tool to be configured - Terraform(specify terraform) or OpenTofu(specify tofu) tf_or_tofu= -#path to cd3 excel eg /cd3user/tenancies//CD3-Customer.xlsx +#path to cd3 excel eg /cd3user/tenancies//CD3-Customer.xlsx cd3file= #specify create_resources to create new resources in OCI(greenfield workflow) diff --git a/cd3_automation_toolkit/setUpOCI.py b/cd3_automation_toolkit/setUpOCI.py index 8025eabc9..358ca939f 100644 --- a/cd3_automation_toolkit/setUpOCI.py +++ b/cd3_automation_toolkit/setUpOCI.py @@ -1,24 +1,12 @@ import argparse import configparser import json -import Database -import Identity -import Compute -import ManagementServices -import DeveloperServices -import Security -import cd3Validator -import cd3FirewallValidator -import Storage -import Network -import SDDC -import Governance -import CostManagement -from commonTools import * from collections import namedtuple import requests import subprocess -import datetime,glob,os +import glob +from ocicloud.python import * +from common.python import * def show_firewall_options(options, quit=False, menu=False, extra=None, index=0): # Just add whitespace between number and option. It just makes it look better @@ -391,7 +379,7 @@ def export_identityOptions(prim_options=[]): def export_compartments(inputfile, outdir,config, signer, ct): resource = 'Compartments' - Identity.export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct) + export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct) options = [Option(None, create_compartments, 'Processing Compartments Tab'), ] execute_options(options) print("\n\nExecute import_commands_compartments.sh script created under home region directory to synch TF with OCI Identity Compartments\n") @@ -399,7 +387,7 @@ def export_compartments(inputfile, outdir,config, signer, ct): def export_policies(inputfile, outdir,config, signer, ct): resource = 'IAM Policies' #compartments = ct.get_compartment_map(var_file, resource) - Identity.export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct, export_compartments=compartments) + export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct, export_compartments=compartments) options = [Option(None, create_policies, 'Processing Policies Tab'), ] execute_options(options) print("\n\nExecute import_commands_policies.sh script created under home region directory to synch TF with OCI " +resource +"\n") @@ -407,7 +395,7 @@ def export_policies(inputfile, outdir,config, signer, ct): def export_groups(inputfile, outdir,config, signer, ct): resource = 'IAM Groups' selected_domains_data = ct.get_identity_domain_data(config, signer, resource,var_file) - Identity.export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct, export_domains=selected_domains_data) + export_identity(inputfile, outdir, service_dir_identity,resource, config, signer, ct, export_domains=selected_domains_data) options = [Option(None, create_groups, 'Processing Groups Tab'), ] execute_options(options) print("\n\nExecute import_commands_groups.sh script created under home region directory to synch TF with OCI " +resource +"\n") @@ -417,16 +405,16 @@ def export_users(inputfile, outdir,config,signer, ct): resource = 'IAM Users' # check if tenancy is identity_domain enabled selected_domains_data = ct.get_identity_domain_data(config, signer, resource,var_file) - Identity.Users.export_users(inputfile, outdir, service_dir_identity, config, signer, ct,export_domains=selected_domains_data) - options = [Option(None, Identity.Users.create_terraform_users, 'Processing Users Tab'), ] + identity.export_users(inputfile, outdir, service_dir_identity, config, signer, ct,export_domains=selected_domains_data) + options = [Option(None, create_terraform_users, 'Processing Users Tab'), ] execute_options(options,inputfile, outdir,service_dir_identity, prefix, ct) print("\n\nExecute import_commands_users.sh script created under home region directory to synch TF with OCI " +resource +"\n") def export_networkSources(inputfile, outdir, config, signer, ct): resource = 'Network Sources' - Identity.NetworkSources.export_networkSources(inputfile, outdir, service_dir_identity, config, signer, ct) - options = [Option(None, Identity.NetworkSources.create_terraform_networkSources, 'Processing NetworkSources Tab'), ] + identity.export_networkSources(inputfile, outdir, service_dir_identity, config, signer, ct) + options = [Option(None, create_terraform_networkSources, 'Processing NetworkSources Tab'), ] execute_options(options, inputfile, outdir, service_dir_identity, prefix, ct) print("\n\nExecute import_commands_networkSources.sh script created under home region directory to synch TF with OCI " +resource +"\n") @@ -442,7 +430,7 @@ def export_governance(prim_options=[]): def export_tags(prim_options=[]): #compartments = ct.get_compartment_map(var_file, 'Tagging Objects') - Governance.export_tags_nongreenfield(inputfile, outdir, service_dir_tagging, config, signer, ct, export_compartments=compartments) + export_tags_nongreenfield(inputfile, outdir, service_dir_tagging, config, signer, ct, export_compartments=compartments) options = [Option(None, create_tags, 'Processing Tags Tab'), ] execute_options(options) print("\n\nExecute import_commands_tags.sh script created under home region directory to synch TF with OCI Tags\n") @@ -450,7 +438,7 @@ def export_tags(prim_options=[]): update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_tagging]) def export_quotas(prim_options=[]): - Governance.export_quotas_nongreenfield(inputfile, outdir, service_dir_quota, config, signer, ct, export_tags=export_tags_list) + export_quotas_nongreenfield(inputfile, outdir, service_dir_quota, config, signer, ct, export_tags=export_tags_list) options = [Option(None, create_quotas, 'Processing Quotas Tab'), ] execute_options(options) print("\n\nExecute import_commands_quotas.sh script created under home region directory to synch TF with OCI Quota\n") @@ -468,7 +456,7 @@ def export_cost_management(prim_options=[]): execute_options(options) def export_budget(prim_options=[]): - CostManagement.export_budgets_nongreenfield(inputfile, outdir, service_dir_budget, config, signer, ct,export_regions,export_tags_list) + export_budgets_nongreenfield(inputfile, outdir, service_dir_budget, config, signer, ct,export_regions,export_tags_list) options = [Option(None, create_budgets, 'Processing Budgets Tab')] execute_options(options) print("\n\nExecute import_commands_budgets.sh script created under each region directory to synch TF with OCI Tags\n") @@ -512,34 +500,34 @@ def export_networking(inputfile, outdir,config, signer, ct, export_regions,expor service_dirs = [] service_dir = outdir_struct #compartments = ct.get_compartment_map(var_file,'Network Objects') - Network.export_networking(inputfile, outdir, service_dir,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) - options = [ Option(None, Network.create_major_objects, 'Processing VCNs and DRGs Tab'), ] + network.export_networking(inputfile, outdir, service_dir,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + options = [ Option(None, create_major_objects, 'Processing VCNs and DRGs Tab'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy) - options = [ Option(None, Network.create_rpc_resource, 'Processing RPCs in DRGs Tab'),] + options = [ Option(None, create_rpc_resource, 'Processing RPCs in DRGs Tab'),] execute_options(options, inputfile, outdir, service_dir_network, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy) options = [ - Option(None, Network.create_terraform_dhcp_options, 'Processing DHCP Tab'), - Option(None, Network.modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), - Option(None, Network.modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), - Option(None, Network.modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), + Option(None, create_terraform_dhcp_options, 'Processing DHCP Tab'), + Option(None, modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), + Option(None, modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), + Option(None, modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy) options = [ - Option(None, Network.create_terraform_drg_route,'Processing DRGs tab for DRG Route Tables and Route Distribution creation'), + Option(None, create_terraform_drg_route,'Processing DRGs tab for DRG Route Tables and Route Distribution creation'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy, network_connectivity_in_setupoci='', modify_network=False) - options = [ Option(None, Network.create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for Subnets'), ] + options = [ Option(None, create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for Subnets'), ] execute_options(options, inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy, network_vlan_in_setupoci='network') - options = [ Option(None, Network.create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for VLANs'), ] + options = [ Option(None, create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for VLANs'), ] execute_options(options, inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy, network_vlan_in_setupoci='vlan') - options = [ Option(None, Network.create_terraform_nsg, 'Processing NSGs Tab'), ] + options = [ Option(None, create_terraform_nsg, 'Processing NSGs Tab'), ] execute_options(options, inputfile, outdir, service_dir_nsg, prefix, ct) print("\n\nExecute import_commands_network_*.sh script created under each region directory to synch TF with OCI Network objects\n") for service in [service_dir_network,service_dir_vlan,service_dir_nsg]: @@ -547,25 +535,25 @@ def export_networking(inputfile, outdir,config, signer, ct, export_regions,expor def export_major_objects(inputfile, outdir, config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'VCN Major Objects') - Network.export_major_objects(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) - Network.export_drg_routetable(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list, _tf_import_cmd=True) + network.export_major_objects(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + export_drg_routetable(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list, _tf_import_cmd=True) options = [ - Option(None, Network.create_major_objects, 'Processing VCNs and DRGs Tab'), + Option(None, create_major_objects, 'Processing VCNs and DRGs Tab'), ] execute_options(options, inputfile, outdir,service_dir_network, prefix, ct, non_gf_tenancy) options = [ - Option(None, Network.create_rpc_resource, 'Processing RPCs in DRGs Tab'), + Option(None, create_rpc_resource, 'Processing RPCs in DRGs Tab'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy) options = [ - Option(None, Network.create_terraform_drg_route,'Processing DRGs tab for DRG Route Tables and Route Distribution creation'), + Option(None, create_terraform_drg_route,'Processing DRGs tab for DRG Route Tables and Route Distribution creation'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy,network_connectivity_in_setupoci='', modify_network=False) options = [ - Option(None, Network.modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), + Option(None, modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), ] execute_options(options, inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy) @@ -574,27 +562,27 @@ def export_major_objects(inputfile, outdir, config, signer, ct, export_regions,e def export_dhcp(inputfile, outdir,config,signer,ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'DHCP') - Network.export_dhcp(inputfile, outdir, service_dir_network,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_dhcp(inputfile, outdir, service_dir_network,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [ - Option(None, Network.create_terraform_dhcp_options, 'Processing DHCP Tab'), + Option(None, create_terraform_dhcp_options, 'Processing DHCP Tab'), ] execute_options(options, inputfile, outdir, service_dir_network,prefix, ct, non_gf_tenancy) print("\n\nExecute import_commands_network_dhcp.sh script created under each region directory to synch TF with OCI Network objects\n") def export_secrules(inputfile, outdir,config,signer,ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'SecRulesInOCI') - Network.export_seclist(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) + export_seclist(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) options = [ - Option(None, Network.modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), + Option(None, modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), ] execute_options(options, inputfile, outdir,service_dir_network, prefix, ct, non_gf_tenancy) print("\n\nExecute import_commands_network_secrules.sh script created under each region directory to synch TF with OCI Network objects\n") def export_routerules(inputfile, outdir,config,signer,ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'RouteRulesInOCI') - Network.export_routetable(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) + export_routetable(inputfile, outdir, service_dir_network, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) options = [ - Option(None, Network.modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), + Option(None, modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), ] execute_options(options, inputfile, outdir, service_dir_network,prefix, ct, non_gf_tenancy) print("\n\nExecute import_commands_network_routerules.sh script created under each region directory to synch TF with OCI Network objects\n") @@ -603,15 +591,15 @@ def export_routerules(inputfile, outdir,config,signer,ct,export_regions,export_t def export_subnets_vlans(inputfile, outdir,config,signer,ct,export_regions,export_tags_list): service_dir = outdir_struct #compartments = ct.get_compartment_map(var_file,'Subnets') - Network.export_subnets_vlans(inputfile, outdir, service_dir,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_subnets_vlans(inputfile, outdir, service_dir,config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [ - Option(None, Network.create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for Subnets'), + Option(None, create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for Subnets'), ] execute_options(options, inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy, network_vlan_in_setupoci='network') options = [ - Option(None, Network.create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for VLANs'), + Option(None, create_terraform_subnet_vlan, 'Processing SubnetsVLANs Tab for VLANs'), ] execute_options(options, inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy, network_vlan_in_setupoci='vlan') @@ -622,9 +610,9 @@ def export_subnets_vlans(inputfile, outdir,config,signer,ct,export_regions,expor def export_nsg(inputfile, outdir,config,signer,ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'NSGs') - Network.export_nsg(inputfile, outdir,service_dir_nsg, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) + network.export_nsg(inputfile, outdir,service_dir_nsg, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list,_tf_import_cmd=True) options = [ - Option(None, Network.create_terraform_nsg, 'Processing NSGs Tab'), + Option(None, create_terraform_nsg, 'Processing NSGs Tab'), ] execute_options(options, inputfile, outdir, service_dir_nsg,prefix, ct) print("\n\nExecute import_commands_network_nsg.sh script created under each region directory to synch TF with OCI Network objects\n") @@ -650,13 +638,13 @@ def export_firewallpolicy(inputfile, outdir, config, signer, ct, export_regions, policy_name_str = ct.fwl_pol_pattern_filter if ct.fwl_pol_pattern_filter else None policies = list(map(lambda x: x.strip(), policy_name_str.split(','))) if policy_name_str else None - Security.export_firewallpolicy(inputfile, outdir, service_dir_firewall, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list,export_policies=policies) + security.export_firewallpolicy(inputfile, outdir, service_dir_firewall, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list,export_policies=policies) create_firewall_policy(inputfile, outdir, service_dir_firewall, prefix, ct,execute_all=True) print("\n\nExecute import_commands_firewallpolicy.sh script created under each region directory to synch TF with OCI Firewall policy objects\n") def export_firewalls(inputfile, outdir, config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file, 'Firewalls') - Security.export_firewall(inputfile, outdir, service_dir_firewall, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) + security.export_firewall(inputfile, outdir, service_dir_firewall, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) create_firewall(inputfile, outdir, service_dir_firewall, prefix, ct) print("\n\nExecute import_commands_firewall.sh script created under each region directory to synch TF with OCI Firewall policy objects\n") @@ -673,7 +661,7 @@ def export_compute(prim_options=[],export_all=False): def export_dedicatedvmhosts(inputfile, outdir, config, signer, ct, export_regions,export_tags_list,export_all): #compartments = ct.get_compartment_map(var_file,'Dedicated VM Hosts') - Compute.export_dedicatedvmhosts(inputfile, outdir, service_dir_dedicated_vm_host, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list) + compute.export_dedicatedvmhosts(inputfile, outdir, service_dir_dedicated_vm_host, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list) #create_compute(prim_options=['Add/Modify/Delete Dedicated VM Hosts']) options = [Option(None, create_dedicatedvmhosts, 'Processing Dedicated VM Hosts Tab'),] execute_options(options) @@ -702,7 +690,7 @@ def export_instances(inputfile, outdir,config,signer, ct, export_regions,export_ display_names = list(map(lambda x: x.strip(), display_name_str.split(','))) if display_name_str else None ad_names = list(map(lambda x: x.strip(), ad_name_str.split(','))) if ad_name_str else None - Compute.export_instances(inputfile, outdir, service_dir_instance,config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list, display_names = display_names, ad_names = ad_names) + compute.export_instances(inputfile, outdir, service_dir_instance,config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list, display_names = display_names, ad_names = ad_names) options = [Option(None, create_instances, 'Processing Instances Tab'), ] execute_options(options) print("\n\nExecute import_commands_instances.sh script created under each region directory to synch TF with OCI Instances\n") @@ -739,7 +727,7 @@ def export_block_volumes(inputfile, outdir,config,signer,ct, export_regions,expo display_names = list(map(lambda x: x.strip(), display_name_str.split(','))) if display_name_str else None ad_names = list(map(lambda x: x.strip(), ad_name_str.split(','))) if ad_name_str else None - Storage.export_blockvolumes(inputfile, outdir, service_dir_block_volume, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list, display_names = display_names, ad_names = ad_names) + storage.export_blockvolumes(inputfile, outdir, service_dir_block_volume, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags = export_tags_list, display_names = display_names, ad_names = ad_names) options = [Option(None, create_block_volumes, 'Processing BlockVolumes Tab'), ] execute_options(options) print("\n\nExecute import_commands_blockvolumes.sh script created under each region directory to synch TF with OCI Block Volume Objects\n") @@ -749,7 +737,7 @@ def export_block_volumes(inputfile, outdir,config,signer,ct, export_regions,expo def export_fss(inputfile, outdir,config, signer, ct, export_regions,export_tags_list,export_all): #compartments = ct.get_compartment_map(var_file,'FSS objects') - Storage.export_fss(inputfile, outdir, service_dir_fss, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags = export_tags_list) + storage.export_fss(inputfile, outdir, service_dir_fss, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags = export_tags_list) options = [Option(None, create_fss, 'Processing FSS Tab'), ] execute_options(options) print("\n\nExecute import_commands_fss.sh script created under each region directory to synch TF with OCI FSS objects\n") @@ -759,7 +747,7 @@ def export_fss(inputfile, outdir,config, signer, ct, export_regions,export_tags_ def export_buckets(inputfile, outdir, config, signer, ct, export_regions,export_tags_list,export_all): #compartments = ct.get_compartment_map(var_file, 'Buckets') - Storage.export_buckets(inputfile, outdir, service_dir_object_storage, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags = export_tags_list) + storage.export_buckets(inputfile, outdir, service_dir_object_storage, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags = export_tags_list) options = [Option(None, create_buckets, 'Processing Buckets Tab'), ] execute_options(options) print("\n\nExecute import_commands_buckets.sh script created under each region directory to synch TF with OCI Object Storage Buckets\n") @@ -778,7 +766,7 @@ def export_loadbalancer(prim_options=[]): def export_lbr(inputfile, outdir,config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'LBR objects') - Network.export_lbr(inputfile, outdir, service_dir_loadbalancer, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_lbr(inputfile, outdir, service_dir_loadbalancer, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [Option(None, create_lb, 'Processing LBaaS Tabs'), ] execute_options(options) print("\n\nExecute import_commands_lbr.sh script created under each region directory to synch TF with OCI LBR objects\n") @@ -788,7 +776,7 @@ def export_lbr(inputfile, outdir,config, signer, ct, export_regions,export_tags_ def export_nlb(inputfile, outdir,config,signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'NLB objects') - Network.export_nlb(inputfile, outdir, service_dir_networkloadbalancer, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_nlb(inputfile, outdir, service_dir_networkloadbalancer, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [Option(None, create_nlb, 'Processing NLB Tabs'), ] execute_options(options) print("\n\nExecute import_commands_nlb.sh script created under each region directory to synch TF with OCI NLB objects\n") @@ -805,7 +793,7 @@ def export_security(prim_options=[]): def export_kms(inputfile, outdir, config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file, 'KMS') - Security.export_keyvaults(inputfile, outdir, service_dir_kms, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + export_keyvaults(inputfile, outdir, service_dir_kms, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [Option(None, create_kms, 'Processing KMS Tab')] execute_options(options) print("\n\nExecute import_commands_kms.sh script created under each region directory to synch TF with OCI Key Vaults\n") @@ -826,7 +814,7 @@ def export_databases(prim_options=[]): def export_dbsystems_vm_bm(inputfile, outdir,config,signer, ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'VM and BM DB Systems') - Database.export_dbsystems_vm_bm(inputfile, outdir, service_dir_dbsystem_vm_bm, config,signer,ct, export_compartments=compartments, export_regions= export_regions,export_tags=export_tags_list) + database.export_dbsystems_vm_bm(inputfile, outdir, service_dir_dbsystem_vm_bm, config,signer,ct, export_compartments=compartments, export_regions= export_regions,export_tags=export_tags_list) options = [Option(None, create_dbsystems_vm_bm, 'Processing DBSystems-VM-BM Tab')] execute_options(options) print("\n\nExecute import_commands_dbsystems-vm-bm.sh script created under each region directory to synch TF with DBSystems\n") @@ -836,8 +824,8 @@ def export_dbsystems_vm_bm(inputfile, outdir,config,signer, ct,export_regions,ex def export_exa_infra_vmclusters(inputfile, outdir,config, signer, ct, export_regions, export_tags_list): #compartments = ct.get_compartment_map(var_file,'EXA Infra and EXA VMClusters') - Database.export_exa_infra(inputfile, outdir, service_dir_database_exacs, config,signer,ct, export_compartments=compartments, export_regions= export_regions,export_tags = export_tags_list) - Database.export_exa_vmclusters(inputfile, outdir, service_dir_database_exacs, config,signer,ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list) + export_exa_infra(inputfile, outdir, service_dir_database_exacs, config,signer,ct, export_compartments=compartments, export_regions= export_regions,export_tags = export_tags_list) + export_exa_vmclusters(inputfile, outdir, service_dir_database_exacs, config,signer,ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list) options = [Option(None, create_exa_infra_vmclusters, '')] execute_options(options) print("\n\nExecute import_commands_exa-infra.sh and import_commands_exa-vmclusters.sh scripts created under each region directory to synch TF with Exa-Infra and Exa-VMClusters\n") @@ -847,7 +835,7 @@ def export_exa_infra_vmclusters(inputfile, outdir,config, signer, ct, export_reg def export_adbs(inputfile, outdir,config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'ADBs') - Database.export_adbs(inputfile, outdir, service_dir_adb, config,signer,ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list) + database.export_adbs(inputfile, outdir, service_dir_adb, config,signer,ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list) options = [Option(None, create_adb, 'Processing ADB Tab')] execute_options(options) print("\n\nExecute import_commands_adb.sh script created under each region directory to synch TF with OCI ADBs\n") @@ -857,9 +845,9 @@ def export_adbs(inputfile, outdir,config, signer, ct, export_regions,export_tags def export_mysql(inputfile, outdir,config,signer, ct,export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file, 'MySQL DB Systems and Configurations') - Database.export_mysql_db(inputfile, outdir, service_dir_mysql_dbsystem, config, signer, ct, + export_mysql_db(inputfile, outdir, service_dir_mysql_dbsystem, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) - Database.export_mysql_configuration(inputfile, outdir, service_dir_mysql_dbsystem, config, signer, ct, + export_mysql_configuration(inputfile, outdir, service_dir_mysql_dbsystem, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) options = [Option(None, create_mysql, '')] execute_options(options,execute_all=True) @@ -883,25 +871,25 @@ def export_management_services(prim_options=[]): def export_notifications(inputfile, outdir, service_dir, config, signer, ct, export_regions, export_tags_list): #compartments = ct.get_compartment_map(var_file,'Notifications') - ManagementServices.export_notifications(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + managementservices.export_notifications(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) create_management_services(prim_options=['Add/Modify/Delete Notifications']) print("\n\nExecute import_commands_notifications.sh script created under each region directory to synch TF with OCI Notifications\n") def export_events(inputfile, outdir, service_dir, config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'Events') - ManagementServices.export_events(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) + managementservices.export_events(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) create_management_services(prim_options=['Add/Modify/Delete Events']) print("\n\nExecute import_commands_events.sh script created under each region directory to synch TF with OCI Events\n") def export_alarms(inputfile, outdir, service_dir, config, signer, ct, export_regions, export_tags_list): #compartments = ct.get_compartment_map(var_file,'Alarms') - ManagementServices.export_alarms(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) + managementservices.export_alarms(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) create_management_services(prim_options=['Add/Modify/Delete Alarms']) print("\n\nExecute import_commands_alarms.sh script created under each region directory to synch TF with OCI Alarms\n") def export_service_connectors(inputfile, outdir, service_dir, config, signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'Service Connectors') - ManagementServices.export_service_connectors(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + managementservices.export_service_connectors(inputfile, outdir, service_dir, config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) create_management_services(prim_options=['Add/Modify/Delete ServiceConnectors']) print("\n\nExecute import_commands_serviceconnectors.sh script created under each region directory to synch TF with OCI Service Connectors\n") @@ -916,7 +904,7 @@ def export_developer_services(prim_options=[]): def export_oke(inputfile, outdir, config,signer, ct, export_regions,export_tags_list): #compartments = ct.get_compartment_map(var_file,'OKE') - DeveloperServices.export_oke(inputfile, outdir, service_dir_oke,config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) + developerservices.export_oke(inputfile, outdir, service_dir_oke,config,signer,ct, export_compartments=compartments, export_regions=export_regions, export_tags=export_tags_list) options = [Option(None, create_oke, 'Processing OKE Tab')] execute_options(options,inputfile, outdir, prefix, '', '', ct) print("\n\nExecute import_commands_oke.sh script created under each region directory to synch TF with OKE\n") @@ -926,8 +914,8 @@ def export_oke(inputfile, outdir, config,signer, ct, export_regions,export_tags_ def export_sddc(prim_options=[]): #compartments = ct.get_compartment_map(var_file,'SDDCs') - SDDC.export_sddc(inputfile, outdir, service_dir_sddc,config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) - SDDC.create_terraform_sddc(inputfile, outdir, service_dir_sddc, prefix, ct) + sddc.export_sddc(inputfile, outdir, service_dir_sddc,config,signer,ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + create_terraform_sddc(inputfile, outdir, service_dir_sddc, prefix, ct) print("\n\nExecute import_commands_sddcs.sh script created under each region directory to synch TF with SDDC\n") # Update modified path list update_path_list(regions_path=export_regions, service_dirs=[service_dir_sddc]) @@ -962,12 +950,12 @@ def export_dns_views_zones_rrsets(inputfile, outdir, service_dir, config, signer if ct.default_dns.lower() == "true": dns_filter = "y" dns_filter = dns_filter if dns_filter else None - Network.export_dns_views_zones_rrsets(inputfile, outdir, service_dir, config, signer, ct, dns_filter=dns_filter, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_dns_views_zones_rrsets(inputfile, outdir, service_dir, config, signer, ct, dns_filter=dns_filter, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [Option(None, create_dns, 'Processing DNS-Views-Zones-Records Tab')] execute_options(options) def export_dns_resolvers(inputfile, outdir, service_dir, config, signer, ct, export_regions, export_tags_list,export_all): #compartments = ct.get_compartment_map(var_file, 'DNS Resolvers') - Network.export_dns_resolvers(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) + network.export_dns_resolvers(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions=export_regions,export_tags=export_tags_list) options = [Option(None, create_dns_resolvers, 'Processing DNS-Resolvers Tab')] execute_options(options) @@ -993,7 +981,7 @@ def create_compartments(): choices = [Option("Validate Compartments", None, None)] errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Identity.create_terraform_compartments(inputfile, outdir, service_dir_identity, prefix, ct) + create_terraform_compartments(inputfile, outdir, service_dir_identity, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_identity]) else: @@ -1006,7 +994,7 @@ def create_groups(): choices = [Option("Validate Groups", None, None)] errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Identity.create_terraform_groups(inputfile, outdir, service_dir_identity, prefix, ct) + create_terraform_groups(inputfile, outdir, service_dir_identity, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_identity]) else: @@ -1020,7 +1008,7 @@ def create_policies(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Identity.create_terraform_policies(inputfile, outdir, service_dir_identity, prefix, ct) + create_terraform_policies(inputfile, outdir, service_dir_identity, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_identity]) else: @@ -1028,13 +1016,13 @@ def create_policies(): exit(1) def create_users(): - Identity.create_terraform_users(inputfile, outdir, service_dir_identity, prefix, ct) + create_terraform_users(inputfile, outdir, service_dir_identity, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_identity]) def create_networksources(): - Identity.NetworkSources.create_terraform_networkSources(inputfile, outdir, service_dir_identity, prefix, ct) + create_terraform_networkSources(inputfile, outdir, service_dir_identity, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_identity]) @@ -1076,7 +1064,7 @@ def create_tags(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Governance.create_terraform_tags(inputfile, outdir, service_dir_tagging, prefix, ct) + create_terraform_tags(inputfile, outdir, service_dir_tagging, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_tagging]) else: @@ -1084,7 +1072,7 @@ def create_tags(): exit(1) def create_quotas(): - Governance.create_terraform_quotas(inputfile, outdir, service_dir_quota, prefix, ct) + create_terraform_quotas(inputfile, outdir, service_dir_quota, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_quota]) @@ -1105,7 +1093,7 @@ def create_budgets(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == True: - CostManagement.create_terraform_budgets(inputfile, outdir, service_dir_budget, prefix, ct) + create_terraform_budgets(inputfile, outdir, service_dir_budget, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_budget]) else: @@ -1142,7 +1130,7 @@ def create_terraform_network(inputfile, outdir, service_dir, prefix, ct, non_gf errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Network.create_all_tf_objects(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy) + create_all_tf_objects(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy) else: print("Please correct the errors in CD3 Sheet and try again. Exiting!!!") exit(1) @@ -1155,7 +1143,7 @@ def modify_terraform_network(inputfile, outdir, service_dir, prefix, ct, non_gf errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Network.create_all_tf_objects(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy, modify_network=True, ) + create_all_tf_objects(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy, modify_network=True, ) else: print("Please correct the errors in CD3 Sheet and try again. Exiting!!!") exit(1) @@ -1164,7 +1152,7 @@ def export_modify_security_rules(inputfile, outdir, service_dir, prefix, ct, non execute_all = False options = [ Option('Export Security Rules (From OCI into SecRulesinOCI sheet)', export_security_rules, 'Exporting Security Rules in OCI'), - Option('Add/Modify/Delete Security Rules (Reads SecRulesinOCI sheet)', Network.modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), + Option('Add/Modify/Delete Security Rules (Reads SecRulesinOCI sheet)', modify_terraform_secrules, 'Processing SecRulesinOCI Tab'), ] if sub_options: options = match_options(options, sub_options) @@ -1184,13 +1172,13 @@ def export_modify_security_rules(inputfile, outdir, service_dir, prefix, ct, non def export_security_rules(inputfile, outdir, service_dir, config, signer, ct, non_gf_tenancy): compartments = ct.get_compartment_map(var_file, 'OCI Security Rules') export_tags_list = get_tags_list('OCI Security Rules') - Network.export_seclist(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list, _tf_import_cmd=False) + export_seclist(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list, _tf_import_cmd=False) def export_modify_route_rules(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy,sub_options=[]): execute_all = False options = [ Option('Export Route Rules (From OCI into RouteRulesinOCI sheet)', export_route_rules, 'Exporting Route Rules in OCI'), - Option('Add/Modify/Delete Route Rules (Reads RouteRulesinOCI sheet)', Network.modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), + Option('Add/Modify/Delete Route Rules (Reads RouteRulesinOCI sheet)', modify_terraform_routerules, 'Processing RouteRulesinOCI Tab'), ] if sub_options: options = match_options(options, sub_options) @@ -1210,13 +1198,13 @@ def export_modify_route_rules(inputfile, outdir, service_dir, prefix, ct, non_gf def export_route_rules(inputfile, outdir, service_dir, config, signer, ct, non_gf_tenancy): compartments = ct.get_compartment_map(var_file, 'OCI Route Rules') export_tags_list = get_tags_list('OCI Route Rules') - Network.export_routetable(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list,_tf_import_cmd=False) + export_routetable(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list,_tf_import_cmd=False) def export_modify_drg_route_rules(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy,sub_options=[]): execute_all = False options = [ Option('Export DRG Route Rules (From OCI into DRGRouteRulesinOCI sheet)', export_drg_route_rules, 'Exporting DRG Route Rules in OCI'), - Option('Add/Modify/Delete DRG Route Rules (Reads DRGRouteRulesinOCI sheet)', Network.modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), + Option('Add/Modify/Delete DRG Route Rules (Reads DRGRouteRulesinOCI sheet)', modify_terraform_drg_routerules, 'Processing DRGRouteRulesinOCI Tab'), ] if sub_options: options = match_options(options, sub_options) @@ -1236,14 +1224,14 @@ def export_modify_drg_route_rules(inputfile, outdir, service_dir, prefix, ct, no def export_drg_route_rules(inputfile, outdir, service_dir, config, signer, ct, non_gf_tenancy): compartments = ct.get_compartment_map(var_file,'OCI DRG Route Rules') export_tags_list = get_tags_list('OCI DRG Route Rules') - Network.export_drg_routetable(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list,_tf_import_cmd=False) + export_drg_routetable(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list,_tf_import_cmd=False) def export_modify_nsgs(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy,sub_options=[]): execute_all = False options = [ Option('Export NSGs (From OCI into NSGs sheet)', export_nsgs, 'Exporting NSGs in OCI'), - Option('Add/Modify/Delete NSGs (Reads NSGs sheet)', Network.create_terraform_nsg, 'Processing NSGs Tab'), + Option('Add/Modify/Delete NSGs (Reads NSGs sheet)', create_terraform_nsg, 'Processing NSGs Tab'), ] if sub_options: options = match_options(options, sub_options) @@ -1255,11 +1243,11 @@ def export_modify_nsgs(inputfile, outdir, service_dir, prefix, ct, non_gf_tenanc def export_nsgs(inputfile, outdir, service_dir, prefix, ct): compartments = ct.get_compartment_map(var_file,'OCI NSGs') export_tags_list = get_tags_list('OCI NSGs') - Network.export_nsg(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list, _tf_import_cmd=False) + network.export_nsg(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions= export_regions, export_tags=export_tags_list, _tf_import_cmd=False) def create_vlans(inputfile, outdir, service_dir, prefix,ct, non_gf_tenancy, network_vlan_in_setupoci='vlan'): - Network.create_terraform_subnet_vlan(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy, network_vlan_in_setupoci='vlan',modify_network=True) - Network.create_terraform_route(inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy=non_gf_tenancy, network_vlan_in_setupoci='vlan',modify_network=True) + create_terraform_subnet_vlan(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy=non_gf_tenancy, network_vlan_in_setupoci='vlan',modify_network=True) + create_terraform_route(inputfile, outdir, service_dir_network, prefix, ct, non_gf_tenancy=non_gf_tenancy, network_vlan_in_setupoci='vlan',modify_network=True) def create_drg_connectivity(inputfile, outdir, service_dir, prefix, ct, non_gf_tenancy,network_vlan_in_setupoci='vlan',sub_options=[]): execute_all = False @@ -1275,8 +1263,8 @@ def create_drg_connectivity(inputfile, outdir, service_dir, prefix, ct, non_gf_ execute_options(options, inputfile, outdir, service_dir, service_dir_network, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy=non_gf_tenancy) def create_rpc(inputfile, outdir, service_dir, service_dir_network, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy): - Network.create_rpc_resource(inputfile, outdir, service_dir, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy=non_gf_tenancy) - Network.create_terraform_drg_route(inputfile, outdir, service_dir_network, prefix, non_gf_tenancy=non_gf_tenancy, ct=ct, network_connectivity_in_setupoci='connectivity', modify_network=True) + create_rpc_resource(inputfile, outdir, service_dir, prefix, auth_mechanism, config_file_path, ct, non_gf_tenancy=non_gf_tenancy) + create_terraform_drg_route(inputfile, outdir, service_dir_network, prefix, non_gf_tenancy=non_gf_tenancy, ct=ct, network_connectivity_in_setupoci='connectivity', modify_network=True) def create_compute(prim_options=[]): options = [ @@ -1297,7 +1285,7 @@ def create_instances(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Compute.create_terraform_instances(inputfile, outdir, service_dir_instance, prefix, ct) + create_terraform_instances(inputfile, outdir, service_dir_instance, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_instance]) else: @@ -1305,7 +1293,7 @@ def create_instances(): exit(1) def create_dedicatedvmhosts(): - Compute.create_terraform_dedicatedhosts(inputfile, outdir, service_dir_dedicated_vm_host, prefix, ct) + create_terraform_dedicatedhosts(inputfile, outdir, service_dir_dedicated_vm_host, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_dedicated_vm_host]) @@ -1331,7 +1319,7 @@ def create_block_volumes(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Storage.create_terraform_block_volumes(inputfile, outdir, service_dir_block_volume, prefix, ct) + create_terraform_block_volumes(inputfile, outdir, service_dir_block_volume, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_block_volume]) else: @@ -1345,7 +1333,7 @@ def create_fss(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Storage.create_terraform_fss(inputfile, outdir, service_dir_fss, prefix, ct) + create_terraform_fss(inputfile, outdir, service_dir_fss, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_fss]) else: @@ -1360,7 +1348,7 @@ def create_buckets(): errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Storage.create_terraform_oss(inputfile, outdir, service_dir_object_storage, prefix, ct) + create_terraform_oss(inputfile, outdir, service_dir_object_storage, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_object_storage]) else: @@ -1382,12 +1370,12 @@ def create_loadbalancer(execute_all=False,prim_options=[]): def create_lb(): options = [ - Option(None, Network.create_terraform_lbr_hostname_certs, 'Creating LBR'), - Option(None, Network.create_backendset_backendservers, 'Creating Backend Sets and Backend Servers'), - Option(None, Network.create_listener, 'Creating Listeners'), - Option(None, Network.create_path_route_set, 'Creating Path Route Sets'), - Option(None, Network.create_ruleset, 'Creating Rule Sets'), - Option(None, Network.create_lb_routing_policy, 'Creating Routing Policies'), + Option(None, create_terraform_lbr_hostname_certs, 'Creating LBR'), + Option(None, create_backendset_backendservers, 'Creating Backend Sets and Backend Servers'), + Option(None, create_listener, 'Creating Listeners'), + Option(None, create_path_route_set, 'Creating Path Route Sets'), + Option(None, create_ruleset, 'Creating Rule Sets'), + Option(None, create_lb_routing_policy, 'Creating Routing Policies'), ] execute_options(options, inputfile, outdir, service_dir_loadbalancer, prefix, ct) # Update modified path list @@ -1396,8 +1384,8 @@ def create_lb(): def create_nlb(): options = [ - Option(None, Network.create_terraform_nlb_listener, 'Creating NLB and Listeners'), - Option(None, Network.create_nlb_backendset_backendservers, 'Creating NLB Backend Sets and Backend Servers'), + Option(None, create_terraform_nlb_listener, 'Creating NLB and Listeners'), + Option(None, create_nlb_backendset_backendservers, 'Creating NLB Backend Sets and Backend Servers'), ] execute_options(options, inputfile, outdir, service_dir_networkloadbalancer, prefix, ct) # Update modified path list @@ -1418,28 +1406,28 @@ def create_databases(execute_all=False,prim_options=[]): execute_options(options) def create_dbsystems_vm_bm(): - Database.create_terraform_dbsystems_vm_bm(inputfile, outdir, service_dir_dbsystem_vm_bm, prefix, ct) + create_terraform_dbsystems_vm_bm(inputfile, outdir, service_dir_dbsystem_vm_bm, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_dbsystem_vm_bm]) def create_exa_infra_vmclusters(): - options = [Option(None, Database.create_terraform_exa_infra, 'Processing Exa-Infra Tab'), - Option(None, Database.create_terraform_exa_vmclusters, 'Processing Exa-VM-Clusters Tab')] + options = [Option(None, create_terraform_exa_infra, 'Processing Exa-Infra Tab'), + Option(None, create_terraform_exa_vmclusters, 'Processing Exa-VM-Clusters Tab')] execute_options(options, inputfile, outdir, service_dir_database_exacs, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_database_exacs]) def create_adb(): - Database.create_terraform_adb(inputfile, outdir, service_dir_adb, prefix, ct) + create_terraform_adb(inputfile, outdir, service_dir_adb, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_adb]) def create_mysql(execute_all=False,prim_options=[]): options = [ - Option('Add/Modify/Delete MySQL DB Systems', Database.create_terraform_mysql_db, 'Processing MySQL-DBSystems Tab'), - Option('Add/Modify/Delete MySQL Configurations', Database.create_terraform_mysql_configuration, 'Processing MySQL-Configurations Tab'), + Option('Add/Modify/Delete MySQL DB Systems', create_terraform_mysql_db, 'Processing MySQL-DBSystems Tab'), + Option('Add/Modify/Delete MySQL Configurations', create_terraform_mysql_configuration, 'Processing MySQL-Configurations Tab'), ] execute_options(options, inputfile, outdir, service_dir_mysql_dbsystem, prefix, ct) # Update modified path list @@ -1448,10 +1436,10 @@ def create_mysql(execute_all=False,prim_options=[]): def create_management_services(execute_all=False,prim_options=[]): options = [ - Option("Add/Modify/Delete Notifications", ManagementServices.create_terraform_notifications, 'Setting up Notifications'), - Option("Add/Modify/Delete Events", ManagementServices.create_terraform_events, 'Setting up Events'), - Option("Add/Modify/Delete Alarms", ManagementServices.create_terraform_alarms, 'Setting up Alarms'), - Option("Add/Modify/Delete ServiceConnectors", ManagementServices.create_service_connectors, + Option("Add/Modify/Delete Notifications", create_terraform_notifications, 'Setting up Notifications'), + Option("Add/Modify/Delete Events", create_terraform_events, 'Setting up Events'), + Option("Add/Modify/Delete Alarms", create_terraform_alarms, 'Setting up Alarms'), + Option("Add/Modify/Delete ServiceConnectors", create_service_connectors, 'Setting up SCHs'), ] if prim_options: @@ -1484,16 +1472,16 @@ def create_developer_services(execute_all=False,prim_options=[]): def create_rm_stack(inputfile, outdir, prefix, auth_mechanism, config_file, ct): regions = get_region_list(rm = True, vizoci = False) - DeveloperServices.create_resource_manager(outdir,var_file, outdir_struct, prefix, auth_mechanism, config_file, ct, regions) + create_resource_manager(outdir,var_file, outdir_struct, prefix, auth_mechanism, config_file, ct, regions) def create_oke(inputfile, outdir, prefix, dummy1, dummy2, ct): - DeveloperServices.create_terraform_oke(inputfile, outdir, service_dir_oke, prefix, ct) + create_terraform_oke(inputfile, outdir, service_dir_oke, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_oke]) def create_sddc(prim_options=[]): - SDDC.create_terraform_sddc(inputfile, outdir, service_dir_sddc, prefix, ct) + create_terraform_sddc(inputfile, outdir, service_dir_sddc, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_sddc]) @@ -1524,20 +1512,20 @@ def create_dns_management(prim_options=[]): def create_dns(): - Network.create_terraform_dns_views(inputfile, outdir, service_dir_dns, prefix, ct) - Network.create_terraform_dns_zones(inputfile, outdir, service_dir_dns, prefix, ct) - Network.create_terraform_dns_rrsets(inputfile, outdir, service_dir_dns, prefix, ct) + create_terraform_dns_views(inputfile, outdir, service_dir_dns, prefix, ct) + create_terraform_dns_zones(inputfile, outdir, service_dir_dns, prefix, ct) + create_terraform_dns_rrsets(inputfile, outdir, service_dir_dns, prefix, ct) def create_dns_resolvers(): - Network.create_terraform_dns_resolvers(inputfile, outdir, service_dir_dns, prefix, ct) + create_terraform_dns_resolvers(inputfile, outdir, service_dir_dns, prefix, ct) def create_logging(prim_options=[]): options = [ - Option('Enable VCN Flow Logs', ManagementServices.enable_service_logging, 'VCN Flow Logs'), - Option('Enable LBaaS Logs', ManagementServices.enable_service_logging, 'LBaaS Logs'), - Option('Enable Object Storage Buckets Logs', ManagementServices.enable_service_logging, 'OSS Logs'), - Option('Enable File Storage Logs', ManagementServices.enable_service_logging, 'File Storage Logs'), - Option('Enable Network Firewall Logs', ManagementServices.enable_service_logging, 'Network Firewall Logs') + Option('Enable VCN Flow Logs', enable_service_logging, 'VCN Flow Logs'), + Option('Enable LBaaS Logs', enable_service_logging, 'LBaaS Logs'), + Option('Enable Object Storage Buckets Logs', enable_service_logging, 'OSS Logs'), + Option('Enable File Storage Logs', enable_service_logging, 'File Storage Logs'), + Option('Enable Network Firewall Logs', enable_service_logging, 'Network Firewall Logs') ] if prim_options: options = match_options(options, prim_options) @@ -1569,7 +1557,7 @@ def create_kms(): choices = [Option("Validate KMS", None, None)] errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) if errors == False: - Security.create_terraform_keyvaults(inputfile, outdir, service_dir_kms, prefix, ct) + create_terraform_keyvaults(inputfile, outdir, service_dir_kms, prefix, ct) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_kms]) else: @@ -1616,7 +1604,7 @@ def enable_cis_cloudguard(): else: region = ct.cg_region region = region.lower() - Security.enable_cis_cloudguard(outdir, service_dir_cloud_guard, prefix, ct, region) + security.enable_cis_cloudguard(outdir, service_dir_cloud_guard, prefix, ct, region) # Update modified path list update_path_list(regions_path=subscribed_regions, service_dirs=[service_dir_cloud_guard]) @@ -2006,7 +1994,7 @@ def clone_firewall_policy( inputfile, outdir, service_dir, config, signer, ct): print("Source Policies are mandatory for cloning. ") exit(1) target_policies = list(map(lambda x: x.strip(), target_policy_str.split(','))) if target_policy_str else None - Security.export_firewallpolicy(inputfile, outdir, service_dir, config, signer, ct, + security.export_firewallpolicy(inputfile, outdir, service_dir, config, signer, ct, export_compartments=compartments, export_regions=export_regions, export_policies=src_policies,target_policies=target_policies,attached_policy_only=attached_policy_only,clone_policy=True) @@ -2039,29 +2027,31 @@ def delete_firewall_policy(inputfile, outdir, service_dir, config, signer, ct): def create_firewall_policy(inputfile, outdir, service_dir, prefix, ct,execute_all=False,sub_options=[]): options = [ Option('Execute All', None, 'Processing all tabs related to Firewall-Policy'), - Option('Add/Modify/Delete Policy', Security.firewallpolicy_create, 'Processing Firewall-Policy Tab'), - Option('Add/Modify/Delete Service', Security.fwpolicy_create_service, + Option('Add/Modify/Delete Policy', firewallpolicy_create, 'Processing Firewall-Policy Tab'), + Option('Add/Modify/Delete Service', fwpolicy_create_service, 'Processing Firewall-Policy-ServicesList Tab'), - Option('Add/Modify/Delete Service-list', Security.fwpolicy_create_servicelist, + Option('Add/Modify/Delete Service-list', fwpolicy_create_servicelist, 'Processing Firewall-Policy-ServiceList Tab'), - Option('Add/Modify/Delete Application', Security.fwpolicy_create_apps, + Option('Add/Modify/Delete Application', fwpolicy_create_apps, 'Processing Firewall-Policy-ApplicationList Tab'), - Option('Add/Modify/Delete Application-list', Security.fwpolicy_create_applicationlist, + Option('Add/Modify/Delete Application-list', fwpolicy_create_applicationlist, 'Processing Firewall-Policy-ApplicationList Tab'), - Option('Add/Modify/Delete Address-list', Security.fwpolicy_create_address, + Option('Add/Modify/Delete Address-list', fwpolicy_create_address, 'Processing Firewall-Policy-AddressList Tab'), - Option('Add/Modify/Delete Url-list', Security.fwpolicy_create_urllist, + Option('Add/Modify/Delete Url-list', fwpolicy_create_urllist, 'Processing Firewall-Policy-UrlList Tab'), - Option('Add/Modify/Delete Security rules', Security.fwpolicy_create_secrules, + Option('Add/Modify/Delete Security rules', fwpolicy_create_secrules, 'Processing Firewall-Policy-SecRule Tab'), - Option('Add/Modify/Delete Mapped Secrets', Security.fwpolicy_create_secret, + Option('Add/Modify/Delete Mapped Secrets', fwpolicy_create_secret, 'Processing Firewall-Policy-Secret Tab'), - Option('Add/Modify/Delete Decryption Rules', Security.fwpolicy_create_decryptrules, + Option('Add/Modify/Delete Decryption Rules', fwpolicy_create_decryptrules, 'Processing Firewall-Policy-DecryptRule Tab'), - Option('Add/Modify/Delete Decryption Profile', Security.fwpolicy_create_decryptionprofile, + Option('Add/Modify/Delete Decryption Profile', fwpolicy_create_decryptionprofile, 'Processing Firewall-Policy-Decryption Tab'), - Option('Add/Modify/Delete Tunnel Inspection Rules', Security.fwpolicy_create_tunnelinspect, + Option('Add/Modify/Delete Tunnel Inspection Rules', fwpolicy_create_tunnelinspect, 'Processing Firewall-Policy-TunnelInspect Tab'), + Option('Add/Modify/Delete NAT Rules', fwpolicy_create_natrules, + 'Processing Firewall-Policy-NatRules Tab'), ] if sub_options and sub_options != ['']: options = match_options(options, sub_options) @@ -2073,7 +2063,7 @@ def create_firewall_policy(inputfile, outdir, service_dir, prefix, ct,execute_al def create_firewall(inputfile, outdir, service_dir, prefix, ct,sub_options=[]): - Security.fw_create(inputfile, outdir, service_dir, prefix, ct) + fw_create(inputfile, outdir, service_dir, prefix, ct) #Execution starts here @@ -2152,7 +2142,7 @@ def create_firewall(inputfile, outdir, service_dir, prefix, ct,sub_options=[]): ## Authenticate Params ct=None -ct = commonTools() +ct = ociCommonTools() config,signer = ct.authenticate(auth_mechanism, config_file_path) ct.setInputParameters(prefix,outdir,inputfile,tf_or_tofu) diff --git a/cd3_automation_toolkit/shell_script.sh b/cd3_automation_toolkit/shell_script.sh index 1ef4f8fbd..ea28ccd4d 100644 --- a/cd3_automation_toolkit/shell_script.sh +++ b/cd3_automation_toolkit/shell_script.sh @@ -14,6 +14,9 @@ sudo dnf install python-pip -y # Install required Python packages pip install --user oci-cli==3.62.2 +pip install --user azure.identity +pip install --user azure.mgmt.compute +pip install --user azure.mgmt.oracledatabase pip install --user pycryptodomex==3.10.1 pip install --user regex==2022.10.31 pip install --user numpy==1.26.4 @@ -33,10 +36,10 @@ pip install --user PyYAML==6.0.1 pip install --user ansible==8.7.0 # Add Python3 site-packages to PYTHONPATH -echo "export PYTHONPATH=\${PYTHONPATH}:/root/.local/lib/python3.9/site-packages/:/cd3user/.local/lib/python3.9/site-packages/" >> /cd3user/.bashrc +echo "export PYTHONPATH=\${PYTHONPATH}:/root/.local/lib/python3.9/site-packages/:/home/cd3user/.local/lib/python3.9/site-packages/" >> /home/cd3user/.bashrc # Add Python binaries to PATH -echo "PATH=\$PATH:/cd3user/.local/bin" >> /cd3user/.bashrc +#echo "PATH=\$PATH:/cd3user/.local/bin" >> /cd3user/.bashrc # Download and install Terraform diff --git a/cd3_automation_toolkit/user-scripts/.outdir_structure_file.properties b/cd3_automation_toolkit/user-scripts/.outdir_structure_file.properties new file mode 100644 index 000000000..ca979e620 --- /dev/null +++ b/cd3_automation_toolkit/user-scripts/.outdir_structure_file.properties @@ -0,0 +1,36 @@ +[Default] +# Format +# OCI_Service_Name=Directory_Name +# Do not Modify the OCI Service Names specified on Left Hand Side +# Modify the directory name specified on Right Hand Side +# Directory will be created for that service under directory. Do not provide absolute path. +# Below data shows the segregation of services as per best practices. Please change as per your requirements. +# You will have to run createTenancy.py from scratch if you want to make any changes to the directory structure later. +# It is mandatory to specify the directory name for each service. + +identity=identity +tagging=tagging +network=network +quota=quota +loadbalancer=loadbalancer +networkloadbalancer=loadbalancer +vlan=vlan +nsg=nsg +# Same Directory must be specified for Instances and Block Volumes. +instance=compute +block-volume = compute +dedicated-vm-host=compute +adb=database +mysql-dbsystem=database +dbsystem-vm-bm=database +database-exacs=database +fss=fss +oke=oke +sddc=ocvs +cloud-guard=security +managementservices=managementservices +budget=budget +kms=kms +object-storage=oss +dns=dns +firewall=firewall \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/__init__.py b/cd3_automation_toolkit/user-scripts/__init__.py index bce6b268a..066c83efc 100644 --- a/cd3_automation_toolkit/user-scripts/__init__.py +++ b/cd3_automation_toolkit/user-scripts/__init__.py @@ -1,3 +1,3 @@ #!/usr/bin/env python3 -from .createTenancyConfig import seek_info \ No newline at end of file + diff --git a/cd3_automation_toolkit/user-scripts/connectAzure.py b/cd3_automation_toolkit/user-scripts/connectAzure.py new file mode 100644 index 000000000..bf2fc8cd8 --- /dev/null +++ b/cd3_automation_toolkit/user-scripts/connectAzure.py @@ -0,0 +1,193 @@ +#!/usr/bin/python3 +# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +# +# This script will help in initializing the docker container; creates config and variables files. +# +# Author: Shruthi Subramanian +# + +import argparse +import logging +import os +import shutil +import datetime +import configparser +from azure.identity import ClientSecretCredential +from azure.mgmt.compute import ComputeManagementClient + + +def paginate(operation, *args, **kwargs): + while True: + response = operation(*args, **kwargs) + for value in response.data: + yield value + kwargs["page"] = response.next_page + if not response.has_next_page: + break + + + +# Execution of code begins here +parser = argparse.ArgumentParser(description="Connects the Container to Azure Subscription") +parser.add_argument("propsfile", help="Full Path of properties file. eg createtenancyAzure.properties") +args = parser.parse_args() +config = configparser.RawConfigParser() +config.read(args.propsfile) + +current_time=str(datetime.datetime.now()) +cloud="Azure" + +# Initialize Toolkit Variables +user_dir = "/cd3user/"+cloud.lower()+"/" +toolkit_dir = os.path.dirname(os.path.abspath(__file__))+"/.." +tf_modules_dir = toolkit_dir + "/azurecloud/terraform" + +setupcloud_props_toolkit_file_path = toolkit_dir + "/setUpAzure.properties" + + + +prefix = config.get('Default', 'prefix').strip() +if prefix == "" or prefix == "\n": + print("Invalid Prefix. Please try again......Exiting !!") + exit(1) + +prefixes=[] +f = os.path.basename(__file__).rstrip("py")+"safe" +safe_file = user_dir + f +if os.path.exists(safe_file): + f=open(safe_file,"r") + safe_file_lines = f.readlines() + for l in safe_file_lines: + if "SUCCESS" in l: + prefixes.append(l.split("\t")[0]) + +if prefixes !=[]: + if prefix in prefixes: + print("WARNING!!! Container has already been successfuly connected to the Azure with same prefix. Please proceed only if you re-running the script for new project subscription") + inp = input("\nDo you want to proceed (y/n):") + if inp.lower()=="n": + exit(1) + + +# Initialize Tenancy Variables + +prefix_dir = user_dir +"/" + prefix +config_files= prefix_dir +"/.config_files" + +terraform_files = prefix_dir + "/terraform_files" +az_provider_file = terraform_files + "/provider.tf" +setupcloud_props_file_path = prefix_dir + "/"+prefix+"_setUp"+cloud+".properties" + +connected = 1 + +# Read Config file Variables +try: + subscription_id='' + tenant_id='' + client_id='' + client_secret='' + + subscription_id = config.get('Default', 'subscription_id').strip() + + tenant_id = config.get('Default', 'tenant_id').strip() + + client_id = config.get('Default', 'client_id').strip() + + client_secret = config.get('Default', 'client_secret').strip() + + if (subscription_id == '' or tenant_id == '' or client_id == '' or client_secret == ''): + print("Creating "+prefix_dir + " without setting up authentication") + connected=0 +except Exception as e: + print(e) + print('Check if input properties exist and try again..exiting...') + exit(1) + + +if not os.path.exists(prefix_dir): + os.makedirs(prefix_dir) +if not os.path.exists(config_files): + os.makedirs(config_files) + + +# Copy input properties file to customer_tenancy_dir +shutil.copy(args.propsfile,config_files+"/"+prefix+"_connectAzure.properties") + +if connected == 1: + credential = ClientSecretCredential( + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret + ) + + # Use the credential to create a client for an Azure service (e.g., Compute) + compute_client = ComputeManagementClient(credential, subscription_id) + + +# 3. Generate setUpCloud.properties file +print("Creating Azure specific setUpAzure.properties.................") +with open(setupcloud_props_toolkit_file_path, 'r+') as setUpCloud_file: + setupcloud_props_toolkit_file_data = setUpCloud_file.read().rstrip() + +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("outdir=", "outdir="+terraform_files) +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("prefix=", "prefix="+prefix) +if connected == 1: + setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("subscription_id=", "subscription_id=" + subscription_id) + setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("tenant_id=", "tenant_id="+tenant_id) + setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("client_id=", "client_id="+client_id) + setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("client_secret=", "client_secret="+client_secret) + +f = open(setupcloud_props_file_path, "w+") +f.write(setupcloud_props_toolkit_file_data) +f.close() + + +# Copy modules dir to terraform_files folder +try: + shutil.copytree(tf_modules_dir, terraform_files ) +except FileExistsError as fe: + print(fe) + + +# 6. Read variables.tf from examples folder and copy the variables as string + +if connected == 1: + print("Creating subscription specific terraform provider file................") + with open(az_provider_file, 'r+') as provider_file: + az_provider_file_data = provider_file.read().rstrip() + + az_provider_file_data = az_provider_file_data.replace("", subscription_id) + az_provider_file_data = az_provider_file_data.replace("", tenant_id) + az_provider_file_data = az_provider_file_data.replace("", client_id) + az_provider_file_data = az_provider_file_data.replace("", client_secret) + + f = open(az_provider_file, "w+") + f.write(az_provider_file_data) + f.close() + +outfile = prefix_dir+'/'+os.path.basename(__file__).rstrip("py")+"out" +logging.basicConfig(filename=outfile, format='%(message)s', filemode='w', level=logging.INFO) + +print("==================================================================================================================================") +print("\nThe toolkit has been setup successfully. !!!\n") + +f = open(safe_file, "a") +data=prefix + "\t" + "SUCCESS\t"+current_time+"\n" +f.write(data) +f.close() + +logging.info("Prefix Specific Working Directory Path: "+prefix_dir+"\n") + +logging.info("\n######################################") +logging.info("Next Steps for using toolkit via CLI") +logging.info("######################################") +logging.info("Modify "+prefix_dir + "/" +prefix+"_setUpAzure.properties with input values for cd3file and workflow_type") +logging.info("cd "+user_dir+"/oci_tools/cd3_automation_toolkit") +logging.info("python setUpCloud.py azure "+prefix_dir + "/" +prefix+"_setUpAzure.properties") + +with open(outfile, 'r') as log_file: + data = log_file.read().rstrip() +print(data) + +print("==================================================================================================================================") + diff --git a/cd3_automation_toolkit/user-scripts/connectGCP.py b/cd3_automation_toolkit/user-scripts/connectGCP.py new file mode 100644 index 000000000..5c7329b86 --- /dev/null +++ b/cd3_automation_toolkit/user-scripts/connectGCP.py @@ -0,0 +1,284 @@ +import argparse +import configparser +import datetime +import shutil +import distutils +import os,sys,logging +sys.path.append(os.getcwd()+"/../gcp/python/") +from gcpCommonTools import * + + + +# Execution of code begins here +parser = argparse.ArgumentParser(description="Connects the Container to GCP Tenant") +parser.add_argument("propsfile", help="Full Path of properties file. eg connectGCP.properties") +args = parser.parse_args() +config = configparser.RawConfigParser() +config.read(args.propsfile) + +current_time=str(datetime.datetime.now()) + +# Initialize Toolkit Variables +user_dir = "/cd3user/cloud_accounts/gcp" +user_dir = "/Users/susingla/PyCharmProjects/orahub-develop/cd3user/cloud_accounts/gcp" +auto_keys_dir = user_dir + "/keys" +toolkit_dir = os.path.dirname(os.path.abspath(__file__))+"/.." +tf_modules_dir = toolkit_dir + "/gcp/terraform" +variables_example_file = tf_modules_dir + "/variables_example.tf" +setupcloud_props_toolkit_file_path = toolkit_dir + "/user-scripts/setUpCloud.properties" + +cloud="GCP" + +prefix = config.get('Default', 'prefix').strip() +if prefix == "" or prefix == "\n": + print("Invalid Prefix. Please try again......Exiting !!") + exit(1) + +prefixes=[] +f = os.path.basename(__file__).rstrip("py")+".safe" +safe_file = user_dir + f +if os.path.exists(safe_file): + f=open(safe_file,"r") + safe_file_lines = f.readlines() + for l in safe_file_lines: + if "SUCCESS" in l: + prefixes.append(l.split("\t")[0]) + +if prefixes !=[]: + if prefix in prefixes: + print("WARNING!!! Container has already been successfuly connected to the GCP with same prefix. Please proceed only if you re-running the script for new project subscription") + inp = input("\nDo you want to proceed (y/n):") + if inp.lower()=="n": + exit(1) + +# Initialize Tenancy Variables +prefix_dir = user_dir +"/" + prefix +config_files= prefix_dir +"/.config_files" + +terraform_files = prefix_dir + "/terraform_files/" +outdir_safe=terraform_files+"/.safe" +setupcloud_props_file_path = prefix_dir + "/"+prefix+"_setUpCloud.properties" + +# Read Config file Variables +try: + organization_id='' + config_file='' + + organization_id = config.get('Default', 'organization_id').strip() + if organization_id == "" or organization_id == "\n": + print("organization_id cannot be left empty...Exiting !!") + exit(1) + + config_file = config.get('Default', 'config_file').strip() + if config_file == "" or config_file == "\n": + config_file = auto_keys_dir +"/gcp_api_private.json" + + if not os.path.isfile(config_file): + print("Invalid JSON Key File at " + config_file + ". Please try again......Exiting !!") + exit(1) + + + outdir_structure_file = config.get('Default', 'outdir_structure_file').strip() + ssh_public_key = config.get('Default', 'ssh_public_key').strip() + +except Exception as e: + print(e) + print('Check if input properties exist and try again..exiting...') + exit(1) + + +if not os.path.exists(prefix_dir): + os.makedirs(prefix_dir) +if not os.path.exists(config_files): + os.makedirs(config_files) +if not os.path.exists(outdir_safe): + os.makedirs(outdir_safe) + +# Copy input properties file to customer_tenancy_dir +shutil.copy(args.propsfile,config_files+"/"+prefix+"_"+os.path.basename(args.propsfile)) + +# 1. Copy outdir_structure_file and config file +# Copy default outdir_structure_file +shutil.copy(toolkit_dir+'/user-scripts/outdir_structure_file.properties', toolkit_dir+'/user-scripts/.outdir_structure_file.properties') + +_outdir_structure_file = '' +dir_values = [] +if (outdir_structure_file != '' and outdir_structure_file != "\n"): + if not os.path.isfile(outdir_structure_file): + print("Invalid outdir_structure_file. Please provide correct file path......Exiting !!") + exit(1) + else: + outdir_config = configparser.RawConfigParser() + outdir_config.read(outdir_structure_file) + for key, value in outdir_config.items("Default"): + if value == '': + print("Out Directory is missing for one or more parameters, for eg. " + key) + print("Please check " + outdir_structure_file) + exit(1) + if value not in dir_values: + dir_values.append(str(value)) + + _outdir_structure_file = prefix_dir+ "/"+prefix+"_outdir_structure_file.properties" + #if not os.path.exists(_outdir_structure_file): + shutil.copyfile(outdir_structure_file, _outdir_structure_file) + print("\nUsing different directories for GCP services as per the input outdir_structure_file..........") +else: + print("\nUsing single out directory for resources..........") + +filename = os.path.basename(config_file) +_config_file=config_files + "/" + filename +shutil.copy(config_file, _config_file) +os.chmod(_config_file,0o600) + + +# 2. Authenticate and Get Projects +gct = gcpCommonTools() +credentials = gct.authenticate(config_file) +gct.get_organization_projects(organization_id,credentials) + +# 3. Generate setUpCloud.properties file +print("Creating GCP specific setUpCloud.properties.................") +with open(setupcloud_props_toolkit_file_path, 'r+') as setUpCloud_file: + setupcloud_props_toolkit_file_data = setUpCloud_file.read().rstrip() + +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("outdir=", "outdir="+terraform_files) +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("prefix=", "prefix="+prefix) +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("organization_id=", "organization_id=" + organization_id) +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("config_file=", "config_file="+_config_file) +setupcloud_props_toolkit_file_data = setupcloud_props_toolkit_file_data.replace("outdir_structure_file=", "outdir_structure_file="+_outdir_structure_file) + +f = open(setupcloud_props_file_path, "w+") +f.write(setupcloud_props_toolkit_file_data) +f.close() + +# 4.Create the TF related files for each project +if not os.path.exists(terraform_files): + os.makedirs(terraform_files) + + +print("Creating GCP specific project directories, terraform provider , variables files.................") +#regions_file_data = "" + +# 5. Read variables.tf from examples folder and copy the variables as string +for id,name in gct.projects.items(): + project=id + + with open(variables_example_file, 'r+') as var_eg_file: + variables_example_file_data = var_eg_file.read().rstrip() + + variables_example_file_data = variables_example_file_data.replace("", _config_file) + variables_example_file_data = variables_example_file_data.replace("", project) + + # Rerunning script for any new project subscription. Process only new prohect directories else continue + if os.path.exists(terraform_files + project): + continue + + os.mkdir(terraform_files + project) + f = open(terraform_files + "/" + project + "/variables_" + project + ".tf", "w+") + f.write(variables_example_file_data) + f.close() + + # 6. Copy terraform modules and variables file to outdir + distutils.dir_util.copy_tree(tf_modules_dir, terraform_files + "/" + project) + + # Manage single and multiple outdir + if (outdir_structure_file == '' or outdir_structure_file == "\n"): + # remove depends_on for single outdir + project_dir = terraform_files + "/" + project + "/" + single_outdir_config = configparser.RawConfigParser() + outdir_config_file = os.path.dirname(os.path.abspath(__file__)) + "/.outdir_structure_file.properties" + + single_outdir_config.read(outdir_config_file) + keys = [] + for key, val in single_outdir_config.items("Default"): + keys.append(key) + for file in os.listdir(project_dir): + # name=file.removesuffix(".tf") + name = file[:-len(".tf")] + if name in keys: + file = project_dir + "/" + file + with open(file, 'r+') as tf_file: + module_data = tf_file.read().rstrip() + module_data = module_data.replace("# depends_on", "depends_on") + tf_file.close() + f = open(file, "w+") + f.write(module_data) + f.close() + else: + project_dir = terraform_files + "/" + project + "/" + for service, service_dir in outdir_config.items("Default"): + service = service.strip().lower() + service_dir = service_dir.strip() + + # Keep the .tf file in default region directory if directory name is empty + if service_dir == "" or service_dir == "\n" or service!='instance': + continue + + project_service_dir=project_dir+service_dir + if not os.path.exists(project_service_dir): + os.mkdir(project_service_dir) + + if (service == 'instance'): + if (os.path.isdir(project_service_dir + '/scripts')): + shutil.rmtree(project_service_dir + '/scripts') + if (os.path.exists(project_dir + 'scripts')): + shutil.move(project_dir + 'scripts', project_service_dir + '/') + with open(project_dir + service + ".tf", 'r+') as tf_file: + module_data = tf_file.read().rstrip() + module_data = module_data.replace("\"./modules", "\"../modules") + + f = open(project_service_dir + "/" + service + ".tf", "w+") + f.write(module_data) + f.close() + os.remove(project_dir + service + ".tf") + + shutil.copyfile(project_dir + "variables_" + project + ".tf", + project_service_dir + "/" + "variables_" + project + ".tf") + shutil.copyfile(project_dir + "provider.tf", project_service_dir + "/" + "provider.tf") + + + os.remove(terraform_files + "/" + project + "/" + "variables_" + project + ".tf") + os.remove(terraform_files + "/" + project + "/" + "provider.tf") + + # 8. Remove terraform example variable file from outdir + os.remove(terraform_files + "/" + project + "/variables_example.tf") + + +# Logging information +f = os.path.basename(__file__).rstrip("py")+".out" +outfile = prefix_dir + "/"+ f +logging.basicConfig(filename=outfile, format='%(message)s', filemode='w', level=logging.INFO) + +print("==================================================================================================================================") +print("\nThe toolkit has been setup successfully. !!!\n") +f = open(safe_file, "a") +data="GCP\t"+prefix + "\t" + "SUCCESS\t"+current_time+"\n" +f.write(data) +f.close() + +logging.info("Tenant Specific Working Directory Path: "+prefix_dir+"\n") + +logging.info("\n######################################") +logging.info("Next Steps for using toolkit via CLI") +logging.info("######################################") +logging.info("Modify "+prefix_dir + "/" +prefix+"_setUpGCP.properties with input values for cd3file and workflow_type") +logging.info("cd "+os.path.dirname(os.path.abspath(__file__))) +logging.info("python setUpGCP.py "+setupcloud_props_file_path) + +with open(outfile, 'r') as log_file: + data = log_file.read().rstrip() +print(data) + +print("==================================================================================================================================") + + + + + + + + + + + + diff --git a/cd3_automation_toolkit/user-scripts/createTenancyConfig.py b/cd3_automation_toolkit/user-scripts/createTenancyConfig.py index b26b83590..26771509c 100644 --- a/cd3_automation_toolkit/user-scripts/createTenancyConfig.py +++ b/cd3_automation_toolkit/user-scripts/createTenancyConfig.py @@ -17,9 +17,11 @@ from oci.object_storage import ObjectStorageClient import glob import subprocess -sys.path.append(os.getcwd()+"/..") from os import environ -from commonTools import * +sys.path.append(os.getcwd()) +sys.path.append(os.getcwd()+"/..") +from ocicloud.python.ociCommonTools import * +from ocicloud.python.cd3Services import * from copy import deepcopy from subprocess import DEVNULL global topic_name @@ -203,9 +205,9 @@ def update_devops_config(prefix, repo_ssh_url,files_in_repo,dir_values,devops_us # create symlink for Git Config file for SSH operations. src = git_config_file - if not os.path.exists("/cd3user/.ssh"): - os.makedirs("/cd3user/.ssh") - dst = "/cd3user/.ssh/config" + if not os.path.exists("/home/cd3user/.ssh"): + os.makedirs("/home/cd3user/.ssh") + dst = "/home/cd3user/.ssh/config" try: os.symlink(src,dst) except FileExistsError as e: @@ -364,7 +366,7 @@ def create_bucket(config, signer): auto_keys_dir = user_dir + "/tenancies/keys" toolkit_dir = os.path.dirname(os.path.abspath(__file__))+"/.." #toolkit_dir = user_dir +"/oci_tools/cd3_automation_toolkit" -terraform_dir = toolkit_dir + "/user-scripts/terraform" +terraform_dir = toolkit_dir + "/ocicloud/terraform" variables_example_file = terraform_dir + "/variables_example.tf" setupoci_props_toolkit_file_path = toolkit_dir + "/setUpOCI.properties" @@ -537,7 +539,7 @@ def create_bucket(config, signer): dir_values = [] # Copy input properties file to customer_tenancy_dir -shutil.copy(args.propsfile,config_files+"/"+prefix+"_"+os.path.basename(args.propsfile)) +shutil.copy(args.propsfile,config_files+"/"+prefix+"_tenancyconfig.properties") # 1. Copy outdir_structure_file @@ -626,7 +628,7 @@ def create_bucket(config, signer): tenancy_id=tenancy ## Authenticate -ct = commonTools() +ct = ociCommonTools() config, signer = ct.authenticate(auth_mechanism, config_file_path) _realm = config['tenancy'].split(".")[2] cloud_domain = "."+oci.regions.REALMS[_realm] @@ -636,7 +638,7 @@ def create_bucket(config, signer): cd3service.fetch_regions(config, signer) #This is needed to be initialised again -ct = commonTools() +ct = ociCommonTools() try: ct.get_subscribedregions(config,signer) except Exception as e: @@ -1134,7 +1136,7 @@ def create_bucket(config, signer): logging.info("Next Steps for using toolkit via CLI") logging.info("######################################") logging.info("Modify "+customer_tenancy_dir + "/" +prefix+"_setUpOCI.properties with input values for cd3file and workflow_type") -logging.info("cd "+user_dir+"/oci_tools/cd3_automation_toolkit/") +logging.info("cd "+user_dir+"/oci_tools/cd3_automation_toolkit") logging.info("python setUpOCI.py "+customer_tenancy_dir + "/" +prefix+"_setUpOCI.properties") with open(outfile, 'r') as log_file: diff --git a/cd3_automation_toolkit/user-scripts/deleteTenancyConfig.py b/cd3_automation_toolkit/user-scripts/deleteTenancyConfig.py index 6ea6df177..c7085adc9 100644 --- a/cd3_automation_toolkit/user-scripts/deleteTenancyConfig.py +++ b/cd3_automation_toolkit/user-scripts/deleteTenancyConfig.py @@ -18,10 +18,12 @@ import oci from oci.object_storage import ObjectStorageClient from copy import deepcopy -sys.path.append(os.getcwd()+"/..") import subprocess from os import environ -from commonTools import * +sys.path.append(os.getcwd()) +sys.path.append(os.getcwd()+"/..") +from ocicloud.python.ociCommonTools import * +from ocicloud.python.cd3Services import * @@ -165,7 +167,7 @@ repo_name = devops_repo.split("/")[1] devops_exists = True - ct = commonTools() + ct = ociCommonTools() config, signer = ct.authenticate(auth_mechanism, config_file_path) try: ct.get_subscribedregions(config,signer) diff --git a/cd3_automation_toolkit/user-scripts/setUpAzure.py b/cd3_automation_toolkit/user-scripts/setUpAzure.py new file mode 100644 index 000000000..7c6a36ad3 --- /dev/null +++ b/cd3_automation_toolkit/user-scripts/setUpAzure.py @@ -0,0 +1,243 @@ +import argparse +import configparser +from collections import namedtuple +import datetime,os +import sys +sys.path.append(os.getcwd()) +sys.path.append(os.getcwd()+"/..") +from azurecloud.python import * +from common.python import * + + +def match_options(options, prim_options): + print("match_options") + user_input = "" + # Iterate over options. Print number and option + for i, option in enumerate(options, 1): + if option.name in prim_options: + user_input += "," + str(i) + user_input = user_input.split(',')[1:] + try: + return [options[int(choice) - 1] for choice in user_input] + except IndexError as ie: + print("\nInvalid Option.....Exiting!!") + exit(1) + + +def show_options(options, quit=False, menu=False, extra=None, index=0): + # Just add whitespace between number and option. It just makes it look better + number_offset = len(str(len(options))) + 1 + # Iterate over options. Print number and option + for i, option in enumerate(options, index): + print(f'{str(i)+".":<{number_offset}} {option.name}') + if quit: + print(f'{"q"+".":<{number_offset}} Press q to quit') + if menu: + print(f'{"m"+".":<{number_offset}} Press m to go back to Main Menu') + if extra: + print(extra) + user_input = input('Enter your choice (specify comma separated to choose multiple choices): ') + user_input = user_input.split(',') + if 'q' in user_input or 'm' in user_input: + return user_input + # Subtract one to account for zero-indexing. The options start at 1 + # #return [options[int(choice)-1] for choice in user_input] + + try: + for choice in user_input: + if int(choice) - index < 0: + print("\nInvalid Option.....Exiting!!") + exit(1) + elif options[int(choice) - index].name == "Execute All": + options.pop(0) + return options + except ValueError as ie: + print("\nInvalid Input.....Try again!!\n") + options = show_options(inputs, quit=True, index=index) + return options + + try: + return [options[int(choice)-index] for choice in user_input] + except IndexError as ie: + print("\nInvalid Option.....Exiting!!") + exit(1) + except ValueError as ie: + print("\nInvalid Input.....Try again!!\n") + options = show_options(inputs, quit=True, index=index) + return options + +def execute_options(options, *args, **kwargs): + global menu, quit + if 'm' in options or 'q' in options: + menu = 'm' in options + quit = 'q' in options + else: + for option in options: + if option.name == "Execute All": + continue + else: + with section(option.text): + option.callback(*args, **kwargs) + + +def create_adb_azure(): + create_terraform_adb_azure(inputfile, outdir, prefix) + +def create_exa_azure(): + create_terraform_exa_infra_azure(inputfile, outdir, prefix) + create_terraform_exa_vmclusters_azure(inputfile, outdir, prefix) + + +def create_db_at_azure(execute_all=False): + options = [ + Option('Add/Modify/Delete ADB @Azure', create_adb_azure, 'Processing ADB-Azure Tab'), + Option('Add/Modify/Delete Exa @Azure', create_exa_azure, 'Processing Exa-Azure Tabs') + # Option('Enable LBaaS Logs', enable_lb_logs, 'LBaaS Logs') + ] + options = show_options(options, quit=True, menu=True, index=1) + if not execute_all: + execute_options(options) + +''' +def export_az_adb(): + export_az_oci_adb(inputfile, outdir, credentials) +''' +def export_az_oci_exa(): + export_az_oci_adb(inputfile, outdir, credentials) + +def export_db_at_azure(execute_all=False): + options = [ + Option('Export ADB @Azure', export_adb_azure, 'Exporting ADB-Azure'), + # Option('Export Exa @Azure', export_az_oci_exa, 'Processing Exa-Azure') + ] + options = show_options(options, quit=True, menu=True, index=1) + if not execute_all: + execute_options(options,inputfile, outdir, credentials) + + create_terraform_adb_azure(inputfile, outdir, prefix) + + +#Execution starts here +global devops +global updated_paths +global import_scripts +updated_paths = [] +import_scripts = [] +# Opt-in to IMDS lookup +exec_start_time = datetime.datetime.now() +parser = argparse.ArgumentParser(description='Sets Up OCI via TF') +parser.add_argument('propsfile', help="Full Path of properties file containing input variables. eg setUpAzure.properties") +#parser.add_argument('--main_options', default="") +#parser.add_argument('--sub_options', default="") +#parser.add_argument('--sub_child_options', default="") +#parser.add_argument('--add_filter', default=None) +#parser.add_argument('--devops', default=False) +args = parser.parse_args() +setUpAz_props = configparser.RawConfigParser() +setUpAz_props.read(args.propsfile) +#devops = args.devops +#main_options = args.main_options.split(",") +#sub_options = args.sub_options.split(",") +#sub_child_options = args.sub_child_options.split(",") + +#Read Config file Variables +try: + workflow_type = setUpAz_props.get('Default', 'workflow_type').strip().lower() + + if (workflow_type == 'export_resources'): + non_gf_tenancy = True + else: + non_gf_tenancy = False + + inputfile = setUpAz_props.get('Default','cd3file').strip() + outdir = setUpAz_props.get('Default', 'outdir').strip() + prefix = setUpAz_props.get('Default', 'prefix').strip() + tf_or_tofu = "terraform" + + if not outdir: + exit_menu('input outdir location cannot be left blank. Exiting... ') + elif not prefix: + exit_menu('input prefix value cannot be left blank. Exiting... ') + elif not inputfile: + exit_menu('input cd3file location cannot be left blank. Exiting... ') + elif '.xls' not in inputfile: + exit_menu('valid formats for input cd3file are either .xls or .xlsx') +except Exception as e: + exit_menu(str(e) + ". Check input properties file and try again. Exiting... ") + + + +Option = namedtuple('Option', ['name', 'callback', 'text']) +extra = '' + +# Pre-work +if not os.path.exists(outdir): + os.makedirs(outdir) + + +#if devops: + # Set Export filters from devops + #export_filters = args.add_filter.split("@") if args.add_filter else [] + #ct.get_export_filters(export_filters) + +## Menu Options +if non_gf_tenancy: + + ct = azrCommonTools() + credentials = ct.authenticate(args.propsfile) + + # verify_outdir_is_empty() + print("\nworkflow_type set to export_resources. Export existing Azure objects and Synch with TF state") + print("We recommend to not have any existing tfvars/tfstate files for export out directory") + #export_regions = get_region_list(rm=False,vizoci=False) + #compartments = ct.get_compartment_map(var_file, "OCI Resources") + #export_tags_list = get_tags_list() + + inputs = [ + Option("Export DB @Azure", export_db_at_azure, "Export DB @Azure"), + + ] + +else: + inputs = [ + Option('Create DB @Azure', create_db_at_azure, 'Create DB @Azure'), + + ] +''' +if main_options and args.main_options != "": + options = match_options(inputs, main_options) + for option in options: + with section(option.text, header=True): + option.callback(prim_options=sub_options) +else: +''' +if True: + print("\nChoose appropriate option from below :\n") + # Run menu + menu = True + while menu: + if non_gf_tenancy: + options = show_options(inputs, quit=True, index=1) + else: + options = show_options(inputs, quit=True, extra='\nSee example folder for sample input files\n', index=1) + if 'q' in options: + exit_menu('Exiting...') + for option in options: + menu = False + with section(option.text, header=True): + option.callback() + if menu: + break +# write updated paths to a file +''' +updated_paths_file = f'{outdir}/.safe/updated_paths.safe' +with open(updated_paths_file, 'w+') as f: + for item in updated_paths: + f.write(str(item).replace('//', '/') + "\n") +f.close() +import_scripts_file = f'{outdir}/.safe/import_scripts.safe' +with open(import_scripts_file, 'w+') as f: + for item in import_scripts: + f.write(str(item).replace('//', '/') + "\n") +f.close() +''' \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/main.tf b/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/main.tf deleted file mode 100644 index 253535843..000000000 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/main.tf +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. -# -############################ -# Resource Block - ManagementServices -# Create Notifications_Subscriptions -############################ - -resource "oci_ons_subscription" "subscription" { - - #Required - compartment_id = var.compartment_id - endpoint = var.endpoint - protocol = var.protocol - topic_id = var.topic_id - - #Optional - defined_tags = var.defined_tags - freeform_tags = var.freeform_tags - -} diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/outputs.tf b/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/outputs.tf deleted file mode 100644 index fed34382a..000000000 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/outputs.tf +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. -# -############################ -# Output Block - ManagementServices -# Create Notifications_Subscriptions -############################ - -output "topic_subscription_tf_id" { - description = "Topic Subscription OCID" - value = oci_ons_subscription.subscription.id -} \ No newline at end of file diff --git a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/variables.tf b/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/variables.tf deleted file mode 100644 index f53a165a3..000000000 --- a/cd3_automation_toolkit/user-scripts/terraform/modules/managementservices/notification-subscription/variables.tf +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. -# -############################ -# Variables Block - ManagementServices -# Create Notifications_Subscriptions -############################ - -variable "compartment_id" { - type = string -} - -variable "endpoint" { - type = string -} - -variable "protocol" { - type = string -} - -variable "topic_id" { - type = string -} - -variable "defined_tags" { - type = map(any) - default = { "Oracle-Tags.CreatedOn" = "$${oci.datetime}", - "Oracle-Tags.CreatedBy" = "$${iam.principal.name}" - } -} - -variable "freeform_tags" { - type = map(any) - default = {} -} \ No newline at end of file diff --git a/jenkins_install/apply.groovy b/jenkins_install/apply.groovy index 103bcbbc3..45566a1ca 100644 --- a/jenkins_install/apply.groovy +++ b/jenkins_install/apply.groovy @@ -104,7 +104,7 @@ pipeline { def toolCmd = env.tf_or_tofu == 'terraform' ? 'terraform' : 'tofu' // Run Terraform/Tofu show and capture the output // Run OPA eval - opaOutput = labelledShell( label: 'Evaluating plan against OPA', script: "cd \"${WORKSPACE}/${env.Region}/${env.Service}\" && ${toolCmd} show -json tfplan.out > tfplan.json && opa eval -f pretty -b /cd3user/oci_tools/cd3_automation_toolkit/user-scripts/OPA/ -i \"${WORKSPACE}/${env.Region}/${env.Service}/tfplan.json\" data.terraform.deny", returnStdout: true).trim() + opaOutput = labelledShell( label: 'Evaluating plan against OPA', script: "cd \"${WORKSPACE}/${env.Region}/${env.Service}\" && ${toolCmd} show -json tfplan.out > tfplan.json && opa eval -f pretty -b /cd3user/oci_tools/cd3_automation_toolkit/common/opa -i \"${WORKSPACE}/${env.Region}/${env.Service}/tfplan.json\" data.terraform.deny", returnStdout: true).trim() if (opaOutput == '[]') { echo "No OPA rules are violated. Proceeding with the next stage." } else { diff --git a/jenkins_install/jenkins.sh b/jenkins_install/jenkins.sh index 0a2ab258e..e17a11ae7 100644 --- a/jenkins_install/jenkins.sh +++ b/jenkins_install/jenkins.sh @@ -20,8 +20,8 @@ fi #cp -r ${JENKINS_INSTALL}/scriptler $JENKINS_HOME cp ${JENKINS_INSTALL}/jcasc.yaml "$JENKINS_HOME/" -if [ ! -e "/cd3user/.ssh/config" ]; then - ln -s /cd3user/tenancies/jenkins_home/git_config /cd3user/.ssh/config +if [ ! -e "/home/cd3user/.ssh/config" ]; then + ln -s /cd3user/tenancies/jenkins_home/git_config /home/cd3user/.ssh/config fi # Copy scriptler directory From 4b0d654c17093e1c0582e0c7e554154ed33ce5d9 Mon Sep 17 00:00:00 2001 From: Suruchi Date: Thu, 18 Sep 2025 14:22:04 +0530 Subject: [PATCH 02/33] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c905f465..63886b204 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Additionally, the toolkit also supports seamless resource management using OCI D 🚀 Click the below button to quickly launch CD3 toolkit container in Oracle Cloud and start managing your Infra as Code.
    -[![Deploy_To_OCI](https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg)](https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/oracle-devrel/cd3-automation-toolkit/archive/refs/heads/main.zip) +[![Deploy_To_OCI](https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg)](https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/oracle-devrel/cd3-automation-toolkit/archive/refs/heads/develop.zip)
    From 91c0f89ba17b89bb3a0ef45ff20108c35227c383 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Thu, 18 Sep 2025 15:02:32 +0530 Subject: [PATCH 03/33] CD3 Automation Toolkit Release v2025.2.0 --- OCIWorkVMStack/scripts/installToolkit.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 657aeca4b..0cbb40d65 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -1,10 +1,12 @@ #!/bin/bash username=cd3user -sudo mkdir -p /$username/mount_path/tenancies -sudo mkdir -p /$username/mount_path/oci_tools logfile="/$username/mount_path/installToolkit.log" toolkit_dir="/tmp/githubCode" +mount_dir="/$username/mount_path" +sudo mkdir -p /$mount_dir/tenancies +sudo mkdir -p /$mount_dir/oci_tools + tenancyconfig_properties="$toolkit_dir/cd3_automation_toolkit/user-scripts/tenancyconfig.properties" start=$(date +%s.%N) sudo sh -c "echo '########################################################################' >> /etc/motd" @@ -68,8 +70,8 @@ sudo podman --version >> $logfile 2>&1 || true echo "***Download Toolkit***" >> $logfile 2>&1 sudo git clone https://github.com/oracle-devrel/cd3-automation-toolkit.git $toolkit_dir >> $logfile 2>&1 -cp -r $toolkit_dir/cd3_automation_toolkit /cd3user/oci_tools/ -cp -r $toolkit_dir/othertools /cd3user/oci_tools/ +cp -r $toolkit_dir/cd3_automation_toolkit /$mount_dir/oci_tools/ +cp -r $toolkit_dir/othertools /$mount_dir/oci_tools/ stop_exec curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/ -o /tmp/metadata.json From fc0f1c1d47364364771040d04a0b97065138f68a Mon Sep 17 00:00:00 2001 From: Suruchi Date: Thu, 18 Sep 2025 15:04:52 +0530 Subject: [PATCH 04/33] Update installToolkit.sh --- OCIWorkVMStack/scripts/installToolkit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 0cbb40d65..3ff99c036 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -69,7 +69,7 @@ fi sudo podman --version >> $logfile 2>&1 || true echo "***Download Toolkit***" >> $logfile 2>&1 -sudo git clone https://github.com/oracle-devrel/cd3-automation-toolkit.git $toolkit_dir >> $logfile 2>&1 +sudo git clone https://github.com/oracle-devrel/cd3-automation-toolkit.git -b develop $toolkit_dir >> $logfile 2>&1 cp -r $toolkit_dir/cd3_automation_toolkit /$mount_dir/oci_tools/ cp -r $toolkit_dir/othertools /$mount_dir/oci_tools/ stop_exec @@ -104,4 +104,4 @@ duration_sec=$(echo "$(date +%s.%N) - $start" | bc) duration_min=$(echo "$duration_sec%3600/60" | bc) execution_time=`printf "%.2f seconds" $duration_sec` echo "Script Execution Time in Seconds: $execution_time" >> $logfile 2>&1 -echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 \ No newline at end of file +echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 From 973ab269381da74d95534c57a08fffce1f327b83 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Thu, 18 Sep 2025 16:10:21 +0530 Subject: [PATCH 05/33] CD3 Automation Toolkit Release v2025.2.0 --- Dockerfile | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100755 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 000000000..5a827d59f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,107 @@ +FROM oraclelinux:9-slim +LABEL maintainer="Team at Oracle" +LABEL description="OCI format to generate CD3 image" + + +########### Input Parameters for image creation ############ +# UID of user on underlying OS. eg 503 for Mac +ARG USER_UID=1001 +# Whether to download Jenkins as part of image creation +ARG USE_DEVOPS=YES +############################################################# + + +ARG USERNAME=cd3user +ARG USER_GID=$USER_UID +# Whether to download Provider as part of image creation +ARG DOWNLOAD_PROVIDER=NO +# TF Provider version +ARG TF_OCI_PROVIDER=7.18.0 +ARG TF_NULL_PROVIDER=3.2.3 + +RUN microdnf install -y sudo && \ + groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID $USERNAME && \ + echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME && \ + mkdir -p /cd3user/tenancies && \ + chown -R $USERNAME:$USERNAME /cd3user/tenancies/ && \ + microdnf install -y vim && \ + microdnf install -y dnf && \ + microdnf install -y wget && \ + microdnf install -y unzip && \ + microdnf install -y graphviz && \ + ln -sf /usr/bin/python3 /usr/bin/python && \ + echo 'alias vi="vim"' >> /etc/bashrc + +USER $USERNAME +#WORKDIR /cd3user/oci_tools/ +#COPY cd3_automation_toolkit cd3_automation_toolkit/ +#COPY othertools othertools/ + +WORKDIR /cd3user/ + +RUN sudo dnf install -y oraclelinux-release-el9 && \ +sudo chown -R $USERNAME:$USERNAME /cd3user/ && \ +sudo sed -i -e 's/\r$//' /cd3user/oci_tools/cd3_automation_toolkit/shell_script.sh && \ +bash /cd3user/oci_tools/cd3_automation_toolkit/shell_script.sh && \ +sudo dnf clean all && \ +sudo rm -rf /var/cache/dnf && \ +sudo chmod -R 740 /cd3user/ && \ +sudo chown -R cd3user:cd3user /cd3user/ + + +RUN if [ "$DOWNLOAD_PROVIDER" == "YES" ]; then \ +# oci provider +sudo wget https://releases.hashicorp.com/terraform-provider-oci/${TF_OCI_PROVIDER}/terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip && \ +sudo mkdir -p /cd3user/.terraform.d/plugins/registry.terraform.io/oracle/oci/${TF_OCI_PROVIDER}/linux_amd64 && \ +sudo unzip terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip -d /cd3user/.terraform.d/plugins/registry.terraform.io/oracle/oci/${TF_OCI_PROVIDER}/linux_amd64 && \ +# null provider +sudo wget https://releases.hashicorp.com/terraform-provider-null/${TF_NULL_PROVIDER}/terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip && \ +sudo mkdir -p /cd3user/.terraform.d/plugins/registry.terraform.io/hashicorp/null/${TF_NULL_PROVIDER}/linux_amd64 && \ +sudo unzip terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip -d /cd3user/.terraform.d/plugins/registry.terraform.io/hashicorp/null/${TF_NULL_PROVIDER}/linux_amd64 && \ +sudo cp -r /cd3user/.terraform.d/plugins/registry.terraform.io /cd3user/.terraform.d/plugins/registry.opentofu.org && \ +sudo chown -R cd3user:cd3user /cd3user/ && \ +sudo rm -rf terraform-provider-null_${TF_NULL_PROVIDER}_linux_amd64.zip terraform-provider-oci_${TF_OCI_PROVIDER}_linux_amd64.zip ;\ + +fi + +##################################### START INSTALLING JENKINS ################################### +ARG JENKINS_VERSION=2.504.1 +ARG JENKINS_SHA=81026db18b0c4aad6b62cf408e4c42e5797661b41c517b37df606238e89b9df1 +ARG JENKINS_PLUGIN_MANAGER_VERSION=2.12.13 +ARG PLUGIN_CLI_URL=https://github.com/jenkinsci/plugin-installation-manager-tool/releases/download/${JENKINS_PLUGIN_MANAGER_VERSION}/jenkins-plugin-manager-${JENKINS_PLUGIN_MANAGER_VERSION}.jar + +ARG JENKINS_HOME=/cd3user/tenancies/jenkins_home +ARG JENKINS_INSTALL=/usr/share/jenkins +ARG REF=/usr/share/jenkins/ref + +ENV USE_DEVOPS ${USE_DEVOPS} +ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk +ENV JENKINS_HOME ${JENKINS_HOME} +ENV JENKINS_INSTALL ${JENKINS_INSTALL} +ENV REF ${REF} +ENV JENKINS_UC https://updates.jenkins.io +ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental +ENV JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals +ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false" +ENV COPY_REFERENCE_FILE_LOG ${JENKINS_HOME}/copy_reference_file.log +ENV CASC_JENKINS_CONFIG ${JENKINS_HOME}/jcasc.yaml +COPY --chown=cd3user:cd3user jenkins_install ${JENKINS_INSTALL}/ +COPY --chown=cd3user:cd3user jenkins_install/init/*.groovy ${REF}/init.groovy.d/ +COPY --chown=cd3user:cd3user jenkins_install/plugins.txt ${REF}/plugins.txt + + +RUN if [ "$USE_DEVOPS" == "YES" ]; then \ + sudo microdnf install -y java-21-openjdk && \ + sudo microdnf install -y java-21-openjdk-devel && \ + sudo microdnf install git-2.39.3 -y && \ + sudo mkdir -p ${REF}/init.groovy.d && \ + sudo chown -R cd3user:cd3user ${JENKINS_INSTALL} && \ + sudo curl -fsSL http://updates.jenkins-ci.org/download/war/${JENKINS_VERSION}/jenkins.war -o ${JENKINS_INSTALL}/jenkins.war && \ + echo "${JENKINS_SHA} ${JENKINS_INSTALL}/jenkins.war" | sha256sum -c - && \ + sudo curl -fsSL ${PLUGIN_CLI_URL} -o ${JENKINS_INSTALL}/jenkins-plugin-manager.jar && \ + sudo java -jar ${JENKINS_INSTALL}/jenkins-plugin-manager.jar --war ${JENKINS_INSTALL}/jenkins.war --verbose -f ${REF}/plugins.txt && \ + sudo chown -R cd3user:cd3user ${JENKINS_INSTALL} && \ + sudo chmod +x ${JENKINS_INSTALL}/jenkins.sh ; \ + fi From fba2ad00f23be24350816fd7f4748684bcf2329a Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Thu, 18 Sep 2025 16:28:56 +0530 Subject: [PATCH 06/33] CD3 Automation Toolkit Release v2025.2.0 --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5a827d59f..51c7b6793 100755 --- a/Dockerfile +++ b/Dockerfile @@ -35,9 +35,9 @@ RUN microdnf install -y sudo && \ echo 'alias vi="vim"' >> /etc/bashrc USER $USERNAME -#WORKDIR /cd3user/oci_tools/ -#COPY cd3_automation_toolkit cd3_automation_toolkit/ -#COPY othertools othertools/ +WORKDIR /cd3user/oci_tools/ +COPY cd3_automation_toolkit cd3_automation_toolkit/ +COPY othertools othertools/ WORKDIR /cd3user/ From 482d1d80be8f250fcc77adf7d00cceb1d9965539 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Thu, 18 Sep 2025 16:49:57 +0530 Subject: [PATCH 07/33] CD3 Automation Toolkit Release v2025.2.0 --- OCIWorkVMStack/scripts/installToolkit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 3ff99c036..2eebcd3a8 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -93,7 +93,7 @@ stop_exec sudo podman images >> $logfile 2>&1 echo "***Setting Up podman Container***" >> $logfile 2>&1 -sudo podman run --name cd3_toolkit -it -p 8443:8443 -d -v /cd3user/mount_path:/cd3user/tenancies cd3_toolkit bash >> $logfile 2>&1 +sudo podman run --name cd3_toolkit -it -p 8443:8443 -d -v /cd3user/mount_path:/cd3user cd3_toolkit bash >> $logfile 2>&1 stop_exec sudo podman ps -a >> $logfile 2>&1 echo "Connect to Container using command - sudo podman exec -it cd3_toolkit bash " >> $logfile 2>&1 @@ -104,4 +104,4 @@ duration_sec=$(echo "$(date +%s.%N) - $start" | bc) duration_min=$(echo "$duration_sec%3600/60" | bc) execution_time=`printf "%.2f seconds" $duration_sec` echo "Script Execution Time in Seconds: $execution_time" >> $logfile 2>&1 -echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 +echo "Script Execution Time in Minutes: approx $duration_min Minutes" >> $logfile 2>&1 \ No newline at end of file From 571507e1075f685dfb71f957f72ccaf61ba717a1 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Fri, 19 Sep 2025 16:38:38 +0530 Subject: [PATCH 08/33] CD3 Automation Toolkit Release v2025.2.0 --- OCIWorkVMStack/scripts/installToolkit.sh | 1 + .../ocicloud/python/OCI_Regions | 21 +- .../ocicloud/python/cd3Validator.py | 13 +- .../python/database/create_terraform_adb.py | 48 +- .../database/export_adb_nonGreenField.py | 29 +- .../python/database/templates/adb-template | 294 ++- .../quota/export_quotas_nonGreenField.py | 2 +- .../ocicloud/terraform/adb.tf | 158 +- .../ocicloud/terraform/backend.tf | 2 +- .../ocicloud/terraform/identity.tf | 10 +- .../dedicated-vm-host/oracle_provider_req.tf | 10 + .../compute/instance/oracle_provider_req.tf | 10 + .../terraform/modules/database/adb/data.tf | 7 +- .../terraform/modules/database/adb/main.tf | 128 +- .../modules/database/adb/variables.tf | 121 +- .../ocicloud/terraform/provider.tf | 2 +- .../ocicloud/terraform/variables_example.tf | 85 +- cd3_automation_toolkit/setUpOCI.properties | 2 +- cd3_automation_toolkit/setUpOCI.py | 6 +- cd3_automation_toolkit/shell_script.sh | 2 +- .../user-scripts/createTenancyConfig.py | 6 +- .../user-scripts/setUpAzure.py | 4 +- othertools/cis_reports.py | 2001 +++++++++++------ 23 files changed, 2026 insertions(+), 936 deletions(-) create mode 100644 cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf create mode 100644 cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/oracle_provider_req.tf diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 2eebcd3a8..76422b919 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -72,6 +72,7 @@ echo "***Download Toolkit***" >> $logfile 2>&1 sudo git clone https://github.com/oracle-devrel/cd3-automation-toolkit.git -b develop $toolkit_dir >> $logfile 2>&1 cp -r $toolkit_dir/cd3_automation_toolkit /$mount_dir/oci_tools/ cp -r $toolkit_dir/othertools /$mount_dir/oci_tools/ +sudo chown -R $username:$username /$mount_dir/oci_tools/ stop_exec curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/ -o /tmp/metadata.json diff --git a/cd3_automation_toolkit/ocicloud/python/OCI_Regions b/cd3_automation_toolkit/ocicloud/python/OCI_Regions index 04908193c..11249805f 100644 --- a/cd3_automation_toolkit/ocicloud/python/OCI_Regions +++ b/cd3_automation_toolkit/ocicloud/python/OCI_Regions @@ -1,22 +1,13 @@ #Region:Region_Key -abilene:us-abilene-1 amsterdam:eu-amsterdam-1 stockholm:eu-stockholm-1 abudhabi:me-abudhabi-1 -saltlake-1:us-saltlake-1 -saltlake-2:us-saltlake-2 bogota:sa-bogota-1 mumbai:ap-mumbai-1 paris:eu-paris-1 cardiff:uk-cardiff-1 -chennai:ap-chennai-1 -dallas:us-dallas-1 -shawnee:us-shawnee-1 dubai:me-dubai-1 -quincy:us-quincy-1 -tukwila:us-tukwila-4 frankfurt:eu-frankfurt-1 -kulai:ap-kulai-1 saopaulo:sa-saopaulo-1 batam:ap-batam-1 hyderabad:ap-hyderabad-1 @@ -25,36 +16,26 @@ seoul:ap-seoul-1 jeddah:me-jeddah-1 johannesburg:af-johannesburg-1 osaka:ap-osaka-1 -desmoines:us-desmoines-1 -kragujevac:eu-kragujevac-1 london:uk-london-1 milan:eu-milan-1 +madrid:eu-madrid-1 melbourne:ap-melbourne-1 marseille:eu-marseille-1 monterrey:mx-monterrey-1 jerusalem:il-jerusalem-1 -boardman:us-boardman-1 -turin:eu-turin-1 tokyo:ap-tokyo-1 -neom:me-neom-1 -delhi:ap-delhi-1 chicago:us-chicago-1 -madrid-3:eu-madrid-3 -madrid-1:eu-madrid-1 phoenix:us-phoenix-1 queretaro:mx-queretaro-1 riyadh:me-riyadh-1 santiago:sa-santiago-1 sanjose:us-sanjose-1 -riodejaneiro:sa-riodejaneiro-2 sydney:ap-sydney-1 valparaiso:sa-valparaiso-1 vinhedo:sa-vinhedo-1 -columbus:us-columbus-1 singapore-2:ap-singapore-2 singapore-1:ap-singapore-1 chuncheon:ap-chuncheon-1 montreal:ca-montreal-1 toronto:ca-toronto-1 -dublin:eu-dublin-3 zurich:eu-zurich-1 diff --git a/cd3_automation_toolkit/ocicloud/python/cd3Validator.py b/cd3_automation_toolkit/ocicloud/python/cd3Validator.py index 492ff4e5c..059ea7a07 100644 --- a/cd3_automation_toolkit/ocicloud/python/cd3Validator.py +++ b/cd3_automation_toolkit/ocicloud/python/cd3Validator.py @@ -1464,9 +1464,9 @@ def validate_budgets(filename,comp_ids): budget_check_result.append(False) if budget_check_result and False in budget_check_result: - return False - else: return True + else: + return False def validate_buckets(filename, comp_ids): @@ -1988,7 +1988,7 @@ def validate_cd3(choices, filename, var_file, prefix, outdir, ct1): #config1, si print("\nValidating Budgets Tab..") budgets_check = validate_budgets(filename,all_comp_ocids) errors = budgets_check - final_check.append(budgets_check) + #final_check.append(budgets_check) if ('Validate KMS' in options[0]): log("\n============================= Verifying KMS Tab ==========================================\n") @@ -2053,7 +2053,9 @@ def validate_cd3(choices, filename, var_file, prefix, outdir, ct1): #config1, si errors = buckets_check # Prints the final result; once the validation is complete - if any([comp_check, groups_check, policies_check, tags_check, instances_check, dns_check, bvs_check,fss_check, vcn_check, vcn_cidr_check, vcn_peer_check, subnet_check, subnet_cidr_check, dhcp_check, drgv2_check,buckets_check, kms_check]) or False in final_check: + final_errors = False + if any([comp_check, groups_check, policies_check, tags_check, instances_check, dns_check, bvs_check,fss_check, vcn_check, vcn_cidr_check, vcn_peer_check, subnet_check, subnet_cidr_check, dhcp_check, drgv2_check,buckets_check, kms_check, budgets_check]):# or True in final_check: + final_errors = True log("=======") log("Summary:") log("=======") @@ -2083,7 +2085,8 @@ def validate_cd3(choices, filename, var_file, prefix, outdir, ct1): #config1, si print("Invalid Choice....Exiting!!") exit(1) - if inspect.stack()[1].function == 'validate_cd3' or errors: + #if inspect.stack()[1].function == 'validate_cd3' or final_errors: + if final_errors: print("Please check the log file at " + customer_tenancy_dir + "/" + file + "\n") del(log) diff --git a/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py index b1212f650..d2d067d06 100644 --- a/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py +++ b/cd3_automation_toolkit/ocicloud/python/database/create_terraform_adb.py @@ -74,9 +74,9 @@ def create_terraform_adb(inputfile, outdir, service_dir, prefix, ct): # Check if values are entered for mandatory fields if str(df.loc[i, 'Region']).lower() == 'nan' or \ str(df.loc[i, 'Compartment Name']).lower() == 'nan' or \ - str(df.loc[i, 'CPU Core Count']).lower() == 'nan' or \ + str(df.loc[i, 'CPU Detail']).lower() == 'nan' or \ str(df.loc[i, 'DB Name']).lower() == 'nan': - print("\nRegion, Compartment Name, CPU Core Count and DB Name fields are mandatory. Please enter a value and try again !!") + print("\nRegion, Compartment Name, CPU Detail and DB Name fields are mandatory. Please enter a value and try again !!") print("\n** Exiting **") exit(1) @@ -106,6 +106,36 @@ def create_terraform_adb(inputfile, outdir, service_dir, prefix, ct): display_tf_name = commonTools.check_tf_variable(display_tf_name) tempdict = {'display_tf_name': display_tf_name} + if columnname == 'CPU Detail': + columnvalue = columnvalue.strip() + cpu_detail = columnvalue.split("::") + tempdict = {'compute_model': cpu_detail[0],'compute_count':cpu_detail[1].split(".")[0]} + + if columnname == 'Is Auto Scaling Enabled': + columnvalue = columnvalue.strip() + tempdict = {'is_auto_scaling_enabled': columnvalue} + + if columnname == 'Data Storage Size' and columnvalue != '': + columnvalue = columnvalue.strip().lower() + data_storage = columnvalue.split("::") + if len(data_storage) > 1: + if data_storage[0] == "gb": + tempdict = {'data_storage_size_in_gb' : data_storage[1]} + elif data_storage[0] == "tb": + tempdict = {'data_storage_size_in_tbs': data_storage[1]} + elif len(data_storage) == 1: + tempdict = {'data_storage_size_in_tbs': columnvalue} + + if columnname.lower() == 'source' and columnvalue != '': + columnvalue = columnvalue.strip() + tempdict = {'adb_source': columnvalue} + + + if columnname == 'Database Workload': + columnvalue = columnvalue.strip() + autonomous_value = commonTools.check_tf_variable(columnvalue).lower() + tempdict = {'autonomous_value': autonomous_value} + if columnname == 'Database Workload': columnvalue = columnvalue.strip() autonomous_value = commonTools.check_tf_variable(columnvalue).lower() @@ -134,16 +164,27 @@ def create_terraform_adb(inputfile, outdir, service_dir, prefix, ct): subnet_id = '' network_compartment_id = '' + subnet_compartment_id = '' vcn_name = '' if columnname == "Network Details": columnvalue = columnvalue.strip() if ("ocid1.subnet.oc" in columnvalue): network_compartment_id = "root" vcn_name = "" + subnet_compartment_id = "root" subnet_id = columnvalue elif columnvalue.lower() != 'nan' and columnvalue.lower() != '': - if len(columnvalue.split("@")) == 2: + if len(columnvalue.split("@")) == 3: + network_compartment_id, part2 = columnvalue.split("@", 1) + network_compartment_id = commonTools.check_tf_variable(network_compartment_id) + vcn_name, part2 = part2.split("::", 1) + subnet_compartment_id, subnet_name = part2.rsplit("@", 1) + subnet_compartment_id = commonTools.check_tf_variable(subnet_compartment_id) + vcn_subnet_name = f'{vcn_name}::{subnet_name}' + + elif len(columnvalue.split("@")) == 2: network_compartment_id = commonTools.check_tf_variable(columnvalue.split("@")[0].strip()) + subnet_compartment_id = network_compartment_id vcn_subnet_name = columnvalue.split("@")[1].strip() else: network_compartment_id = commonTools.check_tf_variable( @@ -158,6 +199,7 @@ def create_terraform_adb(inputfile, outdir, service_dir, prefix, ct): tempdict = {'network_compartment_id': network_compartment_id, 'vcn_name': vcn_name, + 'subnet_compartment_id': subnet_compartment_id, 'subnet_id': subnet_id} if columnname == "License Model" and columnvalue.strip() == "LICENSE_INCLUDED": diff --git a/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py index 16cf5a94d..409846c8f 100644 --- a/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/database/export_adb_nonGreenField.py @@ -25,20 +25,28 @@ def print_adbs(region, vnc_client, adb, values_for_column, ntk_compartment_name, for item in adb.customer_contacts: customer_emails += ","+item.email adb_subnet_id = adb.subnet_id - + cpu_detail = f'{adb.compute_model}::{str(adb.compute_count).split(".")[0]}' + if hasattr(adb, 'data_storage_size_in_gbs') : + data_storage = f'GB::{str(adb.data_storage_size_in_gbs)}' + # data_storage_size_in_tbs will be used over data_storage_size_in_gbs if available + if hasattr(adb, 'data_storage_size_in_tbs') and str(adb.data_storage_size_in_tbs) != "None": + data_storage = f'TB::{str(adb.data_storage_size_in_tbs)}' if (adb_subnet_id is not None): adb_subnet_info = vnc_client.get_subnet(adb_subnet_id) adb_subnet_name = adb_subnet_info.data.display_name # Subnet-Name adb_vcn_name = vnc_client.get_vcn(adb_subnet_info.data.vcn_id).data.display_name - + snet_comp_id = adb_subnet_info.data.compartment_id ntk_compartment_id = vnc_client.get_vcn(adb_subnet_info.data.vcn_id).data.compartment_id # compartment-id network_compartment_name = ntk_compartment_name for comp_name, comp_id in ct.ntk_compartment_ids.items(): if comp_id == ntk_compartment_id: network_compartment_name = comp_name - - vs = network_compartment_name + "@" + adb_vcn_name + "::" + adb_subnet_name - + if comp_id == snet_comp_id: + ntk_comp_name = comp_name + if ntk_compartment_id == snet_comp_id: + vs = network_compartment_name + "@" + adb_vcn_name + "::" + adb_subnet_name + else: + vs = network_compartment_name + "@" + adb_vcn_name + "::"+ ntk_comp_name + "@" + adb_subnet_name # Fetch NSGs NSGs = adb.nsg_ids @@ -81,10 +89,13 @@ def print_adbs(region, vnc_client, adb, values_for_column, ntk_compartment_name, values_for_column[col_header].append(adb.database_edition) else: values_for_column[col_header].append("") - elif col_header == 'CPU Core Count': - values_for_column[col_header].append(adb.cpu_core_count) - elif col_header == 'Data Storage Size in TB': - values_for_column[col_header].append(adb.data_storage_size_in_tbs) + elif col_header == 'CPU Detail': + values_for_column[col_header].append(cpu_detail) + elif col_header == 'Auto Scaling CPU': + values_for_column[col_header].append(str(adb.is_auto_scaling_enabled)) + elif col_header == 'Data Storage Size': + values_for_column[col_header].append(data_storage) + elif col_header == 'Database Workload': val= adb.db_workload if adb.db_workload == "DW": diff --git a/cd3_automation_toolkit/ocicloud/python/database/templates/adb-template b/cd3_automation_toolkit/ocicloud/python/database/templates/adb-template index 18c55e8a2..63547a91c 100644 --- a/cd3_automation_toolkit/ocicloud/python/database/templates/adb-template +++ b/cd3_automation_toolkit/ocicloud/python/database/templates/adb-template @@ -15,100 +15,244 @@ adb = { } {% else %} - {{ display_tf_name }} = { + {{ display_tf_name }} = { - compartment_id = "{{ compartment_name }}" - db_name = "{{ db_name }}" - display_name = "{{ adb_display_name }}" + compartment_id = "{{ compartment_name }}" + db_name = "{{ db_name }}" + display_name = "{{ adb_display_name }}" - admin_password = "{{ admin_password }}" + admin_password = "{{ admin_password }}" - {% if character_set != "" and character_set != "nan" %} - character_set = "{{ character_set }}" - {% endif %} + {% if are_primary_whitelisted_ips_used and are_primary_whitelisted_ips_used.strip().lower() not in ["", "nan"] %} + are_primary_whitelisted_ips_used = {{ are_primary_whitelisted_ips_used | lower }} + {% endif %} - {% if ncharacter_set != "" and ncharacter_set != "nan" %} - ncharacter_set = "{{ ncharacter_set }}" - {% endif %} + {% if auto_refresh_frequency_in_seconds and auto_refresh_frequency_in_seconds.strip().lower() not in ["", "nan"] %} + auto_refresh_frequency_in_seconds = {{ auto_refresh_frequency_in_seconds }} + {% endif %} - {% if customer_contacts and customer_contacts != "" and customer_contacts != "nan" %} - customer_contacts = {{ customer_contacts | replace("\'","\"") }} - {% endif %} - cpu_core_count = {{ cpu_core_count }} + {% if auto_refresh_point_lag_in_seconds and auto_refresh_point_lag_in_seconds.strip().lower() not in ["", "nan"] %} + auto_refresh_point_lag_in_seconds = {{ auto_refresh_point_lag_in_seconds }} + {% endif %} - {% if database_edition == "" %} - database_edition = null - {% else %} - database_edition = "{{ database_edition }}" #Only for BYOL license model - {% endif %} - {% if data_storage_size_in_tb != "" and data_storage_size_in_tb != "nan" %} - data_storage_size_in_tbs = {{ data_storage_size_in_tb }} - {% endif %} - db_version = "19c" - - {% if autonomous_value == 'adw' %} - db_workload = "DW" - {% elif autonomous_value == 'atp' %} - db_workload = "OLTP" - {% elif autonomous_value == 'json' %} - db_workload = "AJD" - {% elif autonomous_value == 'apex' %} - db_workload = "APEX" - {% else %} - db_workload = "{{ autonomous_value }}" - {% endif %} + {% if adb_source and adb_source.strip().lower() not in ["", "nan"] %} + adb_source = {{ adb_source }} + {% endif %} - license_model = "{{ license_model }}" - whitelisted_ips = [{{ whitelisted_ips }}] + {% if source_id and source_id.strip().lower() not in ["", "nan"] %} + source_id = "{{ source_id }}" + {% endif %} - {% if network_compartment_id == "" %} - network_compartment_id = null - {% else %} - network_compartment_id = "{{ network_compartment_id }}" - {% endif %} - nsg_ids = [{{ nsg_ids }}] - {% if subnet_id == "" %} - subnet_id = null - {% else %} - subnet_id = "{{ subnet_id }}" - {% endif %} - {% if vcn_name == "" %} - vcn_name = null - {% else %} - vcn_name = "{{ vcn_name }}" - {% endif %} + {% if autonomous_database_source_backup_id and autonomous_database_source_backup_id.strip().lower() not in ["", "nan"] %} + autonomous_database_source_backup_id = "{{ autonomous_database_source_backup_id.strip() }}" + {% endif %} + + {% if autonomous_database_id and autonomous_database_id.strip().lower() not in ["", "nan"] %} + autonomous_database_id = "{{ autonomous_database_id.strip() }}" + {% endif %} + + {% if is_auto_scaling_for_storage_enabled and is_auto_scaling_for_storage_enabled.strip().lower() not in ["", "nan"] %} + is_auto_scaling_for_storage_enabled = {{ is_auto_scaling_for_storage_enabled | lower }} + {% endif %} + + {% if data_storage_size_in_gb and data_storage_size_in_gb.strip().lower() not in ["", "nan"] %} + data_storage_size_in_gb = {{ data_storage_size_in_gb }} + {% endif %} + + {% if data_storage_size_in_tbs and data_storage_size_in_tbs.strip().lower() not in ["", "nan"] %} + data_storage_size_in_tbs = {{ data_storage_size_in_tbs }} + {% endif %} + + {% if autonomous_maintenance_schedule_type and autonomous_maintenance_schedule_type.strip().lower() not in ["", "nan"] %} + autonomous_maintenance_schedule_type = "{{ autonomous_maintenance_schedule_type.strip() }}" + {% endif %} + + {% if character_set != "" and character_set != "nan" %} + character_set = "{{ character_set }}" + {% endif %} + + compute_count = {{ compute_count }} + compute_model = "{{ compute_model }}" + + {% if customer_contacts and customer_contacts.strip().lower() not in ["", "nan"] %} + customer_contacts = {{ customer_contacts | replace("\'","\"") }} + {% endif %} + + {% if data_safe_status and data_safe_status.strip().lower() not in ["", "nan"] %} + data_safe_status = "{{ data_safe_status.strip() }}" + {% endif %} + + {% if database_edition == "" %} + database_edition = null + {% else %} + database_edition = "{{ database_edition }}" #Only for BYOL license model + {% endif %} + + {% if db_version and db_version.strip().lower() not in ["", "nan"] %} + db_version = "{{ db_version.strip() }}" + {% endif %} + + {% if autonomous_value == 'adw' %} + db_workload = "DW" + {% elif autonomous_value == 'atp' %} + db_workload = "OLTP" + {% elif autonomous_value == 'json' %} + db_workload = "AJD" + {% elif autonomous_value == 'apex' %} + db_workload = "APEX" + {% else %} + db_workload = "{{ autonomous_value }}" + {% endif %} + + {% if is_auto_scaling_enabled and is_auto_scaling_enabled.strip().lower() not in ["", "nan"] %} + is_auto_scaling_enabled = {{ is_auto_scaling_enabled | lower }} + {% endif %} + + + {% if is_dedicated and is_dedicated.strip().lower() not in ["", "nan"] %} + is_dedicated = {{ is_dedicated | lower }} + {% endif %} + + {% if autonomous_container_database_id and autonomous_container_database_id.strip().lower() not in ["", "nan"] %} + autonomous_container_database_id = "{{ autonomous_container_database_id.strip() }}" + {% endif %} + + {% if kms_key_id and kms_key_id.strip().lower() not in ["", "nan"] %} + kms_key_id = "{{ kms_key_id.strip() }}" + {% endif %} + + {% if vault_id and vault_id.strip().lower() not in ["", "nan"] %} + vault_id = "{{ vault_id.strip() }}" + {% endif %} + + + {% if in_memory_percentage and in_memory_percentage.strip().lower() not in ["", "nan"] %} + in_memory_percentage = {{ in_memory_percentage }} + {% endif %} + + + {% if is_local_data_guard_enabled and is_local_data_guard_enabled.strip().lower() not in ["", "nan"] %} + is_local_data_guard_enabled = {{ is_local_data_guard_enabled | lower }} + {% endif %} + + + {% if is_mtls_connection_required and is_mtls_connection_required.strip().lower() not in ["", "nan"] %} + is_mtls_connection_required = {{ is_mtls_connection_required | lower }} + {% endif %} + + {% if tde_kms_key_id and tde_kms_key_id.strip().lower() not in ["", "nan"] %} + tde_kms_key_id = "{{ tde_kms_key_id.strip() }}" + {% endif %} + + license_model = "{{ license_model }}" + + {% if ncharacter_set != "" and ncharacter_set != "nan" %} + ncharacter_set = "{{ ncharacter_set }}" + {% endif %} + + {% if ocpu_count and ocpu_count.strip().lower() not in ["", "nan"] %} + ocpu_count = {{ ocpu_count }} + {% endif %} + + {% if private_endpoint_ip and private_endpoint_ip.strip().lower() not in ["", "nan"] %} + private_endpoint_ip = "{{ private_endpoint_ip.strip() }}" + {% endif %} + + {% if private_endpoint_label and private_endpoint_label.strip().lower() not in ["", "nan"] %} + private_endpoint_label = "{{ private_endpoint_label.strip() }}" + {% endif %} + + {% if refreshable_mode and refreshable_mode.strip().lower() not in ["", "nan"] %} + refreshable_mode = "{{ refreshable_mode.strip() }}" + {% endif %} + + {% if time_of_auto_refresh_start and time_of_auto_refresh_start.strip().lower() not in ["", "nan"] %} + time_of_auto_refresh_start = "{{ time_of_auto_refresh_start.strip() }}" + {% endif %} + + {% if network_compartment_id == "" %} + network_compartment_id = null + {% else %} + network_compartment_id = "{{ network_compartment_id }}" + {% endif %} + {% if subnet_compartment_id and subnet_compartment_id.strip().lower() not in ["", "nan"] %} + subnet_compartment_id = "{{subnet_compartment_id}}" + {% else %} + subnet_compartment_id = null + {% endif %} + {% if subnet_id == "" %} + subnet_id = null + {% else %} + subnet_id = "{{ subnet_id }}" + {% endif %} + {% if vcn_name == "" %} + vcn_name = null + {% else %} + vcn_name = "{{ vcn_name }}" + {% endif %} + + nsg_ids = [{{ nsg_ids }}] + + {% if backup_retention_period_in_days and backup_retention_period_in_days.strip().lower() not in ["", "nan"] %} + backup_retention_period_in_days = {{ backup_retention_period_in_days }} + {% endif %} + + + {% if is_backup_retention_locked and is_backup_retention_locked.strip().lower() not in ["", "nan"] %} + is_backup_retention_locked = {{ is_backup_retention_locked | lower }} + {% endif %} + + + {% if is_replicate_automatic_backups and is_replicate_automatic_backups.strip().lower() not in ["", "nan"] %} + is_replicate_automatic_backups = {{ is_replicate_automatic_backups | lower }} + {% endif %} + + {% if remote_disaster_recovery_type and remote_disaster_recovery_type.strip().lower() not in ["", "nan"] %} + remote_disaster_recovery_type = "{{ remote_disaster_recovery_type.strip() }}" + {% endif %} + + {% if autonomous_database_timestamp and autonomous_database_timestamp.strip().lower() not in ["", "nan"] %} + timestamp = "{{ autonomous_database_timestamp.strip() }}" + {% endif %} + + + {% if use_latest_available_backup_time_stamp and use_latest_available_backup_time_stamp.strip().lower() not in ["", "nan"] %} + use_latest_available_backup_time_stamp = {{ use_latest_available_backup_time_stamp | lower }} + {% endif %} + + whitelisted_ips = [{{ whitelisted_ips }}] {# ##Do not modify below this line## #} {# #} {# ###Section for adding Defined and Freeform Tags### #} {% if defined_tags and defined_tags != 'nan' and defined_tags != '' and defined_tags != [['nan']] %} - {% if defined_tags[0] %} - defined_tags = { + {% if defined_tags[0] %} + defined_tags = { {% for tags in defined_tags %} - {% if not loop.last %} - "{{ tags[0] }}"= "{{ tags[1] }}" , + {% if not loop.last %} + "{{ tags[0] }}"= "{{ tags[1] }}" , + {% else %} + "{{ tags[0] }}"= "{{ tags[1] }}" + {% endif %} + {% endfor %} + } + {% endif %} + {% endif %} + {% if freeform_tags and freeform_tags != 'nan' and freeform_tags != '' and freeform_tags != [['nan']] %} + {% if freeform_tags[0] %} + freeform_tags = { + {% for tags in freeform_tags %} + {% if not loop.last %} + "{{ tags[0] }}"="{{ tags[1] }}", {% else %} - "{{ tags[0] }}"= "{{ tags[1] }}" + "{{ tags[0] }}"="{{ tags[1] }}" {% endif %} {% endfor %} - } - {% endif %} - {% endif %} - {% if freeform_tags and freeform_tags != 'nan' and freeform_tags != '' and freeform_tags != [['nan']] %} - {% if freeform_tags[0] %} - freeform_tags = { - {% for tags in freeform_tags %} - {% if not loop.last %} - "{{ tags[0] }}"="{{ tags[1] }}", - {% else %} - "{{ tags[0] }}"="{{ tags[1] }}" - {% endif %} - {% endfor %} - } - {% endif %} - {% endif %} + } + {% endif %} + {% endif %} {# ###Section for adding Defined and Freeform Tags ends here### #} }, diff --git a/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py index ebc08ef90..f80c98483 100644 --- a/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/governance/quota/export_quotas_nonGreenField.py @@ -36,7 +36,7 @@ def print_quotas(values_for_columns,region, quota,quota_policy): sheet_dict_quotas,values_for_columns) - # Execution of the code begins here +# Execution of the code begins here def export_quotas_nongreenfield(inputfile, outdir, service_dir, config, signer, ct,export_tags): global tf_import_cmd global values_for_column_quotas diff --git a/cd3_automation_toolkit/ocicloud/terraform/adb.tf b/cd3_automation_toolkit/ocicloud/terraform/adb.tf index 7f4f2b448..e611d113f 100755 --- a/cd3_automation_toolkit/ocicloud/terraform/adb.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/adb.tf @@ -9,9 +9,9 @@ data "oci_core_subnets" "oci_subnets_adb" { # depends_on = [module.subnets] # Uncomment to create Network and FSS together #for_each = var.adb != null ? var.adb : {} for_each = { for k, v in var.adb : k => v if v.vcn_name != null } - compartment_id = each.value.network_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.network_compartment_id)) > 0 ? each.value.network_compartment_id : var.compartment_ocids[each.value.network_compartment_id]) : var.compartment_ocids[each.value.network_compartment_id] + compartment_id = each.value.subnet_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.subnet_compartment_id)) > 0 ? each.value.subnet_compartment_id : var.compartment_ocids[each.value.subnet_compartment_id]) : var.compartment_ocids[each.value.subnet_compartment_id] display_name = each.value.subnet_id - vcn_id = data.oci_core_vcns.oci_vcns_adb[each.key].virtual_networks.*.id[0] + vcn_id = length(regexall("ocid1.vcn.oc*", each.value.vcn_name)) > 0 ? each.value.vcn_name : data.oci_core_vcns.oci_vcns_adb[each.key].virtual_networks.*.id[0] } data "oci_core_vcns" "oci_vcns_adb" { @@ -20,77 +20,95 @@ data "oci_core_vcns" "oci_vcns_adb" { for_each = { for k, v in var.adb : k => v if v.vcn_name != null } compartment_id = each.value.network_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.network_compartment_id)) > 0 ? each.value.network_compartment_id : var.compartment_ocids[each.value.network_compartment_id]) : var.compartment_ocids[each.value.network_compartment_id] display_name = each.value.vcn_name + state = "Available" } +/*output "vcns_data" { + value = { for k, v in data.oci_core_vcns.oci_vcns_adb : k => v } +}*/ +locals { + # Get all admin_password values from var.adb + all_passwords = [ + for adb_entry in values(var.adb) : adb_entry.admin_password + ] -module "adb" { - source = "./modules/database/adb" - for_each = var.adb != null ? var.adb : {} - # depends_on = [module.nsgs] - admin_password = each.value.admin_password - character_set = each.value.character_set - compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null - cpu_core_count = each.value.cpu_core_count - database_edition = each.value.database_edition - data_storage_size_in_tbs = each.value.data_storage_size_in_tbs - db_name = each.value.db_name - db_version = each.value.db_version - db_workload = each.value.db_workload - defined_tags = each.value.defined_tags - display_name = each.value.display_name - license_model = each.value.license_model - ncharacter_set = each.value.ncharacter_set - customer_contacts = each.value.customer_contacts - network_compartment_id = each.value.network_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.network_compartment_id)) > 0 ? each.value.network_compartment_id : var.compartment_ocids[each.value.network_compartment_id]) : null - network_security_group_ids = each.value.nsg_ids - freeform_tags = each.value.freeform_tags - subnet_id = each.value.subnet_id != null ? (length(regexall("ocid1.subnet.oc*", each.value.subnet_id)) > 0 ? each.value.subnet_id : data.oci_core_subnets.oci_subnets_adb[each.key].subnets.*.id[0]) : null - vcn_name = each.value.vcn_name != null ? each.value.vcn_name : null - whitelisted_ips = each.value.whitelisted_ips + # Remove empty values + non_empty_passwords = compact(local.all_passwords) - #Optional parameters for ADB - # are_primary_whitelisted_ips_used = var.autonomous_database_are_primary_whitelisted_ips_used - # autonomous_container_database_id = oci_database_autonomous_container_database.test_autonomous_container_database.id - # autonomous_database_backup_id = oci_database_autonomous_database_backup.test_autonomous_database_backup.id - # autonomous_database_id = oci_database_autonomous_database.test_autonomous_database.id - # autonomous_maintenance_schedule_type = var.autonomous_database_autonomous_maintenance_schedule_type - # clone_type = var.autonomous_database_clone_type - # customer_contacts { + # Keep only ones that start with "ocid1.vaultsecret.oc" + vault_secret_ocids = toset([ + for pw in local.non_empty_passwords : pw + if length(regexall("ocid1.vaultsecret.oc*", pw)) > 0 + ]) + decoded_vault_passwords = { + for k, v in data.oci_secrets_secretbundle.vault_secrets : + k => base64decode(v.secret_bundle_content[0].content) + } +} +data "oci_secrets_secretbundle" "vault_secrets" { + for_each = local.vault_secret_ocids + secret_id = each.value +} - #Optional - # email = var.autonomous_database_customer_contacts_email - # } - # data_safe_status = var.autonomous_database_data_safe_status - # data_storage_size_in_gb = var.autonomous_database_data_storage_size_in_gb - # is_access_control_enabled = var.autonomous_database_is_access_control_enabled - # is_auto_scaling_enabled = var.autonomous_database_is_auto_scaling_enabled - # is_auto_scaling_for_storage_enabled = var.autonomous_database_is_auto_scaling_for_storage_enabled - # is_data_guard_enabled = var.autonomous_database_is_data_guard_enabled - # is_dedicated = var.autonomous_database_is_dedicated - # is_free_tier = var.autonomous_database_is_free_tier - # is_local_data_guard_enabled = var.autonomous_database_is_local_data_guard_enabled - # is_mtls_connection_required = var.autonomous_database_is_mtls_connection_required - # is_preview_version_with_service_terms_accepted = var.autonomous_database_is_preview_version_with_service_terms_accepted - # kms_key_id = oci_kms_key.test_key.id - # max_cpu_core_count = var.autonomous_database_max_cpu_core_count - # ocpu_count = var.autonomous_database_ocpu_count - # private_endpoint_label = var.autonomous_database_private_endpoint_label - # refreshable_mode = var.autonomous_database_refreshable_mode - # scheduled_operations { - # #Required - # day_of_week { - # #Required - # name = var.autonomous_database_scheduled_operations_day_of_week_name - # } - # #Optional - # scheduled_start_time = var.autonomous_database_scheduled_operations_scheduled_start_time - # scheduled_stop_time = var.autonomous_database_scheduled_operations_scheduled_stop_time - # } - # source = var.autonomous_database_source - # source_id = oci_database_source.test_source.id - # standby_whitelisted_ips = var.autonomous_database_standby_whitelisted_ips - # timestamp = var.autonomous_database_timestamp - # vault_id = oci_kms_vault.test_vault.id - # whitelisted_ips = var.autonomous_database_whitelisted_ips +module "adb" { + source = "../../modules/database/adb" + for_each = var.adb != null ? var.adb : {} + # depends_on = [module.nsgs] + #admin_password = each.value.admin_password + admin_password = ( + length(regexall("ocid1.vaultsecret.oc*", each.value.admin_password)) > 0 ? + local.decoded_vault_passwords[each.value.admin_password] : + each.value.admin_password + ) + compartment_id = each.value.compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartment_ocids[each.value.compartment_id]) : null + are_primary_whitelisted_ips_used = each.value.are_primary_whitelisted_ips_used != null ? each.value.are_primary_whitelisted_ips_used : null + auto_refresh_frequency_in_seconds = each.value.auto_refresh_frequency_in_seconds != null ? each.value.auto_refresh_frequency_in_seconds : null + auto_refresh_point_lag_in_seconds = each.value.auto_refresh_point_lag_in_seconds != null ? each.value.auto_refresh_point_lag_in_seconds : null + autonomous_container_database_id = each.value.autonomous_container_database_id != null ? each.value.autonomous_container_database_id : null + adb_source = each.value.adb_source != null ? each.value.adb_source :null + source_id = each.value.source_id != null ? each.value.source_id : null + autonomous_database_source_backup_id = each.value.autonomous_database_source_backup_id != null ? each.value.autonomous_database_source_backup_id : null + autonomous_database_id = each.value.autonomous_database_id != null ? each.value.autonomous_database_id : null + autonomous_maintenance_schedule_type = each.value.autonomous_maintenance_schedule_type != null ? each.value.autonomous_maintenance_schedule_type : null + backup_retention_period_in_days = each.value.backup_retention_period_in_days != null ? each.value.backup_retention_period_in_days : null + character_set = each.value.character_set + compute_count = each.value.compute_count + compute_model = each.value.compute_model + customer_contacts = each.value.customer_contacts + data_safe_status = each.value.data_safe_status != null ? each.value.data_safe_status : null + data_storage_size_in_gb = each.value.data_storage_size_in_gb != null ? each.value.data_storage_size_in_gb : null + data_storage_size_in_tbs = each.value.data_storage_size_in_tbs != null ? each.value.data_storage_size_in_tbs : null + database_edition = each.value.database_edition != null ? each.value.database_edition: null + db_name = each.value.db_name + db_version = each.value.db_version + db_workload = each.value.db_workload + defined_tags = each.value.defined_tags + display_name = each.value.display_name + kms_key_id = each.value.kms_key_id != null ? each.value.kms_key_id : null + vault_id = each.value.vault_id != null ? each.value.vault_id : null + freeform_tags = each.value.freeform_tags + network_compartment_id = each.value.network_compartment_id != null ? (length(regexall("ocid1.compartment.oc*", each.value.network_compartment_id)) > 0 ? each.value.network_compartment_id : var.compartment_ocids[each.value.network_compartment_id]) : null + subnet_id = each.value.subnet_id != null ? (length(regexall("ocid1.subnet.oc*", each.value.subnet_id)) > 0 ? each.value.subnet_id : data.oci_core_subnets.oci_subnets_adb[each.key].subnets.*.id[0]) : null + vcn_id = each.value.vcn_name != null ?(length(regexall("ocid1.vcn.oc*", each.value.vcn_name)) > 0 ? each.value.vcn_name : data.oci_core_vcns.oci_vcns_adb[each.key].virtual_networks.*.id[0]):null + in_memory_percentage = each.value.in_memory_percentage != null ? each.value.in_memory_percentage : null + is_auto_scaling_enabled = each.value.is_auto_scaling_enabled != null ? each.value.is_auto_scaling_enabled : null + is_auto_scaling_for_storage_enabled = each.value.is_auto_scaling_for_storage_enabled != null ? each.value.is_auto_scaling_for_storage_enabled : null + is_backup_retention_locked = each.value.is_backup_retention_locked != null ? each.value.is_backup_retention_locked : null + is_dedicated = each.value.is_dedicated != null ? each.value.is_dedicated : null + is_local_data_guard_enabled = each.value.is_local_data_guard_enabled != null ? each.value.is_local_data_guard_enabled : null + is_mtls_connection_required = each.value.is_mtls_connection_required != null ? each.value.is_mtls_connection_required : null + is_replicate_automatic_backups = each.value.is_replicate_automatic_backups != null ? each.value.is_replicate_automatic_backups : null + license_model = each.value.license_model != null ? each.value.license_model : null + ncharacter_set = each.value.ncharacter_set + network_security_group_ids = each.value.nsg_ids != null ? each.value.nsg_ids : null + ocpu_count = each.value.ocpu_count != null ? each.value.ocpu_count : null + private_endpoint_ip = each.value.private_endpoint_ip != null ? each.value.private_endpoint_ip : null + private_endpoint_label = each.value.private_endpoint_label != null ? each.value.private_endpoint_label : null + refreshable_mode = each.value.refreshable_mode != null ? each.value.refreshable_mode : null + remote_disaster_recovery_type = each.value.remote_disaster_recovery_type != null ? each.value.remote_disaster_recovery_type : null + time_of_auto_refresh_start = each.value.time_of_auto_refresh_start != null ? each.value.time_of_auto_refresh_start : null + timestamp = each.value.timestamp != null ? each.value.timestamp : null + use_latest_available_backup_time_stamp = each.value.use_latest_available_backup_time_stamp != null ? each.value.use_latest_available_backup_time_stamp : null + whitelisted_ips = each.value.whitelisted_ips != null ? each.value.whitelisted_ips : null -} \ No newline at end of file +} diff --git a/cd3_automation_toolkit/ocicloud/terraform/backend.tf b/cd3_automation_toolkit/ocicloud/terraform/backend.tf index 6dbd0f147..72183ffbe 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/backend.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/backend.tf @@ -18,7 +18,7 @@ terraform { skip_region_validation = true skip_credentials_validation = true skip_metadata_api_check = true - force_path_style = true + force_path_style = true } } This line will be removed when using remote state*/ \ No newline at end of file diff --git a/cd3_automation_toolkit/ocicloud/terraform/identity.tf b/cd3_automation_toolkit/ocicloud/terraform/identity.tf index 110a8d3e6..1ce10ebe3 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/identity.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/identity.tf @@ -29,7 +29,7 @@ module "sub-compartments-level1" { depends_on = [module.iam-compartments] # insert the 4 required variables here tenancy_ocid = var.tenancy_ocid - compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(merge(module.iam-compartments.*...)[each.value.parent_compartment_id]["compartment_tf_id"], var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id]) + compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id], merge(module.iam-compartments.*...)[each.value.parent_compartment_id]["compartment_tf_id"]) compartment_name = each.value.name compartment_description = each.value.description enable_delete = each.value.enable_delete @@ -46,7 +46,7 @@ module "sub-compartments-level2" { depends_on = [module.sub-compartments-level1] # insert the 4 required variables here tenancy_ocid = var.tenancy_ocid - compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(merge(module.sub-compartments-level1.*...)[each.value.parent_compartment_id]["compartment_tf_id"], var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id]) + compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id], merge(module.sub-compartments-level1.*...)[each.value.parent_compartment_id]["compartment_tf_id"]) compartment_name = each.value.name compartment_description = each.value.description @@ -64,7 +64,7 @@ module "sub-compartments-level3" { depends_on = [module.sub-compartments-level2] # insert the 4 required variables here tenancy_ocid = var.tenancy_ocid - compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(merge(module.sub-compartments-level2.*...)[each.value.parent_compartment_id]["compartment_tf_id"], var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id]) + compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id], merge(module.sub-compartments-level2.*...)[each.value.parent_compartment_id]["compartment_tf_id"]) compartment_name = each.value.name compartment_description = each.value.description enable_delete = each.value.enable_delete @@ -81,7 +81,7 @@ module "sub-compartments-level4" { depends_on = [module.sub-compartments-level3] # insert the 4 required variables here tenancy_ocid = var.tenancy_ocid - compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(merge(module.sub-compartments-level3.*...)[each.value.parent_compartment_id]["compartment_tf_id"], var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id]) + compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id], merge(module.sub-compartments-level3.*...)[each.value.parent_compartment_id]["compartment_tf_id"]) compartment_name = each.value.name compartment_description = each.value.description enable_delete = each.value.enable_delete @@ -98,7 +98,7 @@ module "sub-compartments-level5" { depends_on = [module.sub-compartments-level4] # insert the 4 required variables here tenancy_ocid = var.tenancy_ocid - compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(merge(module.sub-compartments-level4.*...)[each.value.parent_compartment_id]["compartment_tf_id"], var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id]) + compartment_id = length(regexall("ocid1.compartment.oc*", each.value.parent_compartment_id)) > 0 ? each.value.parent_compartment_id : try(var.compartment_ocids[each.value.parent_compartment_id], zipmap(data.oci_identity_compartments.compartments.compartments.*.name, data.oci_identity_compartments.compartments.compartments.*.id)[each.value.parent_compartment_id], merge(module.sub-compartments-level4.*...)[each.value.parent_compartment_id]["compartment_tf_id"]) compartment_name = each.value.name compartment_description = each.value.description enable_delete = each.value.enable_delete diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf new file mode 100644 index 000000000..f1f97aaeb --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/dedicated-vm-host/oracle_provider_req.tf @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} \ No newline at end of file diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/oracle_provider_req.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/oracle_provider_req.tf new file mode 100644 index 000000000..f1f97aaeb --- /dev/null +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/compute/instance/oracle_provider_req.tf @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +# +terraform { + required_providers { + oci = { + source = "oracle/oci" + } + } +} \ No newline at end of file diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf index b3f74ce95..4618ccd73 100755 --- a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/data.tf @@ -10,15 +10,10 @@ locals { nsg_ids = flatten(tolist([for nsg in var.network_security_group_ids : (length(regexall("ocid1.networksecuritygroup.oc*", nsg)) > 0 ? [nsg] : data.oci_core_network_security_groups.network_security_groups_adb[nsg].network_security_groups[*].id)])) } -data "oci_core_vcns" "oci_vcns_adb" { - compartment_id = var.network_compartment_id != null ? var.network_compartment_id : var.compartment_id - display_name = var.vcn_name -} - data "oci_core_network_security_groups" "network_security_groups_adb" { for_each = { for nsg in var.network_security_group_ids : nsg => nsg } compartment_id = var.network_compartment_id != null ? var.network_compartment_id : var.compartment_id display_name = each.value - vcn_id = data.oci_core_vcns.oci_vcns_adb.virtual_networks[0].id + vcn_id = var.vcn_id } diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf index 725197132..55ab382de 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/main.tf @@ -7,30 +7,112 @@ ################################ resource "oci_database_autonomous_database" "autonomous_database" { - #Required - compartment_id = var.compartment_id - db_name = var.db_name + #Required + compartment_id = var.compartment_id - #Optional - admin_password = var.admin_password - character_set = var.character_set - cpu_core_count = var.cpu_core_count - database_edition = var.database_edition - data_storage_size_in_tbs = var.data_storage_size_in_tbs - db_version = var.db_version - db_workload = var.db_workload - defined_tags = var.defined_tags - display_name = var.display_name - license_model = var.license_model - ncharacter_set = var.ncharacter_set - dynamic "customer_contacts" { - for_each = var.customer_contacts!=null ? (var.customer_contacts[0] != "" ? var.customer_contacts : []) : [] - content { + #Optional + admin_password = var.admin_password + are_primary_whitelisted_ips_used = var.are_primary_whitelisted_ips_used != null ? var.are_primary_whitelisted_ips_used : null + auto_refresh_frequency_in_seconds = var.auto_refresh_frequency_in_seconds != null ? var.auto_refresh_frequency_in_seconds : null + auto_refresh_point_lag_in_seconds = var.auto_refresh_point_lag_in_seconds != null ? var.auto_refresh_point_lag_in_seconds : null + autonomous_container_database_id = var.autonomous_container_database_id != null ? var.autonomous_container_database_id : null + autonomous_database_backup_id = var.autonomous_database_source_backup_id != null ? ((var.adb_source != null && var.adb_source == "BACKUP_FROM_ID")? var.autonomous_database_source_backup_id:null) : null + autonomous_database_id = var.autonomous_database_id != null ? ((var.adb_source != null && var.adb_source == "BACKUP_FROM_TIMESTAMP")? var.autonomous_database_id:null) : null + autonomous_maintenance_schedule_type = var.autonomous_maintenance_schedule_type != null ? var.autonomous_maintenance_schedule_type: null + backup_retention_period_in_days = var.backup_retention_period_in_days != null ? var.backup_retention_period_in_days : null + character_set = var.character_set != null ? var.character_set : null + compute_count = var.compute_count + compute_model = var.compute_model + dynamic "customer_contacts" { + for_each = var.customer_contacts!=null ? (var.customer_contacts[0] != "" ? var.customer_contacts : []) : [] + + content { email = customer_contacts.value + } + } + data_safe_status = var.data_safe_status != null ? var.data_safe_status: null + data_storage_size_in_gb = var.data_storage_size_in_gb != null ? var.data_storage_size_in_gb: null + data_storage_size_in_tbs = var.data_storage_size_in_tbs != null ? var.data_storage_size_in_tbs : null + database_edition = var.database_edition + db_name = var.db_name + db_version = var.db_version + db_workload = var.db_workload + defined_tags = var.defined_tags + disaster_recovery_type = var.disaster_recovery_type != null ? var.disaster_recovery_type : null + display_name = var.display_name + dynamic "encryption_key" { + for_each = (var.kms_key_id != null && var.vault_id != null) ? [1] : [] + + content { + kms_key_id = var.kms_key_id + vault_id = var.vault_id + } } - } - nsg_ids = length(var.network_security_group_ids) != 0 ? (local.nsg_ids == [] ? ["INVALID NSG Name"] : local.nsg_ids) : null - freeform_tags = var.freeform_tags - subnet_id = var.subnet_id - whitelisted_ips = var.whitelisted_ips + freeform_tags = var.freeform_tags + in_memory_percentage = var.in_memory_percentage != null ? var.in_memory_percentage : null + is_auto_scaling_enabled = var.is_auto_scaling_enabled != null ? var.is_auto_scaling_enabled : null + is_auto_scaling_for_storage_enabled = var.is_auto_scaling_for_storage_enabled != null ? var.is_auto_scaling_for_storage_enabled : null + is_backup_retention_locked = var.is_backup_retention_locked != null ? var.is_backup_retention_locked : null + is_dedicated = var.is_dedicated != null ? var.is_dedicated : null + is_local_data_guard_enabled = var.is_local_data_guard_enabled != null ? var.is_local_data_guard_enabled : null + is_mtls_connection_required = var.is_mtls_connection_required != null ? var.is_mtls_connection_required : null + is_replicate_automatic_backups = var.is_replicate_automatic_backups != null ? var.is_replicate_automatic_backups : null + kms_key_id = var.kms_key_id != null ? var.kms_key_id : null + license_model = var.license_model + ncharacter_set = var.ncharacter_set + nsg_ids = length(var.network_security_group_ids) != 0 ? (local.nsg_ids == [] ? ["INVALID NSG Name"] : local.nsg_ids) : null + ocpu_count = var.ocpu_count != null ? var.ocpu_count : null + private_endpoint_ip = var.private_endpoint_ip != null ? var.private_endpoint_ip : null + private_endpoint_label = var.private_endpoint_label != null? var.private_endpoint_label : null + refreshable_mode = var.refreshable_mode != null ? var.refreshable_mode : null + remote_disaster_recovery_type = var.remote_disaster_recovery_type!= null? var.remote_disaster_recovery_type : null + secret_id = var.secret_id != null ? var.secret_id: null + secret_version_number = var.secret_version_number != null ? var.secret_version_number : null + vault_id = var.vault_id != null ? var.vault_id : null + source = var.adb_source != null ? var.adb_source : null + source_id = var.source_id != null ? var.source_id: null + standby_whitelisted_ips = var.standby_whitelisted_ips != null ? var.standby_whitelisted_ips : null + subnet_id = var.subnet_id + subscription_id = var.subscription_id != null ? var.subscription_id : null + time_of_auto_refresh_start = var.time_of_auto_refresh_start != null ? var.time_of_auto_refresh_start : null + timestamp = var.timestamp != null ? var.timestamp : null + use_latest_available_backup_time_stamp = var.use_latest_available_backup_time_stamp != null ? var.use_latest_available_backup_time_stamp : null + + whitelisted_ips = var.whitelisted_ips != null ?var.whitelisted_ips: null + lifecycle { + ignore_changes = [ + /* source, + admin_password, + character_set, + compute_count, + compute_model, + customer_contacts, + data_storage_size_in_tbs, + disaster_recovery_type, + encryption_key, # This ignores the entire nested block + in_memory_percentage, + is_auto_scaling_enabled, + is_auto_scaling_for_storage_enabled, + is_backup_retention_locked, + is_dedicated, + is_local_data_guard_enabled, + is_mtls_connection_required, + is_replicate_automatic_backups, + kms_key_id, + ocpu_count, + private_endpoint_ip, + private_endpoint_label, + refreshable_mode, + remote_disaster_recovery_type, + secret_id, + secret_version_number, + vault_id, + source_id, + standby_whitelisted_ips, + subscription_id, + time_of_auto_refresh_start, + timestamp, + use_latest_available_backup_time_stamp,*/ + ] + } } \ No newline at end of file diff --git a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf index ef4faad3d..b3019abfc 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/modules/database/adb/variables.tf @@ -26,11 +26,6 @@ variable "compartment_id" { type = string } -variable "cpu_core_count" { - description = "The number of OCPU cores to be made available to the database" - type = number -} - variable "database_edition" { description = "The database edition of ADB" type = string @@ -105,7 +100,7 @@ variable "subnet_id" { default = "" } -variable "vcn_name" { +variable "vcn_id" { type = string default = "" } @@ -114,3 +109,117 @@ variable "whitelisted_ips" { type = list(string) default = [] } +variable "are_primary_whitelisted_ips_used" { + default = null +} +variable "auto_refresh_frequency_in_seconds" { + default = null +} +variable "auto_refresh_point_lag_in_seconds" { + default = null +} +variable "autonomous_container_database_id" { + default = null +} +variable "adb_source" { + default = null +} +variable "source_id" { + default = null +} +variable "autonomous_database_source_backup_id" { + default = null +} +variable "autonomous_database_id" { + default = null +} + +variable "autonomous_maintenance_schedule_type" { + default = null +} +variable "backup_retention_period_in_days" { + default = null +} +variable "compute_count" { + default = null +} +variable "compute_model" { + default = null +} +variable "data_safe_status" { + default = null +} +variable "data_storage_size_in_gb" { + default = null +} +variable "disaster_recovery_type" { + default = null +} +variable "in_memory_percentage" { + default = null +} +variable "kms_key_id" { + default = null +} +variable "vault_id" { + default = null +} +variable "is_auto_scaling_enabled" { + default = null +} +variable "is_auto_scaling_for_storage_enabled" { + default = null +} +variable "is_backup_retention_locked" { + default = null +} +variable "is_dedicated" { + default = null +} +variable "is_local_data_guard_enabled" { + default = null +} +variable "is_mtls_connection_required" { + default = null +} +variable "is_replicate_automatic_backups" { + default = null +} + +variable "ocpu_count" { + default = null +} +variable "private_endpoint_ip" { + default = null +} +variable "private_endpoint_label" { + default = null +} +variable "refreshable_mode" { + default = null +} +variable "remote_disaster_recovery_type" { + default = null +} +variable "secret_id" { + default = null +} +variable "secret_version_number" { + default = null +} + +variable "standby_whitelisted_ips" { + default = null +} +variable "subscription_id" { + default = null +} +variable "time_of_auto_refresh_start" { + default = null +} +variable "timestamp" { + default = null +} +variable "use_latest_available_backup_time_stamp" { + default = null +} diff --git a/cd3_automation_toolkit/ocicloud/terraform/provider.tf b/cd3_automation_toolkit/ocicloud/terraform/provider.tf index 209d3428c..ceb8f14cf 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/provider.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/provider.tf @@ -19,7 +19,7 @@ terraform { required_providers { oci = { source = "oracle/oci" - version = "7.18.0" + version = "7.19.0" } } } diff --git a/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf b/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf index 0e3aea4b1..c4c8d692a 100644 --- a/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/variables_example.tf @@ -955,26 +955,71 @@ variable "databases" { variable "adb" { type = map(object({ - admin_password = optional(string) - character_set = optional(string) - compartment_id = string - cpu_core_count = optional(number) - database_edition = optional(string) - data_storage_size_in_tbs = optional(number) - customer_contacts = optional(list(string)) - db_name = string - db_version = optional(string) - db_workload = optional(string) - display_name = optional(string) - license_model = optional(string) - ncharacter_set = optional(string) - network_compartment_id = optional(string) - nsg_ids = optional(list(string)) - subnet_id = optional(string) - vcn_name = optional(string) - whitelisted_ips = optional(list(string)) - defined_tags = optional(map(any)) - freeform_tags = optional(map(any)) + admin_password = optional(string) + compartment_id = string + are_primary_whitelisted_ips_used = optional(bool) + auto_refresh_frequency_in_seconds = optional(number) + auto_refresh_point_lag_in_seconds = optional(number) + adb_source = optional(string) + source_id = optional(string) + #source detail used as source_id + autonomous_database_source_backup_id = optional(string) + autonomous_database_id = optional(string) + #storage + is_auto_scaling_for_storage_enabled = optional(bool) + data_storage_size_in_gb = optional(number) + data_storage_size_in_tbs = optional(number) + autonomous_maintenance_schedule_type = optional(string) + character_set = optional(string) + compute_count = number + compute_model = string + ocpu_count = optional(number) + customer_contacts = optional(list(string)) + data_safe_status = optional(string) + database_edition = optional(string) + db_name = string + db_version = optional(string) + db_workload = optional(string) + display_name = optional(string) + is_auto_scaling_enabled = optional(bool) + #Dedicated Exadata Infrastructure + is_dedicated = optional(bool) + autonomous_container_database_id = optional(string) + + # TDE MEK + kms_key_id = optional(string) + # ADB customer managed key + vault_id = optional(string) + # Only to Autonomous Databases on the Exadata Cloud@Customer platform + in_memory_percentage = optional(number) + + is_local_data_guard_enabled = optional(bool) + is_mtls_connection_required = optional(bool) + tde_kms_key_id = optional(string) + license_model = optional(string) + ncharacter_set = optional(string) + private_endpoint_ip = optional(string) + private_endpoint_label = optional(string) + refreshable_mode = optional(string) + time_of_auto_refresh_start = optional(string) + # Network + network_compartment_id = optional(string) + subnet_compartment_id = optional(string) + subnet_id = optional(string) + vcn_name = optional(string) + nsg_ids = optional(list(string)) + #Backup + backup_retention_period_in_days = optional(number) + is_backup_retention_locked = optional(bool) + #DisasterRecoveryConfiguration + is_replicate_automatic_backups = optional(bool) + remote_disaster_recovery_type = optional(string) + ##source=BACKUP_FROM_TIMESTAMP + timestamp = optional(string) + use_latest_available_backup_time_stamp = optional(bool) + whitelisted_ips = optional(list(string)) + defined_tags = optional(map(any)) + freeform_tags = optional(map(any)) })) default = {} } diff --git a/cd3_automation_toolkit/setUpOCI.properties b/cd3_automation_toolkit/setUpOCI.properties index 405ea2390..59715cca3 100644 --- a/cd3_automation_toolkit/setUpOCI.properties +++ b/cd3_automation_toolkit/setUpOCI.properties @@ -25,4 +25,4 @@ cd3file= #specify create_resources to create new resources in OCI(greenfield workflow) #specify export_resources to export resources from OCI(non-greenfield workflow) -workflow_type=create_resources \ No newline at end of file +workflow_type=export_resources \ No newline at end of file diff --git a/cd3_automation_toolkit/setUpOCI.py b/cd3_automation_toolkit/setUpOCI.py index 358ca939f..02abdca21 100644 --- a/cd3_automation_toolkit/setUpOCI.py +++ b/cd3_automation_toolkit/setUpOCI.py @@ -232,7 +232,7 @@ def fetch_compartments(outdir, outdir_struct, ct): var_files={} var_data = {} home_region = ct.home_region - print("outdir specified should contain region directories and then variables_.tf file inside the region directories eg /cd3user/tenancies//terraform_files") + print("outdir specified should contain region directories and then variables_.tf file inside the region directories eg /cd3user/tenancies//terraform_files") print("Verifying out directory and Taking backup of existing variables files...Please wait...") print("\nFetching Compartment Info...Please wait...") ct.get_network_compartment_ids(config['tenancy'], "root", config, signer) @@ -1092,7 +1092,7 @@ def create_budgets(): choices = [Option("Validate Budgets", None, None)] errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) - if errors == True: + if errors == False: create_terraform_budgets(inputfile, outdir, service_dir_budget, prefix, ct) # Update modified path list update_path_list(regions_path=[ct.home_region], service_dirs=[service_dir_budget]) @@ -2192,6 +2192,7 @@ def create_firewall(inputfile, outdir, service_dir, prefix, ct,sub_options=[]): # Set service directories as per outdir_structure file # If single outdir, get service names from /cd3user/oci_tools/cd3_automation_toolkit/user-scripts/.outdir_structure_file.properties +#print("Creating out dir variables...\n") if len(outdir_struct.items())==0: single_outdir_config = configparser.RawConfigParser() outdir_config_file = os.path.dirname(os.path.abspath(__file__))+"/user-scripts/.outdir_structure_file.properties" @@ -2205,6 +2206,7 @@ def create_firewall(inputfile, outdir, service_dir, prefix, ct,sub_options=[]): varname = "service_dir_"+str(key.replace("-","_")).strip() exec(varname + "= value",globals()) +#print("Reading varfile for compartments....\n") var_file = (f'{outdir}/{home_region}/{service_dir_identity}/variables_{home_region}.tf').replace('//','/') try: diff --git a/cd3_automation_toolkit/shell_script.sh b/cd3_automation_toolkit/shell_script.sh index ea28ccd4d..e5f527b94 100644 --- a/cd3_automation_toolkit/shell_script.sh +++ b/cd3_automation_toolkit/shell_script.sh @@ -13,7 +13,7 @@ sudo dnf install python-pip -y #sudo ln -s /usr/bin/pip3 /usr/bin/pip # Install required Python packages -pip install --user oci-cli==3.62.2 +pip install --user oci-cli==3.66.1 pip install --user azure.identity pip install --user azure.mgmt.compute pip install --user azure.mgmt.oracledatabase diff --git a/cd3_automation_toolkit/user-scripts/createTenancyConfig.py b/cd3_automation_toolkit/user-scripts/createTenancyConfig.py index 26771509c..7a9eedbb8 100644 --- a/cd3_automation_toolkit/user-scripts/createTenancyConfig.py +++ b/cd3_automation_toolkit/user-scripts/createTenancyConfig.py @@ -798,6 +798,9 @@ def create_bucket(config, signer): ''' # 4. Generate setUpOCI.properties file +# copying blank template to tenancy prefix for export ready +shutil.copy(f'{toolkit_dir}/example/CD3-Blank-template.xlsx',f'{customer_tenancy_dir}/CD3-Blank-template.xlsx') + #if not os.path.isfile(setupoci_props_file_path): print("Creating Tenancy specific setUpOCI.properties.................") with open(setupoci_props_toolkit_file_path, 'r+') as setUpOci_file: @@ -809,6 +812,7 @@ def create_bucket(config, signer): setupoci_props_toolkit_file_data = setupoci_props_toolkit_file_data.replace("config_file=", "config_file="+config_file_path) setupoci_props_toolkit_file_data = setupoci_props_toolkit_file_data.replace("outdir_structure_file=", "outdir_structure_file="+_outdir_structure_file) setupoci_props_toolkit_file_data = setupoci_props_toolkit_file_data.replace("tf_or_tofu=", "tf_or_tofu="+tf_or_tofu) +setupoci_props_toolkit_file_data = setupoci_props_toolkit_file_data.replace("cd3file=", "cd3file="+customer_tenancy_dir+"/CD3-Blank-template.xlsx") f = open(setupoci_props_file_path, "w+") f.write(setupoci_props_toolkit_file_data) @@ -1136,7 +1140,7 @@ def create_bucket(config, signer): logging.info("Next Steps for using toolkit via CLI") logging.info("######################################") logging.info("Modify "+customer_tenancy_dir + "/" +prefix+"_setUpOCI.properties with input values for cd3file and workflow_type") -logging.info("cd "+user_dir+"/oci_tools/cd3_automation_toolkit") +logging.info("cd "+toolkit_dir) logging.info("python setUpOCI.py "+customer_tenancy_dir + "/" +prefix+"_setUpOCI.properties") with open(outfile, 'r') as log_file: diff --git a/cd3_automation_toolkit/user-scripts/setUpAzure.py b/cd3_automation_toolkit/user-scripts/setUpAzure.py index 7c6a36ad3..1fb046cc0 100644 --- a/cd3_automation_toolkit/user-scripts/setUpAzure.py +++ b/cd3_automation_toolkit/user-scripts/setUpAzure.py @@ -90,8 +90,8 @@ def create_exa_azure(): def create_db_at_azure(execute_all=False): options = [ - Option('Add/Modify/Delete ADB @Azure', create_adb_azure, 'Processing ADB-Azure Tab'), - Option('Add/Modify/Delete Exa @Azure', create_exa_azure, 'Processing Exa-Azure Tabs') + Option('Add/Modify/Delete ADB @Azure', create_adb_azure, 'Processing ADB-Azure Tab') + #Option('Add/Modify/Delete Exa @Azure', create_exa_azure, 'Processing Exa-Azure Tabs') # Option('Enable LBaaS Logs', enable_lb_logs, 'LBaaS Logs') ] options = show_options(options, quit=True, menu=True, index=1) diff --git a/othertools/cis_reports.py b/othertools/cis_reports.py index 632c9c0a9..11f8fa3e2 100644 --- a/othertools/cis_reports.py +++ b/othertools/cis_reports.py @@ -1,5 +1,5 @@ ########################################################################## -# Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. # This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. # # cis_reports.py @@ -35,9 +35,16 @@ except Exception: OUTPUT_TO_XLSX = False -RELEASE_VERSION = "2.8.4" -PYTHON_SDK_VERSION = "2.129.4" -UPDATED_DATE = "July 26, 2024" +try: + import matplotlib.pyplot as plt + import numpy as np + OUTPUT_DIAGRAMS = True +except Exception: + OUTPUT_DIAGRAMS = False + +RELEASE_VERSION = "3.0.1" +PYTHON_SDK_VERSION = "2.152.1" +UPDATED_DATE = "July 16, 2025" ########################################################################## @@ -86,6 +93,7 @@ class CIS_Report: __KMS_DAYS_OLD = 365 __home_region = [] __days_to_expiry = 30 + __days_used = 45 # Time Format __iso_time_format = "%Y-%m-%dT%H:%M:%S" @@ -113,12 +121,20 @@ class CIS_Report: datetime.timedelta(days=__days_to_expiry) str_cert_key_time_max_datetime = cert_key_time_max_datetime.strftime(__iso_time_format) cert_key_time_max_datetime = datetime.datetime.strptime(str_cert_key_time_max_datetime, __iso_time_format) + # For Unused Credentials Check + local_user_time_max_datetime = start_datetime - \ + datetime.timedelta(days=__days_used) + str_local_user_time_max_datetime = local_user_time_max_datetime.strftime(__iso_time_format) + local_user_time_max_datetime = datetime.datetime.strptime(str_local_user_time_max_datetime, __iso_time_format) - def __init__(self, config, signer, proxy, output_bucket, report_directory, report_prefix, report_summary_json, print_to_screen, regions_to_run_in, raw_data, obp, redact_output, oci_url=None, debug=False, all_resources=True): + def __init__(self, config, signer, proxy, output_bucket, report_directory, report_prefix,\ + report_summary_json, print_to_screen, regions_to_run_in, raw_data, obp, \ + redact_output, oci_url=None, debug=False, all_resources=True, \ + disable_api_keys=False): - # CIS Foundation benchmark 2.0.0 - self.cis_foundations_benchmark_2_0 = { + # CIS Foundation benchmark 3.0.0 + self.cis_foundations_benchmark_3_0 = { '1.1': {'section': 'Identity and Access Management', 'recommendation_#': '1.1', 'Title': 'Ensure service level admins are created to manage resources of particular service', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['5.4', '6.7'], 'CCCS Guard Rail': '2,3', 'Remediation': []}, '1.2': {'section': 'Identity and Access Management', 'recommendation_#': '1.2', 'Title': 'Ensure permissions on all resources are given only to the tenancy administrator group', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['3.3'], 'CCCS Guard Rail': '1,2,3', 'Remediation': []}, '1.3': {'section': 'Identity and Access Management', 'recommendation_#': '1.3', 'Title': 'Ensure IAM administrators cannot update tenancy Administrators group', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['3.3', '5.4'], 'CCCS Guard Rail': '2,3', 'Remediation': []}, @@ -134,17 +150,19 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor '1.13': {'section': 'Identity and Access Management', 'recommendation_#': '1.13', 'Title': 'Ensure all OCI IAM user accounts have a valid and current email address', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['5.1'], 'CCCS Guard Rail': '1,2,3', 'Remediation': []}, '1.14': {'section': 'Identity and Access Management', 'recommendation_#': '1.14', 'Title': 'Ensure Instance Principal authentication is used for OCI instances, OCI Cloud Databases and OCI Functions to access OCI resources.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['6.8'], 'CCCS Guard Rail': '6,7', 'Remediation': []}, '1.15': {'section': 'Identity and Access Management', 'recommendation_#': '1.15', 'Title': 'Ensure storage service-level admins cannot delete resources they manage', 'Status': None, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['5.4', '6.8'], 'CCCS Guard Rail': '2,3', 'Remediation': []}, + '1.16': {'section': 'Identity and Access Management', 'recommendation_#': '1.16', 'Title': 'Ensure OCI IAM credentials unused for 45 days or more are disabled', 'Status': None, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['5.3'], 'CCCS Guard Rail': '2', 'Remediation': []}, + '1.17': {'section': 'Identity and Access Management', 'recommendation_#': '1.17', 'Title': 'Ensure there is only one active API Key for any single OCI IAM user.', 'Status': None, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['5'], 'CCCS Guard Rail': '2', 'Remediation': []}, '2.1': {'section': 'Networking', 'recommendation_#': '2.1', 'Title': 'Ensure no security lists allow ingress from 0.0.0.0/0 to port 22.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.2': {'section': 'Networking', 'recommendation_#': '2.2', 'Title': 'Ensure no security lists allow ingress from 0.0.0.0/0 to port 3389.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.3': {'section': 'Networking', 'recommendation_#': '2.3', 'Title': 'Ensure no network security groups allow ingress from 0.0.0.0/0 to port 22.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.4': {'section': 'Networking', 'recommendation_#': '2.4', 'Title': 'Ensure no network security groups allow ingress from 0.0.0.0/0 to port 3389.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, - '2.5': {'section': 'Networking', 'recommendation_#': '2.5', 'Title': 'Ensure the default security list of every VCN restricts all traffic except ICMP.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, + '2.5': {'section': 'Networking', 'recommendation_#': '2.5', 'Title': 'Ensure the default security list of every VCN restricts all traffic except ICMP within VCN.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.6': {'section': 'Networking', 'recommendation_#': '2.6', 'Title': 'Ensure Oracle Integration Cloud (OIC) access is restricted to allowed sources.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.7': {'section': 'Networking', 'recommendation_#': '2.7', 'Title': 'Ensure Oracle Analytics Cloud (OAC) access is restricted to allowed sources or deployed within a Virtual Cloud Network.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, '2.8': {'section': 'Networking', 'recommendation_#': '2.8', 'Title': 'Ensure Oracle Autonomous Shared Database (ADB) access is restricted or deployed within a VCN.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.4', '12.3'], 'CCCS Guard Rail': '2,3,5,7,9', 'Remediation': []}, - '3.1': {'section': 'Compute', 'recommendation_#': '3.1', 'Title': 'Ensure Compute Instance Legacy Metadata service endpoint is disabled.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.6'], 'CCCS Guard Rail': '', 'Remediation': []}, + '3.1': {'section': 'Compute', 'recommendation_#': '3.1', 'Title': 'Ensure Compute Instance Legacy Metadata service endpoint is disabled.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['4.6'], 'CCCS Guard Rail': '', 'Remediation': []}, '3.2': {'section': 'Compute', 'recommendation_#': '3.2', 'Title': 'Ensure Secure Boot is enabled on Compute Instance.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['4.1'], 'CCCS Guard Rail': '', 'Remediation': []}, '3.3': {'section': 'Compute', 'recommendation_#': '3.3', 'Title': 'Ensure In-transit Encryption is enabled on Compute Instance.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': [''], 'CCCS Guard Rail': '', 'Remediation': []}, @@ -160,11 +178,12 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor '4.10': {'section': 'Logging and Monitoring', 'recommendation_#': '4.10', 'Title': 'Ensure a notification is configured for security list changes.', 'Status': False, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.2'], 'CCCS Guard Rail': '11', 'Remediation': []}, '4.11': {'section': 'Logging and Monitoring', 'recommendation_#': '4.11', 'Title': 'Ensure a notification is configured for network security group changes.', 'Status': False, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.2'], 'CCCS Guard Rail': '11', 'Remediation': []}, '4.12': {'section': 'Logging and Monitoring', 'recommendation_#': '4.12', 'Title': 'Ensure a notification is configured for changes to network gateways.', 'Status': False, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['4.2'], 'CCCS Guard Rail': '11', 'Remediation': []}, - '4.13': {'section': 'Logging and Monitoring', 'recommendation_#': '4.13', 'Title': 'Ensure VCN flow logging is enabled for all subnets.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['8.2', '8.5', '13.6'], 'CCCS Guard Rail': '', 'Remediation': []}, + '4.13': {'section': 'Logging and Monitoring', 'recommendation_#': '4.13', 'Title': 'Ensure VCN flow logging is enabled for all subnets.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['8.2', '8.5', '13.6'], 'CCCS Guard Rail': '', 'Remediation': []}, '4.14': {'section': 'Logging and Monitoring', 'recommendation_#': '4.14', 'Title': 'Ensure Cloud Guard is enabled in the root compartment of the tenancy.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['8.2', '8.5', '8.11'], 'CCCS Guard Rail': '1,2,3', 'Remediation': []}, '4.15': {'section': 'Logging and Monitoring', 'recommendation_#': '4.15', 'Title': 'Ensure a notification is configured for Oracle Cloud Guard problems detected.', 'Status': False, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['8.2', '8.11'], 'CCCS Guard Rail': '', 'Remediation': []}, '4.16': {'section': 'Logging and Monitoring', 'recommendation_#': '4.16', 'Title': 'Ensure customer created Customer Managed Key (CMK) is rotated at least annually.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': [], 'CCCS Guard Rail': '6,7', 'Remediation': []}, - '4.17': {'section': 'Logging and Monitoring', 'recommendation_#': '4.17', 'Title': 'Ensure write level Object Storage logging is enabled for all buckets.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['8.2'], 'CCCS Guard Rail': '', 'Remediation': []}, + '4.17': {'section': 'Logging and Monitoring', 'recommendation_#': '4.17', 'Title': 'Ensure write level Object Storage logging is enabled for all buckets.', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['8.2'], 'CCCS Guard Rail': '11', 'Remediation': []}, + '4.18': {'section': 'Logging and Monitoring', 'recommendation_#': '4.18', 'Title': 'Ensure a notification is configured for Local OCI User Authentication.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['8.2'], 'CCCS Guard Rail': '11', 'Remediation': []}, '5.1.1': {'section': 'Storage - Object Storage', 'recommendation_#': '5.1.1', 'Title': 'Ensure no Object Storage buckets are publicly visible.', 'Status': True, 'Level': 1, 'Total': [], 'Findings': [], 'CISv8': ['3.3'], 'CCCS Guard Rail': '', 'Remediation': []}, '5.1.2': {'section': 'Storage - Object Storage', 'recommendation_#': '5.1.2', 'Title': 'Ensure Object Storage Buckets are encrypted with a Customer Managed Key (CMK).', 'Status': True, 'Level': 2, 'Total': [], 'Findings': [], 'CISv8': ['3.11'], 'CCCS Guard Rail': '', 'Remediation': []}, @@ -287,17 +306,32 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Description": "OCI instances, OCI database and OCI functions can access other OCI resources either via an OCI API key associated to a user or by being including in a Dynamic Group that has an IAM policy granting it the required access. Access to OCI Resources refers to making API calls to another OCI resource like Object Storage, OCI Vaults, etc.", "Rationale": "Dynamic Groups reduces the risks related to hard coded credentials. Hard coded API keys can be shared and require rotation which can open them up to being compromised. Compromised credentials could allow access to OCI services outside of the expected radius.", "Impact": "For an OCI instance that contains embedded credential audit the scripts and environment variables to ensure that none of them contain OCI API Keys or credentials.", - "Remediation": "Create Dynamic group and Enter Matching Rules to that includes the instances accessing your OCI resources. Refer:\"https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingdynamicgroups.htm\".", + "Remediation": "Create Dynamic group and Enter Matching Rules to that includes the instances accessing your OCI resources. Refer: \"https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingdynamicgroups.htm\".", "Recommendation": "Evaluate how your instances, functions, and autonomous database interact with other OCI services.", "Observation": "Dynamic Groups reduces the risks related to hard coded credentials. Hard coded API keys can be shared and require rotation which can open them up to being compromised. Compromised credentials could allow access to OCI services outside of the expected radius." }, "1.15": { "Description": "To apply the separation of duties security principle, one can restrict service-level administrators from being able to delete resources they are managing. It means service-level administrators can only manage resources of a specific service but not delete resources for that specific service.

    Example policies for global/tenant level for block volume service-administrators:\n

    \nAllow group VolumeUsers to manage volumes in tenancy where request.permission!='VOLUME_DELETE'\nAllow group VolumeUsers to manage volume-backups in tenancy where request.permission!='VOLUME_BACKUP_DELETE'\n

    Example policies for global/tenant level for file storage system service-administrators:
    \nAllow group FileUsers to manage file-systems in tenancy where request.permission!='FILE_SYSTEM_DELETE'\nAllow group FileUsers to manage mount-targets in tenancy where request.permission!='MOUNT_TARGET_DELETE'\nAllow group FileUsers to manage export-sets in tenancy where request.permission!='EXPORT_SET_DELETE'\n


    Example policies for global/tenant level for object storage system service-administrators:
    \nAllow group BucketUsers to manage objects in tenancy where request.permission!='OBJECT_DELETE'\nAllow group BucketUsers to manage buckets in tenancy where request.permission!='BUCKET_DELETE'\n
    ", - "Rationale": "Creating service-level administrators without the ability to delete the resource they are managing helps in tightly controlling access to Oracle Cloud Infrastructure (OCI) services by implementing the separation of duties security principle.", "Impact": "", + "Rationale": "Creating service-level administrators without the ability to delete the resource they are managing helps in tightly controlling access to Oracle Cloud Infrastructure (OCI) services by implementing the separation of duties security principle.", + "Impact": "", "Remediation": "Add the appropriate where condition to any policy statement that allows the storage service-level to manage the storage service.", "Recommendation": "To apply a separation of duties security principle, it is recommended to restrict service-level administrators from being able to delete resources they are managing.", "Observation": "IAM Policies that give service administrator the ability to delete service resources." }, + "1.16": { + "Description": "OCI IAM Local users can access OCI resources using different credentials, such as passwords or API keys. It is recommended that credentials that have been unused for 45 days or more be deactivated or removed.", + "Rationale": "Disabling or removing unnecessary OCI IAM local users will reduce the window of opportunity for credentials associated with a compromised or abandoned account to be used.", + "Impact": "Deactivating OCI IAM Local users and deleting of an OCI API Key will remove access to OCI", + "Remediation": "Deactivate OCI IAM Local users or delete of an OCI API Key will remove access to OCI", + "Observation": "User(s) with credentials unused in 45 days" + }, + "1.17":{ + "Description": "API Keys are long-term credentials for an OCI IAM user. They can be used to make programmatic requests to the OCI APIs directly or via, OCI SDKs or the OCI CLI.", + "Rationale": "Having a single API Key for an OCI IAM reduces attack surface area and makes it easier to manage.", + "Impact": "Deletion of an OCI API Key will remove programmatic access to OCI APIs.", + "Remediation": "Remove one of the API Keys.", + "Observation": "OCI API Key will grant programmatic access to OCI APIs with the same access as the user it is attached to." + }, "2.1": { "Description": "Security lists provide stateful or stateless filtering of ingress/egress network traffic to OCI resources on a subnet level. It is recommended that no security group allows unrestricted ingress access to port 22.", "Rationale": "Removing unfettered connectivity to remote console services, such as Secure Shell (SSH), reduces a server's exposure to risk.", @@ -331,10 +365,10 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Observation": "Network security groups that allow internet access to port 3389. (Note this does not necessarily mean external traffic can reach a compute instance)." }, "2.5": { - "Description": "A default security list is created when a Virtual Cloud Network (VCN) is created. Security lists provide stateful filtering of ingress and egress network traffic to OCI resources. It is recommended no security list allows unrestricted ingress access to Secure Shell (SSH) via port 22.", - "Rationale": "Removing unfettered connectivity to remote console services, such as SSH on port 22, reduces a server's exposure to unauthorized access.", + "Description": "A default security list is created when a Virtual Cloud Network (VCN) is created and attached to the public subnets in the VCN. Security lists provide stateful or stateless filtering of ingress and egress network traffic to OCI resources in the VCN. It is recommended that the default security list does not allow unrestricted ingress and egress access to resources in the VCN.", + "Rationale": "Removing unfettered connectivity to OCI resource, reduces a server's exposure to unauthorized access or data exfiltration.", "Impact": "For updating an existing environment, care should be taken to ensure that administrators currently relying on an existing ingress from 0.0.0.0/0 have access to ports 22 and/or 3389 through another security group.", - "Remediation": "Select Default Security List for and Remove the Ingress Rule with Source 0.0.0.0/0, IP Protocol 22 and Destination Port Range 22.", + "Remediation": "For updating an existing environment, care should be taken to ensure that administrators currently relying on an existing ingress from 0.0.0.0/0 have access to port 22 through another network security group and servers have egress to specified ports and protocols through another network security group.", "Recommendation": "Create specific custom security lists with workload specific rules and attach to subnets.", "Observation": "Default Security lists that allow more traffic then ICMP." }, @@ -368,7 +402,7 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Impact": "If you disable IMDSv1 on an instance that does not support IMDSv2, you might not be able to connect to the instance when you launch it.", "Remediation": "For each instance select the instance name, under the Instance Details section, next to Instance Metadata Service, click Edit and for the Instance metadata service, select the Version 2 only option.", "Recommendation": "It is recommended that all OCI instances use Instance Metadata Service version 2 (IMDSv2).", - "Observation": "Instances that allow Instance Metadata Service v1." + "Observation": "Instances that allow Instance Metadata Service v1." }, "3.2": { "Description": "Shielded Instances with Secure Boot enabled prevents unauthorized boot loaders and operating systems from booting. This prevent rootkits, bootkits, and unauthorized software from running before the operating system loads. Secure Boot verifies the digital signature of the system's boot software to check its authenticity. The digital signature ensures the operating system has not been tampered with and is from a trusted source. When the system boots and attempts to execute the software, it will first check the digital signature to ensure validity. If the digital signature is not valid, the system will not allow the software to run. Secure Boot is a feature of UEFI(Unified Extensible Firmware Interface) that only allows approved operating systems to boot up.", @@ -376,15 +410,15 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Impact": " To enable you have to terminate the instance and create a new one. Also, Shielded instances do not support live migration. During an infrastructure maintenance event, Oracle Cloud Infrastructure live migrates supported VM instances from the physical VM host that needs maintenance to a healthy VM host with minimal disruption to running instances. If you enable Secure Boot on an instance, the instance cannot be migrated, because the hardware TPM is not migratable. This may result in an outage because the TPM can't be migrate from a unhealthy host to healthy host.", "Remediation": "Terminate the old instance. Create a new instance and ensure on Secure Boot is toggled on under the Security section.", "Recommendation": "", - "Observation": "Instances that don't enable Secure Boot." + "Observation": "Instances that don't enable Secure Boot." }, "3.3": { "Description": "The Block Volume service provides the option to enable in-transit encryption for paravirtualized volume attachments on virtual machine (VM) instances.", "Rationale": "All the data moving between the instance and the block volume is transferred over an internal and highly secure network. If you have specific compliance requirements related to the encryption of the data while it is moving between the instance and the block volume, you should enable the in-transit encryption option.", "Impact": "In-transit encryption for boot and block volumes is only available for virtual machine (VM) instances launched from platform images, along with bare metal instances that use the following shapes: BM.Standard.E3.128, BM.Standard.E4.128, BM.DenseIO.E4.128. It is not supported on other bare metal instances.", - "Remediation": "Terminate the old instance. Create a new instance and ensure Use in-transit encryption is toggled on under the Boot volume section.", + "Remediation": "If available, edit the instance and enable in-transit encryption. If not available terminate the old instance. Create a new instance and ensure Use in-transit encryption is toggled on under the Boot volume section.", "Recommendation": "", - "Observation": "Instances that don't enable in-transit encryption." + "Observation": "Instances that don't enable in-transit encryption." }, "4.1": { "Description": "Using default tags is a way to ensure all resources that support tags are tagged during creation. Tags can be based on static values or based on computed values. It is recommended to setup default tags early on to ensure all created resources will get tagged.\nTags are scoped to Compartments and are inherited by Child Compartments. The recommendation is to create default tags like “CreatedBy” at the Root Compartment level to ensure all resources get tagged.\nWhen using Tags it is important to ensure that Tag Namespaces are protected by IAM Policies otherwise this will allow users to change tags or tag values.\nDepending on the age of the OCI Tenancy there may already be Tag defaults setup at the Root Level and no need for further action to implement this action.", @@ -498,13 +532,13 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Recommendation": "", "Observation": "Cloud Guard has not been configured in the root compartment of the tenancy." }, - "4.15" : { + "4.15": { "Description": "Cloud Guard detects misconfigured resources and insecure activity within a tenancy and provides security administrators with the visibility to resolve these issues. Upon detection, Cloud Guard generates a Problem. It is recommended to setup an Event Rule and Notification that gets triggered when Oracle Cloud Guard Problems are created, dismissed or remediated. Event Rules are compartment scoped and will detect events in child compartments. It is recommended to create the Event rule at the root compartment level.", "Rationale": "Cloud Guard provides an automated means to monitor a tenancy for resources that are configured in an insecure manner as well as risky network activity from these resources. Monitoring and alerting on Problems detected by Cloud Guard will help in identifying changes to the security posture.", "Impact": "There is no performance impact when enabling the above described features but depending on the amount of notifications sent per month there may be a cost associated.", - "Remediation": "Create a Rule Condition by selecting Cloud Guard in the Service Name Drop-down and selecting Detected – Problem, Remediated – Problem and Dismissed - Problem. In the Actions section select Notifications as Action Type and selct the compartment and topic to be used.", + "Remediation": "Create a Rule Condition by selecting Cloud Guard in the Service Name Drop-down and selecting Detected – Problem, Remediated – Problem and Dismissed - Problem. In the Actions section select Notifications as Action Type and select the compartment and topic to be used.", "Recommendation": "", - "Observation": "notifications have been configured for Cloud Guard Problems." + "Observation": "notifications have been configured for Cloud Guard Problems." }, "4.16": { "Description": "Oracle Cloud Infrastructure Vault securely stores master encryption keys that protect your encrypted data. You can use the Vault service to rotate keys to generate new cryptographic material. Periodically rotating keys limits the amount of data encrypted by one key version.", @@ -522,6 +556,14 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "Recommendation": "", "Observation": "object stores have no write level logging enabled." }, + "4.18": { + "Description": "It is recommended that an Event Rule and Notification be set up when a user in the via OCI local authentication. Event Rules are compartment-scoped and will detect events in child compartments. This Event rule is required to be created at the root compartment level.", + "Rationale": "Users should rarely use OCI local authenticated and be authenticated via organizational standard Identity providers, not local credentials. Access in this matter would represent a break glass activity and should be monitored to see if changes made impact the security posture.", + "Impact": "There is no performance impact when enabling the above-described features but depending on the amount of notifications sent per month there may be a cost associated.", + "Remediation": "Create a Rule Condition by selecting Identity SignOn in the Service Name Drop-down and selecting and Event Types: Interactive Login. In the Actions section select Notifications as Action Type and select the compartment and topic to be used.", + "Recommendation": "", + "Observation": "notifications have been configured Local User Authentication." + }, "5.1.1": { "Description": "A bucket is a logical container for storing objects. It is associated with a single compartment that has policies that determine what action a user can perform on a bucket and on all the objects in the bucket. It is recommended that no bucket be publicly accessible.", "Rationale": "Removing unfettered reading of objects in a bucket reduces an organization's exposure to data loss.", @@ -602,7 +644,7 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor } # CIS and OBP Regional Data # 4.6 is not regional because OCI IAM Policies only exist in the home region - self.__cis_regional_checks = {"4.3","4.4","4.5","4.7", "4.8", "4.9", "4.10", "4.11", "4.12"} + self.__cis_regional_checks = {"4.3","4.4","4.5","4.7","4.8", "4.9", "4.10", "4.11", "4.12", "4.18"} self.__obp_regional_checks = {} # CIS monitoring notifications check @@ -684,10 +726,13 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor 'com.oraclecloud.servicegateway.updateservicegateway' ], - "4.15" : [ + "4.15": [ 'com.oraclecloud.cloudguard.problemdetected', 'com.oraclecloud.cloudguard.problemdismissed', 'com.oraclecloud.cloudguard.problemremediated' + ], + "4.18": [ + 'com.oraclecloud.identitysignon.interactivelogin' ] } @@ -734,6 +779,12 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor "volume-backups": ["request.permission=VOLUME_BACKUP_DELETE"], "boot-volume-backups": ["request.permission=BOOT_VOLUME_BACKUP_DELETE"]}} + # CIS Network Filter Check + self.all_traffic_rules = [{'ruleAction': 'INCLUDE', 'protocol': 'all', 'udpOptions': None, 'isEnabled': True, 'sourceCidr': None, + 'samplingRate': 1, 'flowLogType': 'ALL', 'destinationCidr': None, 'icmpOptions': None, 'priority': 0, 'tcpOptions': None}, + {'ruleAction': 'INCLUDE','protocol': 'all','udpOptions': None,'sourceCidr': '0.0.0.0/0','isEnabled': True,'samplingRate': 1, + 'flowLogType': 'ALL','icmpOptions': None,'destinationCidr': '0.0.0.0/0','priority': 0,'tcpOptions': None}] + # Tenancy Data self.__tenancy = None self.__cloud_guard_config = None @@ -755,6 +806,9 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor self.__network_security_groups = [] self.__network_security_lists = [] self.__network_subnets = [] + self.__network_vcns = {} + self.__network_capturefilters = {} + self.__network_fastconnects = {} # Indexed by DRG ID self.__network_drgs = {} # Indexed by DRG ID self.__raw_network_drgs = [] @@ -777,7 +831,8 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor # For Logging & Monitoring checks self.__event_rules = [] self.__logging_list = [] - self.__subnet_logs = {} + self.__subnet_logs = {} # to be deleted + self.__all_logs = {} self.__write_bucket_logs = {} self.__read_bucket_logs = {} self.__load_balancer_access_logs = [] @@ -923,23 +978,28 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor self.__raw_regions.append(record) # By Default it is today's date - self.__report_directory = f'{report_directory}/' if report_directory else f'{self.__tenancy.name}-{self.report_datetime}' + self.__report_directory = f'{report_directory}' if report_directory else f'{self.__tenancy.name}-{self.report_datetime}' self.__report_prefix = f'{report_prefix}_' if report_prefix else '' self.__report_summary_json = report_summary_json # Checking if a Tenancy has Identity Domains enabled try: - domains_checking_url = "https://login.oci.oraclecloud.com/v1/tenantMetadata/" + self.__tenancy.name - domains_check_raw = requests.get(url=domains_checking_url) - domains_check_dict = json.loads(domains_check_raw.content) - self.__identity_domains_enabled = domains_check_dict['flights']['isHenosisEnabled'] + oci.pagination.list_call_get_all_results( + self.__regions[self.__home_region]['identity_client'].list_domains, + compartment_id = self.__tenancy.id, + lifecycle_state = "ACTIVE", + name="Default" + ).data + self.__identity_domains_enabled=True + print_header("Identity Domains Enabled in Tenancy") except Exception as e: - # To be safe if it fails I'll check - self.__identity_domains_enabled = True - debug("__init__: Exception checking identity domains status\n" + str(e)) - self.__errors.append({"id" : "__init__", "error" : str(e)}) - + if e.status == 404: + print_header("Identity Domains Disabled in Tenancy") + self.__identity_domains_enabled = False + else: + raise RuntimeError( + "Failed to list identity domains." + str(e.args)) # Creating signers and config for all regions self.__create_regional_signers(proxy) @@ -973,6 +1033,9 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor self.__obp_checks = True self.__output_raw_data = True + # Determining if OCI API unused for 45 days check is disable or not + self.__disable_api_keys = disable_api_keys + # Determine if __oci_cloud_url will be override with a different realm ex. OC2 or sovreign region self.__oci_cloud_url = "https://cloud.oracle.com" if oci_url: @@ -989,6 +1052,7 @@ def __init__(self, config, signer, proxy, output_bucket, report_directory, repor self.__oci_block_volumes_uri = self.__oci_cloud_url + "/block-storage/volumes/" self.__oci_fss_uri = self.__oci_cloud_url + "/fss/file-systems/" self.__oci_networking_uri = self.__oci_cloud_url + "/networking/vcns/" + self.__oci_network_capturefilter_uri = self.__oci_cloud_url + "/networking/network-command-center/capture-filters/" self.__oci_adb_uri = self.__oci_cloud_url + "/db/adb/" self.__oci_oicinstance_uri = self.__oci_cloud_url + "/oic/integration-instances/" self.__oci_oacinstance_uri = self.__oci_cloud_url + "/analytics/instances/" @@ -1117,7 +1181,12 @@ def __create_regional_signers(self, proxy): if proxy: search.base_client.session.proxies = {'https': proxy} region_values['certificate_client'] = certificate_client - + + logging_search_client = oci.loggingsearch.LogSearchClient(region_config, signer=region_signer) + if proxy: + search.base_client.session.proxies = {'https': proxy} + region_values['logging_search_client'] = logging_search_client + except Exception as e: debug("__create_regional_signers: error reading" + str(self.__config)) self.__errors.append({"id" : "__create_regional_signers", "error" : str(e)}) @@ -1144,16 +1213,17 @@ def __set_managed_paas_compartment(self): def get_date_iso_format(self, val): if not val: return "" - return str(val)[0:19] + return str(val)[0:19].replace(" ","T") ########################################################################## # Load compartments ########################################################################## def __identity_read_compartments(self): print("\nProcessing Compartments...") + self.__compartments = [] try: debug("__identity_read_compartments: Processing Compartments:") - self.__compartments = oci.pagination.list_call_get_all_results( + self.__compartments += oci.pagination.list_call_get_all_results( self.__regions[self.__home_region]['identity_client'].list_compartments, compartment_id=self.__tenancy.id, compartment_id_in_subtree=True, @@ -1179,11 +1249,11 @@ def __identity_read_compartments(self): "region": "" } self.__raw_compartment.append(record) - self.cis_foundations_benchmark_2_0['6.1']['Total'].append(compartment) + self.cis_foundations_benchmark_3_0['6.1']['Total'].append(compartment) # Add root compartment which is not part of the list_compartments self.__compartments.append(self.__tenancy) - deep_link = self.__oci_compartment_uri + compartment.id + deep_link = self.__oci_compartment_uri + self.__tenancy.id root_compartment = { "id": self.__tenancy.id, "name": self.__tenancy.name, @@ -1248,7 +1318,7 @@ def __identity_read_domains(self): # Creating Identity Domains Client and storing it debug("__identity_read_domains: Creating Identity Domain Client for: " + domain.display_name) domain_dict['IdentityDomainClient'] = oci.identity_domains.IdentityDomainsClient(\ - config=self.__config, service_endpoint=domain.url) + config=self.__config, signer=self.__signer, service_endpoint=domain.url) debug("__identity_read_domains: Created Identity Domain Client for: " + domain.display_name) pwd_policy_dict = oci.util.to_dict(domain_dict['IdentityDomainClient'].get_password_policy(\ @@ -1257,6 +1327,8 @@ def __identity_read_domains(self): domain_dict['password_policy'] = pwd_policy_dict domain_dict['errors'] = None self.__identity_domains.append(domain_dict) + debug("-" * 100) + debug(f"__identity_read_domains: Domain Dict is: {domain_dict}") except Exception as e: debug("Identity Domains Error is for domain " + domain.display_name + "\n" + str(e)) @@ -1446,6 +1518,7 @@ def __identity_read_users(self): 'can_use_db_credentials': user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user.can_use_db_credentials if user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user else None, 'can_use_o_auth2_client_credentials': user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user.can_use_o_auth2_client_credentials if user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user else None, 'can_use_smtp_credentials': user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user.can_use_smtp_credentials if user.urn_ietf_params_scim_schemas_oracle_idcs_extension_capabilities_user else None, + 'last_successful_login_date': self.get_date_iso_format(user.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_state_user.last_successful_login_date) if user.urn_ietf_params_scim_schemas_oracle_idcs_extension_user_state_user else None, 'groups': [] } # Adding Groups to the user @@ -1457,13 +1530,13 @@ def __identity_read_users(self): record['api_keys'] = self.__identity_read_user_api_key(user_ocid=user.ocid, identity_domain=identity_domain) record['auth_tokens'] = self.__identity_read_user_auth_token(user.ocid, identity_domain=identity_domain) record['customer_secret_keys'] = self.__identity_read_user_customer_secret_key(user.ocid, identity_domain=identity_domain) - record['database_passowrds'] = self.__identity_read_user_database_password(user.ocid,identity_domain=identity_domain) + record['database_passwords'] = self.__identity_read_user_database_password(user.ocid,identity_domain=identity_domain) else: debug("__identity_read_users: skipping user API Key collection for user: " + str(user.user_name)) record['api_keys'] = None record['auth_tokens'] = None record['customer_secret_keys'] = None - record['database_passowrds'] = None + record['database_passwords'] = None self.__users.append(record) except Exception as e: @@ -1507,6 +1580,7 @@ def __identity_read_users(self): 'can_use_db_credentials': user.capabilities.can_use_db_credentials, 'can_use_o_auth2_client_credentials': user.capabilities.can_use_o_auth2_client_credentials, 'can_use_smtp_credentials': user.capabilities.can_use_smtp_credentials, + 'last_successful_login_date': self.get_date_iso_format(user.last_successful_login_time), 'groups': [] } # Adding Groups to the user @@ -1519,7 +1593,7 @@ def __identity_read_users(self): user.id) record['customer_secret_keys'] = self.__identity_read_user_customer_secret_key( user.id) - record['database_passowrds'] = self.__identity_read_user_database_password(user.id) + record['database_passwords'] = self.__identity_read_user_database_password(user.id) self.__users.append(record) print("\tProcessed " + str(len(self.__users)) + " Users") return self.__users @@ -1532,6 +1606,7 @@ def __identity_read_users(self): except Exception as e: raise RuntimeError( "Error in __identity_read_users: " + str(e.args)) + ########################################################################## # Load user api keys ########################################################################## @@ -1551,8 +1626,11 @@ def __identity_read_user_api_key(self, user_ocid, identity_domain=None): record = oci.util.to_dict(api_key) record['deep_link'] = self.__generate_csv_hyperlink(deep_link, api_key.fingerprint) record['time_created'] = self.get_date_iso_format(record['meta']['created']) + apikey_used_in_45_days = self.__identity_check_logging_for_api_activity(user_ocid=user_ocid, api_key=api_key.fingerprint) + record['apikey_used_in_45_days'] = apikey_used_in_45_days api_keys.append(record) + else: user_api_keys_data = oci.pagination.list_call_get_all_results( self.__regions[self.__home_region]['identity_client'].list_api_keys, @@ -1565,6 +1643,8 @@ def __identity_read_user_api_key(self, user_ocid, identity_domain=None): record['deep_link'] = self.__generate_csv_hyperlink(deep_link, api_key.fingerprint) record['id'] = record['key_id'] record['time_created'] = self.get_date_iso_format(record['time_created']) + apikey_used_in_45_days = self.__identity_check_logging_for_api_activity(user_ocid=user_ocid, api_key=api_key.fingerprint) + record['apikey_used_in_45_days'] = apikey_used_in_45_days api_keys.append(record) return api_keys @@ -1577,6 +1657,116 @@ def __identity_read_user_api_key(self, user_ocid, identity_domain=None): raise RuntimeError( "Error in identity_read_user_api_key: " + str(e.args)) + + ########################################################################## + # Search API Key Last Usage Over 45 days https://github.com/tstahl/oci-remove-unused-apikey-cg-responder/blob/main/func.py + ########################################################################## + def __identity_check_logging_for_api_activity(self, user_ocid, api_key): + + apikey_used_in_45_days = [] + + def numOfDays(date1, date2): + #check which date is greater to avoid days output in -ve number + if date2 > date1: + return (date2-date1).days + else: + return (date1-date2).days + + ########################################################################## + # Inputs: start_date(date), end_date(date), data_ranges(list) max_days_between(int) + # Returns: List of dicts with {"start_date" : start_date, "end_date" : end_date}} + ########################################################################## + def get_date_ranges(start_date, end_date, date_ranges, max_days_between=9): + days_between = numOfDays(start_date, end_date) + if days_between > max_days_between: + next_date = start_date + datetime.timedelta(days=max_days_between) + date_ranges.append({"start_date" : start_date, "end_date" : next_date}) + return get_date_ranges(next_date + datetime.timedelta(days=1), end_date, date_ranges, max_days_between=max_days_between) + else: + + date_ranges.append({"start_date" : start_date, "end_date" : end_date}) + return date_ranges + + ########################################################################## + # Inputs: search_query, start_date and end_date in datetime, results + # Returns: Bool if the key was used in + ########################################################################## + def run_logging_search_query_api_usage(search_query, api_key_used, start_date: datetime, end_date: datetime): + if self.__disable_api_keys: + print("***Skipping Processing Audit Logs for API Key Usage...***") + return api_key_used + else: + print("Processing Audit Logs for API Key Usage...") + for region_key, region_values in self.__regions.items(): + try: + + response = region_values['logging_search_client'].search_logs( + search_logs_details=oci.loggingsearch.models.SearchLogsDetails( + search_query=search_query, + time_start=start_date, + time_end=end_date, + is_return_field_info=False), + limit=100) + + audit_logs = response.data + debug(f"run_logging_search_query_api_usage: response is: {response.data}") + if audit_logs.summary.result_count > 0: + for result in audit_logs.results: + userInfo = { + "principalName" : result.data["data.identity.principalName"], + "principalId" : result.data["data.identity.principalId"] + } + debug(f'run_logging_search_query_api_usage: Audit search results: {userInfo}') + api_key_used.append(userInfo) + break + + else: + debug('run_logging_search_query_api_usage: No APIKey usage records found in the past 14 days in') + + return api_key_used + except Exception as e: + self.__errors.append({"id" : "run_logging_search_query_api_usage", "error" : str(e)}) + debug('run_logging_search_query_api_usage: Exception is:') + debug("\tException is : " + str(e)) + return api_key_used + + debug("__identity_check_logging_for_api_activity: Checking API Key") + principle_id = f'{self.__tenancy.id}/{user_ocid}/{api_key}' + debug(f'__identity_check_logging_for_api_activity: API key is: {api_key}') + + tenancy_search_str = f'\"{self.__tenancy.id}/_Audit_Include_Subcompartment\"' + search_query = "search " + tenancy_search_str + """ | data.identity.credentials = '""" + principle_id + """' and data.identity.tenantId = '""" + self.__tenancy.id + """' | summarize count() by data.identity.principalId, data.identity.principalName""" + debug(f'__identity_check_logging_for_api_activity: Search Query is: {search_query}') + + end_date = self.start_datetime + start_date = end_date - datetime.timedelta(days=self.__days_used) + + search_date_range = get_date_ranges(start_date=start_date, \ + end_date=end_date, \ + date_ranges=[], + max_days_between=13) + + debug(f'__identity_check_logging_for_api_activity: Initiated Threads for dates range : {str(search_date_range)}') + + threads = [] + for dates in search_date_range: + thread = Thread(target=run_logging_search_query_api_usage, \ + args=(search_query, apikey_used_in_45_days, \ + dates['start_date'], dates['end_date'])) + threads.append(thread) + + for thread in threads: + thread.start() + + for thread in threads: + thread.join() + + if apikey_used_in_45_days: + return True + else: + return False + + ########################################################################## # Load user auth tokens ########################################################################## @@ -1681,6 +1871,7 @@ def __identity_read_user_database_password(self, user_ocid, identity_domain=None deep_link = self.__oci_users_uri + "/domains/" + identity_domain['id'] + "/users/" + user_ocid + "/db-passwords" record = oci.util.to_dict(password) record['deep_link'] = deep_link + record['time_created'] = self.get_date_iso_format(record['meta']['created']) database_password.append(record) return database_password @@ -1701,7 +1892,9 @@ def __identity_read_user_database_password(self, user_ocid, identity_domain=None debug("__identity_read_user_database_password: Got Password") deep_link = self.__oci_users_uri + user_ocid + "/db-password" record = oci.util.to_dict(password) + record['ocid'] = record['id'] record['deep_link'] = deep_link + record['time_created'] = self.get_date_iso_format(record['time_created']) database_password.append(record) return database_password @@ -1722,7 +1915,8 @@ def __identity_read_tenancy_policies(self): policies_data = oci.pagination.list_call_get_all_results( self.__regions[self.__home_region]['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Policy resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Policy resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data for policy in policies_data: @@ -1818,7 +2012,9 @@ def __os_read_buckets(self): buckets_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Bucket resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Bucket resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id + ).data # Getting Bucket Info for bucket in buckets_data: @@ -1843,6 +2039,7 @@ def __os_read_buckets(self): "defined_tags": bucket_info.defined_tags, "freeform_tags": bucket_info.freeform_tags, "region": region_key, + "source_resource" : bucket_info.name + "-" + region_key, "notes": "" } self.__buckets.append(record) @@ -1864,6 +2061,7 @@ def __os_read_buckets(self): "defined_tags": bucket.defined_tags, "freeform_tags": "", "region": region_key, + "source_resource" : bucket.display_name + "-" + region_key, "notes": str(e) } self.__buckets.append(record) @@ -1882,7 +2080,9 @@ def __block_volume_read_block_volumes(self): volumes_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Volume resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Volume resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id + ).data # Getting Block Volume inf @@ -1898,18 +2098,11 @@ def __block_volume_read_block_volumes(self): "compartment_id": volume.compartment_id, "size_in_gbs": volume.additional_details['sizeInGBs'], "size_in_mbs": volume.additional_details['sizeInMBs'], - # "source_details": volume.source_details, - "time_created": volume.time_created.strftime(self.__iso_time_format), - # "volume_group_id": volume.volume_group_id, - # "vpus_per_gb": volume.vpus_per_gb, - # "auto_tuned_vpus_per_gb": volume.auto_tuned_vpus_per_gb, "availability_domain": volume.availability_domain, - # "block_volume_replicas": volume.block_volume_replicas, - # "is_auto_tune_enabled": volume.is_auto_tune_enabled, - # "is_hydrated": volume.is_hydrated, + "time_created": volume.time_created.strftime(self.__iso_time_format), + "system_tags": volume.system_tags, "defined_tags": volume.defined_tags, "freeform_tags": volume.freeform_tags, - "system_tags": volume.system_tags, "region": region_key, "notes": "" } @@ -1923,18 +2116,11 @@ def __block_volume_read_block_volumes(self): "compartment_id": "", "size_in_gbs": "", "size_in_mbs": "", - # "source_details": "", - "time_created": "", - # "volume_group_id": "", - # "vpus_per_gb": "", - # "auto_tuned_vpus_per_gb": "", "availability_domain": "", - # "block_volume_replicas": "", - # "is_auto_tune_enabled": "", - # "is_hydrated": "", + "time_created": "", + "system_tags": "", "defined_tags": "", "freeform_tags": "", - "system_tags": "", "region": region_key, "notes": str(e) } @@ -1953,7 +2139,8 @@ def __boot_volume_read_boot_volumes(self): boot_volumes_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query BootVolume resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query BootVolume resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data for boot_volume in boot_volumes_data: @@ -1963,20 +2150,13 @@ def __boot_volume_read_boot_volumes(self): "id": boot_volume.identifier, "display_name": boot_volume.display_name, "deep_link": self.__generate_csv_hyperlink(deep_link, boot_volume.display_name), - # "image_id": boot_volume.image_id, "kms_key_id": boot_volume.additional_details['kmsKeyId'], "lifecycle_state": boot_volume.lifecycle_state, + "compartment_id": boot_volume.compartment_id, "size_in_gbs": boot_volume.additional_details['sizeInGBs'], "size_in_mbs": boot_volume.additional_details['sizeInMBs'], "availability_domain": boot_volume.availability_domain, "time_created": boot_volume.time_created.strftime(self.__iso_time_format), - "compartment_id": boot_volume.compartment_id, - # "auto_tuned_vpus_per_gb": boot_volume.auto_tuned_vpus_per_gb, - # "boot_volume_replicas": boot_volume.boot_volume_replicas, - # "is_auto_tune_enabled": boot_volume.is_auto_tune_enabled, - # "is_hydrated": boot_volume.is_hydrated, - # "source_details": boot_volume.source_details, - # "vpus_per_gb": boot_volume.vpus_per_gb, "system_tags": boot_volume.system_tags, "defined_tags": boot_volume.defined_tags, "freeform_tags": boot_volume.freeform_tags, @@ -1987,21 +2167,14 @@ def __boot_volume_read_boot_volumes(self): record = { "id": boot_volume.identifier, "display_name": boot_volume.display_name, - "deep_link": self.__generate_csv_hyperlink(deep_link, boot_volume.display_name), - # "image_id": "", + "deep_link": "", "kms_key_id": "", "lifecycle_state": "", + "compartment_id": "", "size_in_gbs": "", "size_in_mbs": "", "availability_domain": "", "time_created": "", - "compartment_id": "", - # "auto_tuned_vpus_per_gb": "", - # "boot_volume_replicas": "", - # "is_auto_tune_enabled": "", - # "is_hydrated": "", - # "source_details": "", - # "vpus_per_gb": "", "system_tags": "", "defined_tags": "", "freeform_tags": "", @@ -2023,7 +2196,8 @@ def __fss_read_fsss(self): fss_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query FileSystem resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query FileSystem resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data for fss in fss_data: @@ -2085,7 +2259,8 @@ def __network_read_network_security_groups_rules(self): nsgs_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query NetworkSecurityGroup resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query NetworkSecurityGroup resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data # Looping through NSGs to to get @@ -2149,7 +2324,8 @@ def __network_read_network_security_lists(self): security_lists_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query SecurityList resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query SecurityList resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data # Looping through Security Lists to to get @@ -2216,7 +2392,8 @@ def __network_read_network_subnets(self): subnets_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Subnet resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Subnet resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data try: @@ -2284,6 +2461,63 @@ def __network_read_network_subnets(self): raise RuntimeError( "Error in __network_read_network_subnets " + str(e.args)) + ########################################################################## + # Network VCNs Lists + ########################################################################## + def __network_read_network_vcns(self): + try: + for region_key, region_values in self.__regions.items(): + vcn_data = oci.pagination.list_call_get_all_results( + region_values['search_client'].search_resources, + search_details=oci.resource_search.models.StructuredSearchDetails( + query="query VCN resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id + ).data + + for vcn in vcn_data: + deep_link = self.__oci_networking_uri + vcn.identifier + '?region=' + region_key + record = oci.util.to_dict(vcn) + record['deep_link'] = deep_link + record['subnets'] = {} + record['network_security_groups'] = {} + record['security_lists'] = {} + # Adding VCN to VCN list + self.__network_vcns[vcn.identifier] = record + + print("\tProcessed " + str(len(self.__network_vcns)) + " Virtual Cloud Networks ") + return self.__network_vcns + except Exception as e: + raise RuntimeError( + "Error in __network_read_network_vcns " + str(e.args)) + + ########################################################################## + # Network Capture Filters Dictionary + ########################################################################## + def __network_read_network_capturefilters(self): + try: + for region_key, region_values in self.__regions.items(): + capturefilter_data = oci.pagination.list_call_get_all_results( + region_values['search_client'].search_resources, + search_details=oci.resource_search.models.StructuredSearchDetails( + query="query capturefilter resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id + ).data + + for filter in capturefilter_data: + deep_link = self.__oci_network_capturefilter_uri + filter.identifier + '?region=' + region_key + record = oci.util.to_dict(filter) + record['deep_link'] = deep_link + + # Adding CaptureFilter to CaptureFilter Dict + self.__network_capturefilters[filter.identifier] = record + + print("\tProcessed " + str(len(self.__network_capturefilters)) + " Network Capture Filters ") + + return self.__network_subnets + except Exception as e: + raise RuntimeError( + "Error in __network_read_network_capturefilters " + str(e.args)) + ########################################################################## # Load DRG Attachments ########################################################################## @@ -2295,7 +2529,8 @@ def __network_read_drg_attachments(self): drg_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query DrgAttachment resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query DrgAttachment resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2380,7 +2615,8 @@ def __network_read_drgs(self): drg_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Drg resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Drg resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2464,7 +2700,8 @@ def __network_read_fastonnects(self): fastconnects = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query VirtualCircuit resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query VirtualCircuit resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2578,7 +2815,8 @@ def __network_read_ip_sec_connections(self): ip_sec_connections_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query IPSecConnection resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query IPSecConnection resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data for ip_sec in ip_sec_connections_data: @@ -2677,7 +2915,7 @@ def __network_read_ip_sec_connections(self): ############################################ def __network_topology_dump(self): debug("__network_topology_dump: Starting") - if type(self.__signer) is not oci.auth.signers.InstancePrincipalsDelegationTokenSigner: + if type(self.__signer) is oci.auth.signers.InstancePrincipalsDelegationTokenSigner: self.__errors.append({"id": "__network_topology_dump", "error": "Delegated Tokens via Cloud Shell not supported." }) return def api_function(region_key, region_values, tenancy_id): @@ -2720,7 +2958,8 @@ def __adb_read_adbs(self): adb_query_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query AutonomousDatabase resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query AutonomousDatabase resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2769,7 +3008,8 @@ def __oic_read_oics(self): oic_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query IntegrationInstance resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query IntegrationInstance resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2846,7 +3086,8 @@ def __oac_read_oacs(self): oac_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query AnalyticsInstance resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query AnalyticsInstance resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data compartments = set() @@ -2916,7 +3157,8 @@ def __events_read_event_rules(self): events_rules_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query EventRule resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query EventRule resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data for event_rule in events_rules_data: @@ -2951,7 +3193,8 @@ def __logging_read_log_groups_and_logs(self): log_groups = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query LogGroup resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query LogGroup resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data # Looping through log groups to get logs @@ -2978,6 +3221,7 @@ def __logging_read_log_groups_and_logs(self): log_group_id=log_group.identifier ).data for log in logs: + deep_link = self.__oci_loggroup_uri + log_group.identifier + "/logs/" + log.id + '?region=' + region_key log_record = { "compartment_id": log.compartment_id, @@ -2992,41 +3236,100 @@ def __logging_read_log_groups_and_logs(self): "time_created": log.time_created.strftime(self.__iso_time_format), "time_last_modified": str(log.time_last_modified), "defined_tags": log.defined_tags, - "freeform_tags": log.freeform_tags + "freeform_tags": log.freeform_tags, + "region" : region_key } try: - if log.configuration: - log_record["configuration_compartment_id"] = log.configuration.compartment_id, - log_record["source_category"] = log.configuration.source.category, - log_record["source_parameters"] = log.configuration.source.parameters, - log_record["source_resource"] = log.configuration.source.resource, - log_record["source_service"] = log.configuration.source.service, - log_record["source_source_type"] = log.configuration.source.source_type - log_record["archiving_enabled"] = log.configuration.archiving.is_enabled - - if log.configuration.source.service == 'flowlogs': - self.__subnet_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id} - - elif log.configuration.source.service == 'objectstorage' and 'write' in log.configuration.source.category: - # Only write logs - self.__write_bucket_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id, "region": region_key} - - elif log.configuration.source.service == 'objectstorage' and 'read' in log.configuration.source.category: - # Only read logs - self.__read_bucket_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id, "region": region_key} - - elif log.configuration.source.service == 'loadbalancer' and 'error' in log.configuration.source.category: - self.__load_balancer_error_logs.append( - log.configuration.source.resource) - elif log.configuration.source.service == 'loadbalancer' and 'access' in log.configuration.source.category: - self.__load_balancer_access_logs.append( - log.configuration.source.resource) - elif log.configuration.source.service == 'apigateway' and 'access' in log.configuration.source.category: - self.__api_gateway_access_logs.append( - log.configuration.source.resource) - elif log.configuration.source.service == 'apigateway' and 'error' in log.configuration.source.category: - self.__api_gateway_error_logs.append( - log.configuration.source.resource) + try: + if log_record["log_type"] == "SERVICE" and log_record['lifecycle_state'] == "ACTIVE": + log_record["configuration_compartment_id"] = log.configuration.compartment_id + log_record["source_category"] = log.configuration.source.category + log_record["source_parameters"] = log.configuration.source.parameters + log_record["source_source_type"] = log.configuration.source.source_type + log_record["source_service"] = log.configuration.source.service + # Object storage buckets are indexed by BucketName-region + if log_record["source_service"] == "objectstorage": + log_record["source_resource"] = log.configuration.source.resource + "-" + region_key + else: + log_record["source_resource"] = log.configuration.source.resource + log_record["archiving_enabled"] = log.configuration.archiving.is_enabled + if log_record["source_parameters"] and isinstance(log_record["source_parameters"],dict): + log_record["capture_filter"] = log.configuration.source.parameters["capture_filter"] + else: + log_record["capture_filter"] = None + + elif log_record["lifecycle_state"] == "ACTIVE": + log_record["source_category"] = log.log_type + log_record["source_service"] = log.log_type + log_record["source_resource"] = log.id + log_record["capture_filter"] = None + except Exception as e: + print(log) + print(e) + + #### TESTING SOMETHING NEW #### + + try: + ## Active means your logging + if log_record['lifecycle_state'] == 'ACTIVE': + if self.__all_logs: + + if log_record["source_service"] in self.__all_logs: + + if log_record["source_category"] in self.__all_logs[log_record["source_service"]]: + debug("\t__logging_read_log_groups_and_logs: Adding log for existing service and category ") + self.__all_logs[log_record["source_service"]][log_record["source_category"]][log_record["source_resource"]] = log_record + + else: + debug(f'\t__logging_read_log_groups_and_logs: Adding category {log_record["source_category"]}') + self.__all_logs[log_record["source_service"]][log_record["source_category"]] = {} + self.__all_logs[log_record["source_service"]][log_record["source_category"]][log_record["source_resource"]] = log_record + + else: + debug(f'\t__logging_read_log_groups_and_logs: Adding Service {log_record["source_service"]}, and category {log_record["source_category"]}') + self.__all_logs[log_record["source_service"]] = {} + self.__all_logs[log_record["source_service"]][log_record["source_category"]] = {} + self.__all_logs[log_record["source_service"]][log_record["source_category"]][log_record["source_resource"]] = log_record + + else: + debug(f'\t__logging_read_log_groups_and_logs: Starting Dict: Adding Service {log_record["source_service"]}, and category {log_record["source_category"]}' ) + self.__all_logs[log_record["source_service"]] = {} + self.__all_logs[log_record["source_service"]][log_record["source_category"]] = {} + self.__all_logs[log_record["source_service"]][log_record["source_category"]][log_record["source_resource"]] = log_record + + + except Exception as e: + print(f'\tFailed to parse log: {log_record["id"]}') + self.__errors.append({"id" : log_record["id"], "error" : str(e)}) + print("*" * 80) + print(log_record) + print("#" * 80) + print(e) + print("*" * 80) + + # if log.configuration.source.service == 'flowlogs': + # self.__subnet_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id} + + # elif log.configuration.source.service == 'objectstorage' and 'write' in log.configuration.source.category: + # # Only write logs + # self.__write_bucket_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id, "region": region_key} + + # elif log.configuration.source.service == 'objectstorage' and 'read' in log.configuration.source.category: + # # Only read logs + # self.__read_bucket_logs[log.configuration.source.resource] = {"log_group_id": log.log_group_id, "log_id": log.id, "region": region_key} + + # elif log.configuration.source.service == 'loadbalancer' and 'error' in log.configuration.source.category: + # self.__load_balancer_error_logs.append( + # log.configuration.source.resource) + # elif log.configuration.source.service == 'loadbalancer' and 'access' in log.configuration.source.category: + # self.__load_balancer_access_logs.append( + # log.configuration.source.resource) + # elif log.configuration.source.service == 'apigateway' and 'access' in log.configuration.source.category: + # self.__api_gateway_access_logs.append( + # log.configuration.source.resource) + # elif log.configuration.source.service == 'apigateway' and 'error' in log.configuration.source.category: + # self.__api_gateway_error_logs.append( + # log.configuration.source.resource) except Exception as e: self.__errors.append({"id" : log.id, "error" : str(e)}) # Append Log to log List @@ -3034,11 +3337,11 @@ def __logging_read_log_groups_and_logs(self): except Exception as e: self.__errors.append({"id" : log_group.identifier, "error" : str(e) }) record['notes'] = str(e) - - self.__logging_list.append(record) print("\tProcessed " + str(len(self.__logging_list)) + " Log Group Logs") + # print(self.__all_logs) + return self.__logging_list except Exception as e: raise RuntimeError( @@ -3055,7 +3358,8 @@ def __kms_read_keys(self): keys_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query Key resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query Key resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data vaults_set = set() @@ -3300,7 +3604,8 @@ def __ons_read_subscriptions(self): subs_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query OnsSubscription resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query OnsSubscription resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data debug("\t__ons_read_subscriptions: Recieved " + str(len(subs_data)) + " subscriptions in region " + str(region_key)) for sub in subs_data: @@ -3372,7 +3677,8 @@ def __sch_read_service_connectors(self): service_connectors_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query ServiceConnector resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'") + query="query ServiceConnector resources return allAdditionalFields where compartmentId != '" + self.__managed_paas_compartment_id + "'"), + tenant_id=self.__tenancy.id ).data # Getting Bucket Info @@ -3449,7 +3755,8 @@ def __search_resources_in_root_compartment(self): structured_search_query = oci.resource_search.models.StructuredSearchDetails(query=query_non_compliant) search_results = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, - search_details=structured_search_query + search_details=structured_search_query, + tenant_id=self.__tenancy.id ).data for item in search_results: @@ -3464,7 +3771,8 @@ def __search_resources_in_root_compartment(self): structured_search_all_query = oci.resource_search.models.StructuredSearchDetails(query=query_all_resources) structured_search_all_resources = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, - search_details=structured_search_all_query + search_details=structured_search_all_query, + tenant_id=self.__tenancy.id ).data for item in structured_search_all_resources: @@ -3476,7 +3784,7 @@ def __search_resources_in_root_compartment(self): "id": item.identifier, "region": region_key } - self.cis_foundations_benchmark_2_0['6.2']['Total'].append(record) + self.cis_foundations_benchmark_3_0['6.2']['Total'].append(record) except Exception: self.__errors.append({"id": "search_resources_in_root_compartment Invalid OCID", "error" : str(item)}) debug(f'__search_resources_in_root_compartment: Invalid OCID: {str(item)}') @@ -3498,7 +3806,8 @@ def __search_query_resource_type(self, resource_type, search_client): results = oci.pagination.list_call_get_all_results( search_client.search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query=query) + query=query), + tenant_id=self.__tenancy.id ).data return oci.util.to_dict(results) @@ -3565,9 +3874,11 @@ def __core_instance_read_compute(self): # Returning Instances print("\tProcessed " + str(len(self.__Instance)) + " Compute Instances") - return self.__service_connectors + return self.__Instance except Exception as e: - raise RuntimeError("Error in __core_instance_read_compute " + str(e.args)) + print("__core_instance_read_compute failed to process: " + str(e)) + self.__errors.append({'id' : '__core_instance_read_compute', 'error' : str(e)}) + return [] ########################################################################## @@ -3590,7 +3901,8 @@ def __certificates_read_certificates(self): certificates_data = oci.pagination.list_call_get_all_results( region_values['search_client'].search_resources, search_details=oci.resource_search.models.StructuredSearchDetails( - query="query certificate resources return allAdditionalFields") + query="query certificate resources return allAdditionalFields"), + tenant_id=self.__tenancy.id ).data cert_compartments = {} debug("\t__certificates_read_certificates: Got Ceritificates from ") @@ -3619,8 +3931,18 @@ def __certificates_read_certificates(self): debug("__certificates_read_certificates failed to process: " + str(e)) print("\tProcessed " + str(len(self.__raw_oci_certificates)) + " Certificates") - - + ########################################################################## + # Unifying Network information into a single object for easier processing + ########################################################################## + def __unify_network_data(self): + for subnet in self.__network_subnets: + self.__network_vcns[subnet['vcn_id']]['subnets'][subnet['id']] = subnet + for nsg in self.__network_security_groups: + self.__network_vcns[nsg['vcn_id']]['network_security_groups'][nsg['id']] = nsg + for sl in self.__network_security_lists: + self.__network_vcns[sl['vcn_id']]['security_lists'][sl['id']] = sl + + ########################################################################## # Analyzes Tenancy Data for CIS Report ########################################################################## @@ -3643,8 +3965,8 @@ def __report_cis_analyze_tenancy_data(self): and ("to manage all-resources".upper() in statement.upper()) \ and policy['name'].upper() != "Tenant Admin Policy".upper(): # If there are more than manage all-resources in you don't meet this rule - self.cis_foundations_benchmark_2_0['1.1']['Status'] = False - self.cis_foundations_benchmark_2_0['1.1']['Findings'].append(policy) + self.cis_foundations_benchmark_3_0['1.1']['Status'] = False + self.cis_foundations_benchmark_3_0['1.1']['Findings'].append(policy) break # 1.2 Check @@ -3654,8 +3976,8 @@ def __report_cis_analyze_tenancy_data(self): and "to manage all-resources in tenancy".upper() in statement.upper() \ and policy['name'].upper() != "Tenant Admin Policy".upper(): - self.cis_foundations_benchmark_2_0['1.2']['Status'] = False - self.cis_foundations_benchmark_2_0['1.2']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.2']['Status'] = False + self.cis_foundations_benchmark_3_0['1.2']['Findings'].append( policy) # 1.3 Check - May want to add a service check @@ -3671,78 +3993,98 @@ def __report_cis_analyze_tenancy_data(self): if all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.3']["targets"]): pass else: - self.cis_foundations_benchmark_2_0['1.3']['Findings'].append(policy) - self.cis_foundations_benchmark_2_0['1.3']['Status'] = False + self.cis_foundations_benchmark_3_0['1.3']['Findings'].append(policy) + self.cis_foundations_benchmark_3_0['1.3']['Status'] = False else: - self.cis_foundations_benchmark_2_0['1.3']['Findings'].append(policy) - self.cis_foundations_benchmark_2_0['1.3']['Status'] = False + self.cis_foundations_benchmark_3_0['1.3']['Findings'].append(policy) + self.cis_foundations_benchmark_3_0['1.3']['Status'] = False # CIS Total 1.1,1,2,1.3 Adding - All IAM Policies for to CIS Total - self.cis_foundations_benchmark_2_0['1.1']['Total'] = self.__policies - self.cis_foundations_benchmark_2_0['1.2']['Total'] = self.__policies - self.cis_foundations_benchmark_2_0['1.3']['Total'] = self.__policies + self.cis_foundations_benchmark_3_0['1.1']['Total'] = self.__policies + self.cis_foundations_benchmark_3_0['1.2']['Total'] = self.__policies + self.cis_foundations_benchmark_3_0['1.3']['Total'] = self.__policies # 1.4 Check - Password Policy - Only in home region - if self.__tenancy_password_policy: - if self.__tenancy_password_policy.password_policy.is_lowercase_characters_required: - self.cis_foundations_benchmark_2_0['1.4']['Status'] = True + if not(self.__identity_domains_enabled) and self.__tenancy_password_policy: + if self.__tenancy_password_policy.password_policy.minimum_password_length >= 14: + self.cis_foundations_benchmark_3_0['1.4']['Status'] = True + else: + self.cis_foundations_benchmark_3_0['1.4']['Status'] = False else: - self.cis_foundations_benchmark_2_0['1.4']['Status'] = None + self.cis_foundations_benchmark_3_0['1.4']['Status'] = None - # 1.5 and 1.6 Checking Identity Domains Password Policy for expiry less than 365 and + # 1.4, 1.5 and 1.6 Checking Identity Domains Password Policy for expiry less than 365 and debug("__report_cis_analyze_tenancy_data: Identity Domains Enabled is: " + str(self.__identity_domains_enabled)) if self.__identity_domains_enabled: for domain in self.__identity_domains: if domain['password_policy']: debug("Policy " + domain['display_name'] + " password expiry is " + str(domain['password_policy']['password_expires_after'])) debug("Policy " + domain['display_name'] + " reuse is " + str(domain['password_policy']['num_passwords_in_history'])) + debug("Policy " + domain['display_name'] + " length is " + str(domain['password_policy']['min_length'])) + + + if domain['password_policy']['min_length']: + if domain['password_policy']['min_length'] > 14: + self.cis_foundations_benchmark_3_0['1.4']['Findings'].append(domain) + else: + self.cis_foundations_benchmark_3_0['1.4']['Findings'].append(domain) + if domain['password_policy']['password_expires_after']: if domain['password_policy']['password_expires_after'] > 365: - self.cis_foundations_benchmark_2_0['1.5']['Findings'].append(domain) - + self.cis_foundations_benchmark_3_0['1.5']['Findings'].append(domain) + else: + self.cis_foundations_benchmark_3_0['1.5']['Findings'].append(domain) if domain['password_policy']['num_passwords_in_history']: if domain['password_policy']['num_passwords_in_history'] < 24: - self.cis_foundations_benchmark_2_0['1.6']['Findings'].append(domain) + self.cis_foundations_benchmark_3_0['1.6']['Findings'].append(domain) + else: + self.cis_foundations_benchmark_3_0['1.6']['Findings'].append(domain) else: - debug("__report_cis_analyze_tenancy_data 1.5 and 1.6 no password policy") - self.cis_foundations_benchmark_2_0['1.5']['Findings'].append(domain) - self.cis_foundations_benchmark_2_0['1.6']['Findings'].append(domain) + debug("__report_cis_analyze_tenancy_data 1.4, 1.5 and 1.6 no password policy") + self.cis_foundations_benchmark_3_0['1.4']['Findings'].append(domain) + self.cis_foundations_benchmark_3_0['1.5']['Findings'].append(domain) + self.cis_foundations_benchmark_3_0['1.6']['Findings'].append(domain) + if self.cis_foundations_benchmark_3_0['1.4']['Findings']: + self.cis_foundations_benchmark_3_0['1.4']['Status'] = False + else: + self.cis_foundations_benchmark_3_0['1.4']['Status'] = True - if self.cis_foundations_benchmark_2_0['1.5']['Findings']: - self.cis_foundations_benchmark_2_0['1.5']['Status'] = False + if self.cis_foundations_benchmark_3_0['1.5']['Findings']: + self.cis_foundations_benchmark_3_0['1.5']['Status'] = False else: - self.cis_foundations_benchmark_2_0['1.5']['Status'] = True + self.cis_foundations_benchmark_3_0['1.5']['Status'] = True - if self.cis_foundations_benchmark_2_0['1.6']['Findings']: - self.cis_foundations_benchmark_2_0['1.6']['Status'] = False + if self.cis_foundations_benchmark_3_0['1.6']['Findings']: + self.cis_foundations_benchmark_3_0['1.6']['Status'] = False else: - self.cis_foundations_benchmark_2_0['1.6']['Status'] = True + self.cis_foundations_benchmark_3_0['1.6']['Status'] = True # Adding all identity domains to Total - self.cis_foundations_benchmark_2_0['1.5']['Total'] = self.__identity_domains - self.cis_foundations_benchmark_2_0['1.6']['Total'] = self.__identity_domains + self.cis_foundations_benchmark_3_0['1.4']['Total'] = self.__identity_domains + self.cis_foundations_benchmark_3_0['1.5']['Total'] = self.__identity_domains + self.cis_foundations_benchmark_3_0['1.6']['Total'] = self.__identity_domains # 1.7 Check - Local Users w/o MFA for user in self.__users: if not(user['is_federated']) and user['can_use_console_password'] and not (user['is_mfa_activated']) and user['lifecycle_state']: - self.cis_foundations_benchmark_2_0['1.7']['Status'] = False - self.cis_foundations_benchmark_2_0['1.7']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.7']['Status'] = False + self.cis_foundations_benchmark_3_0['1.7']['Findings'].append( user) # CIS Total 1.7 Adding - All Users to CIS Total - self.cis_foundations_benchmark_2_0['1.7']['Total'] = self.__users + self.cis_foundations_benchmark_3_0['1.7']['Total'] = self.__users # 1.8 Check - API Keys over 90 for user in self.__users: if user['api_keys']: for key in user['api_keys']: if self.api_key_time_max_datetime >= datetime.datetime.strptime(key['time_created'], self.__iso_time_format): - self.cis_foundations_benchmark_2_0['1.8']['Status'] = False + self.cis_foundations_benchmark_3_0['1.8']['Status'] = False finding = { "user_name": user['name'], "user_id": user['id'], @@ -3753,18 +4095,18 @@ def __report_cis_analyze_tenancy_data(self): 'time_created': key['time_created'] } - self.cis_foundations_benchmark_2_0['1.8']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.8']['Findings'].append( finding) # CIS Total 1.8 Adding - Customer Secrets to CIS Total - self.cis_foundations_benchmark_2_0['1.8']['Total'].append(key) + self.cis_foundations_benchmark_3_0['1.8']['Total'].append(key) # CIS 1.9 Check - Old Customer Secrets for user in self.__users: if user['customer_secret_keys']: for key in user['customer_secret_keys']: if self.api_key_time_max_datetime >= datetime.datetime.strptime(key['time_created'], self.__iso_time_format): - self.cis_foundations_benchmark_2_0['1.9']['Status'] = False + self.cis_foundations_benchmark_3_0['1.9']['Status'] = False finding = { "user_name": user['name'], "user_id": user['id'], @@ -3776,17 +4118,17 @@ def __report_cis_analyze_tenancy_data(self): 'time_expires': key['time_expires'] } - self.cis_foundations_benchmark_2_0['1.9']['Findings'].append(finding) + self.cis_foundations_benchmark_3_0['1.9']['Findings'].append(finding) # CIS Total 1.9 Adding - Customer Secrets to CIS Total - self.cis_foundations_benchmark_2_0['1.9']['Total'].append(key) + self.cis_foundations_benchmark_3_0['1.9']['Total'].append(key) # CIS 1.10 Check - Old Auth Tokens for user in self.__users: if user['auth_tokens']: for key in user['auth_tokens']: if self.api_key_time_max_datetime >= datetime.datetime.strptime(key['time_created'], self.__iso_time_format): # and key['lifecycle_state'] == 'ACTIVE': - self.cis_foundations_benchmark_2_0['1.10']['Status'] = False + self.cis_foundations_benchmark_3_0['1.10']['Status'] = False finding = { "user_name": user['name'], @@ -3800,50 +4142,71 @@ def __report_cis_analyze_tenancy_data(self): # "token": key['token'] } - self.cis_foundations_benchmark_2_0['1.10']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.10']['Findings'].append( finding) # CIS Total 1.10 Adding - Keys to CIS Total - self.cis_foundations_benchmark_2_0['1.10']['Total'].append( + self.cis_foundations_benchmark_3_0['1.10']['Total'].append( key) + # CIS 1.11 Check - Old DB Password + #__iso_time_format1 = "%Y-%m-%dT%H:%M:%S.%fZ" + for user in self.__users: + if user['database_passwords']: + for key in user['database_passwords']: + if self.api_key_time_max_datetime >= datetime.datetime.strptime(key['time_created'], self.__iso_time_format): + self.cis_foundations_benchmark_3_0['1.11']['Status'] = False + + finding = { + "user_name": user['name'], + "user_id": user['id'], + "id": key['ocid'], + "description": key['description'], + # "expires-on": key['expires_on'] + } + + self.cis_foundations_benchmark_3_0['1.11']['Findings'].append(finding) + + # CIS Total 1.11 Adding - Keys to CIS Total + self.cis_foundations_benchmark_3_0['1.11']['Total'].append(key) + # CIS 1.12 Active Admins with API keys # Iterating through all users to see if they have API Keys and if they are active users for user in self.__users: if 'Administrators' in user['groups'] and user['api_keys'] and user['lifecycle_state']: - self.cis_foundations_benchmark_2_0['1.12']['Status'] = False - self.cis_foundations_benchmark_2_0['1.12']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.12']['Status'] = False + self.cis_foundations_benchmark_3_0['1.12']['Findings'].append( user) # CIS Total 1.12 Adding - All IAM Users in Administrator group to CIS Total if 'Administrators' in user['groups'] and user['lifecycle_state']: - self.cis_foundations_benchmark_2_0['1.12']['Total'].append(user) + self.cis_foundations_benchmark_3_0['1.12']['Total'].append(user) # CIS 1.13 Check - This check is complete uses email verification # Iterating through all users to see if they have API Keys and if they are active users for user in self.__users: if user['external_identifier'] is None and user['lifecycle_state'] and not (user['email_verified']): - self.cis_foundations_benchmark_2_0['1.13']['Status'] = False - self.cis_foundations_benchmark_2_0['1.13']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.13']['Status'] = False + self.cis_foundations_benchmark_3_0['1.13']['Findings'].append( user) # CIS Total 1.13 Adding - All IAM Users for to CIS Total - self.cis_foundations_benchmark_2_0['1.13']['Total'] = self.__users + self.cis_foundations_benchmark_3_0['1.13']['Total'] = self.__users # CIS 1.14 Check - Ensure Dynamic Groups are used for OCI instances, OCI Cloud Databases and OCI Function to access OCI resources # Iterating through all dynamic groups ensure there are some for fnfunc, instance or autonomous. Using reverse logic so starts as a false for dynamic_group in self.__dynamic_groups: if any(oci_resource.upper() in str(dynamic_group['matching_rule'].upper()) for oci_resource in self.cis_iam_checks['1.14']['resources']): - self.cis_foundations_benchmark_2_0['1.14']['Status'] = True + self.cis_foundations_benchmark_3_0['1.14']['Status'] = True else: - self.cis_foundations_benchmark_2_0['1.14']['Findings'].append( + self.cis_foundations_benchmark_3_0['1.14']['Findings'].append( dynamic_group) # Clearing finding - if self.cis_foundations_benchmark_2_0['1.14']['Status']: - self.cis_foundations_benchmark_2_0['1.14']['Findings'] = [] + if self.cis_foundations_benchmark_3_0['1.14']['Status']: + self.cis_foundations_benchmark_3_0['1.14']['Findings'] = [] # CIS Total 1.14 Adding - All Dynamic Groups for to CIS Total - self.cis_foundations_benchmark_2_0['1.14']['Total'] = self.__dynamic_groups + self.cis_foundations_benchmark_3_0['1.14']['Total'] = self.__dynamic_groups # CIS 1.15 Check - Ensure storage service-level admins cannot delete resources they manage. # Iterating through all policies @@ -3857,27 +4220,92 @@ def __report_cis_analyze_tenancy_data(self): clean_where_clause = split_statement[1].upper().replace(" ", "").replace("'", "") if all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15'][resource]) and \ not(all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15-storage-admin'][resource])): - debug("__report_cis_analyze_tenancy_data no permissions to delete storage: " + str(policy['name'])) + debug("__report_cis_analyze_tenancy_data CIS 1.15 no permissions to delete storage: " + str(policy['name'])) pass # Checking if this is the Storage admin with allowed elif all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15-storage-admin'][resource]) and \ not(all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15'][resource])): - debug("__report_cis_analyze_tenancy_data storage admin policy is: " + str(policy['name'])) + debug("__report_cis_analyze_tenancy_data CIS 1.15 storage admin policy is: " + str(policy['name'])) pass else: - self.cis_foundations_benchmark_2_0['1.15']['Findings'].append(policy) - debug("__report_cis_analyze_tenancy_data else policy is\n: " + str(policy['name'])) + self.cis_foundations_benchmark_3_0['1.15']['Findings'].append(policy) + debug("__report_cis_analyze_tenancy_data CIS 1.15 else policy is\n: " + str(policy['name'])) else: - self.cis_foundations_benchmark_2_0['1.15']['Findings'].append(policy) + self.cis_foundations_benchmark_3_0['1.15']['Findings'].append(policy) + + if self.cis_foundations_benchmark_3_0['1.15']['Findings']: + self.cis_foundations_benchmark_3_0['1.15']['Status'] = False + else: + self.cis_foundations_benchmark_3_0['1.15']['Status'] = True + + # CIS Total 1.15 Adding - All IAM Policies for to CIS Total + self.cis_foundations_benchmark_3_0['1.15']['Total'] = self.__policies + + # CIS 1.16 Check - Users with API Keys over 45 days + + for user in self.__users: + + login_over_45_days = None + api_key_over_45_days = None + if user['lifecycle_state']: # and not(user['is_federated']) and user['can_use_console_password']: + debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Login Over 45 days is: {login_over_45_days}') + if user['last_successful_login_date']: + last_successful_login_date = user['last_successful_login_date'].split(".")[0] + if self.local_user_time_max_datetime > datetime.datetime.strptime(last_successful_login_date, self.__iso_time_format): + login_over_45_days = True + debug(f"__report_cis_analyze_tenancy_data CIS 1.16 Last login is {user['last_successful_login_date']} and max login is {self.local_user_time_max_datetime}") + else: + login_over_45_days = False + else: + debug("__report_cis_analyze_tenancy_data CIS 1.16 No Last login") + login_over_45_days = True - if self.cis_foundations_benchmark_2_0['1.15']['Findings']: - self.cis_foundations_benchmark_2_0['1.15']['Status'] = False + else: + debug("__report_cis_analyze_tenancy_data CIS 1.16 INACTIVE USE") + login_over_45_days = False + + if user['api_keys']: + debug("__report_cis_analyze_tenancy_data CIS 1.16 API Key Check") + for api_key in user['api_keys']: + if api_key['apikey_used_in_45_days']: + api_key_over_45_days = True + else: + debug("__report_cis_analyze_tenancy_data CIS 1.16 API Key used in under 45 days") + api_key_over_45_days = True + # else: + # api_key_over_45_days = False + + debug(f"__report_cis_analyze_tenancy_data CIS 1.16 User: {user['id']}") + debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Over Login Over 45: {login_over_45_days}') + debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Over API Key Over 45: {api_key_over_45_days}') + if login_over_45_days or api_key_over_45_days: + finding = user.copy() + finding['login_over_45_days'] = login_over_45_days + finding['api_key_over_45_days'] = api_key_over_45_days + self.cis_foundations_benchmark_3_0['1.16']['Findings'].append(finding) + + if self.cis_foundations_benchmark_3_0['1.16']['Findings']: + self.cis_foundations_benchmark_3_0['1.16']['Status'] = False else: - self.cis_foundations_benchmark_2_0['1.15']['Status'] = True + self.cis_foundations_benchmark_3_0['1.16']['Status'] = True # CIS Total 1.15 Adding - All IAM Policies for to CIS Total - self.cis_foundations_benchmark_2_0['1.15']['Total'] = self.__policies + self.cis_foundations_benchmark_3_0['1.16']['Total'] = self.__users + + + + # CIS 1.17 Check - Ensure there is only one active API Key for any single OCI IAM user + for user in self.__users: + if user['api_keys'] and not(len(user['api_keys']) < 2): + self.cis_foundations_benchmark_3_0['1.17']['Findings'].append(user) + + if self.cis_foundations_benchmark_3_0['1.17']['Findings']: + self.cis_foundations_benchmark_3_0['1.17']['Status'] = False + else: + self.cis_foundations_benchmark_3_0['1.17']['Status'] = True + # CIS Total 1.17 Adding - All IAM Policies for to CIS Total + self.cis_foundations_benchmark_3_0['1.17']['Total'] = self.__users # CIS 2.1, 2.2, & 2.5 Check - Security List Ingress from 0.0.0.0/0 on ports 22, 3389 for sl in self.__network_security_lists: @@ -3888,40 +4316,47 @@ def __report_cis_analyze_tenancy_data(self): port_max = irule['tcp_options']['destinationPortRange']['max'] ports_range = range(port_min, port_max + 1) if 22 in ports_range: - self.cis_foundations_benchmark_2_0['2.1']['Status'] = False - self.cis_foundations_benchmark_2_0['2.1']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.1']['Status'] = False + self.cis_foundations_benchmark_3_0['2.1']['Findings'].append(sl) if 3389 in ports_range: - self.cis_foundations_benchmark_2_0['2.2']['Status'] = False - self.cis_foundations_benchmark_2_0['2.2']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.2']['Status'] = False + self.cis_foundations_benchmark_3_0['2.2']['Findings'].append(sl) break else: # If TCP Options is null it includes all ports - self.cis_foundations_benchmark_2_0['2.1']['Status'] = False - self.cis_foundations_benchmark_2_0['2.1']['Findings'].append(sl) - self.cis_foundations_benchmark_2_0['2.2']['Status'] = False - self.cis_foundations_benchmark_2_0['2.2']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.1']['Status'] = False + self.cis_foundations_benchmark_3_0['2.1']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.2']['Status'] = False + self.cis_foundations_benchmark_3_0['2.2']['Findings'].append(sl) break elif irule['source'] == "0.0.0.0/0" and irule['protocol'] == 'all': # All Protocols allowed included TCP and all ports - self.cis_foundations_benchmark_2_0['2.1']['Status'] = False - self.cis_foundations_benchmark_2_0['2.1']['Findings'].append(sl) - self.cis_foundations_benchmark_2_0['2.2']['Status'] = False - self.cis_foundations_benchmark_2_0['2.2']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.1']['Status'] = False + self.cis_foundations_benchmark_3_0['2.1']['Findings'].append(sl) + self.cis_foundations_benchmark_3_0['2.2']['Status'] = False + self.cis_foundations_benchmark_3_0['2.2']['Findings'].append(sl) break # CIS Total 2.1, 2.2 Adding - All SLs for to CIS Total - self.cis_foundations_benchmark_2_0['2.1']['Total'] = self.__network_security_lists - self.cis_foundations_benchmark_2_0['2.2']['Total'] = self.__network_security_lists + self.cis_foundations_benchmark_3_0['2.1']['Total'] = self.__network_security_lists + self.cis_foundations_benchmark_3_0['2.2']['Total'] = self.__network_security_lists # CIS 2.5 Check - any rule with 0.0.0.0 where protocol not 1 (ICMP) # CIS Total 2.5 Adding - All Default Security List for to CIS Total for sl in self.__network_security_lists: if sl['display_name'].startswith("Default Security List for "): - self.cis_foundations_benchmark_2_0['2.5']['Total'].append(sl) - for irule in sl['ingress_security_rules']: - if irule['source'] == "0.0.0.0/0" and irule['protocol'] != '1': - self.cis_foundations_benchmark_2_0['2.5']['Status'] = False - self.cis_foundations_benchmark_2_0['2.5']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.5']['Total'].append(sl) + for irule in sl['ingress_security_rules'] + sl['egress_security_rules']: + if 'source' in irule and irule['source'] == "0.0.0.0/0": + debug("__report_cis_analyze_tenancy_data: Security List has bad ingress rule") + self.cis_foundations_benchmark_3_0['2.5']['Status'] = False + self.cis_foundations_benchmark_3_0['2.5']['Findings'].append( + sl) + break + elif 'destination' in irule and irule['destination'] == "0.0.0.0/0" and irule['protocol'] != '1': + debug("Security List has bad egress rule") + self.cis_foundations_benchmark_3_0['2.5']['Status'] = False + self.cis_foundations_benchmark_3_0['2.5']['Findings'].append( sl) break @@ -3934,62 +4369,62 @@ def __report_cis_analyze_tenancy_data(self): port_max = rule['tcp_options'].destination_port_range.max ports_range = range(port_min, port_max + 1) if 22 in ports_range: - self.cis_foundations_benchmark_2_0['2.3']['Status'] = False - self.cis_foundations_benchmark_2_0['2.3']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.3']['Status'] = False + self.cis_foundations_benchmark_3_0['2.3']['Findings'].append( nsg) if 3389 in ports_range: - self.cis_foundations_benchmark_2_0['2.4']['Status'] = False - self.cis_foundations_benchmark_2_0['2.4']['Findings'].append(nsg) + self.cis_foundations_benchmark_3_0['2.4']['Status'] = False + self.cis_foundations_benchmark_3_0['2.4']['Findings'].append(nsg) break else: # If TCP Options is null it includes all ports - self.cis_foundations_benchmark_2_0['2.3']['Status'] = False - self.cis_foundations_benchmark_2_0['2.3']['Findings'].append(nsg) - self.cis_foundations_benchmark_2_0['2.4']['Status'] = False - self.cis_foundations_benchmark_2_0['2.4']['Findings'].append(nsg) + self.cis_foundations_benchmark_3_0['2.3']['Status'] = False + self.cis_foundations_benchmark_3_0['2.3']['Findings'].append(nsg) + self.cis_foundations_benchmark_3_0['2.4']['Status'] = False + self.cis_foundations_benchmark_3_0['2.4']['Findings'].append(nsg) break elif rule['source'] == "0.0.0.0/0" and rule['protocol'] == 'all': # All Protocols allowed included TCP and all ports - self.cis_foundations_benchmark_2_0['2.3']['Status'] = False - self.cis_foundations_benchmark_2_0['2.3']['Findings'].append(nsg) - self.cis_foundations_benchmark_2_0['2.4']['Status'] = False - self.cis_foundations_benchmark_2_0['2.4']['Findings'].append(nsg) + self.cis_foundations_benchmark_3_0['2.3']['Status'] = False + self.cis_foundations_benchmark_3_0['2.3']['Findings'].append(nsg) + self.cis_foundations_benchmark_3_0['2.4']['Status'] = False + self.cis_foundations_benchmark_3_0['2.4']['Findings'].append(nsg) break # CIS Total 2.2 & 2.4 Adding - All NSGs Instances to CIS Total - self.cis_foundations_benchmark_2_0['2.3']['Total'] = self.__network_security_groups - self.cis_foundations_benchmark_2_0['2.4']['Total'] = self.__network_security_groups + self.cis_foundations_benchmark_3_0['2.3']['Total'] = self.__network_security_groups + self.cis_foundations_benchmark_3_0['2.4']['Total'] = self.__network_security_groups # CIS 2.6 - Ensure Oracle Integration Cloud (OIC) access is restricted to allowed sources # Iterating through OIC instance have network access rules and ensure 0.0.0.0/0 is not in the list for integration_instance in self.__integration_instances: if not (integration_instance['network_endpoint_details']): - self.cis_foundations_benchmark_2_0['2.6']['Status'] = False - self.cis_foundations_benchmark_2_0['2.6']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.6']['Status'] = False + self.cis_foundations_benchmark_3_0['2.6']['Findings'].append( integration_instance) elif integration_instance['network_endpoint_details']: if "0.0.0.0/0" in str(integration_instance['network_endpoint_details']): - self.cis_foundations_benchmark_2_0['2.6']['Status'] = False - self.cis_foundations_benchmark_2_0['2.6']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.6']['Status'] = False + self.cis_foundations_benchmark_3_0['2.6']['Findings'].append( integration_instance) # CIS Total 2.6 Adding - All OIC Instances to CIS Total - self.cis_foundations_benchmark_2_0['2.6']['Total'] = self.__integration_instances + self.cis_foundations_benchmark_3_0['2.6']['Total'] = self.__integration_instances # CIS 2.7 - Ensure Oracle Analytics Cloud (OAC) access is restricted to allowed sources or deployed within a VCN for analytics_instance in self.__analytics_instances: if analytics_instance['network_endpoint_type'].upper() == 'PUBLIC': if not (analytics_instance['network_endpoint_details'].whitelisted_ips): - self.cis_foundations_benchmark_2_0['2.7']['Status'] = False - self.cis_foundations_benchmark_2_0['2.7']['Findings'].append(analytics_instance) + self.cis_foundations_benchmark_3_0['2.7']['Status'] = False + self.cis_foundations_benchmark_3_0['2.7']['Findings'].append(analytics_instance) elif "0.0.0.0/0" in analytics_instance['network_endpoint_details'].whitelisted_ips: - self.cis_foundations_benchmark_2_0['2.7']['Status'] = False - self.cis_foundations_benchmark_2_0['2.7']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.7']['Status'] = False + self.cis_foundations_benchmark_3_0['2.7']['Findings'].append( analytics_instance) # CIS Total 2.7 Adding - All OAC Instances to CIS Total - self.cis_foundations_benchmark_2_0['2.7']['Total'] = self.__analytics_instances + self.cis_foundations_benchmark_3_0['2.7']['Total'] = self.__analytics_instances # CIS 2.8 Check - Ensure Oracle Autonomous Shared Databases (ADB) access is restricted to allowed sources or deployed within a VCN # Iterating through ADB Checking for null NSGs, whitelisted ip or allowed IPs 0.0.0.0/0 @@ -3997,120 +4432,191 @@ def __report_cis_analyze_tenancy_data(self): for autonomous_database in self.__autonomous_databases: if autonomous_database['lifecycle_state'] not in [ oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_TERMINATED, oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_TERMINATING, oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_UNAVAILABLE ]: if not (autonomous_database['whitelisted_ips']) and not (autonomous_database['subnet_id']): - self.cis_foundations_benchmark_2_0['2.8']['Status'] = False - self.cis_foundations_benchmark_2_0['2.8']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.8']['Status'] = False + self.cis_foundations_benchmark_3_0['2.8']['Findings'].append( autonomous_database) elif autonomous_database['whitelisted_ips']: for value in autonomous_database['whitelisted_ips']: if '0.0.0.0/0' in str(autonomous_database['whitelisted_ips']): - self.cis_foundations_benchmark_2_0['2.8']['Status'] = False - self.cis_foundations_benchmark_2_0['2.8']['Findings'].append( + self.cis_foundations_benchmark_3_0['2.8']['Status'] = False + self.cis_foundations_benchmark_3_0['2.8']['Findings'].append( autonomous_database) # CIS Total 2.8 Adding - All ADBs to CIS Total - self.cis_foundations_benchmark_2_0['2.8']['Total'] = self.__autonomous_databases + self.cis_foundations_benchmark_3_0['2.8']['Total'] = self.__autonomous_databases # From CIS 2.0 CIS 4.1 Check - Ensure Audit log retention == 365 - Only checking in home region # if self.__audit_retention_period >= 365: - # self.cis_foundations_benchmark_2_0['4.1']['Status'] = True + # self.cis_foundations_benchmark_3_0['4.1']['Status'] = True for instance in self.__Instance: # CIS Check 3.1 Metadata Service v2 Enabled if instance['instance_options'] is None or not(instance['instance_options']['are_legacy_imds_endpoints_disabled']): debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't disable IMDSv1") - self.cis_foundations_benchmark_2_0['3.1']['Status'] = False - self.cis_foundations_benchmark_2_0['3.1']['Findings'].append(instance) + self.cis_foundations_benchmark_3_0['3.1']['Status'] = False + self.cis_foundations_benchmark_3_0['3.1']['Findings'].append(instance) # CIS Check 3.2 Secure Boot enabled if instance['platform_config'] is None or not(instance['platform_config']['is_secure_boot_enabled']): debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable secure boot") - self.cis_foundations_benchmark_2_0['3.2']['Status'] = False - self.cis_foundations_benchmark_2_0['3.2']['Findings'].append(instance) + self.cis_foundations_benchmark_3_0['3.2']['Status'] = False + self.cis_foundations_benchmark_3_0['3.2']['Findings'].append(instance) # CIS Check 3.3 Encryption in Transit enabled if instance['launch_options'] is None or not(instance['launch_options']['is_pv_encryption_in_transit_enabled']): debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable encryption in transit") - self.cis_foundations_benchmark_2_0['3.3']['Status'] = False - self.cis_foundations_benchmark_2_0['3.3']['Findings'].append(instance) + self.cis_foundations_benchmark_3_0['3.3']['Status'] = False + self.cis_foundations_benchmark_3_0['3.3']['Findings'].append(instance) # CIS Total 3.1 Adding - All Instances to CIS Total - self.cis_foundations_benchmark_2_0['3.1']['Total'] = self.__Instance + self.cis_foundations_benchmark_3_0['3.1']['Total'] = self.__Instance # CIS Total 3.2 Adding - All Instances to CIS Total - self.cis_foundations_benchmark_2_0['3.2']['Total'] = self.__Instance + self.cis_foundations_benchmark_3_0['3.2']['Total'] = self.__Instance # CIS Total 3.3 Adding - All Instances to CIS Total - self.cis_foundations_benchmark_2_0['3.3']['Total'] = self.__Instance + self.cis_foundations_benchmark_3_0['3.3']['Total'] = self.__Instance # CIS Check 4.1 - Check for Default Tags in Root Compartment # Iterate through tags looking for ${iam.principal.name} for tag in self.__tag_defaults: if tag['value'] == "${iam.principal.name}": - self.cis_foundations_benchmark_2_0['4.1']['Status'] = True + self.cis_foundations_benchmark_3_0['4.1']['Status'] = True # CIS Total 4.1 Adding - All Tag Defaults to CIS Total - self.cis_foundations_benchmark_2_0['4.1']['Total'] = self.__tag_defaults + self.cis_foundations_benchmark_3_0['4.1']['Total'] = self.__tag_defaults # CIS Check 4.2 - Check for Active Notification and Subscription - if len(self.__subscriptions) > 0: - self.cis_foundations_benchmark_2_0['4.2']['Status'] = True + for sub in self.__subscriptions: + if sub['lifecycle_state'] == 'ACTIVE': + self.cis_foundations_benchmark_3_0['4.2']['Status'] = True + else: + self.cis_foundations_benchmark_3_0['4.2']['Findings'].append(sub) + + # CIS Check 4.2 Total - All Subscriptions to CIS Total - self.cis_foundations_benchmark_2_0['4.2']['Total'] = self.__subscriptions + self.cis_foundations_benchmark_3_0['4.2']['Total'] = self.__subscriptions - # CIS Checks 4.3 - 4.12 and 4.15 + # CIS Checks 4.3 - 4.12 and 4.15 and 4.18 # Iterate through all event rules for event in self.__event_rules: - # Convert Event Condition to dict - eventtype_jsonable_str = event['condition'].lower().replace("'", "\"") - try: - eventtype_dict = json.loads(eventtype_jsonable_str) - except Exception: - print("*** Invalid Event Condition for event (not in JSON format): " + event['display_name'] + " ***") - eventtype_dict = {} - # Issue 256: 'eventtype' not in eventtype_dict (i.e. missing in event condition) - if eventtype_dict and 'eventtype' in eventtype_dict: - for key, changes in self.cis_monitoring_checks.items(): - # Checking if all cis change list is a subset of event condition - try: - # Checking if each region has the required events - if (all(x in eventtype_dict['eventtype'] for x in changes)) and key in self.__cis_regional_checks: - self.__cis_regional_findings_data[key][event['region']] = True - - # Cloud Guard Check is only required in the Cloud Guard Reporting Region - elif key == "4.15" and event['region'] == self.__cloud_guard_config.reporting_region and \ - (all(x in eventtype_dict['eventtype'] for x in changes)): - self.cis_foundations_benchmark_2_0[key]['Status'] = True - - # For Checks that are home region based checking those - elif (all(x in eventtype_dict['eventtype'] for x in changes)) and \ - key not in self.__cis_regional_checks and event['region'] == self.__home_region: - self.cis_foundations_benchmark_2_0[key]['Status'] = True + if event['lifecycle_state'] == "ACTIVE": + # Convert Event Condition to dict + eventtype_jsonable_str = event['condition'].lower().replace("'", "\"") + try: + eventtype_dict = json.loads(eventtype_jsonable_str) + except Exception: + print("*** Invalid Event Condition for event (not in JSON format): " + event['display_name'] + " ***") + eventtype_dict = {} - except Exception: - print("*** Invalid Event Data for event: " + event['display_name'] + " ***") + # Issue 256: 'eventtype' not in eventtype_dict (i.e. missing in event condition) + if eventtype_dict and 'eventtype' in eventtype_dict: + for key, changes in self.cis_monitoring_checks.items(): + # Checking if all cis change list is a subset of event condition + try: + # Checking if each region has the required events + if (all(x in eventtype_dict['eventtype'] for x in changes)) and key in self.__cis_regional_checks: + self.__cis_regional_findings_data[key][event['region']] = True + + # Cloud Guard Check is only required in the Cloud Guard Reporting Region + elif self.__cloud_guard_config and key == "4.15" and \ + event['region'] == self.__cloud_guard_config.reporting_region and \ + (all(x in eventtype_dict['eventtype'] for x in changes)): + self.cis_foundations_benchmark_3_0[key]['Status'] = True + + # For Checks that are home region based checking those + elif (all(x in eventtype_dict['eventtype'] for x in changes)) and \ + key not in self.__cis_regional_checks and event['region'] == self.__home_region: + self.cis_foundations_benchmark_3_0[key]['Status'] = True + + except Exception as e: + print(e) + print("*** Invalid Event Data for event: " + event['display_name'] + " ***") # ******* Iterating through Regional Checks adding findings for key, findings in self.__cis_regional_findings_data.items(): if all(findings.values()): - self.cis_foundations_benchmark_2_0[key]['Status'] = True + self.cis_foundations_benchmark_3_0[key]['Status'] = True + ### Testing ### # CIS Check 4.13 - VCN FlowLog enable # Generate list of subnets IDs for subnet in self.__network_subnets: - if not (subnet['id'] in self.__subnet_logs): - self.cis_foundations_benchmark_2_0['4.13']['Status'] = False - self.cis_foundations_benchmark_2_0['4.13']['Findings'].append( - subnet) + vcn_id = subnet['vcn_id'] + try: + if self.__all_logs and 'flowlogs' in self.__all_logs and \ + 'vcn' in self.__all_logs['flowlogs'] and vcn_id in self.__all_logs['flowlogs']['vcn']: + + debug(f"__report_cis_analyze_tenancy_data: Flowlogs checking VCN {vcn_id} for Subnet: {subnet['id']} ") + if self.__all_logs['flowlogs']['vcn'][vcn_id]['capture_filter']: + capture_filter_id = self.__all_logs['flowlogs']['vcn'][vcn_id]['capture_filter'] + capture_filter = self.__network_capturefilters[capture_filter_id] + + if not(self.all_traffic_rules[0] in capture_filter['additional_details']['flowLogCaptureFilterRules'] or \ + self.all_traffic_rules[1] in capture_filter['additional_details']['flowLogCaptureFilterRules']): + # VCN is being logging but it is has a capture filter we need to check + debug(f"__report_cis_analyze_tenancy_data: Flowlogs Capture Filter {capture_filter_id} Rules not compliant.") + capture_filter = self.__network_capturefilters[capture_filter_id] + self.cis_foundations_benchmark_3_0['4.13']['Status'] = False + self.cis_foundations_benchmark_3_0['4.13']['Findings'].append(subnet) + + elif self.__all_logs and 'flowlogs' in self.__all_logs and \ + 'subnet' in self.__all_logs['flowlogs'] and subnet['id'] in self.__all_logs['flowlogs']['subnet']: + + debug(f"__report_cis_analyze_tenancy_data: Flowlogs checking Subnet {subnet['id']} in subnet") + debug(self.__all_logs['flowlogs']['subnet'][subnet['id']]['capture_filter']) + if self.__all_logs['flowlogs']['subnet'][subnet['id']]['capture_filter']: + debug(f"__report_cis_analyze_tenancy_data: Flowlogs checking Subnet {subnet['id']} capture filter in subnet") + capture_filter_id = self.__all_logs['flowlogs']['subnet'][subnet['id']]['capture_filter'] + capture_filter = self.__network_capturefilters[capture_filter_id] + if not(self.all_traffic_rules[0] in capture_filter['additional_details']['flowLogCaptureFilterRules'] or \ + self.all_traffic_rules[1] in capture_filter['additional_details']['flowLogCaptureFilterRules']): + # VCN is being logging but it is has a capture filter we need to check + debug(f"__report_cis_analyze_tenancy_data: Flowlogs Capture Filter {capture_filter_id} Rules not compliant.") + self.cis_foundations_benchmark_3_0['4.13']['Status'] = False + self.cis_foundations_benchmark_3_0['4.13']['Findings'].append(subnet) + + elif self.__all_logs and self.__all_logs['flowlogs'] and \ + 'all' in self.__all_logs['flowlogs'] and subnet['id'] in self.__all_logs['flowlogs']['all']: + + debug(f"__report_cis_analyze_tenancy_data: Flowlogs checking Subnet {subnet['id']} in all") + debug(self.__all_logs['flowlogs']['all'][subnet['id']]['capture_filter']) + if self.__all_logs['flowlogs']['all'][subnet['id']]['capture_filter']: + debug(f"__report_cis_analyze_tenancy_data: Flowlogs checking Subnet {subnet['id']} capture filter in all") + + capture_filter_id = self.__all_logs['flowlogs']['all'][subnet['id']]['capture_filter'] + capture_filter = self.__network_capturefilters[capture_filter_id] + if not(self.all_traffic_rules[0] in capture_filter['additional_details']['flowLogCaptureFilterRules'] or \ + self.all_traffic_rules[1] in capture_filter['additional_details']['flowLogCaptureFilterRules']): + # VCN is being logging but it is has a capture filter we need to check + debug(f"__report_cis_analyze_tenancy_data: Flowlogs Capture Filter {capture_filter_id} Rules not compliant.") + self.cis_foundations_benchmark_3_0['4.13']['Status'] = False + self.cis_foundations_benchmark_3_0['4.13']['Findings'].append(subnet) + + else: + debug(f"__report_cis_analyze_tenancy_data: Flowlogs count not find Subnet {subnet['id']}, it is a finding") + self.cis_foundations_benchmark_3_0['4.13']['Status'] = False + self.cis_foundations_benchmark_3_0['4.13']['Findings'].append(subnet) + except Exception as e: + self.cis_foundations_benchmark_3_0['4.13']['Status'] = False + if ".capturefilter." in str(e): + print(f"Unable to read capturefilter rules for: {str(e)}.\n*** Please ensure your auditor has permissions: 'to read capture-filters in tenancy. ***") + self.__errors.append({"id" : str(e), "error" : "Unable to read capturefilter rules *** Please ensure your auditor has permissions: 'to read capture-filters in tenancy'."}) + else: + msg = f'Unable to process all logs and capture filter rules: {str(e)}' + print(msg) + self.__errors.append({"id": "__network_subnet_logs", "error": msg}) + # CIS Check 4.13 Total - Adding All Subnets to total - self.cis_foundations_benchmark_2_0['4.13']['Total'] = self.__network_subnets + self.cis_foundations_benchmark_3_0['4.13']['Total'] = self.__network_subnets # CIS Check 4.14 - Cloud Guard enabled debug("__report_cis_analyze_tenancy_data Cloud Guard Check: " + str(self.__cloud_guard_config_status)) if self.__cloud_guard_config_status == 'ENABLED': - self.cis_foundations_benchmark_2_0['4.14']['Status'] = True + self.cis_foundations_benchmark_3_0['4.14']['Status'] = True else: - self.cis_foundations_benchmark_2_0['4.14']['Status'] = False + self.cis_foundations_benchmark_3_0['4.14']['Status'] = False # CIS Check 4.16 - Encryption keys over 365 # Generating list of keys @@ -4118,103 +4624,109 @@ def __report_cis_analyze_tenancy_data(self): try: if self.kms_key_time_max_datetime and self.kms_key_time_max_datetime >= datetime.datetime.strptime(key['currentKeyVersion_time_created'], self.__iso_time_format): - self.cis_foundations_benchmark_2_0['4.16']['Status'] = False - self.cis_foundations_benchmark_2_0['4.16']['Findings'].append( + self.cis_foundations_benchmark_3_0['4.16']['Status'] = False + self.cis_foundations_benchmark_3_0['4.16']['Findings'].append( key) if self.kms_key_time_max_datetime is None: - self.cis_foundations_benchmark_2_0['4.16']['Status'] = False - self.cis_foundations_benchmark_2_0['4.16']['Findings'].append( + self.cis_foundations_benchmark_3_0['4.16']['Status'] = False + self.cis_foundations_benchmark_3_0['4.16']['Findings'].append( key) except Exception: - self.cis_foundations_benchmark_2_0['4.16']['Status'] = False - self.cis_foundations_benchmark_2_0['4.16']['Findings'].append( + self.cis_foundations_benchmark_3_0['4.16']['Status'] = False + self.cis_foundations_benchmark_3_0['4.16']['Findings'].append( key) # CIS Check 4.16 Total - Adding Key to total - self.cis_foundations_benchmark_2_0['4.16']['Total'].append(key) + self.cis_foundations_benchmark_3_0['4.16']['Total'].append(key) # CIS Check 4.17 - Object Storage with Logs - # Generating list of buckets names - for bucket in self.__buckets: - if not (bucket['name'] in self.__write_bucket_logs): - self.cis_foundations_benchmark_2_0['4.17']['Status'] = False - self.cis_foundations_benchmark_2_0['4.17']['Findings'].append( - bucket) + # Generating list of buckets names and need to make sure they have write level bucekt logs + if self.__all_logs and 'objectstorage' in self.__all_logs and\ + 'write' in self.__all_logs['objectstorage']: + + for bucket in self.__buckets: + if not (bucket['name'] + "-" + bucket['region'] in self.__all_logs['objectstorage']['write']): + self.cis_foundations_benchmark_3_0['4.17']['Status'] = False + self.cis_foundations_benchmark_3_0['4.17']['Findings'].append( + bucket) + else: + self.cis_foundations_benchmark_3_0['4.17']['Status'] = False + self.cis_foundations_benchmark_3_0['4.17']['Findings'] +=self.__buckets # CIS Check 4.17 Total - Adding All Buckets to total - self.cis_foundations_benchmark_2_0['4.17']['Total'] = self.__buckets + self.cis_foundations_benchmark_3_0['4.17']['Total'] = self.__buckets # CIS Section 5.1 Bucket Checks # Generating list of buckets names for bucket in self.__buckets: if 'public_access_type' in bucket: if bucket['public_access_type'] != 'NoPublicAccess': - self.cis_foundations_benchmark_2_0['5.1.1']['Status'] = False - self.cis_foundations_benchmark_2_0['5.1.1']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.1.1']['Status'] = False + self.cis_foundations_benchmark_3_0['5.1.1']['Findings'].append( bucket) if 'kms_key_id' in bucket: if not (bucket['kms_key_id']): - self.cis_foundations_benchmark_2_0['5.1.2']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.1.2']['Findings'].append( bucket) - self.cis_foundations_benchmark_2_0['5.1.2']['Status'] = False + self.cis_foundations_benchmark_3_0['5.1.2']['Status'] = False if 'versioning' in bucket: if bucket['versioning'] != "Enabled": - self.cis_foundations_benchmark_2_0['5.1.3']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.1.3']['Findings'].append( bucket) - self.cis_foundations_benchmark_2_0['5.1.3']['Status'] = False + self.cis_foundations_benchmark_3_0['5.1.3']['Status'] = False # CIS Check 5.1.1,5.1.2,5.1.3 Total - Adding All Buckets to total - self.cis_foundations_benchmark_2_0['5.1.1']['Total'] = self.__buckets - self.cis_foundations_benchmark_2_0['5.1.2']['Total'] = self.__buckets - self.cis_foundations_benchmark_2_0['5.1.3']['Total'] = self.__buckets + self.cis_foundations_benchmark_3_0['5.1.1']['Total'] = self.__buckets + self.cis_foundations_benchmark_3_0['5.1.2']['Total'] = self.__buckets + self.cis_foundations_benchmark_3_0['5.1.3']['Total'] = self.__buckets # CIS Section 5.2.1 Block Volume Checks # Generating list of block volumes names for volume in self.__block_volumes: if 'kms_key_id' in volume: if not (volume['kms_key_id']): - self.cis_foundations_benchmark_2_0['5.2.1']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.2.1']['Findings'].append( volume) - self.cis_foundations_benchmark_2_0['5.2.1']['Status'] = False + self.cis_foundations_benchmark_3_0['5.2.1']['Status'] = False # CIS Check 5.2.1 Total - Adding All Block Volumes to total - self.cis_foundations_benchmark_2_0['5.2.1']['Total'] = self.__block_volumes + self.cis_foundations_benchmark_3_0['5.2.1']['Total'] = self.__block_volumes # CIS Section 5.2.2 Boot Volume Checks # Generating list of boot names for boot_volume in self.__boot_volumes: if 'kms_key_id' in boot_volume: if not (boot_volume['kms_key_id']): - self.cis_foundations_benchmark_2_0['5.2.2']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.2.2']['Findings'].append( boot_volume) - self.cis_foundations_benchmark_2_0['5.2.2']['Status'] = False + self.cis_foundations_benchmark_3_0['5.2.2']['Status'] = False # CIS Check 4.2.2 Total - Adding All Block Volumes to total - self.cis_foundations_benchmark_2_0['5.2.2']['Total'] = self.__boot_volumes + self.cis_foundations_benchmark_3_0['5.2.2']['Total'] = self.__boot_volumes # CIS Section 5.3.1 FSS Checks # Generating list of FSS names for file_system in self.__file_storage_system: if 'kms_key_id' in file_system: if not (file_system['kms_key_id']): - self.cis_foundations_benchmark_2_0['5.3.1']['Findings'].append( + self.cis_foundations_benchmark_3_0['5.3.1']['Findings'].append( file_system) - self.cis_foundations_benchmark_2_0['5.3.1']['Status'] = False + self.cis_foundations_benchmark_3_0['5.3.1']['Status'] = False # CIS Check 4.3.1 Total - Adding All Block Volumes to total - self.cis_foundations_benchmark_2_0['5.3.1']['Total'] = self.__file_storage_system + self.cis_foundations_benchmark_3_0['5.3.1']['Total'] = self.__file_storage_system # CIS Section 6 Checks # Checking if more than one compartment because of the ManagedPaaS Compartment if len(self.__compartments) < 2: - self.cis_foundations_benchmark_2_0['6.1']['Status'] = False + self.cis_foundations_benchmark_3_0['6.1']['Status'] = False if len(self.__resources_in_root_compartment) > 0: for item in self.__resources_in_root_compartment: - self.cis_foundations_benchmark_2_0['6.2']['Status'] = False - self.cis_foundations_benchmark_2_0['6.2']['Findings'].append( + self.cis_foundations_benchmark_3_0['6.2']['Status'] = False + self.cis_foundations_benchmark_3_0['6.2']['Findings'].append( item) ########################################################################## @@ -4234,24 +4746,10 @@ def __get_children(self, parent, compartments): return kids ########################################################################## - # Analyzes Tenancy Data for Oracle Best Practices Report + # Initializes OBP Checks ########################################################################## - def __obp_analyze_tenancy_data(self): - - ####################################### - # Budget Checks - ####################################### - # Determines if a Budget Exists with an alert rule - if len(self.__budgets) > 0: - for budget in self.__budgets: - if budget['alert_rule_count'] > 0 and budget['target_compartment_id'] == self.__tenancy.id: - self.obp_foundations_checks['Cost_Tracking_Budgets']['Status'] = True - self.obp_foundations_checks['Cost_Tracking_Budgets']['OBP'].append(budget) - else: - self.obp_foundations_checks['Cost_Tracking_Budgets']['Findings'].append(budget) - - # Stores Regional Checks - for region_key, region_values in self.__regions.items(): + def __obp_init_regional_checks(self): + for region_key in self.__regions.keys(): self.__obp_regional_checks[region_key] = { "Audit": { "tenancy_level_audit": False, @@ -4277,16 +4775,21 @@ def __obp_analyze_tenancy_data(self): "status": False }, } - - ####################################### - # OCI Audit Log Compartments Checks - ####################################### - list_of_all_compartments = [] - dict_of_compartments = {} - for compartment in self.__compartments: - list_of_all_compartments.append(compartment.id) - - # Building a Hash Table of Parent Child Hieracrchy for Audit + + ########################################################################## + # OBP Budgets Check + ########################################################################## + def __obp_check_budget(self): + if len(self.__budgets) > 0: + for budget in self.__budgets: + if budget['alert_rule_count'] > 0 and budget['target_compartment_id'] == self.__tenancy.id: + self.obp_foundations_checks['Cost_Tracking_Budgets']['Status'] = True + self.obp_foundations_checks['Cost_Tracking_Budgets']['OBP'].append(budget) + else: + self.obp_foundations_checks['Cost_Tracking_Budgets']['Findings'].append(budget) + + def __obp_check_audit_log_compartments(self): + # Building a Hash Table of Parent Child Hierarchy for Audit dict_of_compartments = {} for compartment in self.__compartments: if "tenancy" not in compartment.id: @@ -4295,11 +4798,8 @@ def __obp_analyze_tenancy_data(self): except Exception: dict_of_compartments[compartment.compartment_id] = [] dict_of_compartments[compartment.compartment_id].append(compartment.id) - - # This is used for comparing compartments that are audit to the full list of compartments - set_of_all_compartments = set(list_of_all_compartments) - - # Collecting Servie Connectors Logs related to compartments + + # Collecting Service Connectors Logs related to compartments for sch_id, sch_values in self.__service_connectors.items(): # Only Active SCH with a target that is configured if sch_values['lifecycle_state'].upper() == "ACTIVE" and sch_values['target_kind']: @@ -4309,7 +4809,7 @@ def __obp_analyze_tenancy_data(self): if source['compartment_id'] == self.__tenancy.id and source['log_group_id'].upper() == "_Audit_Include_Subcompartment".upper(): self.__obp_regional_checks[sch_values['region']]['Audit']['tenancy_level_audit'] = True self.__obp_regional_checks[sch_values['region']]['Audit']['tenancy_level_include_sub_comps'] = True - + # Since it is not the Tenancy we should add the compartment to the list and check if sub compartment are included elif source['log_group_id'].upper() == "_Audit_Include_Subcompartment".upper(): self.__obp_regional_checks[sch_values['region']]['Audit']['compartments'] += self.__get_children(source['compartment_id'], dict_of_compartments) @@ -4318,10 +4818,13 @@ def __obp_analyze_tenancy_data(self): except Exception: # There can be empty log groups pass + # Analyzing Service Connector Audit Logs to see if each region has all compartments for region_key, region_values in self.__obp_regional_checks.items(): # Checking if I already found the tenancy ocid with all child compartments included if not region_values['Audit']['tenancy_level_audit']: + list_of_all_compartments = [compartment.id for compartment in self.__compartments] + set_of_all_compartments = set(list_of_all_compartments) audit_findings = set_of_all_compartments - set(region_values['Audit']['compartments']) # If there are items in the then it is not auditing everything in the tenancy if audit_findings: @@ -4329,20 +4832,20 @@ def __obp_analyze_tenancy_data(self): else: region_values['Audit']['tenancy_level_audit'] = True region_values['Audit']['findings'] = [] - + # Consolidating Audit findings into the OBP Checks for region_key, region_values in self.__obp_regional_checks.items(): # If this flag is set all compartments are not logged in region if not region_values['Audit']['tenancy_level_audit']: self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['Status'] = False - + # If this flag is set the region has the tenancy logging and all sub compartments flag checked if not region_values['Audit']['tenancy_level_include_sub_comps']: self.obp_foundations_checks['SIEM_Audit_Incl_Sub_Comp']['Status'] = False self.obp_foundations_checks['SIEM_Audit_Incl_Sub_Comp']['Findings'].append({"region_name": region_key}) else: self.obp_foundations_checks['SIEM_Audit_Incl_Sub_Comp']['OBP'].append({"region_name": region_key}) - + # Compartment Logs that are missed in the region for compartment in region_values['Audit']['findings']: try: @@ -4380,7 +4883,7 @@ def __obp_analyze_tenancy_data(self): exists_already = list(filter(lambda source: source['id'] == record['id'] and source['region'] == record['region'], self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['Findings'])) if not exists_already: self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['Findings'].append(record) - + # Compartment logs that are not missed in the region for compartment in region_values['Audit']['compartments']: try: @@ -4419,161 +4922,79 @@ def __obp_analyze_tenancy_data(self): if not exists_already: self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['OBP'].append(record) + def __obp_check_cloud_guard(self): ####################################### - # Subnet and Bucket Log Checks + # Cloud Guard Checks ####################################### - for sch_id, sch_values in self.__service_connectors.items(): - # Only Active SCH with a target that is configured - if sch_values['lifecycle_state'].upper() == "ACTIVE" and sch_values['target_kind']: - # Subnet Logs Checks - for subnet_id, log_values in self.__subnet_logs.items(): - - log_id = log_values['log_id'] - log_group_id = log_values['log_group_id'] - log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": subnet_id} - - subnet_log_group_in_sch = list(filter(lambda source: source['log_group_id'] == log_group_id, sch_values['log_sources'])) - subnet_log_in_sch = list(filter(lambda source: source['log_id'] == log_id, sch_values['log_sources'])) + cloud_guard_record = { + "cloud_guard_endable": True if self.__cloud_guard_config_status == 'ENABLED' else False, + "target_at_root": False, + "targert_configuration_detector": False, + "targert_configuration_detector_customer_owned": False, + "target_activity_detector": False, + "target_activity_detector_customer_owned": False, + "target_threat_detector": False, + "target_threat_detector_customer_owned": False, + "target_responder_recipes": False, + "target_responder_recipes_customer_owned": False, + "target_responder_event_rule": False, + } - # Checking if the Subnets's log group in is in SCH's log sources & the log_id is empty so it covers everything in the log group - if subnet_log_group_in_sch and not (subnet_log_in_sch): - self.__obp_regional_checks[sch_values['region']]['VCN']['subnets'].append(log_record) + try: + # Cloud Guard Target attached to the root compartment with activity, config, and threat detector plus a responder + if self.__cloud_guard_targets[self.__tenancy.id]: - # Checking if the Subnet's log id in is in the service connector's log sources if so I will add it - elif subnet_log_in_sch: - self.__obp_regional_checks[sch_values['region']]['VCN']['subnets'].append(log_record) + cloud_guard_record['target_at_root'] = True - # else: - # self.__obp_regional_checks[sch_values['region']]['VCN']['findings'].append(subnet_id) - - # Bucket Write Logs Checks - for bucket_name, log_values in self.__write_bucket_logs.items(): - log_id = log_values['log_id'] - log_group_id = log_values['log_group_id'] - log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": bucket_name} - log_region = log_values['region'] - - bucket_log_group_in_sch = list(filter(lambda source: source['log_group_id'] == log_group_id and sch_values['region'] == log_region, sch_values['log_sources'])) - bucket_log_in_sch = list(filter(lambda source: source['log_id'] == log_id and sch_values['region'] == log_region, sch_values['log_sources'])) - - # Checking if the Bucket's log group in is in SCH's log sources & the log_id is empty so it covers everything in the log group - if bucket_log_group_in_sch and not (bucket_log_in_sch): - self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['buckets'].append(log_record) - - # Checking if the Bucket's log Group in is in the service connector's log sources if so I will add it - elif bucket_log_in_sch: - self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['buckets'].append(log_record) - - # else: - # self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['findings'].append(bucket_name) - - # Bucket Read Log Checks - - for bucket_name, log_values in self.__read_bucket_logs.items(): - log_id = log_values['log_id'] - log_group_id = log_values['log_group_id'] - log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": bucket_name} - - log_region = log_values['region'] - - bucket_log_group_in_sch = list(filter(lambda source: source['log_group_id'] == log_group_id and sch_values['region'] == log_region, sch_values['log_sources'])) - bucket_log_in_sch = list(filter(lambda source: source['log_id'] == log_id and sch_values['region'] == log_region, sch_values['log_sources'])) - - # Checking if the Bucket's log group in is in SCH's log sources & the log_id is empty so it covers everything in the log group - if bucket_log_group_in_sch and not (bucket_log_in_sch): - self.__obp_regional_checks[sch_values['region']]['Read_Bucket']['buckets'].append(log_record) - - # Checking if the Bucket's log id in is in the service connector's log sources if so I will add it - elif bucket_log_in_sch: - self.__obp_regional_checks[sch_values['region']]['Read_Bucket']['buckets'].append(log_record) - - # Consolidating regional SERVICE LOGGING findings into centralized finding report - for region_key, region_values in self.__obp_regional_checks.items(): - - for finding in region_values['VCN']['subnets']: - logged_subnet = list(filter(lambda subnet: subnet['id'] == finding['id'], self.__network_subnets)) - # Checking that the subnet has not already been written to OBP - existing_finding = list(filter(lambda subnet: subnet['id'] == finding['id'], self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'])) - if len(logged_subnet) != 0: - record = logged_subnet[0].copy() - record['sch_id'] = finding['sch_id'] - record['sch_name'] = finding['sch_name'] - - if logged_subnet and not (existing_finding): - self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'].append(record) - # else: - # print("Found this subnet being logged but the subnet does not exist: " + str(finding)) - - for finding in region_values['Write_Bucket']['buckets']: - logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['id'], self.__buckets)) - if len(logged_bucket) != 0: - record = logged_bucket[0].copy() - record['sch_id'] = finding['sch_id'] - record['sch_name'] = finding['sch_name'] - - if logged_bucket: - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['OBP'].append(record) - - for finding in region_values['Read_Bucket']['buckets']: - logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['id'], self.__buckets)) - if len(logged_bucket) != 0: - record = logged_bucket[0].copy() - record['sch_id'] = finding['sch_id'] - record['sch_name'] = finding['sch_name'] - - if logged_bucket: - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['OBP'].append(record) - - # Finding looking at all buckets and seeing if they meet one of the OBPs in one of the regions - for finding in self.__buckets: - read_logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['name'] and bucket['region'] == finding['region'], self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['OBP'])) - if not (read_logged_bucket): - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings'].append(finding) - - write_logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['name'] and bucket['region'] == finding['region'], self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['OBP'])) - if not (write_logged_bucket): - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings'].append(finding) + if self.__cloud_guard_targets[self.__tenancy.id]: + if self.__cloud_guard_targets[self.__tenancy.id]['target_detector_recipes']: + for recipe in self.__cloud_guard_targets[self.__tenancy.id]['target_detector_recipes']: + if recipe.detector.upper() == 'IAAS_CONFIGURATION_DETECTOR': + cloud_guard_record['targert_configuration_detector'] = True + if recipe.owner.upper() == "CUSTOMER": + cloud_guard_record['targert_configuration_detector_customer_owned'] = True - # Finding looking at all subnet and seeing if they meet one of the OBPs in one of the regions - for finding in self.__network_subnets: - logged_subnet = list(filter(lambda subnet: subnet['id'] == finding['id'], self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'])) - if not (logged_subnet): - self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Findings'].append(finding) + elif recipe.detector.upper() == 'IAAS_ACTIVITY_DETECTOR': + cloud_guard_record['target_activity_detector'] = True + if recipe.owner.upper() == "CUSTOMER": + cloud_guard_record['target_activity_detector_customer_owned'] = True - # Setting VCN Flow Logs Findings - if self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Findings']: - self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Status'] = False + elif recipe.detector.upper() == 'IAAS_THREAT_DETECTOR': + cloud_guard_record['target_threat_detector'] = True + if recipe.owner.upper() == "CUSTOMER": + cloud_guard_record['target_threat_detector_customer_owned'] = True - else: - self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Status'] = True + if self.__cloud_guard_targets[self.__tenancy.id]['target_responder_recipes']: + cloud_guard_record['target_responder_recipes'] = True + for recipe in self.__cloud_guard_targets[self.__tenancy.id]['target_responder_recipes']: + if recipe.owner.upper() == 'CUSTOMER': + cloud_guard_record['target_responder_recipes_customer_owned'] = True - # Setting Write Bucket Findings - if self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings']: - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = False + for rule in recipe.effective_responder_rules: + if rule.responder_rule_id.upper() == 'EVENT' and rule.details.is_enabled: + cloud_guard_record['target_responder_event_rule'] = True - elif not self.__service_connectors: - # If there are no service connectors then by default all buckets are not logged - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = False - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings'] += self.__buckets + cloud_guard_record['target_id'] = self.__cloud_guard_targets[self.__tenancy.id]['id'] + cloud_guard_record['target_name'] = self.__cloud_guard_targets[self.__tenancy.id]['display_name'] - else: - self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = True + except Exception: + pass - # Setting Read Bucket Findings - if self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings']: - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = False + all_cloud_guard_checks = True + for key, value in cloud_guard_record.items(): + if not (value): + all_cloud_guard_checks = False - elif not self.__service_connectors: - # If there are no service connectors then by default all buckets are not logged - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = False - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings'] += self.__buckets + self.obp_foundations_checks['Cloud_Guard_Config']['Status'] = all_cloud_guard_checks + if all_cloud_guard_checks: + self.obp_foundations_checks['Cloud_Guard_Config']['OBP'].append(cloud_guard_record) else: - self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = True - - ####################################### - # OBP Networking Checks - ####################################### + self.obp_foundations_checks['Cloud_Guard_Config']['Findings'].append(cloud_guard_record) + ####################################### + # OBP Networking Checks + ####################################### + def __obp_check_networking(self): # Fast Connect Connections for drg_id, drg_values in self.__network_drg_attachments.items(): @@ -4600,13 +5021,16 @@ def __obp_analyze_tenancy_data(self): elif attachment['network_type'].upper() == 'VIRTUAL_CIRCUIT': # Checking for Provision and BGP enabled Virtual Circuits and that it is associated - for virtual_circuit in self.__network_fastconnects[attachment['drg_id']]: - if attachment['network_id'] == virtual_circuit['id']: - if virtual_circuit['lifecycle_state'].upper() == 'PROVISIONED' and virtual_circuit['bgp_session_state'].upper() == "UP": - # Good VC to increment number of VCs and append the provider name - fast_connect_providers.add(virtual_circuit['provider_name']) - number_of_valid_fast_connect_circuits += 1 - + try: + for virtual_circuit in self.__network_fastconnects[attachment['drg_id']]: + if attachment['network_id'] == virtual_circuit['id']: + if virtual_circuit['lifecycle_state'].upper() == 'PROVISIONED' and virtual_circuit['bgp_session_state'].upper() == "UP": + # Good VC to increment number of VCs and append the provider name + fast_connect_providers.add(virtual_circuit['provider_name']) + number_of_valid_fast_connect_circuits += 1 + except Exception: + debug("__obp_analyze_tenancy_data: Fast Connect Connections check: DRG ID not found " + str(drg_id)) + self.__errors.append({"id" : str(drg_id), "error" : str("__obp_analyze_tenancy_data: Fast Connect Connections check: DRG ID not found")}) try: record = { "drg_id": drg_id, @@ -4657,78 +5081,10 @@ def __obp_analyze_tenancy_data(self): self.obp_foundations_checks["Networking_Connectivity"]["Findings"] += region_values["Network_Connectivity"]["findings"] self.obp_foundations_checks["Networking_Connectivity"]["OBP"] += region_values["Network_Connectivity"]["drgs"] - ####################################### - # Cloud Guard Checks - ####################################### - cloud_guard_record = { - "cloud_guard_endable": True if self.__cloud_guard_config_status == 'ENABLED' else False, - "target_at_root": False, - "targert_configuration_detector": False, - "targert_configuration_detector_customer_owned": False, - "target_activity_detector": False, - "target_activity_detector_customer_owned": False, - "target_threat_detector": False, - "target_threat_detector_customer_owned": False, - "target_responder_recipes": False, - "target_responder_recipes_customer_owned": False, - "target_responder_event_rule": False, - } - - try: - # Cloud Guard Target attached to the root compartment with activity, config, and threat detector plus a responder - if self.__cloud_guard_targets[self.__tenancy.id]: - - cloud_guard_record['target_at_root'] = True - - if self.__cloud_guard_targets[self.__tenancy.id]: - if self.__cloud_guard_targets[self.__tenancy.id]['target_detector_recipes']: - for recipe in self.__cloud_guard_targets[self.__tenancy.id]['target_detector_recipes']: - if recipe.detector.upper() == 'IAAS_CONFIGURATION_DETECTOR': - cloud_guard_record['targert_configuration_detector'] = True - if recipe.owner.upper() == "CUSTOMER": - cloud_guard_record['targert_configuration_detector_customer_owned'] = True - - elif recipe.detector.upper() == 'IAAS_ACTIVITY_DETECTOR': - cloud_guard_record['target_activity_detector'] = True - if recipe.owner.upper() == "CUSTOMER": - cloud_guard_record['target_activity_detector_customer_owned'] = True - - elif recipe.detector.upper() == 'IAAS_THREAT_DETECTOR': - cloud_guard_record['target_threat_detector'] = True - if recipe.owner.upper() == "CUSTOMER": - cloud_guard_record['target_threat_detector_customer_owned'] = True - - if self.__cloud_guard_targets[self.__tenancy.id]['target_responder_recipes']: - cloud_guard_record['target_responder_recipes'] = True - for recipe in self.__cloud_guard_targets[self.__tenancy.id]['target_responder_recipes']: - if recipe.owner.upper() == 'CUSTOMER': - cloud_guard_record['target_responder_recipes_customer_owned'] = True - - for rule in recipe.effective_responder_rules: - if rule.responder_rule_id.upper() == 'EVENT' and rule.details.is_enabled: - cloud_guard_record['target_responder_event_rule'] = True - - cloud_guard_record['target_id'] = self.__cloud_guard_targets[self.__tenancy.id]['id'] - cloud_guard_record['target_name'] = self.__cloud_guard_targets[self.__tenancy.id]['display_name'] - - except Exception: - pass - - all_cloud_guard_checks = True - for key, value in cloud_guard_record.items(): - if not (value): - all_cloud_guard_checks = False - - self.obp_foundations_checks['Cloud_Guard_Config']['Status'] = all_cloud_guard_checks - if all_cloud_guard_checks: - self.obp_foundations_checks['Cloud_Guard_Config']['OBP'].append(cloud_guard_record) - else: - self.obp_foundations_checks['Cloud_Guard_Config']['Findings'].append(cloud_guard_record) - - ####################################### - # Certificate Expiry Check - ####################################### - + ####################################### + # OBP Certificate Expiry Check + ####################################### + def __obp_check_certificates(self): for cert in self.__raw_oci_certificates: debug("\t__obp_analyze_tenancy_data: Iterating through certificates") @@ -4747,6 +5103,186 @@ def __obp_analyze_tenancy_data(self): else: self.obp_foundations_checks['Certificates_Near_Expiry']['Status'] = True + ####################################### + # OBP Subnet Log Checks + ####################################### + def __obp_check_subnet_logs(self): + cis_logged_subnets = set() + all_subnet_nets = set() + for subnet in self.cis_foundations_benchmark_3_0['4.13']['Findings']: + cis_logged_subnets.add(subnet['id']) + for subnet in self.cis_foundations_benchmark_3_0['4.13']['Total']: + all_subnet_nets.add(subnet['id']) + + list_of_properly_logged_subnets = all_subnet_nets - cis_logged_subnets + # need to check for no logs + for sch_id, sch_values in self.__service_connectors.items(): + if self.__all_logs and 'flowlogs' in self.__all_logs and \ + sch_values['lifecycle_state'].upper() == "ACTIVE" and sch_values['target_kind']: + for subnet_id in list_of_properly_logged_subnets: + log_values = None + if 'subnet' in self.__all_logs['flowlogs'] and subnet_id in self.__all_logs['flowlogs']['subnet']: + log_values = self.__all_logs['flowlogs']['subnet'][subnet_id] + elif 'all' in self.__all_logs['flowlogs'] and subnet_id in self.__all_logs['flowlogs']['all']: + log_values = self.__all_logs['flowlogs']['all'][subnet_id] + elif 'vcn' in self.__all_logs['flowlogs'] and self.__all_logs['flowlogs']['vcn']: + for vcn_id, vcn_values in self.__network_vcns.items(): + if subnet_id in vcn_values['subnets']: + log_values = self.__all_logs['flowlogs']['vcn'][vcn_id] + + log_id = log_values['id'] + log_group_id = log_values['log_group_id'] + log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": subnet_id} + + subnet_log_group_in_sch = list(filter(lambda source: source['log_group_id'] == log_group_id, sch_values['log_sources'])) + subnet_log_in_sch = list(filter(lambda source: source['log_id'] == log_id, sch_values['log_sources'])) + + if subnet_log_group_in_sch and not (subnet_log_in_sch): + self.__obp_regional_checks[sch_values['region']]['VCN']['subnets'].append(log_record) + elif subnet_log_in_sch: + self.__obp_regional_checks[sch_values['region']]['VCN']['subnets'].append(log_record) + + for region_values in self.__obp_regional_checks.values(): + for finding in region_values['VCN']['subnets']: + logged_subnet = list(filter(lambda subnet: subnet['id'] == finding['id'], self.__network_subnets)) + existing_finding = list(filter(lambda subnet: subnet['id'] == finding['id'], self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'])) + if len(logged_subnet) != 0: + record = logged_subnet[0].copy() + record['sch_id'] = finding['sch_id'] + record['sch_name'] = finding['sch_name'] + if logged_subnet and not (existing_finding): + self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'].append(record) + + for finding in self.__network_subnets: + logged_subnet = list(filter(lambda subnet: subnet['id'] == finding['id'], self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['OBP'])) + if not (logged_subnet): + self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Findings'].append(finding) + + if self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Findings']: + self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Status'] = False + else: + self.obp_foundations_checks['SIEM_VCN_Flow_Logging']['Status'] = True + + ####################################### + # OBP Subnet and Bucket Log Checks + ####################################### + def __obp_check_bucket_logs(self): + for sch_id, sch_values in self.__service_connectors.items(): + if self.__all_logs and 'objectstorage' in self.__all_logs and \ + sch_values['lifecycle_state'].upper() == "ACTIVE" and sch_values['target_kind']: + + # Bucket Write Logs Checks + # for bucket_name, log_values in self.__write_bucket_logs.items(): + if 'write' in self.__all_logs['objectstorage']: + for bucket_name, log_values in self.__all_logs['objectstorage']['write'].items(): + log_id = log_values['id'] + log_group_id = log_values['log_group_id'] + log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": bucket_name} + log_region = log_values['region'] + + bucket_log_group_in_sch = any(source['log_group_id'] == log_group_id and sch_values['region'] == log_region for source in sch_values['log_sources']) + bucket_log_in_sch = any(source['log_id'] == log_id and sch_values['region'] == log_region for source in sch_values['log_sources']) + + # Checking if the Bucket's log group in is in SCH's log sources & the log_id is empty so it covers everything in the log group + if bucket_log_group_in_sch and not (bucket_log_in_sch): + self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['buckets'].append(log_record) + + # Checking if the Bucket's log Group in is in the service connector's log sources if so I will add it + elif bucket_log_in_sch: + self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['buckets'].append(log_record) + + # else: + # self.__obp_regional_checks[sch_values['region']]['Write_Bucket']['findings'].append(bucket_name) + + # Bucket Read Log Checks + if 'read' in self.__all_logs['objectstorage']: + for bucket_name, log_values in self.__all_logs['objectstorage']['read'].items(): + log_id = log_values['id'] + log_group_id = log_values['log_group_id'] + log_record = {"sch_id": sch_id, "sch_name": sch_values['display_name'], "id": bucket_name} + + log_region = log_values['region'] + + bucket_log_group_in_sch = list(filter(lambda source: source['log_group_id'] == log_group_id and sch_values['region'] == log_region, sch_values['log_sources'])) + bucket_log_in_sch = list(filter(lambda source: source['log_id'] == log_id and sch_values['region'] == log_region, sch_values['log_sources'])) + + # Checking if the Bucket's log group in is in SCH's log sources & the log_id is empty so it covers everything in the log group + if bucket_log_group_in_sch and not (bucket_log_in_sch): + self.__obp_regional_checks[sch_values['region']]['Read_Bucket']['buckets'].append(log_record) + + # Checking if the Bucket's log id in is in the service connector's log sources if so I will add it + elif bucket_log_in_sch: + self.__obp_regional_checks[sch_values['region']]['Read_Bucket']['buckets'].append(log_record) + + # Consolidating regional SERVICE LOGGING findings into centralized finding report + for region_values in self.__obp_regional_checks.values(): + for finding in region_values['Write_Bucket']['buckets']: + logged_bucket = list(filter(lambda bucket: bucket['source_resource'] == finding['id'], self.__buckets)) + if len(logged_bucket) != 0: + record = logged_bucket[0].copy() + record['sch_id'] = finding['sch_id'] + record['sch_name'] = finding['sch_name'] + + if logged_bucket: + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['OBP'].append(record) + + for finding in region_values['Read_Bucket']['buckets']: + logged_bucket = list(filter(lambda bucket: bucket['source_resource'] == finding['id'], self.__buckets)) + if len(logged_bucket) != 0: + record = logged_bucket[0].copy() + record['sch_id'] = finding['sch_id'] + record['sch_name'] = finding['sch_name'] + + if logged_bucket: + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['OBP'].append(record) + + # Finding looking at all buckets and seeing if they meet one of the OBPs in one of the regions + for finding in self.__buckets: + read_logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['name'] and bucket['region'] == finding['region'], self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['OBP'])) + if not (read_logged_bucket): + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings'].append(finding) + + write_logged_bucket = list(filter(lambda bucket: bucket['name'] == finding['name'] and bucket['region'] == finding['region'], self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['OBP'])) + if not (write_logged_bucket): + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings'].append(finding) + # Setting Write Bucket Findings + if self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings']: + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = False + + elif not self.__service_connectors: + # If there are no service connectors then by default all buckets are not logged + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = False + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Findings'] += self.__buckets + + else: + self.obp_foundations_checks['SIEM_Write_Bucket_Logs']['Status'] = True + + # Setting Read Bucket Findings + if self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings']: + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = False + + elif not self.__service_connectors: + # If there are no service connectors then by default all buckets are not logged + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = False + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Findings'] += self.__buckets + else: + self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = True + + + ########################################################################## + # Analyzes Tenancy Data for Oracle Best Practices Report + ########################################################################## + def __obp_analyze_tenancy_data(self): + self.__obp_init_regional_checks() + self.__obp_check_budget() + self.__obp_check_audit_log_compartments() + self.__obp_check_cloud_guard() + self.__obp_check_networking() + self.__obp_check_certificates() + self.__obp_check_bucket_logs() + self.__obp_check_subnet_logs() + + ########################################################################## # Orchestrates data collection and CIS report generation ########################################################################## @@ -4755,16 +5291,23 @@ def __report_generate_cis_report(self, level): # Creating summary report summary_report = [] - for key, recommendation in self.cis_foundations_benchmark_2_0.items(): + for key, recommendation in self.cis_foundations_benchmark_3_0.items(): if recommendation['Level'] <= level: - report_filename = "cis" + " " + recommendation['section'] + "_" + recommendation['recommendation_#'] + report_filename = f'{self.__report_prefix}cis {recommendation["section"]}_{recommendation["recommendation_#"]}' report_filename = report_filename.replace(" ", "_").replace(".", "-").replace("_-_", "_") + ".csv" if recommendation['Status']: compliant_output = "Yes" + compliance_percentage = "100%" elif recommendation['Status'] is None: compliant_output = "Not Applicable" + compliance_percentage = "N/A" else: compliant_output = "No" + compliance_percentage = ( + str(int(( + (len(recommendation.get('Total') or []) - len(recommendation.get('Findings') or [])) + / len(recommendation.get('Total') or []) * 100 + )) if len(recommendation.get('Total') or []) > 0 else 0) + "%") record = { "Recommendation #": f"{key}", "Section": recommendation['section'], @@ -4773,6 +5316,7 @@ def __report_generate_cis_report(self, level): "Findings": (str(len(recommendation['Findings'])) if len(recommendation['Findings']) > 0 else " "), "Compliant Items": str(len(recommendation['Total']) - len(recommendation['Findings'])), "Total": (str(len(recommendation['Total'])) if len(recommendation['Total']) > 0 else " "), + "Compliance Percentage Per Recommendation": compliance_percentage, "Title": recommendation['Title'], "CIS v8": recommendation['CISv8'], "CCCS Guard Rail": recommendation['CCCS Guard Rail'], @@ -4786,7 +5330,7 @@ def __report_generate_cis_report(self, level): # self.__print_to_csv_file("cis", recommendation['section'] + "_" + recommendation['recommendation_#'], recommendation['Findings']) # Screen output for CIS Summary Report - print_header("CIS Foundations Benchmark 2.0.0 Summary Report") + print_header("CIS Foundations Benchmark 3.0.0 Summary Report") print('Num' + "\t" + "Level " + "\t" "Compliant" + "\t" + "Findings " + "\t" + "Total " + "\t\t" + 'Title') print('#' * 90) @@ -4814,30 +5358,120 @@ def __report_generate_cis_report(self, level): summary_file_name = self.__report_generate_html_summary_report("cis", "html_summary_report", summary_report) summary_files.append(summary_file_name) + if OUTPUT_DIAGRAMS: + diagram_file_name = self.__generate_compliance_diagram("cis", "summary_compliance", summary_report) + summary_files.append(diagram_file_name) + diagram_file_name = self.__generate_compliance_by_area_diagram("cis", "summary_compliance_by_focus_area", summary_report) + summary_files.append(diagram_file_name) + # Outputing to a bucket if I have one if summary_files and self.__output_bucket: for summary_file in summary_files: self.__os_copy_report_to_object_storage( self.__output_bucket, summary_file) - for key, recommendation in self.cis_foundations_benchmark_2_0.items(): + for key, recommendation in self.cis_foundations_benchmark_3_0.items(): if recommendation['Level'] <= level: report_file_name = self.__print_to_csv_file("cis", recommendation['section'] + "_" + recommendation['recommendation_#'], recommendation['Findings']) if report_file_name and self.__output_bucket: self.__os_copy_report_to_object_storage( self.__output_bucket, report_file_name) + ########################################################################## + # Generate summary diagrams + ########################################################################## + diagram_colors = ['#4C825C','#C74634'] + diagram_values = ['Compliant', 'Non-compliant'] + diagram_sections = ( + 'Identity and Access Management', + 'Networking', + 'Compute', + 'Logging and Monitoring', + 'Storage', + 'Asset Management' + ) + diagram_fontweight = 'bold' + diagram_fontcolor_reverse = 'white' + + ########################################################################## + # __cis_compliance + ########################################################################## + def __cis_compliance(self, filename, title, values=None): + plt.close('all') + plt.figure(figsize=(6,5)) + wegdes, labels, pcttexts = plt.pie(values, labels=self.diagram_values, colors=self.diagram_colors, autopct='%.0f%%', wedgeprops={'linewidth': 3.0, 'edgecolor': 'white'}, startangle=90, counterclock=False, radius=1.1) + for t in labels: + t.set_fontweight(self.diagram_fontweight) + for p in pcttexts: + p.set_fontweight(self.diagram_fontweight) + p.set_color(self.diagram_fontcolor_reverse) + plt.title(title, fontweight=self.diagram_fontweight, pad=30.0) + plt.savefig(filename) + + ########################################################################## + # __cis_compliance_by_area + ########################################################################## + def __cis_compliance_by_area(self, filename, title, section_values=None): + plt.close('all') + height = 0.4 + fig, ax = plt.subplots(figsize=(10,5), layout='compressed') + y = np.arange(len(self.diagram_sections)) + p = ax.barh(y - height/2, section_values[self.diagram_values[0]], height, color=self.diagram_colors[0]) + ax.bar_label(p, padding=-16, color=self.diagram_fontcolor_reverse, fontweight=self.diagram_fontweight) + p = ax.barh(y + (height/2), section_values[self.diagram_values[1]], height, color=self.diagram_colors[1]) + ax.bar_label(p, padding=-16, color=self.diagram_fontcolor_reverse, fontweight=self.diagram_fontweight) + ax.set_frame_on(False) + ax.set_title(title, fontweight=self.diagram_fontweight, loc='left') + ax.set_yticks(y) + ax.set_yticklabels(self.diagram_sections, fontweight=self.diagram_fontweight) + ax.invert_yaxis() + plt.tick_params(left=False, right=False, labelbottom=False, bottom=False) + plt.savefig(filename) + + ########################################################################## + # __generate_compliance_diagram + ########################################################################## + def __generate_compliance_diagram(self, header, file_subject, data): + compliant = 0 + non_compliant = 0 + for finding in data: + if finding['Compliant'] == 'Yes': + compliant += 1 + else: + non_compliant += 1 + cis_compliance_file = self.__get_output_file_path(header, file_subject, '.png') + self.__cis_compliance(cis_compliance_file, 'CIS Recommendation Compliance', [compliant, non_compliant]) + return cis_compliance_file + + ########################################################################## + # __generate_compliance_by_area_diagram + ########################################################################## + def __generate_compliance_by_area_diagram(self, header, file_subject, data): + compliants = [] + non_compliants = [] + for section in self.diagram_sections: + compliant = 0 + non_compliant = 0 + for finding in data: + if section in finding['Section']: + if finding['Compliant'] == 'Yes': + compliant += 1 + else: + non_compliant += 1 + compliants.append(compliant) + non_compliants.append(non_compliant) + + cis_compliance_by_area_file = self.__get_output_file_path(header, file_subject, '.png') + self.__cis_compliance_by_area(cis_compliance_by_area_file, 'CIS Recommendation Compliance per Focus Area', { + self.diagram_values[0]: compliants, + self.diagram_values[1]: non_compliants, + }) + return cis_compliance_by_area_file + ########################################################################## # Generates an HTML report ########################################################################## def __report_generate_html_summary_report(self, header, file_subject, data): - try: - # Creating report directory - if not os.path.isdir(self.__report_directory): - os.mkdir(self.__report_directory) - - except Exception as e: - raise Exception("Error in creating report directory: " + str(e.args)) try: # if no data @@ -4845,9 +5479,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): return None # get the file name of the HTML - file_name = header + "_" + file_subject - file_name = (file_name.replace(" ", "_")).replace(".", "-").replace("_-_", "_") + ".html" - file_path = os.path.join(self.__report_directory, f'{self.__report_prefix}{file_name}') + file_path = self.__get_output_file_path(header, file_subject, '.html') # add report_datetimeto each dictionary result = [dict(item, extract_date=self.start_time_str) @@ -4873,7 +5505,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): # generate fields fields = ['Recommendation #', 'Compliant', 'Section', 'Details'] - html_title = 'CIS OCI Foundations Benchmark 2.0.0 - Compliance Report' + html_title = 'CIS OCI Foundations Benchmark 3.0.0 - Compliance Report' with open(file_path, mode='w') as html_file: # Creating table header html_file.write('') @@ -4911,7 +5543,11 @@ def __report_generate_html_summary_report(self, header, file_subject, data): r = result[0] extract_date = r['extract_date'].replace('T',' ') html_file.write(f'
    Extract Date: {extract_date} UTC
    ') - html_file.write("") + html_file.write('') + if OUTPUT_DIAGRAMS: + # Include dashboard + html_file.write(f'
    ') + html_file.write(f'
     
    ') # Navigation html_file.write('
    ') html_file.write('
    ') @@ -4965,7 +5601,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): if int(total) > 1: tmp += 's' html_file.write(f'{str(compliant)}{tmp}\n') - html_file.write(f"{str(row['Section'])}\n") + html_file.write(f'{str(row["Section"])}\n') # Details html_file.write('') html_file.write(f'') @@ -4990,9 +5626,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write("
    Title{str(row["Title"])}
    \n") # Line html_file.write('
    ') - html_file.write('
    ') - html_file.write('

    Non-compliant Recommendations

    ') - html_file.write('
    ') + html_file.write('

    Non-compliant Recommendations

    ') html_file.write('
    ') html_file.write('
    ') html_file.write('
    ') @@ -5028,7 +5662,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write(f'{v}\n') else: html_file.write(f'{v}\n') - f = row['Findings'] + f = row['Findings'] t = row['Total'] tmp = '' if t != ' ': @@ -5047,14 +5681,14 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write('CCCS Guard Rail') html_file.write('File') html_file.write(f'{str(row["Level"])}') - cis_v8 = str(row["CIS v8"]).replace("[","").replace("]","").replace("'","") + cis_v8 = str(row["CIS v8"]).replace("[", "").replace("]", "").replace("'", "") html_file.write(f'{cis_v8}') html_file.write(f'{str(row["CCCS Guard Rail"])}') v = str(row['Filename']) if v == ' ': html_file.write(' ') else: - html_file.write(f'{v}') + html_file.write(f'{v}') html_file.write('') html_file.write("") @@ -5064,7 +5698,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write('
    ') # Creating appendix for the report for finding in html_appendix: - fing = self.cis_foundations_benchmark_2_0[finding] + fing = self.cis_foundations_benchmark_3_0[finding] html_file.write(f'

    {finding} – {fing["Title"]}

    \n') for item_key, item_value in self.cis_report_data[finding].items(): if item_value != "": @@ -5085,20 +5719,19 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write(f"

    {v}

    \n") html_file.write("
    \n") # Closing HTML + report_year = str(self.start_datetime.strftime('%Y')) html_file.write("""
    \n") +
    \n') print("HTML: " + file_subject.ljust(22) + " --> " + file_path) # Used by Upload @@ -5223,7 +5856,9 @@ def __collect_tenancy_data(self): self.__ons_read_subscriptions, self.__network_read_network_security_lists, self.__network_read_network_security_groups_rules, + self.__network_read_network_vcns, self.__network_read_network_subnets, + self.__network_read_network_capturefilters, self.__adb_read_adbs, self.__oic_read_oics, self.__oac_read_oacs, @@ -5231,7 +5866,6 @@ def __collect_tenancy_data(self): self.__boot_volume_read_boot_volumes, self.__fss_read_fsss, self.__core_instance_read_compute, - self.__certificates_read_certificates ] # Oracle Best practice functions @@ -5242,8 +5876,8 @@ def __collect_tenancy_data(self): self.__network_read_drgs, self.__network_read_drg_attachments, self.__sch_read_service_connectors, - self.__network_topology_dump - ] + self.__certificates_read_certificates + ] else: obp_functions = [] @@ -5251,7 +5885,8 @@ def __collect_tenancy_data(self): if self.__all_resources: all_resources = [ - self.__search_resources_all_resources_in_tenancy, + self.__network_topology_dump, + self.__search_resources_all_resources_in_tenancy ] else: all_resources = [] @@ -5269,6 +5904,9 @@ def execute_function(func): for future in concurrent.futures.as_completed(futures): future.result() + if obp_functions: + self.__unify_network_data() + ########################################################################## # Generate Raw Data Output ########################################################################## @@ -5288,6 +5926,8 @@ def __report_generate_raw_data_output(self): "network_security_groups": self.__network_security_groups, "network_security_lists": self.__network_security_lists, "network_subnets": self.__network_subnets, + "network_vcns": list(self.__network_vcns.values()), + "network_capture_filters": list(self.__network_capturefilters.values()), "autonomous_databases": self.__autonomous_databases, "analytics_instances": self.__analytics_instances, "integration_instances": self.__integration_instances, @@ -5353,18 +5993,26 @@ def __os_copy_report_to_object_storage(self, bucketname, filename): "Error opening file os_copy_report_to_object_storage: " + str(e.args)) ########################################################################## - # Print to CSV + # Get output file path with suffix ########################################################################## - def __print_to_csv_file(self, header, file_subject, data): - debug("__print_to_csv_file: " + header + "_" + file_subject) + def __get_output_file_path(self, header, file_subject, suffix): try: # Creating report directory if not os.path.isdir(self.__report_directory): os.mkdir(self.__report_directory) except Exception as e: - raise Exception( - "Error in creating report directory: " + str(e.args)) + raise Exception(f'Error in creating report directory: {str(e.args)}') + + file_name = f'{header}_{file_subject}' + file_name = f'{file_name.replace(" ", "_").replace(".", "-").replace("_-_", "_")}{suffix}' + return os.path.join(self.__report_directory, f'{self.__report_prefix}{file_name}') + + ########################################################################## + # Print to CSV + ########################################################################## + def __print_to_csv_file(self, header, file_subject, data): + debug("__print_to_csv_file: " + header + "_" + file_subject) try: # if no data @@ -5372,10 +6020,7 @@ def __print_to_csv_file(self, header, file_subject, data): return None # get the file name of the CSV - - file_name = header + "_" + file_subject - file_name = (file_name.replace(" ", "_")).replace(".", "-").replace("_-_", "_") + ".csv" - file_path = os.path.join(self.__report_directory, f'{self.__report_prefix}{file_name}') + file_path = self.__get_output_file_path(header, file_subject, '.csv') # add report_datetimeto each dictionary result = [dict(item, extract_date=self.start_time_str) @@ -5423,26 +6068,14 @@ def __print_to_csv_file(self, header, file_subject, data): # Print to JSON ########################################################################## def __print_to_json_file(self, header, file_subject, data): - try: - # Creating report directory - if not os.path.isdir(self.__report_directory): - os.mkdir(self.__report_directory) - - except Exception as e: - raise Exception( - "Error in creating report directory: " + str(e.args)) try: # if no data if len(data) == 0: return None - # get the file name of the CSV - - file_name = header + "_" + file_subject - file_name = (file_name.replace(" ", "_") - ).replace(".", "-").replace("_-_","_") + ".json" - file_path = os.path.join(self.__report_directory, f'{self.__report_prefix}{file_name}') + # get the file name of the JSON + file_path = self.__get_output_file_path(header, file_subject, '.json') # Serializing JSON to string json_object = json.dumps(data, indent=4) @@ -5470,26 +6103,14 @@ def __print_to_json_file(self, header, file_subject, data): # Print to PKL ########################################################################## def __print_to_pkl_file(self, header, file_subject, data): - try: - # Creating report directory - if not os.path.isdir(self.__report_directory): - os.mkdir(self.__report_directory) - - except Exception as e: - raise Exception( - "Error in creating report directory: " + str(e.args)) try: # if no data if len(data) == 0: return None - # get the file name of the CSV - - file_name = header + "_" + file_subject - file_name = (file_name.replace(" ", "_") - ).replace(".", "-").replace("_-_","_") + ".pkl" - file_path = os.path.join(self.__report_directory, f'{self.__report_prefix}{file_name}') + # get the file name of the PKL + file_path = self.__get_output_file_path(header, file_subject, '.pkl') # Writing to json file with open(file_path, 'wb') as pkl_file: @@ -5504,9 +6125,7 @@ def __print_to_pkl_file(self, header, file_subject, data): except Exception as e: raise Exception("Error in __print_to_pkl_file: " + str(e.args)) - - - + ########################################################################## # Orchestrates Data collection and reports ########################################################################## @@ -5739,7 +6358,9 @@ def execute_report(): help='Checks for OCI best practices.') parser.add_argument('--all-resources', action='store_true', default=False, help='Uses Advanced Search Service to query all resources in the tenancy and outputs to a JSON. This also enables OCI Best Practice Checks (--obp) and All resource to csv (--raw) flags.') - parser.add_argument('--redact_output', action='store_true', default=False, + parser.add_argument('--disable-api-usage-check', action='store_true', default=False, + help='Disables the checking of OCI API unused for 45 days or more.') + parser.add_argument('--redact-output', action='store_true', default=False, help='Redacts OCIDs in output CSV and JSON files.') parser.add_argument('--deeplink-url-override', default=None, dest='oci_url', help='Replaces the base OCI URL (https://cloud.oracle.com) for deeplinks (i.e. https://oc10.cloud.oracle.com).') @@ -5752,7 +6373,7 @@ def execute_report(): parser.add_argument('-v', action='store_true', default=False, dest='version', help='Show the version of the script and exit.') parser.add_argument('--debug', action='store_true', default=False, - dest='debug', help='Enables debugging messages. This feature is in beta.') + dest='debug', help='Enables debugging messages printed to screen.') cmd = parser.parse_args() if cmd.version: @@ -5762,14 +6383,23 @@ def execute_report(): config, signer = create_signer(cmd.file_location, cmd.config_profile, cmd.is_instance_principals, cmd.is_delegation_token, cmd.is_security_token) config['retry_strategy'] = oci.retry.DEFAULT_RETRY_STRATEGY report = CIS_Report(config, signer, cmd.proxy, cmd.output_bucket, cmd.report_directory, cmd.report_prefix, cmd.report_summary_json, cmd.print_to_screen, \ - cmd.regions, cmd.raw, cmd.obp, cmd.redact_output, oci_url=cmd.oci_url, debug=cmd.debug, all_resources=cmd.all_resources) + cmd.regions, cmd.raw, cmd.obp, cmd.redact_output, oci_url=cmd.oci_url, debug=cmd.debug, all_resources=cmd.all_resources, disable_api_keys=cmd.disable_api_usage_check) csv_report_directory = report.generate_reports(int(cmd.level)) - try: - if OUTPUT_TO_XLSX: + if OUTPUT_TO_XLSX: + try: report_prefix = f'{cmd.report_prefix}_' if cmd.report_prefix else '' workbook = Workbook(f'{csv_report_directory}/{report_prefix}Consolidated_Report.xlsx', {'in_memory': True}) - for csvfile in glob.glob(f'{csv_report_directory}/{report_prefix}*.csv'): + if OUTPUT_DIAGRAMS: + try: + worksheet = workbook.add_worksheet('cis_summary_charts') + worksheet.insert_image('B2', f'{csv_report_directory}/{report_prefix}cis_summary_compliance.png') + worksheet.insert_image('L2', f'{csv_report_directory}/{report_prefix}cis_summary_compliance_by_focus_area.png') + except Exception: + pass + csvfiles = glob.glob(f'{csv_report_directory}/{report_prefix}*.csv') + csvfiles.sort() + for csvfile in csvfiles: worksheet_name = csvfile.split(os.path.sep)[-1].replace(report_prefix, "").replace(".csv", "").replace("raw_data_", "raw_").replace("Findings", "fds").replace("Best_Practices", "bps") @@ -5797,10 +6427,13 @@ def execute_report(): # Skipping the deep link due to formating errors in xlsx if "=HYPERLINK" not in col: worksheet.write(r, c, col) + worksheet.autofilter(0, 0, r - 1, c - 1) + worksheet.autofit() + workbook.close() - except Exception as e: - print("** Failed to output to excel. Please use CSV files. **") - print(e) + except Exception as e: + print("** Failed to output to Excel. Please use CSV files. **") + print(e) ########################################################################## From 1f8b9a5fef10495c69a60d76d4813400ca012dfb Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Fri, 19 Sep 2025 18:52:41 +0530 Subject: [PATCH 09/33] CD3 Automation Toolkit Release v2025.2.0 --- cd3_automation_toolkit/setUpOCI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cd3_automation_toolkit/setUpOCI.py b/cd3_automation_toolkit/setUpOCI.py index 02abdca21..950d693b5 100644 --- a/cd3_automation_toolkit/setUpOCI.py +++ b/cd3_automation_toolkit/setUpOCI.py @@ -1087,7 +1087,7 @@ def create_cost_management(prim_options=[]): def create_budgets(): - errors = True + errors = False if (workflow_type == 'create_resources'): choices = [Option("Validate Budgets", None, None)] errors = cd3Validator.validate_cd3(choices, inputfile, var_file, prefix, outdir, ct) From 89f48b0ceadddb814c40211e03d101772ee47a6f Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Mon, 22 Sep 2025 14:20:27 +0530 Subject: [PATCH 10/33] CD3 Automation Toolkit Release v2025.2.0 --- .../costmanagement/budget/create_terraform_budget.py | 2 +- .../budget/export_budgets_nonGreenField.py | 4 +++- .../developerservices/oke/export_oke_nonGreenField.py | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py index 0497c10d7..bc4a249c7 100644 --- a/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py +++ b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/create_terraform_budget.py @@ -151,7 +151,7 @@ def create_terraform_budgets(inputfile, outdir, service_dir, prefix,ct): tempdict = {'budget_end_date': columnvalue.strip()} elif columnname == "Alert Recipients" and columnvalue != 'nan': - tempdict = {'alert_recipients': columnvalue.strip()} + tempdict = {'alert_recipients': columnvalue.strip().replace("\n", "\\n")} elif columnname == "Alert Message" and columnvalue != 'nan': tempdict = {'alert_message': columnvalue} diff --git a/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py index 46978ae2b..5e7a57b73 100644 --- a/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/costmanagement/budget/export_budgets_nonGreenField.py @@ -34,7 +34,7 @@ def print_budgets(values_for_columns, region, budget,budget_name,budget_alert_ru value = budget_name if budget else "" values_for_columns[col_header].append(value) - if (col_header == "Description"): + elif (col_header == "Description"): value = budget.description if budget else "" values_for_columns[col_header].append(value) elif (col_header == "Scope"): @@ -187,6 +187,8 @@ def export_budgets_nongreenfield(inputfile, outdir, service_dir, config, signer, alert_id = "budgets/"+budget_id+"/alertRules/"+str(budget_alert_rule.id) if budget_tf_name in budget_done : budget = [] + # if budget_done and budget_tf_name == budget_done[-1]: + # continue print_budgets(values_for_column_budgets, region, budget,budget_name,budget_alert_rule,ct) budget_done.append(budget_tf_name) tf_resource = f'module.budget-alert-rules[\\"{alert_tf_name}\\"].oci_budget_alert_rule.alert_rule' diff --git a/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py index a541a7075..c7fe0f105 100644 --- a/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py @@ -369,7 +369,7 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod values_for_column_oke[col_header].append(None) elif 'nodepool freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_info != None): - values_for_column_oke = commonTools.export_tags(nodepool_info, col_header,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_tags(nodepool_info, col_header,values_for_column_oke) else: values_for_column_oke[col_header].append(None) @@ -401,21 +401,21 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod elif 'lb defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): - values_for_column_oke = commonTools.export_tags(cluster_info.options.service_lb_config, col_header, + values_for_column_oke = ociCommonTools.export_tags(cluster_info.options.service_lb_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) elif 'lb freeform tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): - values_for_column_oke = commonTools.export_tags(cluster_info.options.service_lb_config, col_header, + values_for_column_oke = ociCommonTools.export_tags(cluster_info.options.service_lb_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) elif 'volume defined tags' in col_header.lower() and col_header.lower() in ociCommonTools.tagColumns: if (nodepool_count <= 1): - values_for_column_oke = commonTools.export_tags(cluster_info.options.persistent_volume_config, + values_for_column_oke = ociCommonTools.export_tags(cluster_info.options.persistent_volume_config, col_header, values_for_column_oke) else: values_for_column_oke[col_header].append(None) @@ -433,7 +433,7 @@ def print_oke(values_for_column_oke, reg, compartment_name, compartment_name_nod values_for_column_oke = ociCommonTools.export_tags(cluster_info, col_header, values_for_column_oke) else: oci_objs = [cluster_info,image_policy_config, nodepool_info] - values_for_column_oke = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_oke,values_for_column_oke) + values_for_column_oke = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_oke,values_for_column_oke) # Execution of the code begins here def export_oke(inputfile, outdir,service_dir, config, signer, ct, export_compartments=[], export_regions=[],export_tags=[]): From 3056fd743b477f466275e591ef3ffb68b131dfad Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Mon, 22 Sep 2025 18:15:35 +0530 Subject: [PATCH 11/33] CD3 Automation Toolkit Release v2025.2.0 --- .../python/developerservices/oke/export_oke_nonGreenField.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py index c7fe0f105..d6878cdb8 100644 --- a/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/oke/export_oke_nonGreenField.py @@ -543,6 +543,7 @@ def export_oke(inputfile, outdir,service_dir, config, signer, ct, export_compart for nodepool_info in nodepoolList: if nodepool_info.lifecycle_state!="ACTIVE": + nodepool_info = None continue # Tags filter From 1f9ca1e2e7f70d9d7427fb34c3ed9ec928f5311d Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Mon, 22 Sep 2025 21:31:44 +0530 Subject: [PATCH 12/33] CD3 Automation Toolkit Release v2025.2.0 --- .../keyvault/export_keyvaults_nonGreenField.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py index 4860abf4b..f8f8bf971 100644 --- a/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/security/keyvault/export_keyvaults_nonGreenField.py @@ -164,7 +164,7 @@ def export_keyvaults(inputfile, outdir, service_dir, config, signer, ct, export_ else: values_for_column_kms[col_header].append('') elif str(col_header).lower() in ["vault defined tags", "vault freeform tags"]: - values_for_column_kms = commonTools.export_tags(vault, col_header, + values_for_column_kms = ociCommonTools.export_tags(vault, col_header, values_for_column_kms) elif col_header == 'Key Compartment Name': @@ -186,12 +186,12 @@ def export_keyvaults(inputfile, outdir, service_dir, config, signer, ct, export_ values_for_column_kms[col_header].append(get_key_data.auto_key_rotation_details.rotation_interval_in_days if hasattr(get_key_data.auto_key_rotation_details, 'rotation_interval_in_days') else '') elif str(col_header).lower() in ["key defined tags" , "key freeform tags"]: if len(key.defined_tags) != 0: - values_for_column_kms = commonTools.export_tags(key, col_header, values_for_column_kms) + values_for_column_kms = ociCommonTools.export_tags(key, col_header, values_for_column_kms) else: values_for_column_kms[col_header].append('') else: oci_objs = [vault, key, get_key_data, get_vault_data, get_vault_data.replica_details] - values_for_column_kms = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_kms = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_kms, values_for_column_kms) else: @@ -216,13 +216,13 @@ def export_keyvaults(inputfile, outdir, service_dir, config, signer, ct, export_ values_for_column_kms[col_header].append(get_key_data.auto_key_rotation_details.rotation_interval_in_days if hasattr(get_key_data.auto_key_rotation_details,'rotation_interval_in_days') else '') elif str(col_header).lower() in ["key defined tags", "key freeform tags"]: if len(key.defined_tags) != 0: - values_for_column_kms = commonTools.export_tags(key, col_header, + values_for_column_kms = ociCommonTools.export_tags(key, col_header, values_for_column_kms) else: values_for_column_kms[col_header].append('') else: oci_objs = [key, get_key_data] - values_for_column_kms = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_kms = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_kms, values_for_column_kms) pass @@ -245,11 +245,11 @@ def export_keyvaults(inputfile, outdir, service_dir, config, signer, ct, export_ else: values_for_column_kms[col_header].append('') elif str(col_header).lower() in ["vault defined tags", "vault freeform tags"]: - values_for_column_kms = commonTools.export_tags(vault, col_header, + values_for_column_kms = ociCommonTools.export_tags(vault, col_header, values_for_column_kms) else: oci_objs = [vault, get_vault_data, get_vault_data.replica_details] - values_for_column_kms = commonTools.export_extra_columns(oci_objs, col_header, + values_for_column_kms = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_kms, values_for_column_kms) From 3f2325a17e3e2c50d0bdb164ff440f99a6efddbf Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Tue, 23 Sep 2025 18:12:37 +0530 Subject: [PATCH 13/33] CD3 Automation Toolkit Release v2025.2.0 --- OCIWorkVMStack/scripts/installToolkit.sh | 2 +- .../user-scripts/connectAzure.py | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/OCIWorkVMStack/scripts/installToolkit.sh b/OCIWorkVMStack/scripts/installToolkit.sh index 76422b919..01b10f0f0 100644 --- a/OCIWorkVMStack/scripts/installToolkit.sh +++ b/OCIWorkVMStack/scripts/installToolkit.sh @@ -7,7 +7,7 @@ mount_dir="/$username/mount_path" sudo mkdir -p /$mount_dir/tenancies sudo mkdir -p /$mount_dir/oci_tools -tenancyconfig_properties="$toolkit_dir/cd3_automation_toolkit/user-scripts/tenancyconfig.properties" +tenancyconfig_properties="/$mount_dir/oci_tools/cd3_automation_toolkit/user-scripts/tenancyconfig.properties" start=$(date +%s.%N) sudo sh -c "echo '########################################################################' >> /etc/motd" sudo sh -c "echo ' Welcome to CD3 Automation Toolkit WorkVM' >> /etc/motd" diff --git a/cd3_automation_toolkit/user-scripts/connectAzure.py b/cd3_automation_toolkit/user-scripts/connectAzure.py index bf2fc8cd8..9a9094b9a 100644 --- a/cd3_automation_toolkit/user-scripts/connectAzure.py +++ b/cd3_automation_toolkit/user-scripts/connectAzure.py @@ -13,8 +13,7 @@ import datetime import configparser from azure.identity import ClientSecretCredential -from azure.mgmt.compute import ComputeManagementClient - +from azure.core.exceptions import ClientAuthenticationError def paginate(operation, *args, **kwargs): while True: @@ -96,7 +95,7 @@ def paginate(operation, *args, **kwargs): client_secret = config.get('Default', 'client_secret').strip() if (subscription_id == '' or tenant_id == '' or client_id == '' or client_secret == ''): - print("Creating "+prefix_dir + " without setting up authentication") + print("Creating "+prefix_dir + " without setting up authentication\n") connected=0 except Exception as e: print(e) @@ -114,14 +113,18 @@ def paginate(operation, *args, **kwargs): shutil.copy(args.propsfile,config_files+"/"+prefix+"_connectAzure.properties") if connected == 1: - credential = ClientSecretCredential( + try: + credential = ClientSecretCredential( tenant_id=tenant_id, client_id=client_id, - client_secret=client_secret - ) - - # Use the credential to create a client for an Azure service (e.g., Compute) - compute_client = ComputeManagementClient(credential, subscription_id) + client_secret=client_secret) + token = credential.get_token("https://management.azure.com/.default") + print("Azure credentials are valid. Proceeding") + except ClientAuthenticationError as e: + print(f"\nAzure credentials are invalid. Exiting!!!") + exit(1) + except Exception as e: + print(f"An unexpected error occurred: {e}") # 3. Generate setUpCloud.properties file From 6bc13ea67e44ca17e0ad68483240820fce108054 Mon Sep 17 00:00:00 2001 From: Suruchi Date: Tue, 23 Sep 2025 21:01:43 +0530 Subject: [PATCH 14/33] Automation Toolkit Release v2025.2.0 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 51c7b6793..10a44b68e 100755 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ARG USER_GID=$USER_UID # Whether to download Provider as part of image creation ARG DOWNLOAD_PROVIDER=NO # TF Provider version -ARG TF_OCI_PROVIDER=7.18.0 +ARG TF_OCI_PROVIDER=7.19.0 ARG TF_NULL_PROVIDER=3.2.3 RUN microdnf install -y sudo && \ From a46d798b18e341fab3740ef0c5ae35736d5da6be Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Tue, 23 Sep 2025 22:59:31 +0530 Subject: [PATCH 15/33] Automation Toolkit Release v2025.2.0 --- Dockerfile | 2 +- cd3_automation_toolkit/ocicloud/terraform/adb.tf | 2 +- cd3_automation_toolkit/user-scripts/connectAzure.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 51c7b6793..10a44b68e 100755 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ARG USER_GID=$USER_UID # Whether to download Provider as part of image creation ARG DOWNLOAD_PROVIDER=NO # TF Provider version -ARG TF_OCI_PROVIDER=7.18.0 +ARG TF_OCI_PROVIDER=7.19.0 ARG TF_NULL_PROVIDER=3.2.3 RUN microdnf install -y sudo && \ diff --git a/cd3_automation_toolkit/ocicloud/terraform/adb.tf b/cd3_automation_toolkit/ocicloud/terraform/adb.tf index e611d113f..a3daff169 100755 --- a/cd3_automation_toolkit/ocicloud/terraform/adb.tf +++ b/cd3_automation_toolkit/ocicloud/terraform/adb.tf @@ -51,7 +51,7 @@ data "oci_secrets_secretbundle" "vault_secrets" { module "adb" { - source = "../../modules/database/adb" + source = "./modules/database/adb" for_each = var.adb != null ? var.adb : {} # depends_on = [module.nsgs] #admin_password = each.value.admin_password diff --git a/cd3_automation_toolkit/user-scripts/connectAzure.py b/cd3_automation_toolkit/user-scripts/connectAzure.py index 9a9094b9a..b3cff47a4 100644 --- a/cd3_automation_toolkit/user-scripts/connectAzure.py +++ b/cd3_automation_toolkit/user-scripts/connectAzure.py @@ -95,7 +95,7 @@ def paginate(operation, *args, **kwargs): client_secret = config.get('Default', 'client_secret').strip() if (subscription_id == '' or tenant_id == '' or client_id == '' or client_secret == ''): - print("Creating "+prefix_dir + " without setting up authentication\n") + print("\n\nCreating "+prefix_dir + " without setting up authentication\n") connected=0 except Exception as e: print(e) @@ -119,7 +119,7 @@ def paginate(operation, *args, **kwargs): client_id=client_id, client_secret=client_secret) token = credential.get_token("https://management.azure.com/.default") - print("Azure credentials are valid. Proceeding") + print("\nAzure credentials are valid. Proceeding...") except ClientAuthenticationError as e: print(f"\nAzure credentials are invalid. Exiting!!!") exit(1) @@ -185,7 +185,7 @@ def paginate(operation, *args, **kwargs): logging.info("Next Steps for using toolkit via CLI") logging.info("######################################") logging.info("Modify "+prefix_dir + "/" +prefix+"_setUpAzure.properties with input values for cd3file and workflow_type") -logging.info("cd "+user_dir+"/oci_tools/cd3_automation_toolkit") +logging.info("cd /cd3user/oci_tools/cd3_automation_toolkit") logging.info("python setUpCloud.py azure "+prefix_dir + "/" +prefix+"_setUpAzure.properties") with open(outfile, 'r') as log_file: From 038c84bf250fe715de772fb9783e4d67c00d98f1 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Wed, 24 Sep 2025 11:44:39 +0530 Subject: [PATCH 16/33] Automation Toolkit Release v2025.2.0 --- .../resourcemanager/create_resource_manager_stack.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py b/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py index 8db79fceb..4e6b28f23 100644 --- a/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py +++ b/cd3_automation_toolkit/ocicloud/python/developerservices/resourcemanager/create_resource_manager_stack.py @@ -13,6 +13,7 @@ import time import csv import base64 +import oci sys.path.append(os.getcwd() + "../") from common.python.commonTools import * from oci.config import DEFAULT_LOCATION From 98179fd43d76223874057711eb2f566e6aeaa4ef Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Wed, 24 Sep 2025 19:34:43 +0530 Subject: [PATCH 17/33] Automation Toolkit Release v2025.2.0 --- .../export_events_notifications_nonGreenField.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py index 55de2574d..029252813 100644 --- a/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py +++ b/cd3_automation_toolkit/ocicloud/python/managementservices/eventsnotifications/export_events_notifications_nonGreenField.py @@ -57,7 +57,7 @@ def print_notifications(values_for_column_notifications,region, ntk_compartment if (sbpn == None): values_for_column_notifications[col_header].append("") else: - values_for_column_notifications = commonTools.export_tags(sbpn, col_header, values_for_column_notifications) + values_for_column_notifications = ociCommonTools.export_tags(sbpn, col_header, values_for_column_notifications) elif col_header.lower() in ociCommonTools.tagColumns: values_for_column_notifications = ociCommonTools.export_tags(nftn_info, col_header, values_for_column_notifications) else: @@ -165,11 +165,11 @@ def events_rows(values_for_column_events, region, ntk_compartment_name, event_na values_for_column_events[col_header].append(event_is_enabled) elif (col_header == "Topic"): values_for_column_events[col_header].append(action_name) - elif col_header.lower() in commonTools.tagColumns: - values_for_column_events = commonTools.export_tags(event, col_header, values_for_column_events) + elif col_header.lower() in ociCommonTools.tagColumns: + values_for_column_events = ociCommonTools.export_tags(event, col_header, values_for_column_events) else: oci_objs = [event,event_info] - values_for_column_events = commonTools.export_extra_columns(oci_objs, col_header, sheet_dict_events,values_for_column_events) + values_for_column_events = ociCommonTools.export_extra_columns(oci_objs, col_header, sheet_dict_events,values_for_column_events) # Execution for Events export starts here def export_events(inputfile, outdir, service_dir, config, signer, ct,export_compartments=[], export_regions=[],export_tags=[]): From 2685b878a33049ca27b6b861a1815cd7a57dc211 Mon Sep 17 00:00:00 2001 From: xs2suruchi Date: Fri, 26 Sep 2025 17:46:16 +0530 Subject: [PATCH 18/33] Automation Toolkit Release v2025.2.0 --- .../example/CD3-Blank-template.xlsx | Bin 235451 -> 235467 bytes .../example/CD3-CIS-template.xlsx | Bin 300038 -> 301816 bytes .../example/CD3-HubSpoke-template.xlsx | Bin 271275 -> 271150 bytes .../example/CD3-SingleVCN-template.xlsx | Bin 285344 -> 287155 bytes .../export_dbsystems_vm_bm_nonGreenField.py | 6 ++-- .../export_exa_infra_nonGreenField.py | 6 ++-- .../export_exa_vmclusters_nonGreenField.py | 2 +- .../users/export_users_nonGreenField.py | 2 +- .../basenetwork/templates/subnet-template | 4 +-- ...loneexport_firewallpolicy_nonGreenField.py | 32 +++++++++--------- .../firewall/fwpolicy_create_secret.py | 2 +- .../objectstorage/export_terraform_oss.py | 2 +- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/cd3_automation_toolkit/example/CD3-Blank-template.xlsx b/cd3_automation_toolkit/example/CD3-Blank-template.xlsx index 6aad6e70ec7626e43694e85076dc6ec8c2d46acb..4d2292ddb98b55e15a1c156f39d58c68cbd4e967 100644 GIT binary patch delta 77420 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 H18n1L+T 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