2021-08-25 12:40:32 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Text ;
using System.Text.Json ;
2021-12-10 15:36:47 -05:00
using System.Threading.Tasks ;
2021-08-25 12:40:32 -04:00
using System.Xml ;
2024-05-22 13:17:22 -04:00
using EpicGames.Core ;
2023-03-07 21:23:47 -05:00
using Microsoft.Extensions.Logging ;
2024-05-22 13:17:22 -04:00
using UnrealBuildBase ;
2021-08-25 12:40:32 -04:00
2021-12-10 16:56:09 -05:00
namespace AutomationTool.Tasks
2021-08-25 12:40:32 -04:00
{
/// <summary>
/// Parameters for a AWS ECS deploy task
/// </summary>
public class AwsEcsDeployTaskParameters
{
/// <summary>
/// Task definition file to use
/// </summary>
[TaskParameter(Optional = false)]
2024-05-21 20:54:09 -04:00
public string TaskDefinitionFile { get ; set ; }
2021-08-25 12:40:32 -04:00
/// <summary>
2021-09-02 05:15:26 -04:00
/// Docker image to set in new task definition (will replace %%DOCKER_PATTERN%% with this value)
2021-08-25 12:40:32 -04:00
/// </summary>
[TaskParameter(Optional = false)]
2024-05-21 20:54:09 -04:00
public string DockerImage { get ; set ; }
2021-08-25 12:40:32 -04:00
2021-09-02 05:15:26 -04:00
/// <summary>
/// App version to set in new task definition (will replace %%VERSION%% with this value)
/// </summary>
[TaskParameter(Optional = true)]
2024-05-21 20:54:09 -04:00
public string Version { get ; set ; }
2021-09-02 05:15:26 -04:00
2021-08-25 12:40:32 -04:00
/// <summary>
/// Cluster ARN representing AWS ECS cluster to operate on
/// </summary>
[TaskParameter(Optional = false)]
2024-05-21 20:54:09 -04:00
public string Cluster { get ; set ; }
2021-08-25 12:40:32 -04:00
/// <summary>
/// Service name to update and deploy to
/// </summary>
[TaskParameter(Optional = false)]
2024-05-21 20:54:09 -04:00
public string Service { get ; set ; }
2021-08-25 12:40:32 -04:00
/// <summary>
/// Environment variables
/// </summary>
[TaskParameter(Optional = true)]
2024-05-21 20:54:09 -04:00
public string Environment { get ; set ; }
2021-08-25 12:40:32 -04:00
/// <summary>
/// File to read environment from
/// </summary>
[TaskParameter(Optional = true)]
2024-05-21 20:54:09 -04:00
public string EnvironmentFile { get ; set ; }
2021-08-25 12:40:32 -04:00
/// <summary>
/// Write output to the log
/// </summary>
[TaskParameter(Optional = true)]
2024-05-21 20:54:09 -04:00
public bool LogOutput { get ; set ; } = false ;
2021-08-25 12:40:32 -04:00
}
/// <summary>
/// Creates a new AWS ECS task definition and updates the ECS service to use this new revision of the task def
/// </summary>
[TaskElement("Aws-EcsDeploy", typeof(AwsEcsDeployTaskParameters))]
public class AwsEcsDeployTask : SpawnTaskBase
{
/// <summary>
/// Parameters for this task
/// </summary>
2024-05-22 13:17:22 -04:00
readonly AwsEcsDeployTaskParameters _parameters ;
2021-08-25 12:40:32 -04:00
/// <summary>
/// Construct an AWS ECS deploy task
/// </summary>
2024-05-22 13:17:22 -04:00
/// <param name="parameters">Parameters for the task</param>
public AwsEcsDeployTask ( AwsEcsDeployTaskParameters parameters )
2021-08-25 12:40:32 -04:00
{
2024-05-22 13:17:22 -04:00
_parameters = parameters ;
2021-08-25 12:40:32 -04:00
}
/// <summary>
2024-05-22 13:17:22 -04:00
/// ExecuteAsync the task.
2021-08-25 12:40:32 -04:00
/// </summary>
2024-05-22 13:17:22 -04:00
/// <param name="job">Information about the current job</param>
/// <param name="buildProducts">Set of build products produced by this node.</param>
/// <param name="tagNameToFileSet">Mapping from tag names to the set of files they include</param>
public override async Task ExecuteAsync ( JobContext job , HashSet < FileReference > buildProducts , Dictionary < string , HashSet < FileReference > > tagNameToFileSet )
2021-08-25 12:40:32 -04:00
{
2024-05-22 13:17:22 -04:00
string taskDefTemplate = await File . ReadAllTextAsync ( ResolveFile ( _parameters . TaskDefinitionFile ) . FullName ) ;
string taskDefRendered = taskDefTemplate . Replace ( "%%DOCKER_IMAGE%%" , _parameters . DockerImage , StringComparison . Ordinal ) ;
if ( _parameters . Version ! = null )
2021-09-02 05:15:26 -04:00
{
2024-05-22 13:17:22 -04:00
taskDefRendered = taskDefRendered . Replace ( "%%VERSION%%" , _parameters . Version , StringComparison . Ordinal ) ;
2021-09-02 05:15:26 -04:00
}
2021-08-25 12:40:32 -04:00
2024-05-22 13:17:22 -04:00
FileReference tempTaskDefFile = FileReference . Combine ( Unreal . RootDirectory , "Engine" , "Intermediate" , "Build" , "AwsEcsDeployTaskTemp.json" ) ;
DirectoryReference . CreateDirectory ( tempTaskDefFile . Directory ) ;
await File . WriteAllTextAsync ( tempTaskDefFile . FullName , taskDefRendered , new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false ) ) ;
2021-08-25 12:40:32 -04:00
2024-05-22 13:17:22 -04:00
IProcessResult createTaskDefResult = await SpawnTaskBase . ExecuteAsync ( "aws" , $"ecs register-task-definition --cli-input-json \" file : //{tempTaskDefFile.FullName}\"", envVars: ParseEnvVars(_parameters.Environment, _parameters.EnvironmentFile), logOutput: _parameters.LogOutput);
2021-08-25 12:40:32 -04:00
2024-05-22 13:17:22 -04:00
JsonDocument taskDefJson = JsonDocument . Parse ( createTaskDefResult . Output ) ;
string taskDefFamily = taskDefJson . RootElement . GetProperty ( "taskDefinition" ) . GetProperty ( "family" ) . GetString ( ) ;
string taskDefRevision = taskDefJson . RootElement . GetProperty ( "taskDefinition" ) . GetProperty ( "revision" ) . ToString ( ) ;
2021-08-25 12:40:32 -04:00
2024-05-22 13:17:22 -04:00
string @params = $"ecs update-service --cluster {_parameters.Cluster} --service {_parameters.Service} --task-definition {taskDefFamily}:{taskDefRevision}" ;
await SpawnTaskBase . ExecuteAsync ( "aws" , @params , envVars : ParseEnvVars ( _parameters . Environment , _parameters . EnvironmentFile ) , logOutput : _parameters . LogOutput ) ;
Logger . LogInformation ( "Service {Service} updated to use new task def {TaskDefFamily}:{TaskDefRevision}" , _parameters . Service , taskDefFamily , taskDefRevision ) ;
2021-08-25 12:40:32 -04:00
}
/// <summary>
/// Output this task out to an XML writer.
/// </summary>
2024-05-22 13:17:22 -04:00
public override void Write ( XmlWriter writer )
2021-08-25 12:40:32 -04:00
{
2024-05-22 13:17:22 -04:00
Write ( writer , _parameters ) ;
2021-08-25 12:40:32 -04:00
}
/// <summary>
/// Find all the tags which are used as inputs to this task
/// </summary>
/// <returns>The tag names which are read by this task</returns>
public override IEnumerable < string > FindConsumedTagNames ( )
{
yield break ;
}
/// <summary>
/// Find all the tags which are modified by this task
/// </summary>
/// <returns>The tag names which are modified by this task</returns>
public override IEnumerable < string > FindProducedTagNames ( )
{
yield break ;
}
}
}