/// <summary> /// Substitutes the property tokens in the supplied string. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="input">The input string.</param> /// <returns>The substituted string</returns> public async Task<string> SubstituteTokensInString(RuntimeContext runtimeContext, TaskContext taskContext, string input) { string output = input; var matches = ImageRegex.Matches(input); if (matches.Count > 0) { foreach (Match match in matches) { string networkDomainId = match.Groups[1].Value; var publicIps = await ListAvailablePublicIps(runtimeContext.AccountDetails, networkDomainId); if (publicIps.Count == 0) { await AddPublicIpBlock(runtimeContext.AccountDetails, networkDomainId); publicIps = await ListAvailablePublicIps(runtimeContext.AccountDetails, networkDomainId); } if (publicIps.Count == 0) { throw new InvalidOperationException("Failed to find free public IP address."); } output = output.Replace(match.Groups[0].Value, publicIps[0]); } } return output; }
/// <summary> /// Substitutes the property tokens in the supplied string. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="input">The input string.</param> /// <returns>The substituted string</returns> public async Task<string> SubstituteTokensInString(RuntimeContext runtimeContext, TaskContext taskContext, string input) { return await Task.Run(() => { return SubstituteTokensInString(input, taskContext.Parameters, true); }); }
/// <summary> /// Runs the orchestration. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="orchestrationObject">The orchestration object.</param> /// <param name="resources">The resources.</param> /// <returns>The async <see cref="Task"/>.</returns> public async Task RunOrchestration(RuntimeContext runtimeContext, TaskContext taskContext, JObject orchestrationObject, IEnumerable<Resource> resources) { _logProvider = runtimeContext.LogProvider; _docsApiClient = new DocsApiClient(orchestrationObject["docsServiceUrl"].Value<string>()); _orchestratorClient = new OrchestratorApiClient(orchestrationObject["orchestratorServiceUrl"].Value<string>()); await Macro.SubstituteTokensInJObject(runtimeContext, taskContext, orchestrationObject); await SendConfiguration((JArray)orchestrationObject["configuration"]); await SendEnvironment((JObject)orchestrationObject["environment"], resources, taskContext.ResourcesProperties); LaunchRunbook(orchestrationObject["runbook"].Value<string>()); }
/// <summary> /// Begins the processing asynchronously. /// </summary> /// <returns>The async <see cref="Task"/>.</returns> private async Task BeginProcessingAsync() { var runtimeContext = new RuntimeContext { AccountDetails = await CaasAuthentication.Authenticate(UserName, Password, Region), LogProvider = new ConsoleLogProvider() }; var taskBuilder = new TaskBuilder(); var taskExecutor = taskBuilder.BuildTasksFromDeploymentLog(ResolvePath(DeploymentLog)); var log = await taskExecutor.Execute(runtimeContext); Console.WriteLine($"Result: {log.Status}"); }
/// <summary> /// Executes the task. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <returns>The async <see cref="Task"/>.</returns> public async Task Execute(RuntimeContext runtimeContext, TaskContext taskContext) { await Macro.SubstituteTokensInJObject(runtimeContext, taskContext, Resource.ResourceDefinition); var deployer = new ResourceDeployer(runtimeContext, Resource.ResourceId, Resource.ResourceType); var resourceLog = await deployer.DeployAndWait(Resource.ResourceDefinition); taskContext.Log.Resources.Add(resourceLog); taskContext.ResourcesProperties.Add(resourceLog.ResourceId, resourceLog.Details); if (resourceLog.DeploymentStatus == ResourceLogStatus.Failed) { taskContext.Log.Status = DeploymentLogStatus.Failed; } }
/// <summary> /// Executes the task. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <returns>The async <see cref="Task"/>.</returns> public async Task Execute(RuntimeContext runtimeContext, TaskContext taskContext) { if (ExistingResources == null) { return; } foreach (var existingResource in ExistingResources) { existingResource.ExistingCaasId = await Macro.SubstituteTokensInString(runtimeContext, taskContext, existingResource.ExistingCaasId); var deployer = new ResourceDeployer(runtimeContext, existingResource.ResourceId, existingResource.ResourceType); var resource = await deployer.Get(existingResource.ExistingCaasId); taskContext.ResourcesProperties.Add(existingResource.ResourceId, resource); } }
/// <summary> /// Executes the task. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <returns>The async <see cref="Task"/>.</returns> public async Task Execute(RuntimeContext runtimeContext, TaskContext taskContext) { if (ResourceLog.CaasId != null) { var deployer = new ResourceDeployer(runtimeContext, ResourceLog.ResourceId, ResourceLog.ResourceType); var resourceLog = await deployer.DeleteAndWait(ResourceLog.CaasId); taskContext.Log.Resources.Add(resourceLog); if (resourceLog.DeploymentStatus == ResourceLogStatus.Failed) { taskContext.Log.Status = DeploymentLogStatus.Failed; } } }
/// <summary> /// Executes the task. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <returns>The async <see cref="Task"/>.</returns> public async Task Execute(RuntimeContext runtimeContext, TaskContext taskContext) { var providerTypeName = Orchestration["provider"].Value<String>(); var providerType = Type.GetType(providerTypeName); if (providerType == null) { runtimeContext.LogProvider.LogError($"Unable to create Orchestration Provider of type {providerTypeName}."); return; } var provider = (IOrchestrationProvider)Activator.CreateInstance(providerType); runtimeContext.LogProvider.LogMessage($"Running Orchestration Provider '{providerTypeName}'."); await provider.RunOrchestration(runtimeContext, taskContext, Orchestration, Resources); }
/// <summary> /// Substitutes the property tokens in the supplied string. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="input">The input string.</param> /// <returns>The substituted string</returns> public static async Task<string> SubstituteTokensInString(RuntimeContext runtimeContext, TaskContext taskContext, string input) { var value = input; if (string.IsNullOrEmpty(value)) { return value; } foreach (var macro in Macros) { value = await macro.SubstituteTokensInString(runtimeContext, taskContext, value); } return value; }
/// <summary> /// Substitutes the property tokens in the supplied string. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="input">The input string.</param> /// <returns>The substituted string</returns> public async Task<string> SubstituteTokensInString(RuntimeContext runtimeContext, TaskContext taskContext, string input) { string output = input; var matches = ImageRegex.Matches(input); if (matches.Count > 0) { foreach (Match match in matches) { string imageType = match.Groups[1].Value; string location = match.Groups[2].Value; string imageName = match.Groups[3].Value; using (var client = HttpClientFactory.GetClient(runtimeContext.AccountDetails, "text/xml")) { var url = (imageType == "customerImage") ? string.Format(ImageUrl, runtimeContext.AccountDetails.OrgId, imageName) : string.Format(ImageUrl, "base", imageName); var response = await client.GetAsync(runtimeContext.AccountDetails.BaseUrl + url); response.ThrowForHttpFailure(); var responseBody = await response.Content.ReadAsStringAsync(); var document = XDocument.Parse(responseBody); var imageId = document.Root .Elements(ServerNamespace + "image") .Where(e => e.Attribute("location").Value == location) .Select(e => e.Attribute("id").Value) .FirstOrDefault(); if (imageId == null) { throw new TemplateParserException($"Image '{imageName}' not found in datacenter '{location}'."); } output = output.Replace(match.Groups[0].Value, imageId); } } } return output; }
/// <summary> /// Substitutes the tokens in supplied JSON object. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="resourceDefinition">The resource definition.</param> /// <returns>The async <see cref="Task"/>.</returns> public static async Task SubstituteTokensInJObject(RuntimeContext runtimeContext, TaskContext taskContext, JObject resourceDefinition) { foreach (var parameter in resourceDefinition) { if (parameter.Value is JObject) { await SubstituteTokensInJObject(runtimeContext, taskContext, (JObject)parameter.Value); } else if (parameter.Value is JValue) { var value = parameter.Value.Value<string>(); value = await SubstituteTokensInString(runtimeContext, taskContext, value); if (value == string.Empty) { parameter.Value.Replace(null); } else { parameter.Value.Replace(new JValue(value)); } } else if (parameter.Value is JArray) { foreach (var jtoken in ((JArray)parameter.Value)) { if (jtoken is JObject) { await SubstituteTokensInJObject(runtimeContext, taskContext, (JObject)jtoken); } else { var value = jtoken.Value<string>(); value = await SubstituteTokensInString(runtimeContext, taskContext, value); ((JValue)jtoken).Replace(new JValue(value)); } } } } }
/// <summary> /// Substitutes the property tokens in the supplied string. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <param name="input">The input string.</param> /// <returns>The substituted string</returns> public async Task<string> SubstituteTokensInString(RuntimeContext runtimeContext, TaskContext taskContext, string input) { return await Task.Run(() => { string output = input; if (taskContext.ResourcesProperties != null) { MatchCollection resourceMatches = ResourcePropertyRegex.Matches(output); while (resourceMatches.Count > 0) { Match resourceMatch = resourceMatches[resourceMatches.Count - 1]; string resourceId = resourceMatch.Groups[1].Value; string property = resourceMatch.Groups[2].Value; JObject resource; if (!taskContext.ResourcesProperties.TryGetValue(resourceId, out resource)) { throw new TemplateParserException($"Referenced resource '{resourceId}' not found."); } var newValue = resource.SelectToken(property).Value<string>(); if (MacroUtilities.IsNested(output, resourceMatch)) { newValue = "'" + newValue + "'"; } output = output.Replace(resourceMatch.Groups[0].Value, newValue); resourceMatches = ResourcePropertyRegex.Matches(output); } } return output; }); }
/// <summary> /// Initializes a new instance of the <see cref="ResourceDeployer"/> class. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="resourceId">The resource identifier.</param> /// <param name="resourceType">Type of the resource.</param> public ResourceDeployer(RuntimeContext runtimeContext, string resourceId, ResourceType resourceType) { _resourceId = resourceId; _resourceType = resourceType; _resourceApi = ResourceApis[resourceType]; _accountDetails = runtimeContext.AccountDetails; _logProvider = runtimeContext.LogProvider; }
/// <summary> /// Performs the request. /// </summary> /// <param name="arguments">The arguments.</param> /// <returns>The async <see cref="Task"/>.</returns> private static async Task PerformRequest(Dictionary<string, string> arguments) { try { var accountDetails = await CaasAuthentication.Authenticate( arguments["username"], arguments["password"], arguments["region"]); var runtimeContext = new RuntimeContext { AccountDetails = accountDetails, LogProvider = new ConsoleLogProvider() }; var taskBuilder = new TaskBuilder(); if (arguments["action"].ToLower() == "deploy") { var parametersFile = arguments.ContainsKey("parameters") ? arguments["parameters"] : null; var templateFile = arguments["template"]; var taskExecutor = taskBuilder.BuildTasksFromDeploymentTemplate(templateFile, parametersFile); var log = await taskExecutor.Execute(runtimeContext); Console.WriteLine($"Result: {log.Status}"); log.SaveToFile(arguments["deploymentlog"]); Console.WriteLine($"Complete! Deployment log written to {arguments["deploymentlog"]}."); if (taskExecutor.Context.OutputParameters != null) { Console.WriteLine("OUTPUT PARAMETERS:"); foreach (var param in taskExecutor.Context.OutputParameters) { Console.WriteLine($"{param.Key}: {param.Value}"); } } } else if (arguments["action"].ToLower() == "delete") { var deploymentLogFile = arguments["deploymentlog"]; var taskExecutor = taskBuilder.BuildTasksFromDeploymentLog(deploymentLogFile); var log = await taskExecutor.Execute(runtimeContext); Console.WriteLine($"Result: {log.Status}"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Executes the task. /// </summary> /// <param name="runtimeContext">The runtime context.</param> /// <param name="taskContext">The task execution context.</param> /// <returns>The async <see cref="Task"/>.</returns> public Task Execute(RuntimeContext runtimeContext, TaskContext taskContext) { throw new NotSupportedException("Post-Deploy script not supported."); }
/// <summary> /// Begins the processing asynchronously. /// </summary> /// <returns>The async <see cref="Task"/>.</returns> private async Task BeginProcessingAsync() { var runtimeContext = new RuntimeContext { AccountDetails = await CaasAuthentication.Authenticate(UserName, Password, Region), LogProvider = new ConsoleLogProvider() }; var taskBuilder = new TaskBuilder(); var taskExecutor = taskBuilder.BuildTasksFromDeploymentTemplate(ResolvePath(Template), ResolvePath(Parameters)); var log = await taskExecutor.Execute(runtimeContext); Console.WriteLine($"Result: {log.Status}"); WriteLog(log, ResolvePath(DeploymentLog)); Console.WriteLine($"Complete! Deployment log written to {DeploymentLog}."); if (taskExecutor.Context.OutputParameters != null) { Console.WriteLine("OUTPUT PARAMETERS:"); foreach (var param in taskExecutor.Context.OutputParameters) { Console.WriteLine($"{param.Key}: {param.Value}"); } } }