diff --git a/prebuilt-tasks/pom.xml b/prebuilt-tasks/pom.xml index 01501f526..bdb8e4652 100644 --- a/prebuilt-tasks/pom.xml +++ b/prebuilt-tasks/pom.xml @@ -16,6 +16,9 @@ 2.6.1 20230227 6.5.0.202303070854-r + 1.37.0 + 1.8.1 + 2.24.0 @@ -134,6 +137,23 @@ spring-test test + + + com.azure + azure-core + ${azure-core-version} + + + com.azure + azure-identity + ${azure-identity-version} + + + com.azure.resourcemanager + azure-resourcemanager + ${azure-resourcemanager-version} + + diff --git a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTask.java b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTask.java new file mode 100644 index 000000000..8648c69ac --- /dev/null +++ b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTask.java @@ -0,0 +1,131 @@ +package com.redhat.parodos.tasks.azure; + +import java.util.List; + +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.VirtualMachine; +import com.azure.resourcemanager.network.models.Network; +import com.azure.resourcemanager.network.models.NetworkInterface; +import com.azure.resourcemanager.network.models.PublicIpAddress; +import com.azure.resourcemanager.resources.models.ResourceGroup; +import com.redhat.parodos.workflow.exception.MissingParameterException; +import com.redhat.parodos.workflow.parameter.WorkParameter; +import com.redhat.parodos.workflow.parameter.WorkParameterType; +import com.redhat.parodos.workflow.task.enums.WorkFlowTaskOutput; +import com.redhat.parodos.workflow.task.infrastructure.BaseInfrastructureWorkFlowTask; +import com.redhat.parodos.workflows.work.DefaultWorkReport; +import com.redhat.parodos.workflows.work.WorkContext; +import com.redhat.parodos.workflows.work.WorkReport; +import com.redhat.parodos.workflows.work.WorkStatus; +import com.sun.jdi.InternalException; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AzureCreateVirtualMachineTask extends BaseInfrastructureWorkFlowTask { + + static final String VM_USER_NAME_KEY = "vm-user-name"; + static final String VM_SSH_PUBLIC_KEY_KEY = "vm-ssh-public-key"; + static final String AZURE_TENANT_ID_KEY = "azure-tenant-id"; + static final String AZURE_SUBSCRIPTION_ID_KEY = "azure-subscription-id"; + static final String AZURE_CLIENT_ID_KEY = "azure-client-id"; + static final String AZURE_CLIENT_SECRET_KEY = "azure-client-secret"; + static final String AZURE_RESOURCES_PREFIX_KEY = "azure-resources-prefix"; + + private AzureResourceClient azureResourceClient; + + public AzureCreateVirtualMachineTask() { + this(new AzureResourceClientImpl()); + } + + AzureCreateVirtualMachineTask(AzureResourceClient azureResourceClient) { + this.azureResourceClient = azureResourceClient; + } + + @Override + public @NonNull List getWorkFlowTaskParameters() { + return List.of( + WorkParameter.builder().key(VM_USER_NAME_KEY).description("The user name for the Virtual Machine login") + .type(WorkParameterType.TEXT).optional(false).build(), + WorkParameter.builder().key(VM_SSH_PUBLIC_KEY_KEY) + .description("The SSH public key for the Virtual Machine login").type(WorkParameterType.TEXT) + .optional(false).build(), + WorkParameter.builder().key(AZURE_TENANT_ID_KEY) + .description("The unique identifier of the Azure Active Directory instance") + .type(WorkParameterType.TEXT).optional(false).build(), + WorkParameter.builder().key(AZURE_SUBSCRIPTION_ID_KEY) + .description("The GUID that uniquely identifies your subscription to use Azure services") + .type(WorkParameterType.TEXT).optional(false).build(), + WorkParameter.builder().key(AZURE_CLIENT_ID_KEY).description( + "The unique Application (client) ID assigned to your app by Azure AD when the app was registered") + .type(WorkParameterType.TEXT).optional(false).build(), + WorkParameter.builder().key(AZURE_CLIENT_SECRET_KEY) + .description("The password of the service principal").type(WorkParameterType.TEXT) + .optional(false).build(), + WorkParameter.builder().key(AZURE_RESOURCES_PREFIX_KEY) + .description("A designated prefix for naming all Azure resources").type(WorkParameterType.TEXT) + .optional(false).build()); + } + + @Override + /** + * Execute task, creates Virtual Machine in Azure Results with Virtual Machine created + * with public IP. This VM can be accessed using ssh (with provided username and ssh + * key) the public IP address is added to the context returned when the task is + * completed. Key: public-ip-address + */ + public WorkReport execute(WorkContext context) { + try { + final String userName = getRequiredParameterValue(context, VM_USER_NAME_KEY); + final String sshKey = getRequiredParameterValue(context, VM_SSH_PUBLIC_KEY_KEY); + + final String azureTenantId = getRequiredParameterValue(context, AZURE_TENANT_ID_KEY); + final String azureSubscriptionId = getRequiredParameterValue(context, AZURE_SUBSCRIPTION_ID_KEY); + final String azureClientId = getRequiredParameterValue(context, AZURE_CLIENT_ID_KEY); + final String azureClientSecret = getRequiredParameterValue(context, AZURE_CLIENT_SECRET_KEY); + final String resourcesPrefix = getRequiredParameterValue(context, AZURE_RESOURCES_PREFIX_KEY); + + this.azureResourceClient.init(azureTenantId, azureClientId, azureClientSecret, azureSubscriptionId); + + ResourceGroup resourceGroup = azureResourceClient.createResourceGroup(resourcesPrefix); + + AvailabilitySet availabilitySet = azureResourceClient.createAvailabilitySet(resourcesPrefix); + + PublicIpAddress publicIPAddress = azureResourceClient.createPublicIpAddress(resourcesPrefix); + + Network network = azureResourceClient.createNetwork(resourcesPrefix); + + NetworkInterface networkInterface = azureResourceClient.createNetworkInterface(resourcesPrefix, network, + publicIPAddress); + + VirtualMachine virtualMachine = azureResourceClient.createVirtualMachine(resourcesPrefix, networkInterface, + availabilitySet, userName, sshKey); + + PublicIpAddress publicIpAddress = virtualMachine.getPrimaryPublicIPAddress(); + if (publicIpAddress == null) { + log.error("VirtualMachine was created but without public IP"); + throw new InternalException("The new created VirtualMachine missing public IP address"); + } + + String ipAddress = publicIpAddress.ipAddress(); + log.info("VirtualMachine was created with public IP {}", ipAddress); + context.put("public-ip-address", ipAddress); + } + catch (MissingParameterException e) { + log.error("Task {} failed: missing required parameter, error: {}", getName(), e.getMessage()); + return new DefaultWorkReport(WorkStatus.FAILED, context, e); + } + catch (Exception e) { + log.error("Task {} failed, with error: {}", getName(), e.getMessage()); + return new DefaultWorkReport(WorkStatus.FAILED, context, e); + } + + return new DefaultWorkReport(WorkStatus.COMPLETED, context); + } + + @Override + public @NonNull List getWorkFlowTaskOutputs() { + return List.of(WorkFlowTaskOutput.OTHER); + } + +} diff --git a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClient.java b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClient.java new file mode 100644 index 000000000..ee3aa046c --- /dev/null +++ b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClient.java @@ -0,0 +1,27 @@ +package com.redhat.parodos.tasks.azure; + +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.VirtualMachine; +import com.azure.resourcemanager.network.models.Network; +import com.azure.resourcemanager.network.models.NetworkInterface; +import com.azure.resourcemanager.network.models.PublicIpAddress; +import com.azure.resourcemanager.resources.models.ResourceGroup; + +interface AzureResourceClient { + + void init(String azureTenantId, String azureClientId, String azureClientSecret, String azureSubscriptionId); + + ResourceGroup createResourceGroup(String resourcesPrefix); + + AvailabilitySet createAvailabilitySet(String resourcesPrefix); + + PublicIpAddress createPublicIpAddress(String resourcesPrefix); + + Network createNetwork(String resourcesPrefix); + + NetworkInterface createNetworkInterface(String resourcesPrefix, Network network, PublicIpAddress publicIPAddress); + + VirtualMachine createVirtualMachine(String resourcesPrefix, NetworkInterface networkInterface, + AvailabilitySet availabilitySet, String userName, String sshKey); + +} diff --git a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClientImpl.java b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClientImpl.java new file mode 100644 index 000000000..862857f55 --- /dev/null +++ b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/azure/AzureResourceClientImpl.java @@ -0,0 +1,85 @@ +package com.redhat.parodos.tasks.azure; + +import com.azure.core.credential.TokenCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.management.AzureEnvironment; +import com.azure.core.management.Region; +import com.azure.core.management.profile.AzureProfile; +import com.azure.identity.ClientSecretCredentialBuilder; +import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage; +import com.azure.resourcemanager.compute.models.VirtualMachine; +import com.azure.resourcemanager.compute.models.VirtualMachineSizeTypes; +import com.azure.resourcemanager.network.models.Network; +import com.azure.resourcemanager.network.models.NetworkInterface; +import com.azure.resourcemanager.network.models.PublicIpAddress; +import com.azure.resourcemanager.resources.models.ResourceGroup; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +class AzureResourceClientImpl implements AzureResourceClient { + + private AzureResourceManager azureResourceManager; + + @Override + public void init(String azureTenantId, String azureClientId, String azureClientSecret, String azureSubscriptionId) { + TokenCredential credential = new ClientSecretCredentialBuilder().tenantId(azureTenantId).clientId(azureClientId) + .clientSecret(azureClientSecret).build(); + AzureProfile profile = new AzureProfile(azureTenantId, azureSubscriptionId, AzureEnvironment.AZURE); + azureResourceManager = AzureResourceManager.configure().withLogLevel(HttpLogDetailLevel.BASIC) + .authenticate(credential, profile).withDefaultSubscription(); + } + + @Override + public ResourceGroup createResourceGroup(String resourcesPrefix) { + log.info("Creating resource group..."); + return azureResourceManager.resourceGroups().define(resourcesPrefix + "ResourceGroup") + .withRegion(Region.US_EAST).create(); + } + + @Override + public AvailabilitySet createAvailabilitySet(String resourcesPrefix) { + log.info("Creating availability set..."); + return azureResourceManager.availabilitySets().define(resourcesPrefix + "AvailabilitySet") + .withRegion(Region.US_EAST).withExistingResourceGroup(resourcesPrefix + "ResourceGroup").create(); + } + + @Override + public PublicIpAddress createPublicIpAddress(String resourcesPrefix) { + log.info("Creating public IP address..."); + return azureResourceManager.publicIpAddresses().define(resourcesPrefix + "PublicIP").withRegion(Region.US_EAST) + .withExistingResourceGroup(resourcesPrefix + "ResourceGroup").withDynamicIP().create(); + } + + @Override + public Network createNetwork(String resourcesPrefix) { + log.info("Creating virtual network..."); + return azureResourceManager.networks().define(resourcesPrefix + "VN").withRegion(Region.US_EAST) + .withExistingResourceGroup(resourcesPrefix + "ResourceGroup").withAddressSpace("10.0.0.0/16") + .withSubnet(resourcesPrefix + "Subnet", "10.0.0.0/24").create(); + } + + @Override + public NetworkInterface createNetworkInterface(String resourcesPrefix, Network network, + PublicIpAddress publicIPAddress) { + log.info("Creating network interface..."); + return azureResourceManager.networkInterfaces().define(resourcesPrefix + "NIC").withRegion(Region.US_EAST) + .withExistingResourceGroup(resourcesPrefix + "ResourceGroup").withExistingPrimaryNetwork(network) + .withSubnet(resourcesPrefix + "Subnet").withPrimaryPrivateIPAddressDynamic() + .withExistingPrimaryPublicIPAddress(publicIPAddress).create(); + } + + @Override + public VirtualMachine createVirtualMachine(String resourcesPrefix, NetworkInterface networkInterface, + AvailabilitySet availabilitySet, String userName, String sshKey) { + log.info("Creating virtual machine..."); + return azureResourceManager.virtualMachines().define(resourcesPrefix + "VM").withRegion(Region.US_EAST) + .withExistingResourceGroup(resourcesPrefix + "ResourceGroup") + .withExistingPrimaryNetworkInterface(networkInterface) + .withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_18_04_LTS).withRootUsername(userName) + .withSsh(sshKey).withComputerName(resourcesPrefix + "VM").withExistingAvailabilitySet(availabilitySet) + .withSize(VirtualMachineSizeTypes.STANDARD_D3_V2).create(); + } + +} diff --git a/prebuilt-tasks/src/test/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTaskTest.java b/prebuilt-tasks/src/test/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTaskTest.java new file mode 100644 index 000000000..34b794d8f --- /dev/null +++ b/prebuilt-tasks/src/test/java/com/redhat/parodos/tasks/azure/AzureCreateVirtualMachineTaskTest.java @@ -0,0 +1,154 @@ +package com.redhat.parodos.tasks.azure; + +import java.util.HashMap; + +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.VirtualMachine; +import com.azure.resourcemanager.network.models.Network; +import com.azure.resourcemanager.network.models.NetworkInterface; +import com.azure.resourcemanager.network.models.PublicIpAddress; +import com.azure.resourcemanager.resources.models.ResourceGroup; +import com.redhat.parodos.workflow.context.WorkContextDelegate; +import com.redhat.parodos.workflow.exception.MissingParameterException; +import com.redhat.parodos.workflows.work.WorkContext; +import com.redhat.parodos.workflows.work.WorkReport; +import com.redhat.parodos.workflows.work.WorkStatus; +import com.sun.jdi.InternalException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class AzureCreateVirtualMachineTaskTest { + + private static WorkContext ctx; + + private static AzureResourceClient azureResourceClient; + + // Define all Azure resources mocks + private static AzureCreateVirtualMachineTask underTest; + + private static ResourceGroup resourceGroup; + + private static AvailabilitySet availabilitySet; + + private static PublicIpAddress publicIPAddress; + + private static Network network; + + private static NetworkInterface networkInterface; + + private static VirtualMachine virtualMachine; + + private static final String[] requiredParamsKeys = { AzureCreateVirtualMachineTask.VM_USER_NAME_KEY, + AzureCreateVirtualMachineTask.VM_SSH_PUBLIC_KEY_KEY, AzureCreateVirtualMachineTask.AZURE_TENANT_ID_KEY, + AzureCreateVirtualMachineTask.AZURE_SUBSCRIPTION_ID_KEY, AzureCreateVirtualMachineTask.AZURE_CLIENT_ID_KEY, + AzureCreateVirtualMachineTask.AZURE_CLIENT_SECRET_KEY, + AzureCreateVirtualMachineTask.AZURE_RESOURCES_PREFIX_KEY }; + + private static final String resourcesPrefix = AzureCreateVirtualMachineTask.AZURE_RESOURCES_PREFIX_KEY + + "-testValue"; + + private static final String userName = AzureCreateVirtualMachineTask.VM_USER_NAME_KEY + "-testValue"; + + private static final String sshKey = AzureCreateVirtualMachineTask.VM_SSH_PUBLIC_KEY_KEY + "-testValue"; + + @BeforeEach + public void setUp() throws Exception { + // Initiate all Azure resources mocks + azureResourceClient = mock(AzureResourceClient.class); + resourceGroup = mock(ResourceGroup.class); + availabilitySet = mock(AvailabilitySet.class); + publicIPAddress = mock(PublicIpAddress.class); + network = mock(Network.class); + networkInterface = mock(NetworkInterface.class); + virtualMachine = mock(VirtualMachine.class); + + underTest = new AzureCreateVirtualMachineTask(azureResourceClient); + underTest.setBeanName("AzureCreateVirtualMachineTask"); + ctx = new WorkContext(); + + HashMap map = new HashMap<>(); + for (String paramKey : requiredParamsKeys) { + map.put(paramKey, paramKey + "-testValue"); + WorkContextDelegate.write(ctx, WorkContextDelegate.ProcessType.WORKFLOW_TASK_EXECUTION, underTest.getName(), + WorkContextDelegate.Resource.ARGUMENTS, map); + } + + when(azureResourceClient.createResourceGroup(resourcesPrefix)).thenReturn(resourceGroup); + when(azureResourceClient.createAvailabilitySet(resourcesPrefix)).thenReturn(availabilitySet); + when(azureResourceClient.createPublicIpAddress(resourcesPrefix)).thenReturn(publicIPAddress); + when(azureResourceClient.createNetwork(resourcesPrefix)).thenReturn(network); + when(azureResourceClient.createNetworkInterface(resourcesPrefix, network, publicIPAddress)) + .thenReturn(networkInterface); + when(azureResourceClient.createVirtualMachine(resourcesPrefix, networkInterface, availabilitySet, userName, + sshKey)).thenReturn(virtualMachine); + } + + @Test + public void testHappyFlow() { + // given + String publicIP = "11.11.11.11"; + when(virtualMachine.getPrimaryPublicIPAddress()).thenReturn(publicIPAddress); + when(publicIPAddress.ipAddress()).thenReturn(publicIP); + + // when + WorkReport result = underTest.execute(ctx); + + // then + verify(azureResourceClient, times(1)).createResourceGroup(resourcesPrefix); + verify(azureResourceClient, times(1)).createAvailabilitySet(resourcesPrefix); + verify(azureResourceClient, times(1)).createPublicIpAddress(resourcesPrefix); + verify(azureResourceClient, times(1)).createNetwork(resourcesPrefix); + verify(azureResourceClient, times(1)).createNetworkInterface(resourcesPrefix, network, publicIPAddress); + verify(azureResourceClient, times(1)).createVirtualMachine(resourcesPrefix, networkInterface, availabilitySet, + userName, sshKey); + + assertEquals(WorkStatus.COMPLETED, result.getStatus()); + assertEquals(publicIP, ctx.get("public-ip-address")); + + } + + @Test + public void testVmMissingPublicIPErr() { + // given + String publicIP = "11.11.11.11"; + when(virtualMachine.getPrimaryPublicIPAddress()).thenReturn(null); + + // when + WorkReport result = underTest.execute(ctx); + + // then + assertEquals(WorkStatus.FAILED, result.getStatus()); + assertEquals(InternalException.class, result.getError().getClass()); + assertEquals("The new created VirtualMachine missing public IP address", result.getError().getMessage()); + + } + + @Test + public void testMissingRequiredParamErr() { + // given + WorkContext ctx = new WorkContext(); + HashMap map = new HashMap<>(); + + for (String paramKey : requiredParamsKeys) { + // when + WorkReport result = underTest.execute(ctx); + + // then + assertEquals(WorkStatus.FAILED, result.getStatus()); + assertEquals(MissingParameterException.class, result.getError().getClass()); + assertEquals("missing parameter(s) for ParameterName: " + paramKey, result.getError().getMessage()); + + // Adding this key to the context for next for loop + map.put(paramKey, paramKey + "-testValue"); + WorkContextDelegate.write(ctx, WorkContextDelegate.ProcessType.WORKFLOW_TASK_EXECUTION, underTest.getName(), + WorkContextDelegate.Resource.ARGUMENTS, map); + } + } + +} diff --git a/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/AzureVirtualMachineWorkFlowConfiguration.java b/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/AzureVirtualMachineWorkFlowConfiguration.java new file mode 100644 index 000000000..e91228566 --- /dev/null +++ b/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/AzureVirtualMachineWorkFlowConfiguration.java @@ -0,0 +1,30 @@ +package com.redhat.parodos.examples.azure; + +import com.redhat.parodos.tasks.azure.AzureCreateVirtualMachineTask; +import com.redhat.parodos.workflow.annotation.Infrastructure; +import com.redhat.parodos.workflow.consts.WorkFlowConstants; +import com.redhat.parodos.workflows.workflow.SequentialFlow; +import com.redhat.parodos.workflows.workflow.WorkFlow; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AzureVirtualMachineWorkFlowConfiguration { + + @Bean + AzureCreateVirtualMachineTask azureCreateVirtualMachineTask() { + return new AzureCreateVirtualMachineTask(); + } + + @Bean(name = "azureVirtualMachineWorkFlow" + WorkFlowConstants.INFRASTRUCTURE_WORKFLOW) + @Infrastructure + WorkFlow azureVirtualMachineWorkFlow( + @Qualifier("azureCreateVirtualMachineTask") AzureCreateVirtualMachineTask azureCreateVirtualMachineTask) { + return SequentialFlow.Builder.aNewSequentialFlow() + .named("azureVirtualMachineWorkFlow" + WorkFlowConstants.INFRASTRUCTURE_WORKFLOW) + .execute(azureCreateVirtualMachineTask).build(); + } + +} diff --git a/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/README.md b/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/README.md new file mode 100644 index 000000000..6296ae052 --- /dev/null +++ b/workflow-examples/src/main/java/com/redhat/parodos/examples/azure/README.md @@ -0,0 +1,117 @@ +# Running AzureVirtualMachine WorkFlow Configuration instructions + +AzureVirtualMachineWorkFlow Configuration is an illustration of configuration utilizing the AzureVirtualMachineCreateVM Task. +Below are guidelines on executing this example workflow configuration using curl. + +## 1. Prerequisites + +* Have account in azure, at least contributor user is required (In this case, second step should be requested from Admin). +* You updated workflow-service running and accessible from your machine. + +## 2. Create App Registration in Azure account + +The workflow-service java application needs read and create permissions in your Azure subscription to run the AzureVirtualMachineCreateVM Task. Create a service principal, which its credentials would be used by the application. Service principals provide a way to create a noninteractive account associated with your identity to which you grant only the privileges your app needs to run. + +This step must be done by Admin user in Azure. +It can be done only ones, make sure it has the required expiration date. + +### Configure the environment variable + +- **`AZURE_SUBSCRIPTION_ID`**: Use the id value from `az account show` in the Azure CLI 2.0. + +### Create a service principal by using the Azure CLI 2.0, and capture the output + +```shell +az ad sp create-for-rbac \ +--name AzureJavaTest \ +--role Contributor \ +--scopes /subscriptions/${AZURE_SUBSCRIPTION_ID} +``` + +## 3. Execute the workflow using curl + +### Configure the environment variables + +- **`AZURE_SUBSCRIPTION_ID`**: Use the id value from `az account show` in the Azure CLI 2.0. +- **`AZURE_CLIENT_ID`**: Use the appId value from the output taken from a service principal output. +- **`AZURE_CLIENT_SECRET`**: Use the password value from the service principal output. +- **`AZURE_TENANT_ID`**: Use the tenant value from the service principal output. +- **`AZURE_RESOURCES_PREFIX`**: A designated prefix for naming all Azure resources +- **`VM_USER_NAME`**: The username for the Virtual Machine login +- **`VM_SSH_PUBLIC_KEY`**: The SSH public key for the Virtual Machine login +- **`PARODOS_PROJECT_ID`**: Parodos project ID + +### Execute the workflow + +```shell +curl -X 'POST' -u test:test \ + 'http://localhost:8080/api/v1/workflows' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "arguments": [], + "projectId": "'"${PARODOS_PROJECT_ID}"'", + "workFlowName": "azureVirtualMachineWorkFlow_INFRASTRUCTURE_WORKFLOW", + "works": [ + { + "arguments": [ + { + "key": "azure-tenant-id", + "value": "'"${AZURE_TENANT_ID}"'" + }, + { + "key": "azure-subscription-id", + "value": "'"${AZURE_SUBSCRIPTION_ID}"'" + }, + { + "key": "azure-client-id", + "value": "'"${AZURE_CLIENT_ID}"'" + }, + { + "key": "azure-client-secret", + "value": "'"${AZURE_CLIENT_SECRET}"'" + }, + { + "key": "azure-resources-prefix", + "value": "'"${AZURE_RESOURCES_PREFIX}"'" + }, + { + "key": "vm-user-name", + "value": "'"${VM_USER_NAME}"'" + }, + { + "key": "vm-ssh-public-key", + "value": "'"${VM_SSH_PUBLIC_KEY}"'" + } + ], + "type": "TASK", + "workName": "azureCreateVirtualMachineTask" + } + ] +}' +``` +## 4. Validate access to the VM + +### Configure the environment variables + +- **`VM_PUBLIC_IP`**: The public IP was assigned to the VM, you can find it in the workflow-service logs +- **`VM_USER_NAME`**: The username for the Virtual Machine login +- **`PRIVATE_SSH_KEY_PATH`**: The private ssh key which its public key was used for the VM creation in previous step + +### Access the VM using ssh + +```shell +ssh -i ${PRIVATE_SSH_KEY_PATH} ${VM_USER_NAME}@${VM_PUBLIC_IP} +``` +## 5. Delete all resources in Azure + +### Configure the environment variables + +- **`AZURE_RESOURCES_PREFIX`**: A designated prefix for naming all Azure resources + +### delete the VM + +```shell +az group delete -n "${AZURE_RESOURCES_PREFIX}ResourceGroup" +``` +