diff --git a/.github/workflows/DetectDocGeneratorChanges.yml b/.github/workflows/DetectDocGeneratorChanges.yml new file mode 100644 index 000000000..9382ddd56 --- /dev/null +++ b/.github/workflows/DetectDocGeneratorChanges.yml @@ -0,0 +1,52 @@ +name: Detect Doc Generator Changes + +on: [pull_request] + +permissions: + id-token: write + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }} + role-duration-seconds: 7200 + aws-region: us-west-2 + - uses: actions/checkout@v2 + with: + fetch-depth: '0' + - name: Setup .NET Core 6.0 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Run Client Generator + run: | + cd ./src/AWS.Deploy.DocGenerator + dotnet run --project ./AWS.Deploy.DocGenerator.csproj + - name: Check For Git Untracked Changes + id: gitcheck + shell: pwsh + run: | + $newFiles=$(git ls-files --others --exclude-standard | wc -l) + $modifiedFiles=$(git diff --name-only | wc -l) + "newFiles=$newFiles" >> $env:GITHUB_OUTPUT + "modifiedFiles=$modifiedFiles" >> $env:GITHUB_OUTPUT + - name: Fail If New Files Detected + if: steps.gitcheck.outputs.newFiles != 0 + run: | + echo "New files have been generated after running 'AWS.Deploy.DocGenerator'. Make sure to add the new files to your working branch." + exit 1 + - name: Fail If Modified Files Detected + if: steps.gitcheck.outputs.modifiedFiles != 0 + run: | + echo "Updated files have been generated after running 'AWS.Deploy.DocGenerator'. Make sure to commit the updated files to your working branch." + exit 1 \ No newline at end of file diff --git a/.github/workflows/doc-builder.yml b/.github/workflows/doc-builder.yml index 6ef8917ad..37a48550f 100644 --- a/.github/workflows/doc-builder.yml +++ b/.github/workflows/doc-builder.yml @@ -6,14 +6,46 @@ on: # Allow the workflow to be triggered also manually. workflow_dispatch: + +permissions: + id-token: write + contents: write jobs: deploy: runs-on: ubuntu-latest steps: + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }} + aws-region: us-west-2 - uses: actions/checkout@v2 + with: + fetch-depth: '0' - uses: actions/setup-python@v2 with: python-version: 3.x + - name: Setup .NET Core 6.0 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x - run: pip install mkdocs-material==8.2.9 + - run: pip install mkdocs-awesome-pages-plugin==2.8.0 + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Run Client Generator + run: | + cd ./src/AWS.Deploy.DocGenerator + dotnet run --project ./AWS.Deploy.DocGenerator.csproj + - name: Commit and Push next version + id: commit-push + run: | + git config --global user.email "github-aws-sdk-dotnet-automation@amazon.com" + git config --global user.name "aws-sdk-dotnet-automation" + git add site/ + git commit -m "Update documentation generated by AWS.Deploy.DocGenerator" + git push - run: mkdocs gh-deploy --force \ No newline at end of file diff --git a/AWS.Deploy.sln b/AWS.Deploy.sln index b5be2de78..d8f591869 100644 --- a/AWS.Deploy.sln +++ b/AWS.Deploy.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32126.317 MinimumVisualStudioVersion = 10.0.40219.1 @@ -68,6 +68,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiNET6", "testapps\WebA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWasm60", "testapps\BlazorWasm60\BlazorWasm60.csproj", "{CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AWS.Deploy.DocGenerator", "src\AWS.Deploy.DocGenerator\AWS.Deploy.DocGenerator.csproj", "{6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Deploy.DocGenerator.UnitTests", "test\AWS.Deploy.DocGenerator.UnitTests\AWS.Deploy.DocGenerator.UnitTests.csproj", "{7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -166,6 +170,14 @@ Global {CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E}.Debug|Any CPU.Build.0 = Debug|Any CPU {CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E}.Release|Any CPU.ActiveCfg = Release|Any CPU {CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E}.Release|Any CPU.Build.0 = Release|Any CPU + {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84}.Release|Any CPU.Build.0 = Release|Any CPU + {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -196,6 +208,8 @@ Global {7C330493-9BF7-4DB6-815B-807C08500AC6} = {C3A0C716-BDEA-4393-B223-AF8F8531522A} {B2EA65BD-9FFE-4452-B2DC-574EB1A9FAF1} = {C3A0C716-BDEA-4393-B223-AF8F8531522A} {CEEBEC39-40E5-4A9B-878A-6EDB52B9B43E} = {C3A0C716-BDEA-4393-B223-AF8F8531522A} + {6D4BD0C2-C2A0-4AFB-BC22-623DD64A4F84} = {11C7056E-93C1-408B-BD87-5270595BBE0E} + {7E661545-7DFD-4FE3-A5F9-767FAE30DFFE} = {BD466B5C-D8B0-4069-98A9-6DC8F01FA757} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5A4B2863-1763-4496-B122-651A38A4F5D7} diff --git a/mkdocs.yml b/mkdocs.yml index c6e15ceee..d260a0156 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -31,7 +31,11 @@ nav: - Overview: docs/deployment-projects/index.md - Recipe File: docs/deployment-projects/recipe-file.md - CDK Project: docs/deployment-projects/cdk-project.md - - Integrating with CI/CD: docs/cicd.md + - Integrating with CI/CD: + - Overview: docs/cicd/cicd.md + - Deployment Settings File: docs/cicd/deployment-settings-file.md + - Deployment Recipes: + - ... | flat - Tutorials: - Customizing deployment projects: tutorials/custom-project.md - Troubleshooting Guide: @@ -58,3 +62,7 @@ theme: markdown_extensions: - pymdownx.emoji: emoji_index: !!python/name:materialx.emoji.twemoji + +plugins: + - search + - awesome-pages \ No newline at end of file diff --git a/site/content/docs/cicd.md b/site/content/docs/cicd/cicd.md similarity index 92% rename from site/content/docs/cicd.md rename to site/content/docs/cicd/cicd.md index 94e45b84f..c706458f4 100644 --- a/site/content/docs/cicd.md +++ b/site/content/docs/cicd/cicd.md @@ -1,6 +1,6 @@ # Integrating with CI/CD -You can use AWS Deploy Tool when developing your app using any Continuous Deployment system. Continuous Deployment systems let you automatically build, test and deploy your application each time you check in updates to your source code. Before you can use AWS Deploy Tool in your CD pipeline, you must have [required pre-requisites](../docs/getting-started/pre-requisites.md) installed and configured in the CD environment. +You can use AWS Deploy Tool when developing your app using any Continuous Deployment system. Continuous Deployment systems let you automatically build, test and deploy your application each time you check in updates to your source code. Before you can use AWS Deploy Tool in your CD pipeline, you must have [required pre-requisites](../../docs/getting-started/pre-requisites.md) installed and configured in the CD environment. ### Suppressing prompts with `--silent` @@ -49,10 +49,10 @@ This will create a JSON file at `MyWebApplication/MyWebApplication/deploymentset ```json { - "AWSProfile": + "AWSProfile": , "AWSRegion": , "ApplicationName": , - "RecipeId": + "RecipeId": , "Settings": } ``` @@ -67,6 +67,8 @@ This will create a JSON file at `MyWebApplication/MyWebApplication/deploymentset * _**Settings**_: This is a JSON blob that stores the values of all available settings that can be tweaked to adjust the deployment configuration. +For more info on how to create your own `Deployment settings file`, go to [Creating a deployment settings file](deployment-settings-file.md) + ### Invoking from CI/CD The `--apply` switch on the deploy command allows you to specify a deployment settings file. diff --git a/site/content/docs/cicd/deployment-settings-file.md b/site/content/docs/cicd/deployment-settings-file.md new file mode 100644 index 000000000..728d8ea85 --- /dev/null +++ b/site/content/docs/cicd/deployment-settings-file.md @@ -0,0 +1,93 @@ +# Creating a deployment settings file + +### What is a deployment settings file + +A deployment settings file allows you to define the deployment settings of your application in a _JSON_ format. This JSON file can be version controlled and plugged into your CI/CD system for future deployments. + +Deployment settings files could be used as a way to automate your deployments or use them in a [CI/CD setting](./cicd.md) where you would define all the settings that you need to apply for your deployment and then use the `--apply` flag on the CLI to link to the deployment setting file. + +By doing this, the AWS .NET deployment tool reads all the settings you have defined and applies them to the deployment. You will need to do a final confirmation to initiate the deployment in the CLI. However, you can bypass the confirmation by making the deployment a silent one. This can be done by adding the `--silent` flag which will turn off any prompts. + +The deployment settings file has the following structure: + +```json +{ + "AWSProfile": , + "AWSRegion": , + "ApplicationName": , + "RecipeId": , + "Settings": +} +``` + +* _**AWSProfile**_: The name of the AWS profile that will be used during deployment. + +* _**AWSRegion**_: The name of the AWS region where the deployed application is hosted. + +* _**ApplicationName**_: The name that is used to identify your cloud application within AWS. If the application is deployed via AWS CDK, then this name points to the CloudFormation stack. + +* _**RecipeId**_: The recipe identifier that will be used to deploy your application to AWS. + +* _**Settings**_: This is a JSON blob that stores the values of all available settings that can be tweaked to adjust the deployment configuration. This is represented as a _JSON_ object that contains the deployment setting IDs and values as a key/pair configuration. + +*Note:* _**AWSProfile, AWSRegion and ApplicationName**_ are optional and can be overriden by using the appropriate command line switches. This enables users to craft a *deployment settings file* that could be used for multiple AWS profiles and regions. + +An example of overriding _**AWSProfile, AWSRegion and ApplicationName**_ in the CLI: +``` +dotnet aws deploy --application-name WebApp1 --profile default --region us-west-2 +``` + +Each recipe has its own set of settings that can be configured. The following pages in this section list the settings for each recipe that can be used to fill in the `Settings` section of the file. + +### Example of a deployment settings file + +An example of what a deployment settings file would look like: +```json +{ + "AWSProfile": "default", + "AWSRegion": "us-west-2", + "ApplicationName": "WebApp1", + "RecipeId": "AspNetAppEcsFargate", + "Settings": { + "ECSCluster": { + "CreateNew": true, + "NewClusterName": "WebApp1-Cluster" + }, + "ECSServiceName": "WebApp1-service", + "DesiredCount": 3, + "ApplicationIAMRole": { + "CreateNew": true + } + } +} +``` +Settings that contain child settings under them are represented as another _JSON_ object similar to the example provided above. + +### How to create a deployment settings file + +1. Create a new `JSON` file. +2. Add the 3 properties _**AWSProfile, AWSRegion and ApplicationName**_. These are generic and not tied to a specific *Recipe* file. +> _**AWSProfile**_: The name of the AWS profile that will be used during deployment. +> _**AWSRegion**_: The name of the AWS region where the deployed application is hosted. +> _**ApplicationName**_: The name that is used to identify your cloud application within AWS. If the application is deployed via AWS CDK, then this name points to the CloudFormation stack. +3. Pick a *Recipe* from the **Deployment Recipes** section in the navigation to use for your deployment. A Recipe defines the .NET application type and the AWS compute to deploy it to. For example [ASP.NET Core App to Amazon ECS using AWS Fargate](./recipes/ASP.NET%20Core%20App%20to%20Amazon%20ECS%20using%20AWS%20Fargate.md). +4. Add a _**Settings**_ object to define deployment settings. +5. To set the `ECS Service Name`, get the ID from the *Recipe* which is `ECSServiceName`. The value needs to be the same type as the `Type` of setting. `ECS Service Name` has a type `String`, so give it a value `WebApp1-service`. +6. To set `ECS Cluster`, the ID is `ECSCluster` and the setting has a type `Object`. The value of `Object` types is another JSON blob representing the setting ID and value of the `Object's children settings`. To set the 2 children settings `Create New ECS Cluster` and `New Cluster Name`, use the IDs `CreateNew` and `NewClusterName` respectively. `Create New ECS Cluster` has a type `Bool` so we can set `true` or `false`, and `New Cluster Name` is a `String`. The deployment settings file will look like this: +```json +{ + "AWSProfile": "default", + "AWSRegion": "us-west-2", + "ApplicationName": "WebApp1", + "RecipeId": "AspNetAppEcsFargate", + "Settings": { + "ECSCluster": { + "CreateNew": true, + "NewClusterName": "WebApp1-Cluster" + }, + "ECSServiceName": "WebApp1-service" + } +} +``` + +Keep adding more settings by using the *Recipe* you selected as reference and be mindful of the type of setting you are setting. \ No newline at end of file diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to AWS App Runner.md b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS App Runner.md new file mode 100644 index 000000000..18308b24b --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS App Runner.md @@ -0,0 +1,133 @@ +**Recipe ID:** AspNetAppAppRunner + +**Recipe Description:** This ASP.NET Core application will be built as a container image on Linux and deployed to AWS App Runner, a fully managed service for web applications and APIs. If your project does not contain a Dockerfile, it will be automatically generated, otherwise an existing Dockerfile will be used. Recommended if you want to deploy your web application as a Linux container image on a fully managed environment. + +**Settings:** + +* **Service Name** + * ID: ServiceName + * Description: The name of the AWS App Runner service. + * Type: String +* **Port** + * ID: Port + * Description: The port the container is listening for requests on. + * Type: Int +* **Start Command** + * ID: StartCommand + * Description: Override the start command from the image's default start command. + * Type: String +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Service Access IAM Role** + * ID: ServiceAccessIAMRole + * Description: The Identity and Access Management (IAM) role that provides gives the AWS App Runner service access to pull the container image from ECR. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **CPU** + * ID: Cpu + * Description: The number of CPU units reserved for each instance of your App Runner service. + * Type: String +* **Memory** + * ID: Memory + * Description: The amount of memory reserved for each instance of your App Runner service. + * Type: String +* **Encryption KMS Key** + * ID: EncryptionKmsKey + * Description: The ARN of the KMS key that's used for encryption of application logs. + * Type: String +* **Health Check Protocol** + * ID: HealthCheckProtocol + * Description: The IP protocol that App Runner uses to perform health checks for your service. + * Type: String +* **Health Check Path** + * ID: HealthCheckPath + * Description: The URL that health check requests are sent to. + * Type: String +* **Health Check Interval** + * ID: HealthCheckInterval + * Description: The time interval, in seconds, between health checks. + * Type: Int +* **Health Check Timeout** + * ID: HealthCheckTimeout + * Description: The time, in seconds, to wait for a health check response before deciding it failed. + * Type: Int +* **Health Check Healthy Threshold** + * ID: HealthCheckHealthyThreshold + * Description: The number of consecutive checks that must succeed before App Runner decides that the service is healthy. + * Type: Int +* **Health Check Unhealthy Threshold** + * ID: HealthCheckUnhealthyThreshold + * Description: The number of consecutive checks that must fail before App Runner decides that the service is unhealthy. + * Type: Int +* **VPC Connector** + * ID: VPCConnector + * Description: App Runner requires this resource when you want to associate your App Runner service to a custom Amazon Virtual Private Cloud (Amazon VPC). + * Type: Object + * Settings: + * **Use VPC Connector** + * ID: UseVPCConnector + * Description: Do you want to use a VPC Connector to connect to a VPC? + * Type: Bool + * **Create New VPC Connector** + * ID: CreateNew + * Description: Do you want to create a new VPC Connector? + * Type: Bool + * **Existing VPC Connector ID** + * ID: VpcConnectorId + * Description: The ID of the existing VPC Connector to use. + * Type: String + * **Create New VPC** + * ID: CreateNewVpc + * Description: Do you want to create a new VPC to use for the VPC Connector? + * Type: Bool + * **VPC ID** + * ID: VpcId + * Description: A list of VPC IDs that App Runner should use when it associates your service with a custom Amazon VPC. + * Type: String + * **Subnets** + * ID: Subnets + * Description: A list of IDs of subnets that App Runner should use when it associates your service with a custom Amazon VPC. Specify IDs of subnets of a single Amazon VPC. App Runner determines the Amazon VPC from the subnets you specify. + * Type: List + * **Security Groups** + * ID: SecurityGroups + * Description: A list of IDs of security groups that App Runner should use for access to AWS resources under the specified subnets. If not specified, App Runner uses the default security group of the Amazon VPC. The default security group allows all outbound traffic. + * Type: List +* **Environment Variables** + * ID: AppRunnerEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Docker Build Args** + * ID: DockerBuildArgs + * Description: The list of additional options to append to the `docker build` command. + * Type: String +* **Dockerfile Path** + * ID: DockerfilePath + * Description: Specify a path to a Dockerfile as either an absolute path or a path relative to the project. + * Type: String +* **Docker Execution Directory** + * ID: DockerExecutionDirectory + * Description: Specifies the docker execution directory where the docker build command will be executed from. + * Type: String +* **ECR Repository Name** + * ID: ECRRepositoryName + * Description: Specifies the ECR repository where the Docker images will be stored + * Type: String diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Linux.md b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Linux.md new file mode 100644 index 000000000..2b5756de4 --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Linux.md @@ -0,0 +1,185 @@ +**Recipe ID:** AspNetAppElasticBeanstalkLinux + +**Recipe Description:** This ASP.NET Core application will be built and deployed to AWS Elastic Beanstalk on Linux. Recommended if you want to deploy your application directly to EC2 hosts, not as a container image. + +**Settings:** + +* **Elastic Beanstalk Application** + * ID: BeanstalkApplication + * Description: The Elastic Beanstalk application. + * Type: Object + * Settings: + * **Create new Elastic Beanstalk application** + * ID: CreateNew + * Description: Do you want to create new application? + * Type: Bool + * **Application Name** + * ID: ApplicationName + * Description: The Elastic Beanstalk application name. + * Type: String + * **Application Name** + * ID: ExistingApplicationName + * Description: The Elastic Beanstalk application name. + * Type: String +* **Environment Name** + * ID: BeanstalkEnvironment + * Description: The Elastic Beanstalk environment name. + * Type: Object + * Settings: + * **Environment Name** + * ID: EnvironmentName + * Description: The Elastic Beanstalk environment name. + * Type: String +* **EC2 Instance Type** + * ID: InstanceType + * Description: The EC2 instance type of the EC2 instances created for the environment. + * Type: String +* **Environment Type** + * ID: EnvironmentType + * Description: The type of environment to create; for example, a single instance for development work or load balanced for production. + * Type: String +* **Load Balancer Type** + * ID: LoadBalancerType + * Description: The type of load balancer for your environment. + * Type: String +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Service IAM Role** + * ID: ServiceIAMRole + * Description: A service role is the IAM role that Elastic Beanstalk assumes when calling other services on your behalf. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Key Pair** + * ID: EC2KeyPair + * Description: The EC2 key pair used to SSH into EC2 instances for the Elastic Beanstalk environment. + * Type: String +* **Beanstalk Platform** + * ID: ElasticBeanstalkPlatformArn + * Description: The name of the Elastic Beanstalk platform to use with the environment. + * Type: String +* **Managed Platform Updates** + * ID: ElasticBeanstalkManagedPlatformUpdates + * Description: Enable managed platform updates to apply platform updates automatically during a weekly maintenance window that you choose. Your application stays available during the update process. + * Type: Object + * Settings: + * **Enable Managed Platform Updates** + * ID: ManagedActionsEnabled + * Description: Do you want to enable Managed Platform Updates? + * Type: Bool + * **Preferred Start Time** + * ID: PreferredStartTime + * Description: Configure a maintenance window for managed actions in UTC. Valid values are Day and time in the 'day:hour:minute' format. For example, 'Sun:00:00'. + * Type: String + * **Update Level** + * ID: UpdateLevel + * Description: The highest level of update to apply with managed platform updates. Platforms are versioned major.minor.patch. For example, 2.0.8 has a major version of 2, a minor version of 0, and a patch version of 8. + * Type: String +* **Enable AWS X-Ray Tracing Support** + * ID: XRayTracingSupportEnabled + * Description: AWS X-Ray is a service that collects data about requests that your application serves, and provides tools you can use to view, filter, and gain insights into that data to identify issues and opportunities for optimization. Do you want to enable AWS X-Ray tracing support? + * Type: Bool +* **Reverse Proxy** + * ID: ReverseProxy + * Description: By default Nginx is used as a reverse proxy in front of the .NET Core web server Kestrel. To use Kestrel as the front facing web server then select `none` as the reverse proxy. + * Type: String +* **Enhanced Health Reporting** + * ID: EnhancedHealthReporting + * Description: Enhanced health reporting provides free real-time application and operating system monitoring of the instances and other resources in your environment. + * Type: String +* **Health Check URL** + * ID: HealthCheckURL + * Description: Customize the load balancer health check to ensure that your application, and not just the web server, is in a good state. + * Type: String +* **Rolling Updates** + * ID: ElasticBeanstalkRollingUpdates + * Description: When a configuration change requires replacing instances, Elastic Beanstalk can perform the update in batches to avoid downtime while the change is propagated. During a rolling update, capacity is only reduced by the size of a single batch, which you can configure. Elastic Beanstalk takes one batch of instances out of service, terminates them, and then launches a batch with the new configuration. After the new batch starts serving requests, Elastic Beanstalk moves on to the next batch. + * Type: Object + * Settings: + * **Enable Rolling Updates** + * ID: RollingUpdatesEnabled + * Description: Do you want to enable Rolling Updates? + * Type: Bool + * **Rolling Update Type** + * ID: RollingUpdateType + * Description: This includes three types: time-based rolling updates, health-based rolling updates, and immutable updates. Time-based rolling updates apply a PauseTime between batches. Health-based rolling updates wait for new instances to pass health checks before moving on to the next batch. Immutable updates launch a full set of instances in a new Auto Scaling group. + * Type: String + * **Max Batch Size** + * ID: MaxBatchSize + * Description: The number of instances included in each batch of the rolling update. + * Type: Int + * **Min Instances In Service** + * ID: MinInstancesInService + * Description: The minimum number of instances that must be in service within the Auto Scaling group while other instances are terminated. + * Type: Int + * **Pause Time** + * ID: PauseTime + * Description: The amount of time (in seconds, minutes, or hours) the Elastic Beanstalk service waits after it completed updates to one batch of instances and before it continues on to the next batch. (ISO8601 duration format: PT#H#M#S where each # is the number of hours, minutes, and/or seconds, respectively.) + * Type: String + * **Timeout** + * ID: Timeout + * Description: The maximum amount of time (in minutes or hours) to wait for all instances in a batch of instances to pass health checks before canceling the update. (ISO8601 duration format: PT#H#M#S where each # is the number of hours, minutes, and/or seconds, respectively.) + * Type: String +* **CName Prefix** + * ID: CNamePrefix + * Description: If specified, the environment attempts to use this value as the prefix for the CNAME in your Elastic Beanstalk environment URL. If not specified, the CNAME is generated automatically by appending a random alphanumeric string to the environment name. + * Type: String +* **Environment Variables** + * ID: ElasticBeanstalkEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Virtual Private Cloud (VPC)** + * ID: VPC + * Description: A VPC enables you to launch the application into a virtual network that you've defined + * Type: Object + * Settings: + * **Use a VPC ** + * ID: UseVPC + * Description: Do you want to use a Virtual Private Cloud (VPC)? + * Type: Bool + * **Create New VPC** + * ID: CreateNew + * Description: Do you want to create a new VPC? + * Type: Bool + * **VPC ID** + * ID: VpcId + * Description: A list of VPC IDs that Elastic Beanstalk should use when it associates your service with a custom Amazon VPC. + * Type: String + * **EC2 Instance Subnets** + * ID: Subnets + * Description: A list of IDs of subnets that Elastic Beanstalk should use when it associates your environment with a custom Amazon VPC. Specify IDs of subnets of a single Amazon VPC. + * Type: List + * **Security Groups** + * ID: SecurityGroups + * Description: Lists the Amazon EC2 security groups to assign to the EC2 instances in the Auto Scaling group to define firewall rules for the instances. + * Type: List +* **Dotnet Build Configuration** + * ID: DotnetBuildConfiguration + * Description: The build configuration to use for the dotnet build + * Type: String +* **Dotnet Publish Args** + * ID: DotnetPublishArgs + * Description: The list of additional dotnet publish args passed to the target application. + * Type: String +* **Self Contained Build** + * ID: SelfContainedBuild + * Description: Publishing your app as self-contained produces an application that includes the .NET runtime and libraries. Users can run it on a machine that doesn't have the .NET runtime installed. + * Type: Bool diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Windows.md b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Windows.md new file mode 100644 index 000000000..5014bbec3 --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to AWS Elastic Beanstalk on Windows.md @@ -0,0 +1,184 @@ +**Recipe ID:** AspNetAppElasticBeanstalkWindows + +**Recipe Description:** This ASP.NET Core application will be built and deployed to AWS Elastic Beanstalk on Windows. Recommended if you do not want to deploy your application as a container image. + +**Settings:** + +* **Elastic Beanstalk Application** + * ID: BeanstalkApplication + * Description: The Elastic Beanstalk application. + * Type: Object + * Settings: + * **Create new Elastic Beanstalk application** + * ID: CreateNew + * Description: Do you want to create new application? + * Type: Bool + * **Application Name** + * ID: ApplicationName + * Description: The Elastic Beanstalk application name. + * Type: String + * **Application Name** + * ID: ExistingApplicationName + * Description: The Elastic Beanstalk application name. + * Type: String +* **Environment Name** + * ID: EnvironmentName + * Description: The Elastic Beanstalk environment name. + * Type: String +* **EC2 Instance Type** + * ID: InstanceType + * Description: The EC2 instance type of the EC2 instances created for the environment. + * Type: String +* **Environment Type** + * ID: EnvironmentType + * Description: The type of environment to create; for example, a single instance for development work or load balanced for production. + * Type: String +* **Load Balancer Type** + * ID: LoadBalancerType + * Description: The type of load balancer for your environment. + * Type: String +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Service IAM Role** + * ID: ServiceIAMRole + * Description: A service role is the IAM role that Elastic Beanstalk assumes when calling other services on your behalf. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Key Pair** + * ID: EC2KeyPair + * Description: The EC2 key pair used to SSH into EC2 instances for the Elastic Beanstalk environment. + * Type: String +* **Beanstalk Platform** + * ID: ElasticBeanstalkPlatformArn + * Description: The name of the Elastic Beanstalk platform to use with the environment. + * Type: String +* **Managed Platform Updates** + * ID: ElasticBeanstalkManagedPlatformUpdates + * Description: Enable managed platform updates to apply platform updates automatically during a weekly maintenance window that you choose. Your application stays available during the update process. + * Type: Object + * Settings: + * **Enable Managed Platform Updates** + * ID: ManagedActionsEnabled + * Description: Do you want to enable Managed Platform Updates? + * Type: Bool + * **Preferred Start Time** + * ID: PreferredStartTime + * Description: Configure a maintenance window for managed actions in UTC. Valid values are Day and time in the 'day:hour:minute' format. For example, 'Sun:00:00'. + * Type: String + * **Update Level** + * ID: UpdateLevel + * Description: The highest level of update to apply with managed platform updates. Platforms are versioned major.minor.patch. For example, 2.0.8 has a major version of 2, a minor version of 0, and a patch version of 8. + * Type: String +* **Enable AWS X-Ray Tracing Support** + * ID: XRayTracingSupportEnabled + * Description: AWS X-Ray is a service that collects data about requests that your application serves, and provides tools you can use to view, filter, and gain insights into that data to identify issues and opportunities for optimization. Do you want to enable AWS X-Ray tracing support? + * Type: Bool +* **IIS Web Site** + * ID: IISWebSite + * Description: The IIS Web Site the application will be installed in. + * Type: String +* **IIS Application Path** + * ID: IISAppPath + * Description: The IIS application path that will be the root of the application. + * Type: String +* **Enhanced Health Reporting** + * ID: EnhancedHealthReporting + * Description: Enhanced health reporting provides free real-time application and operating system monitoring of the instances and other resources in your environment. + * Type: String +* **Health Check URL** + * ID: HealthCheckURL + * Description: Customize the load balancer health check to ensure that your application, and not just the web server, is in a good state. + * Type: String +* **Rolling Updates** + * ID: ElasticBeanstalkRollingUpdates + * Description: When a configuration change requires replacing instances, Elastic Beanstalk can perform the update in batches to avoid downtime while the change is propagated. During a rolling update, capacity is only reduced by the size of a single batch, which you can configure. Elastic Beanstalk takes one batch of instances out of service, terminates them, and then launches a batch with the new configuration. After the new batch starts serving requests, Elastic Beanstalk moves on to the next batch. + * Type: Object + * Settings: + * **Enable Rolling Updates** + * ID: RollingUpdatesEnabled + * Description: Do you want to enable Rolling Updates? + * Type: Bool + * **Rolling Update Type** + * ID: RollingUpdateType + * Description: This includes three types: time-based rolling updates, health-based rolling updates, and immutable updates. Time-based rolling updates apply a PauseTime between batches. Health-based rolling updates wait for new instances to pass health checks before moving on to the next batch. Immutable updates launch a full set of instances in a new Auto Scaling group. + * Type: String + * **Max Batch Size** + * ID: MaxBatchSize + * Description: The number of instances included in each batch of the rolling update. + * Type: Int + * **Min Instances In Service** + * ID: MinInstancesInService + * Description: The minimum number of instances that must be in service within the Auto Scaling group while other instances are terminated. + * Type: Int + * **Pause Time** + * ID: PauseTime + * Description: The amount of time (in seconds, minutes, or hours) the Elastic Beanstalk service waits after it completed updates to one batch of instances and before it continues on to the next batch. (ISO8601 duration format: PT#H#M#S where each # is the number of hours, minutes, and/or seconds, respectively.) + * Type: String + * **Timeout** + * ID: Timeout + * Description: The maximum amount of time (in minutes or hours) to wait for all instances in a batch of instances to pass health checks before canceling the update. (ISO8601 duration format: PT#H#M#S where each # is the number of hours, minutes, and/or seconds, respectively.) + * Type: String +* **CName Prefix** + * ID: CNamePrefix + * Description: If specified, the environment attempts to use this value as the prefix for the CNAME in your Elastic Beanstalk environment URL. If not specified, the CNAME is generated automatically by appending a random alphanumeric string to the environment name. + * Type: String +* **Environment Variables** + * ID: ElasticBeanstalkEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Virtual Private Cloud (VPC)** + * ID: VPC + * Description: A VPC enables you to launch the application into a virtual network that you've defined + * Type: Object + * Settings: + * **Use a VPC ** + * ID: UseVPC + * Description: Do you want to use a Virtual Private Cloud (VPC)? + * Type: Bool + * **Create New VPC** + * ID: CreateNew + * Description: Do you want to create a new VPC? + * Type: Bool + * **VPC ID** + * ID: VpcId + * Description: A list of VPC IDs that Elastic Beanstalk should use when it associates your service with a custom Amazon VPC. + * Type: String + * **EC2 Instance Subnets** + * ID: Subnets + * Description: A list of IDs of subnets that Elastic Beanstalk should use when it associates your environment with a custom Amazon VPC. Specify IDs of subnets of a single Amazon VPC. + * Type: List + * **Security Groups** + * ID: SecurityGroups + * Description: Lists the Amazon EC2 security groups to assign to the EC2 instances in the Auto Scaling group to define firewall rules for the instances. + * Type: List +* **Dotnet Build Configuration** + * ID: DotnetBuildConfiguration + * Description: The build configuration to use for the dotnet build + * Type: String +* **Dotnet Publish Args** + * ID: DotnetPublishArgs + * Description: The list of additional dotnet publish args passed to the target application. + * Type: String +* **Self Contained Build** + * ID: SelfContainedBuild + * Description: Publishing your app as self-contained produces an application that includes the .NET runtime and libraries. Users can run it on a machine that doesn't have the .NET runtime installed. + * Type: Bool diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to Amazon ECS using AWS Fargate.md b/site/content/docs/cicd/recipes/ASP.NET Core App to Amazon ECS using AWS Fargate.md new file mode 100644 index 000000000..c2ec6f391 --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to Amazon ECS using AWS Fargate.md @@ -0,0 +1,203 @@ +**Recipe ID:** AspNetAppEcsFargate + +**Recipe Description:** This ASP.NET Core application will be deployed to Amazon Elastic Container Service (Amazon ECS) with compute power managed by AWS Fargate compute engine. If your project does not contain a Dockerfile, it will be automatically generated, otherwise an existing Dockerfile will be used. Recommended if you want to deploy your application as a container image on Linux. + +**Settings:** + +* **ECS Cluster** + * ID: ECSCluster + * Description: The ECS cluster used for the deployment. + * Type: Object + * Settings: + * **Create New ECS Cluster** + * ID: CreateNew + * Description: Do you want to create a new ECS cluster? + * Type: Bool + * **Existing Cluster ARN** + * ID: ClusterArn + * Description: The ARN of the existing cluster to use. + * Type: String + * **New Cluster Name** + * ID: NewClusterName + * Description: The name of the new cluster to create. + * Type: String +* **ECS Service Name** + * ID: ECSServiceName + * Description: The name of the ECS service running in the cluster. + * Type: String +* **Desired Task Count** + * ID: DesiredCount + * Description: The desired number of ECS tasks to run for the service. + * Type: Int +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Virtual Private Cloud (VPC)** + * ID: Vpc + * Description: A VPC enables you to launch the application into a virtual network that you've defined. + * Type: Object + * Settings: + * **Use default VPC** + * ID: IsDefault + * Description: Do you want to use the default VPC for the deployment? + * Type: Bool + * **Create New VPC** + * ID: CreateNew + * Description: Do you want to create a new VPC? + * Type: Bool + * **Existing VPC ID** + * ID: VpcId + * Description: The ID of the existing VPC to use. + * Type: String +* **ECS Service Security Groups** + * ID: AdditionalECSServiceSecurityGroups + * Description: A list of EC2 security groups to assign to the ECS service. This is commonly used to provide access to Amazon RDS databases running in their own security groups. + * Type: List +* **Task CPU** + * ID: TaskCpu + * Description: The number of CPU units used by the task. See the following for details on CPU values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **Task Memory** + * ID: TaskMemory + * Description: The amount of memory (in MB) used by the task. See the following for details on memory values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **Elastic Load Balancer** + * ID: LoadBalancer + * Description: Load Balancer the ECS Service will register tasks to. + * Type: Object + * Settings: + * **Create New Load Balancer** + * ID: CreateNew + * Description: Do you want to create a new Load Balancer? + * Type: Bool + * **Existing Load Balancer ARN** + * ID: ExistingLoadBalancerArn + * Description: The ARN of an existing load balancer to use. + * Type: String + * **Deregistration delay (seconds)** + * ID: DeregistrationDelayInSeconds + * Description: The amount of time to allow requests to finish before deregistering ECS tasks. + * Type: Int + * **Health Check Path** + * ID: HealthCheckPath + * Description: The ping path destination where Elastic Load Balancing sends health check requests. + * Type: String + * **Health Check Timeout** + * ID: HealthCheckTimeout + * Description: The amount of time, in seconds, during which no response from a target means a failed health check. + * Type: Int + * **Health Check Interval** + * ID: HealthCheckInternval + * Description: The approximate interval, in seconds, between health checks of an individual instance. + * Type: Int + * **Healthy Threshold Count** + * ID: HealthyThresholdCount + * Description: The number of consecutive health check successes required before considering an unhealthy target healthy. + * Type: Int + * **Unhealthy Threshold Count** + * ID: UnhealthyThresholdCount + * Description: The number of consecutive health check successes required before considering an unhealthy target unhealthy. + * Type: Int + * **Type of Listener Condition** + * ID: ListenerConditionType + * Description: The type of listener rule to create to direct traffic to ECS service. + * Type: String + * **Listener Condition Path Pattern** + * ID: ListenerConditionPathPattern + * Description: The resource path pattern to use for the listener rule. (i.e. "/api/*") + * Type: String + * **Listener Condition Priority** + * ID: ListenerConditionPriority + * Description: Priority of the condition rule. The value must be unique for the Load Balancer listener. + * Type: Int + * **Internet-Facing** + * ID: InternetFacing + * Description: Should the load balancer have an internet-routable address? Internet-facing load balancers can route requests from clients over the internet. Internal load balancers can route requests only from clients with access to the VPC. + * Type: Bool +* **AutoScaling** + * ID: AutoScaling + * Description: The AutoScaling configuration for the ECS service. + * Type: Object + * Settings: + * **Enable** + * ID: Enabled + * Description: Do you want to enable AutoScaling? + * Type: Bool + * **Minimum Capacity** + * ID: MinCapacity + * Description: The minimum number of ECS tasks handling the demand for the ECS service. + * Type: Int + * **Maximum Capacity** + * ID: MaxCapacity + * Description: The maximum number of ECS tasks handling the demand for the ECS service. + * Type: Int + * **AutoScaling Metric** + * ID: ScalingType + * Description: The metric to monitor for scaling changes. + * Type: String + * **CPU Target Utilization** + * ID: CpuTypeTargetUtilizationPercent + * Description: The target cpu utilization percentage that triggers a scaling change. + * Type: Double + * **Scale in cooldown (seconds)** + * ID: CpuTypeScaleInCooldownSeconds + * Description: The amount of time, in seconds, after a scale in activity completes before another scale in activity can start. + * Type: Int + * **Scale out cooldown (seconds)** + * ID: CpuTypeScaleOutCooldownSeconds + * Description: The amount of time, in seconds, after a scale out activity completes before another scale out activity can start. + * Type: Int + * **Memory Target Utilization** + * ID: MemoryTypeTargetUtilizationPercent + * Description: The target memory utilization percentage that triggers a scaling change. + * Type: Double + * **Scale in cooldown (seconds)** + * ID: MemoryTypeScaleInCooldownSeconds + * Description: The amount of time, in seconds, after a scale in activity completes before another scale in activity can start. + * Type: Int + * **Scale out cooldown (seconds)** + * ID: MemoryTypeScaleOutCooldownSeconds + * Description: The amount of time, in seconds, after a scale out activity completes before another scale out activity can start. + * Type: Int + * **Request per task** + * ID: RequestTypeRequestsPerTarget + * Description: The number of request per ECS task that triggers a scaling change. + * Type: Int + * **Scale in cooldown (seconds)** + * ID: RequestTypeScaleInCooldownSeconds + * Description: The amount of time, in seconds, after a scale in activity completes before another scale in activity can start. + * Type: Int + * **Scale out cooldown (seconds)** + * ID: RequestTypeScaleOutCooldownSeconds + * Description: The amount of time, in seconds, after a scale out activity completes before another scale out activity can start. + * Type: Int +* **Environment Variables** + * ID: ECSEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Docker Build Args** + * ID: DockerBuildArgs + * Description: The list of additional options to append to the `docker build` command. + * Type: String +* **Dockerfile Path** + * ID: DockerfilePath + * Description: Specify a path to a Dockerfile as either an absolute path or a path relative to the project. + * Type: String +* **Docker Execution Directory** + * ID: DockerExecutionDirectory + * Description: Specifies the docker execution directory where the docker build command will be executed from. + * Type: String +* **ECR Repository Name** + * ID: ECRRepositoryName + * Description: Specifies the ECR repository where the Docker images will be stored + * Type: String diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Environment.md b/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Environment.md new file mode 100644 index 000000000..ef83da49f --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Environment.md @@ -0,0 +1,34 @@ +**Recipe ID:** AspNetAppExistingBeanstalkEnvironment + +**Recipe Description:** This ASP.NET Core application will be built and deployed to an existing AWS Elastic Beanstalk environment. Recommended if you want to deploy your application directly to EC2 hosts, not as a container image. + +**Settings:** + +* **Enhanced Health Reporting** + * ID: EnhancedHealthReporting + * Description: Enhanced health reporting provides free real-time application and operating system monitoring of the instances and other resources in your environment. + * Type: String +* **Enable AWS X-Ray Tracing Support** + * ID: XRayTracingSupportEnabled + * Description: AWS X-Ray is a service that collects data about requests that your application serves, and provides tools you can use to view, filter, and gain insights into that data to identify issues and opportunities for optimization. Do you want to enable AWS X-Ray tracing support? + * Type: Bool +* **Reverse Proxy** + * ID: ReverseProxy + * Description: By default Nginx is used as a reverse proxy in front of the .NET Core web server Kestrel. To use Kestrel as the front facing web server then select `none` as the reverse proxy. + * Type: String +* **Health Check URL** + * ID: HealthCheckURL + * Description: Customize the load balancer health check to ensure that your application, and not just the web server, is in a good state. + * Type: String +* **Dotnet Build Configuration** + * ID: DotnetBuildConfiguration + * Description: The build configuration to use for the dotnet build + * Type: String +* **Dotnet Publish Args** + * ID: DotnetPublishArgs + * Description: The list of additional dotnet publish args passed to the target application. + * Type: String +* **Self Contained Build** + * ID: SelfContainedBuild + * Description: Publishing your app as self-contained produces an application that includes the .NET runtime and libraries. Users can run it on a machine that doesn't have the .NET runtime installed. + * Type: Bool diff --git a/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Windows Environment.md b/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Windows Environment.md new file mode 100644 index 000000000..70ce5b49d --- /dev/null +++ b/site/content/docs/cicd/recipes/ASP.NET Core App to Existing AWS Elastic Beanstalk Windows Environment.md @@ -0,0 +1,38 @@ +**Recipe ID:** AspNetAppExistingBeanstalkWindowsEnvironment + +**Recipe Description:** This ASP.NET Core application will be built and deployed to an existing AWS Elastic Beanstalk Windows environment. Recommended if you want to deploy your application directly to EC2 hosts, not as a container image. + +**Settings:** + +* **IIS Web Site** + * ID: IISWebSite + * Description: The IIS Web Site the application will be installed in. + * Type: String +* **IIS Application Path** + * ID: IISAppPath + * Description: The IIS application path that will be the root of the application. + * Type: String +* **Enhanced Health Reporting** + * ID: EnhancedHealthReporting + * Description: Enhanced health reporting provides free real-time application and operating system monitoring of the instances and other resources in your environment. + * Type: String +* **Enable AWS X-Ray Tracing Support** + * ID: XRayTracingSupportEnabled + * Description: AWS X-Ray is a service that collects data about requests that your application serves, and provides tools you can use to view, filter, and gain insights into that data to identify issues and opportunities for optimization. Do you want to enable AWS X-Ray tracing support? + * Type: Bool +* **Health Check URL** + * ID: HealthCheckURL + * Description: Customize the load balancer health check to ensure that your application, and not just the web server, is in a good state. + * Type: String +* **Dotnet Build Configuration** + * ID: DotnetBuildConfiguration + * Description: The build configuration to use for the dotnet build + * Type: String +* **Dotnet Publish Args** + * ID: DotnetPublishArgs + * Description: The list of additional dotnet publish args passed to the target application. + * Type: String +* **Self Contained Build** + * ID: SelfContainedBuild + * Description: Publishing your app as self-contained produces an application that includes the .NET runtime and libraries. Users can run it on a machine that doesn't have the .NET runtime installed. + * Type: Bool diff --git a/site/content/docs/cicd/recipes/Blazor WebAssembly App.md b/site/content/docs/cicd/recipes/Blazor WebAssembly App.md new file mode 100644 index 000000000..f3b7dbf08 --- /dev/null +++ b/site/content/docs/cicd/recipes/Blazor WebAssembly App.md @@ -0,0 +1,88 @@ +**Recipe ID:** BlazorWasm + +**Recipe Description:** This Blazor WebAssembly application will be built and hosted in a new Amazon Simple Storage Service (Amazon S3) bucket. The Blazor application will be exposed publicly through a CloudFront distribution using the Amazon S3 bucket as the origin. + +**Settings:** + +* **Index Document** + * ID: IndexDocument + * Description: The default page to use when the endpoint is accessed with no resource path. + * Type: String +* **Error Document** + * ID: ErrorDocument + * Description: The error page to use when an error occurs while accessing the resource path. + * Type: String +* **Redirect 404 and 403 Errors** + * ID: Redirect404ToRoot + * Description: Redirect any 404 and 403 requests to the index document. This is useful in Blazor applications that modify the resource path in the browser. If the modified resource path is reused in a new browser it will result in a 403 from Amazon CloudFront since no S3 object exists at that resource path. + * Type: Bool +* **Backend REST API** + * ID: BackendApi + * Description: URI to a backend rest api that will be added as an origin to the CloudFront distribution. For example an API Gateway endpoint. + * Type: Object + * Settings: + * **Enable** + * ID: Enable + * Description: Enable adding backend rest api + * Type: Bool + * **Uri** + * ID: Uri + * Description: Uri to the backend rest api + * Type: String + * **Resource Path Pattern** + * ID: ResourcePathPattern + * Description: The resource path pattern to determine which request go to backend rest api. (i.e. "/api/*") + * Type: String +* **CloudFront Access Logging** + * ID: AccessLogging + * Description: Configure if and how access logs are written for the CloudFront distribution + * Type: Object + * Settings: + * **Enable** + * ID: Enable + * Description: Enable CloudFront Access Logging + * Type: Bool + * **Log Cookies** + * ID: LogIncludesCookies + * Description: Include cookies in access logs + * Type: Bool + * **Create Logging Bucket** + * ID: CreateLoggingS3Bucket + * Description: Create new S3 bucket for access logs to be stored. Bucket and logs will be retained after deployment is deleted. + * Type: Bool + * **Logging Bucket** + * ID: ExistingS3LoggingBucket + * Description: S3 bucket to use for storing access logs + * Type: String + * **Logging S3 Key Prefix** + * ID: LoggingS3KeyPrefix + * Description: Optional S3 key prefix to store access logs (e.g. app-name/) + * Type: String +* **CloudFront Price Class** + * ID: PriceClass + * Description: Configure the edge locations that will respond to request for the CloudFront distribution + * Type: String +* **Enable IPv6** + * ID: EnableIpv6 + * Description: Control if IPv6 should be enabled for the CloudFront distribution + * Type: Bool +* **Maximum HTTP Version** + * ID: MaxHttpVersion + * Description: The maximum http version that users can use to communicate with the CloudFront distribution + * Type: String +* **Web ACL Arn** + * ID: WebAclId + * Description: The AWS WAF (web application firewall) ACL arn + * Type: String +* **Dotnet Build Configuration** + * ID: DotnetBuildConfiguration + * Description: The build configuration to use for the dotnet build + * Type: String +* **Dotnet Publish Args** + * ID: DotnetPublishArgs + * Description: The list of additional dotnet publish args passed to the target application. + * Type: String +* **Self Contained Build** + * ID: SelfContainedBuild + * Description: Publishing your app as self-contained produces an application that includes the .NET runtime and libraries. Users can run it on a machine that doesn't have the .NET runtime installed. + * Type: Bool diff --git a/site/content/docs/cicd/recipes/Container Image to Amazon Elastic Container Registry (ECR).md b/site/content/docs/cicd/recipes/Container Image to Amazon Elastic Container Registry (ECR).md new file mode 100644 index 000000000..19235e884 --- /dev/null +++ b/site/content/docs/cicd/recipes/Container Image to Amazon Elastic Container Registry (ECR).md @@ -0,0 +1,26 @@ +**Recipe ID:** PushContainerImageEcr + +**Recipe Description:** This .NET application will be built using an existing Dockerfile. The Docker container image will then be pushed to Amazon ECR, a fully managed container registry. + +**Settings:** + +* **Image Tag** + * ID: ImageTag + * Description: This tag will be associated to the container images which are pushed to Amazon Elastic Container Registry. + * Type: String +* **Docker Build Args** + * ID: DockerBuildArgs + * Description: The list of additional options to append to the `docker build` command. + * Type: String +* **Dockerfile Path** + * ID: DockerfilePath + * Description: Specify a path to a Dockerfile as either an absolute path or a path relative to the project. + * Type: String +* **Docker Execution Directory** + * ID: DockerExecutionDirectory + * Description: Specifies the docker execution directory where the docker build command will be executed from. + * Type: String +* **ECR Repository Name** + * ID: ECRRepositoryName + * Description: Specifies the ECR repository where the Docker images will be stored + * Type: String diff --git a/site/content/docs/cicd/recipes/Scheduled Task on Amazon Elastic Container Service (ECS) using AWS Fargate.md b/site/content/docs/cicd/recipes/Scheduled Task on Amazon Elastic Container Service (ECS) using AWS Fargate.md new file mode 100644 index 000000000..29705c8ba --- /dev/null +++ b/site/content/docs/cicd/recipes/Scheduled Task on Amazon Elastic Container Service (ECS) using AWS Fargate.md @@ -0,0 +1,85 @@ +**Recipe ID:** ConsoleAppEcsFargateScheduleTask + +**Recipe Description:** This .NET Console application will be built using a Dockerfile and deployed as a scheduled task to Amazon Elastic Container Service (Amazon ECS) with compute power managed by AWS Fargate compute engine. If your project does not contain a Dockerfile it will be automatically generated, otherwise an existing Dockerfile will be used. Recommended if you want to deploy a scheduled task as a container image on Linux. + +**Settings:** + +* **ECS Cluster** + * ID: ECSCluster + * Description: The ECS cluster used for the deployment. + * Type: Object + * Settings: + * **Create New ECS Cluster** + * ID: CreateNew + * Description: Do you want to create a new ECS cluster? + * Type: Bool + * **Existing Cluster ARN** + * ID: ClusterArn + * Description: The ARN of the existing cluster to use. + * Type: String + * **New Cluster Name** + * ID: NewClusterName + * Description: The name of the new cluster to create. + * Type: String +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Task Schedule** + * ID: Schedule + * Description: The schedule or rate (frequency) that determines when Amazon CloudWatch Events runs the rule. For details about the format for this value, see the CloudWatch Events guide: https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html + * Type: String +* **Virtual Private Cloud (VPC)** + * ID: Vpc + * Description: A VPC enables you to launch the application into a virtual network that you've defined. + * Type: Object + * Settings: + * **Use default VPC** + * ID: IsDefault + * Description: Do you want to use the default VPC? + * Type: Bool + * **Create New VPC** + * ID: CreateNew + * Description: Do you want to create a new VPC? + * Type: Bool + * **Existing VPC ID** + * ID: VpcId + * Description: The ID of the existing VPC to use. + * Type: String +* **Task CPU** + * ID: TaskCpu + * Description: The number of CPU units used by the task. See the following for details on CPU values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **Task Memory** + * ID: TaskMemory + * Description: The amount of memory (in MB) used by the task. See the following for details on memory values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **Environment Variables** + * ID: ECSEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Docker Build Args** + * ID: DockerBuildArgs + * Description: The list of additional options to append to the `docker build` command. + * Type: String +* **Dockerfile Path** + * ID: DockerfilePath + * Description: Specify a path to a Dockerfile as either an absolute path or a path relative to the project. + * Type: String +* **Docker Execution Directory** + * ID: DockerExecutionDirectory + * Description: Specifies the docker execution directory where the docker build command will be executed from. + * Type: String +* **ECR Repository Name** + * ID: ECRRepositoryName + * Description: Specifies the ECR repository where the Docker images will be stored + * Type: String diff --git a/site/content/docs/cicd/recipes/Service on Amazon Elastic Container Service (ECS) using AWS Fargate.md b/site/content/docs/cicd/recipes/Service on Amazon Elastic Container Service (ECS) using AWS Fargate.md new file mode 100644 index 000000000..51c4ba2d2 --- /dev/null +++ b/site/content/docs/cicd/recipes/Service on Amazon Elastic Container Service (ECS) using AWS Fargate.md @@ -0,0 +1,138 @@ +**Recipe ID:** ConsoleAppEcsFargateService + +**Recipe Description:** This .NET Console application will be built using a Dockerfile and deployed as a service to Amazon Elastic Container Service (Amazon ECS) with compute power managed by AWS Fargate compute engine. If your project does not contain a Dockerfile it will be automatically generated, otherwise an existing Dockerfile will be used. Recommended if you want to deploy a service as a container image on Linux. + +**Settings:** + +* **ECS Cluster** + * ID: ECSCluster + * Description: The ECS cluster used for the deployment. + * Type: Object + * Settings: + * **Create New ECS Cluster** + * ID: CreateNew + * Description: Do you want to create a new ECS cluster? + * Type: Bool + * **Existing Cluster ARN** + * ID: ClusterArn + * Description: The ARN of the existing cluster to use. + * Type: String + * **New Cluster Name** + * ID: NewClusterName + * Description: The name of the new cluster to create. + * Type: String +* **ECS Service Name** + * ID: ECSServiceName + * Description: The name of the ECS service running in the cluster. + * Type: String +* **Desired Task Count** + * ID: DesiredCount + * Description: The desired number of ECS tasks to run for the service. + * Type: Int +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool + * **Existing Role ARN** + * ID: RoleArn + * Description: The ARN of the existing role to use. + * Type: String +* **Virtual Private Cloud (VPC)** + * ID: Vpc + * Description: A VPC enables you to launch the application into a virtual network that you've defined. + * Type: Object + * Settings: + * **Use default VPC** + * ID: IsDefault + * Description: Do you want to use the default VPC for the deployment? + * Type: Bool + * **Create New VPC** + * ID: CreateNew + * Description: Do you want to create a new VPC? + * Type: Bool + * **Existing VPC ID** + * ID: VpcId + * Description: The ID of the existing VPC to use. + * Type: String +* **ECS Service Security Groups** + * ID: ECSServiceSecurityGroups + * Description: A comma-delimited list of EC2 security groups to assign to the ECS service. This is commonly used to provide access to Amazon RDS databases running in their own security groups. + * Type: String +* **Task CPU** + * ID: TaskCpu + * Description: The number of CPU units used by the task. See the following for details on CPU values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **Task Memory** + * ID: TaskMemory + * Description: The amount of memory (in MB) used by the task. See the following for details on memory values: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs + * Type: Int +* **AutoScaling** + * ID: AutoScaling + * Description: The AutoScaling configuration for the ECS service. + * Type: Object + * Settings: + * **Enable** + * ID: Enabled + * Description: Do you want to enable AutoScaling? + * Type: Bool + * **Minimum Capacity** + * ID: MinCapacity + * Description: The minimum number of ECS tasks handling the demand for the ECS service. + * Type: Int + * **Maximum Capacity** + * ID: MaxCapacity + * Description: The maximum number of ECS tasks handling the demand for the ECS service. + * Type: Int + * **AutoScaling Metric** + * ID: ScalingType + * Description: The metric to monitor for scaling changes. + * Type: String + * **CPU Target Utilization** + * ID: CpuTypeTargetUtilizationPercent + * Description: The target cpu utilization percentage that triggers a scaling change. + * Type: Double + * **Scale in cooldown (seconds)** + * ID: CpuTypeScaleInCooldownSeconds + * Description: The amount of time, in seconds, after a scale in activity completes before another scale in activity can start. + * Type: Int + * **Scale out cooldown (seconds)** + * ID: CpuTypeScaleOutCooldownSeconds + * Description: The amount of time, in seconds, after a scale out activity completes before another scale out activity can start. + * Type: Int + * **Memory Target Utilization** + * ID: MemoryTypeTargetUtilizationPercent + * Description: The target memory utilization percentage that triggers a scaling change. + * Type: Double + * **Scale in cooldown (seconds)** + * ID: MemoryTypeScaleInCooldownSeconds + * Description: The amount of time, in seconds, after a scale in activity completes before another scale in activity can start. + * Type: Int + * **Scale out cooldown (seconds)** + * ID: MemoryTypeScaleOutCooldownSeconds + * Description: The amount of time, in seconds, after a scale out activity completes before another scale out activity can start. + * Type: Int +* **Environment Variables** + * ID: ECSEnvironmentVariables + * Description: Configure environment properties for your application. + * Type: KeyValue +* **Docker Build Args** + * ID: DockerBuildArgs + * Description: The list of additional options to append to the `docker build` command. + * Type: String +* **Dockerfile Path** + * ID: DockerfilePath + * Description: Specify a path to a Dockerfile as either an absolute path or a path relative to the project. + * Type: String +* **Docker Execution Directory** + * ID: DockerExecutionDirectory + * Description: Specifies the docker execution directory where the docker build command will be executed from. + * Type: String +* **ECR Repository Name** + * ID: ECRRepositoryName + * Description: Specifies the ECR repository where the Docker images will be stored + * Type: String diff --git a/site/content/faq.md b/site/content/faq.md index 927cbad04..4c4dcfb69 100644 --- a/site/content/faq.md +++ b/site/content/faq.md @@ -25,4 +25,4 @@ ASP.NET Core applications can be deployed to AWS Elastic Beanstalk picking the " Yes, you can deploy your application using the "Publish to AWS" feature in the AWS Toolkit for Visual Studio. This feature exposes the same functionality as the AWS Deploy Tool for .NET CLI. To learn more, go to [Publish to AWS](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/publish-experience.html) in the AWS Toolkit for Visual Studio User Guide. #### *FAQ: Can I invoke AWS Deploy Tool from my CI/CD pipeline?* -Yes, you can. To learn more, go to [Integrating with CI/CD](docs/cicd.md) +Yes, you can. To learn more, go to [Integrating with CI/CD](docs/cicd/cicd.md) diff --git a/site/content/index.md b/site/content/index.md index 06e6a561d..142bb5531 100644 --- a/site/content/index.md +++ b/site/content/index.md @@ -13,7 +13,7 @@ AWS Deploy Tool has the following capabilities: * **Help with learning AWS CDK for .NET!** - Gradually learn the underlying AWS tools that AWS Deploy Tool for .NET is built on, such as the AWS CDK. ### Availability -####... in .NET CLI +#### ... in .NET CLI AWS Deploy Tool for .NET is available for download as a NuGet package. See [How to install](docs/getting-started/installation.md) section. diff --git a/src/AWS.Deploy.CLI/ServerMode/Controllers/RecipeController.cs b/src/AWS.Deploy.CLI/ServerMode/Controllers/RecipeController.cs index b3ade005a..37d0b5d28 100644 --- a/src/AWS.Deploy.CLI/ServerMode/Controllers/RecipeController.cs +++ b/src/AWS.Deploy.CLI/ServerMode/Controllers/RecipeController.cs @@ -1,17 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\r // SPDX-License-Identifier: Apache-2.0 -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AWS.Deploy.CLI.ServerMode.Models; using AWS.Deploy.Common; -using AWS.Deploy.Common.DeploymentManifest; -using AWS.Deploy.Common.IO; using AWS.Deploy.Common.Recipes; -using AWS.Deploy.Orchestration; -using AWS.Deploy.Orchestration.Utilities; using AWS.Deploy.Recipes; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; @@ -32,6 +27,52 @@ public RecipeController(IRecipeHandler recipeHandler, IProjectDefinitionParser p _projectDefinitionParser = projectDefinitionParser; } + private async Task> GetAllAvailableRecipes(string? projectPath = null) + { + var recipePaths = new HashSet { RecipeLocator.FindRecipeDefinitionsPath() }; + HashSet customRecipePaths = new HashSet(); + + if (!string.IsNullOrEmpty(projectPath)) + { + var projectDefinition = await _projectDefinitionParser.Parse(projectPath); + customRecipePaths = await _recipeHandler.LocateCustomRecipePaths(projectDefinition); + } + + return await _recipeHandler.GetRecipeDefinitions(recipeDefinitionPaths: recipePaths.Union(customRecipePaths).ToList()); + } + + /// + /// Gets a list of available recipe IDs. + /// + [HttpGet("recipes")] + [SwaggerOperation(OperationId = "ListAllRecipes")] + [SwaggerResponse(200, type: typeof(ListAllRecipesOutput))] + [ProducesResponseType(Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest)] + public async Task ListAllRecipes([FromQuery] string? projectPath = null) + { + var recipeDefinitions = await GetAllAvailableRecipes(projectPath); + + var recipes = recipeDefinitions + .Select(x => + new RecipeSummary( + x.Id, + x.Version, + x.Name, + x.Description, + x.ShortDescription, + x.TargetService, + x.DeploymentType.ToString(), + x.DeploymentBundle.ToString()) + ).ToList(); + + var output = new ListAllRecipesOutput + { + Recipes = recipes + }; + + return Ok(output); + } + /// /// Gets a summary of the specified Recipe. /// @@ -46,15 +87,8 @@ public async Task GetRecipe(string recipeId, [FromQuery] string? return BadRequest($"A Recipe ID was not provided."); } - ProjectDefinition? projectDefinition = null; - var recipePaths = new HashSet { RecipeLocator.FindRecipeDefinitionsPath() }; - HashSet customRecipePaths = new HashSet(); - if (!string.IsNullOrEmpty(projectPath)) - { - projectDefinition = await _projectDefinitionParser.Parse(projectPath); - customRecipePaths = await _recipeHandler.LocateCustomRecipePaths(projectDefinition); - } - var recipeDefinitions = await _recipeHandler.GetRecipeDefinitions(recipeDefinitionPaths: recipePaths.Union(customRecipePaths).ToList()); + var recipeDefinitions = await GetAllAvailableRecipes(projectPath); + var selectedRecipeDefinition = recipeDefinitions.FirstOrDefault(x => x.Id.Equals(recipeId)); if (selectedRecipeDefinition == null) @@ -75,5 +109,51 @@ public async Task GetRecipe(string recipeId, [FromQuery] string? return Ok(output); } + + /// + /// Gets a summary of the specified recipe option settings. + /// + [HttpGet("{recipeId}/settings")] + [SwaggerOperation(OperationId = "GetRecipeOptionSettings")] + [SwaggerResponse(200, type: typeof(List))] + [ProducesResponseType(Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest)] + public async Task GetRecipeOptionSettings(string recipeId, [FromQuery] string? projectPath = null) + { + if (string.IsNullOrEmpty(recipeId)) + { + return BadRequest($"A Recipe ID was not provided."); + } + + var recipeDefinitions = await GetAllAvailableRecipes(projectPath); + + var selectedRecipeDefinition = recipeDefinitions.FirstOrDefault(x => x.Id.Equals(recipeId)); + + if (selectedRecipeDefinition == null) + { + return BadRequest($"Recipe ID {recipeId} not found."); + } + + var settings = GetOptionSettingSummary(selectedRecipeDefinition.OptionSettings); + + return Ok(settings); + } + + private List GetOptionSettingSummary(List optionSettingItems) + { + var settings = new List(); + foreach (var optionSetting in optionSettingItems) + { + settings.Add(new RecipeOptionSettingSummary( + optionSetting.Id, + optionSetting.Name, + optionSetting.Description, + optionSetting.Type.ToString() + ) + { + Settings = GetOptionSettingSummary(optionSetting.ChildOptionSettings) + }); + } + return settings; + } } } diff --git a/src/AWS.Deploy.CLI/ServerMode/Models/ListAllRecipesOutput.cs b/src/AWS.Deploy.CLI/ServerMode/Models/ListAllRecipesOutput.cs new file mode 100644 index 000000000..ace3a6be9 --- /dev/null +++ b/src/AWS.Deploy.CLI/ServerMode/Models/ListAllRecipesOutput.cs @@ -0,0 +1,19 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Collections.Generic; +using AWS.Deploy.CLI.ServerMode.Controllers; + +namespace AWS.Deploy.CLI.ServerMode.Models +{ + /// + /// Output returned by the API + /// + public class ListAllRecipesOutput + { + /// + /// A list of Recipe IDs + /// + public IList Recipes { get; set; } = new List(); + } +} diff --git a/src/AWS.Deploy.CLI/ServerMode/Models/RecipeOptionSettingSummary.cs b/src/AWS.Deploy.CLI/ServerMode/Models/RecipeOptionSettingSummary.cs new file mode 100644 index 000000000..90d7dcca7 --- /dev/null +++ b/src/AWS.Deploy.CLI/ServerMode/Models/RecipeOptionSettingSummary.cs @@ -0,0 +1,48 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Collections.Generic; +using AWS.Deploy.Common.Recipes; + +namespace AWS.Deploy.CLI.ServerMode.Models +{ + /// + /// Represents a recipe returned through server mode. + /// + public class RecipeOptionSettingSummary + { + /// + /// The unique id of setting. + /// + public string Id { get; set; } + + /// + /// The display friendly name of the setting. + /// + public string Name { get; set; } + + /// + /// The description of what the setting is used for. + /// + public string Description { get; set; } + + /// + /// The type of primitive value expected for this setting. + /// For example String, Int + /// + public string Type { get; set; } + + /// + /// Child option settings for value types. + /// + public List Settings { get; set; } = new List(); + + public RecipeOptionSettingSummary(string id, string name, string description, string type) + { + Id = id; + Name = name; + Description = description; + Type = type; + } + } +} diff --git a/src/AWS.Deploy.DocGenerator/AWS.Deploy.DocGenerator.csproj b/src/AWS.Deploy.DocGenerator/AWS.Deploy.DocGenerator.csproj new file mode 100644 index 000000000..9078b200e --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/AWS.Deploy.DocGenerator.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + + + + + + + + diff --git a/src/AWS.Deploy.DocGenerator/App.cs b/src/AWS.Deploy.DocGenerator/App.cs new file mode 100644 index 000000000..25939c12d --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/App.cs @@ -0,0 +1,34 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using System.Linq; +using System.Threading.Tasks; +using AWS.Deploy.DocGenerator.Generators; +using Microsoft.Extensions.DependencyInjection; + +namespace AWS.Deploy.DocGenerator +{ + public class App + { + private readonly IServiceProvider _serviceProvider; + + public App(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task Run(string[] args) + { + var generatorTypes = System.Reflection.Assembly.GetExecutingAssembly() + .GetTypes() + .Where(type => typeof(IDocGenerator).IsAssignableFrom(type) && !type.IsInterface); + + foreach (var generatorType in generatorTypes) + { + var instance = (IDocGenerator) ActivatorUtilities.CreateInstance(_serviceProvider, generatorType); + await instance.Generate(); + } + } + } +} diff --git a/src/AWS.Deploy.DocGenerator/Generators/DeploymentSettingsFileGenerator.cs b/src/AWS.Deploy.DocGenerator/Generators/DeploymentSettingsFileGenerator.cs new file mode 100644 index 000000000..e80cf341a --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/Generators/DeploymentSettingsFileGenerator.cs @@ -0,0 +1,74 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AWS.Deploy.Common.IO; +using AWS.Deploy.DocGenerator.Utilities; +using AWS.Deploy.ServerMode.Client; + +namespace AWS.Deploy.DocGenerator.Generators +{ + /// + /// Creates documentation for the deployment settings file that can be used as part of a CI/CD pipeline. + /// + public class DeploymentSettingsFileGenerator : IDocGenerator + { + private readonly IRestAPIClient _restAPIClient; + private readonly IFileManager _fileManager; + + public DeploymentSettingsFileGenerator(IRestAPIClient restAPIClient, IFileManager fileManager) + { + _restAPIClient = restAPIClient; + _fileManager = fileManager; + } + + /// + /// Creates markdown files per recipe that lists all the option settings that can be used in the deployment settings file. + /// + public async Task Generate() + { + var recipes = await _restAPIClient.ListAllRecipesAsync(null); + + foreach (var recipeSummary in recipes.Recipes) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.AppendLine($"**Recipe ID:** {recipeSummary.Id}"); + stringBuilder.AppendLine(); + stringBuilder.AppendLine($"**Recipe Description:** {recipeSummary.Description}"); + stringBuilder.AppendLine(); + stringBuilder.AppendLine("**Settings:**"); + stringBuilder.AppendLine(); + + var optionSettings = await _restAPIClient.GetRecipeOptionSettingsAsync(recipeSummary.Id, null); + + GenerateChildSettings(stringBuilder, 0, optionSettings); + + var fullPath = DocGeneratorExtensions.DetermineDocsPath($"content/docs/cicd/recipes/{recipeSummary.Name}.md"); + await _fileManager.WriteAllTextAsync(fullPath, stringBuilder.ToString()); + } + } + + private void GenerateChildSettings(StringBuilder stringBuilder, int level, ICollection settings) + { + var titlePadding = new string(' ', level * 4); + var detailsPadding = new string(' ', (level + 1) * 4); + foreach (var setting in settings) + { + stringBuilder.AppendLine($"{titlePadding}* **{setting.Name}**"); + stringBuilder.AppendLine($"{detailsPadding}* ID: {setting.Id}"); + stringBuilder.AppendLine($"{detailsPadding}* Description: {setting.Description}"); + stringBuilder.AppendLine($"{detailsPadding}* Type: {setting.Type}"); + + if (setting.Settings.Any()) + { + stringBuilder.AppendLine($"{detailsPadding}* Settings:"); + GenerateChildSettings(stringBuilder, level + 2, setting.Settings); + } + } + } + } +} diff --git a/src/AWS.Deploy.DocGenerator/Generators/IDocGenerator.cs b/src/AWS.Deploy.DocGenerator/Generators/IDocGenerator.cs new file mode 100644 index 000000000..ba7fdac78 --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/Generators/IDocGenerator.cs @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Threading.Tasks; + +namespace AWS.Deploy.DocGenerator.Generators +{ + /// + /// Interface for documentation generators such as + /// + public interface IDocGenerator + { + /// + /// Generates documentation content into the documentation folder of the repository. + /// + public Task Generate(); + } +} diff --git a/src/AWS.Deploy.DocGenerator/Program.cs b/src/AWS.Deploy.DocGenerator/Program.cs new file mode 100644 index 000000000..06881a377 --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/Program.cs @@ -0,0 +1,53 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using AWS.Deploy.CLI.Extensions; +using AWS.Deploy.DocGenerator.Utilities; +using AWS.Deploy.CLI; +using System.Threading; +using AWS.Deploy.ServerMode.Client; +using AWS.Deploy.CLI.Commands; +using AWS.Deploy.ServerMode.Client.Utilities; + +namespace AWS.Deploy.DocGenerator +{ + public class Program + { + public static async Task Main(string[] args) + { + var serviceCollection = new ServiceCollection(); + + serviceCollection.AddCustomServices(); + serviceCollection.AddGeneratorServices(); + + serviceCollection.AddSingleton(serviceProvider => + { + var interactiveService = serviceProvider.GetRequiredService(); + var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); + var serverCommand = new ServerModeCommand(interactiveService, 4152, null, true); + + _ = serverCommand.ExecuteAsync(new CancellationTokenSource().Token); + + var baseUrl = $"http://localhost:{4152}/"; + + var client = new RestAPIClient(baseUrl, httpClient); + + client.WaitUntilServerModeReady().GetAwaiter().GetResult(); + + return client; + }); + + var serviceProvider = serviceCollection.BuildServiceProvider(); + + // calls the Run method in App, which is replacing Main + var app = serviceProvider.GetService(); + if (app == null) + { + throw new Exception("App dependencies aren't injected correctly." + + " Verify DocGeneratorExtensions has all the required dependencies to instantiate App."); + } + + await app.Run(args); + } + } +} diff --git a/src/AWS.Deploy.DocGenerator/Utilities/DocGeneratorExtensions.cs b/src/AWS.Deploy.DocGenerator/Utilities/DocGeneratorExtensions.cs new file mode 100644 index 000000000..742eecddc --- /dev/null +++ b/src/AWS.Deploy.DocGenerator/Utilities/DocGeneratorExtensions.cs @@ -0,0 +1,49 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using Microsoft.Extensions.DependencyInjection; +using AWS.Deploy.DocGenerator.Generators; +using System.IO; + +namespace AWS.Deploy.DocGenerator.Utilities +{ + public static class DocGeneratorExtensions + { + /// + /// Extension method for that injects essential app dependencies. + /// + /// instance that holds the app dependencies. + /// + public static void AddGeneratorServices(this IServiceCollection serviceCollection, ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + serviceCollection.AddSingleton(); + + // required to run the application + serviceCollection.AddSingleton(); + } + + /// + /// Locates the documentation folder in the current repository. + /// + /// A sub-directory to add to the documentation path + /// The path to a specific folder in the documentation folder of the repository. + public static string DetermineDocsPath(string subdirectory) + { + var dir = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (!string.Equals(dir?.Name, "src") && !string.Equals(dir?.Name, "test")) + { + if (dir == null) + break; + + dir = dir.Parent; + } + + if (dir == null || dir.Parent == null) + throw new Exception("Could not determine file path of current directory."); + + return Path.Combine(dir.Parent.FullName, "site", subdirectory); + } + } +} diff --git a/src/AWS.Deploy.ServerMode.Client/RestAPI.cs b/src/AWS.Deploy.ServerMode.Client/RestAPI.cs index 6184238ca..34487f169 100644 --- a/src/AWS.Deploy.ServerMode.Client/RestAPI.cs +++ b/src/AWS.Deploy.ServerMode.Client/RestAPI.cs @@ -172,6 +172,17 @@ public partial interface IRestAPIClient /// A server side error occurred. System.Threading.Tasks.Task HealthAsync(System.Threading.CancellationToken cancellationToken); + /// Gets a list of available recipe IDs. + /// Success + /// A server side error occurred. + System.Threading.Tasks.Task ListAllRecipesAsync(string projectPath); + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Gets a list of available recipe IDs. + /// Success + /// A server side error occurred. + System.Threading.Tasks.Task ListAllRecipesAsync(string projectPath, System.Threading.CancellationToken cancellationToken); + /// Gets a summary of the specified Recipe. /// Success /// A server side error occurred. @@ -183,6 +194,17 @@ public partial interface IRestAPIClient /// A server side error occurred. System.Threading.Tasks.Task GetRecipeAsync(string recipeId, string projectPath, System.Threading.CancellationToken cancellationToken); + /// Gets a summary of the specified recipe option settings. + /// Success + /// A server side error occurred. + System.Threading.Tasks.Task> GetRecipeOptionSettingsAsync(string recipeId, string projectPath); + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Gets a summary of the specified recipe option settings. + /// Success + /// A server side error occurred. + System.Threading.Tasks.Task> GetRecipeOptionSettingsAsync(string recipeId, string projectPath, System.Threading.CancellationToken cancellationToken); + /// Requests to stop the deployment tool. Any open sessions are implicitly closed. /// This may return Microsoft.AspNetCore.Mvc.OkResult prior to the server being stopped, /// clients may need to wait or check the health after requesting shutdown. @@ -1496,6 +1518,97 @@ public async System.Threading.Tasks.Task HealthAsync(System. } } + /// Gets a list of available recipe IDs. + /// Success + /// A server side error occurred. + public System.Threading.Tasks.Task ListAllRecipesAsync(string projectPath) + { + return ListAllRecipesAsync(projectPath, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Gets a list of available recipe IDs. + /// Success + /// A server side error occurred. + public async System.Threading.Tasks.Task ListAllRecipesAsync(string projectPath, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/v1/Recipe/recipes?"); + if (projectPath != null) + { + urlBuilder_.Append(System.Uri.EscapeDataString("projectPath") + "=").Append(System.Uri.EscapeDataString(ConvertToString(projectPath, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } + urlBuilder_.Length--; + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + if (status_ == 400) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad Request", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + /// Gets a summary of the specified Recipe. /// Success /// A server side error occurred. @@ -1591,6 +1704,101 @@ public async System.Threading.Tasks.Task GetRecipeAsync(string re } } + /// Gets a summary of the specified recipe option settings. + /// Success + /// A server side error occurred. + public System.Threading.Tasks.Task> GetRecipeOptionSettingsAsync(string recipeId, string projectPath) + { + return GetRecipeOptionSettingsAsync(recipeId, projectPath, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Gets a summary of the specified recipe option settings. + /// Success + /// A server side error occurred. + public async System.Threading.Tasks.Task> GetRecipeOptionSettingsAsync(string recipeId, string projectPath, System.Threading.CancellationToken cancellationToken) + { + if (recipeId == null) + throw new System.ArgumentNullException("recipeId"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/v1/Recipe/{recipeId}/settings?"); + urlBuilder_.Replace("{recipeId}", System.Uri.EscapeDataString(ConvertToString(recipeId, System.Globalization.CultureInfo.InvariantCulture))); + if (projectPath != null) + { + urlBuilder_.Append(System.Uri.EscapeDataString("projectPath") + "=").Append(System.Uri.EscapeDataString(ConvertToString(projectPath, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } + urlBuilder_.Length--; + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + if (status_ == 400) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad Request", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + /// Requests to stop the deployment tool. Any open sessions are implicitly closed. /// This may return Microsoft.AspNetCore.Mvc.OkResult prior to the server being stopped, /// clients may need to wait or check the health after requesting shutdown. @@ -2019,6 +2227,17 @@ public partial class HealthStatusOutput public SystemStatus Status { get; set; } + } + + /// Output returned by the M:AWS.Deploy.CLI.ServerMode.Controllers.RecipeController.ListAllRecipes(System.String) API + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.1.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class ListAllRecipesOutput + { + /// A list of Recipe IDs + [Newtonsoft.Json.JsonProperty("recipes", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.ICollection Recipes { get; set; } + + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.1.0 (Newtonsoft.Json v13.0.0.0)")] @@ -2145,6 +2364,34 @@ public System.Collections.Generic.IDictionary AdditionalProperti } + } + + /// Represents a recipe AWS.Deploy.Common.Recipes.OptionSettingItem returned through server mode. + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.1.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class RecipeOptionSettingSummary + { + /// The unique id of setting. + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Id { get; set; } + + /// The display friendly name of the setting. + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Name { get; set; } + + /// The description of what the setting is used for. + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Description { get; set; } + + /// The type of primitive value expected for this setting. + /// For example String, Int + [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Type { get; set; } + + /// Child option settings for AWS.Deploy.Common.Recipes.OptionSettingValueType.Object value types. + [Newtonsoft.Json.JsonProperty("settings", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.ICollection Settings { get; set; } + + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.1.0 (Newtonsoft.Json v13.0.0.0)")] diff --git a/src/AWS.Deploy.ServerMode.Client/Utilities/ServerModeUtilities.cs b/src/AWS.Deploy.ServerMode.Client/Utilities/ServerModeUtilities.cs new file mode 100644 index 000000000..906ca366c --- /dev/null +++ b/src/AWS.Deploy.ServerMode.Client/Utilities/ServerModeUtilities.cs @@ -0,0 +1,45 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System; +using Amazon.Runtime; +using System.Threading.Tasks; +using System.Threading; + +namespace AWS.Deploy.ServerMode.Client.Utilities +{ + public static class ServerModeUtilities + { + /// + /// Checks server mode health API and waits until the API returns a `Ready` status. + /// This is useful when initializing a server mode connection to make sure server mode is ready to accept requests. + /// + public static async Task WaitUntilServerModeReady(this RestAPIClient restApiClient, CancellationToken cancellationToken = default(CancellationToken)) + { + await WaitUntilHelper.WaitUntil(async () => + { + var status = SystemStatus.Error; + try + { + status = (await restApiClient.HealthAsync()).Status; + } + catch (Exception) + { + } + + return status == SystemStatus.Ready; + }, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10), cancellationToken); + } + + /// + /// Uses AWS .NET SDK to resolve the default credentials from multiple fallback sources. + /// This includes AWS credentials file stored on the local machine, environment variables , etc... + /// This method does not take into account the AWS Profile and Region defined on the CLI level for AWS Deploy Tool for .NET. + /// + public static Task ResolveDefaultCredentials() + { + var testCredentials = FallbackCredentialsFactory.GetCredentials(); + return Task.FromResult(testCredentials); + } + } +} diff --git a/src/AWS.Deploy.ServerMode.Client/WaitUntilHelper.cs b/src/AWS.Deploy.ServerMode.Client/Utilities/WaitUntilHelper.cs similarity index 88% rename from src/AWS.Deploy.ServerMode.Client/WaitUntilHelper.cs rename to src/AWS.Deploy.ServerMode.Client/Utilities/WaitUntilHelper.cs index c628f239a..ae2bdda33 100644 --- a/src/AWS.Deploy.ServerMode.Client/WaitUntilHelper.cs +++ b/src/AWS.Deploy.ServerMode.Client/Utilities/WaitUntilHelper.cs @@ -6,11 +6,11 @@ using System.Threading; using System.Threading.Tasks; -namespace AWS.Deploy.ServerMode.Client +namespace AWS.Deploy.ServerMode.Client.Utilities { internal static class WaitUntilHelper { - private static async Task WaitUntil(Func> predicate, TimeSpan frequency, TimeSpan timeout, CancellationToken cancellationToken) + public static async Task WaitUntil(Func> predicate, TimeSpan frequency, TimeSpan timeout, CancellationToken cancellationToken) { var waitTask = Task.Run(async () => { diff --git a/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ExistingWindowsEnvironment/ServerModeTests.cs b/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ExistingWindowsEnvironment/ServerModeTests.cs index 06262d7a0..d215dce83 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ExistingWindowsEnvironment/ServerModeTests.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ExistingWindowsEnvironment/ServerModeTests.cs @@ -11,6 +11,7 @@ using AWS.Deploy.CLI.Commands; using AWS.Deploy.CLI.IntegrationTests.Utilities; using AWS.Deploy.ServerMode.Client; +using AWS.Deploy.ServerMode.Client.Utilities; using Xunit; namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests.ExistingWindowsEnvironment @@ -31,7 +32,7 @@ public async Task DeployToExistingWindowsBeanstalkEnvironment() { var projectPath = _fixture.TestAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4031; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_fixture.ToolInteractiveService, portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -42,7 +43,7 @@ public async Task DeployToExistingWindowsBeanstalkEnvironment() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { diff --git a/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ServerModeTests.cs b/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ServerModeTests.cs index 67eeabf7e..4bd214164 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ServerModeTests.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/BeanstalkBackwardsCompatibilityTests/ServerModeTests.cs @@ -12,6 +12,7 @@ using AWS.Deploy.CLI.IntegrationTests.Utilities; using AWS.Deploy.Orchestration.Utilities; using AWS.Deploy.ServerMode.Client; +using AWS.Deploy.ServerMode.Client.Utilities; using Xunit; namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests @@ -32,7 +33,7 @@ public async Task DeployToExistingBeanstalkEnvironment() { var projectPath = _fixture.TestAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4031; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_fixture.ToolInteractiveService, portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -43,7 +44,7 @@ public async Task DeployToExistingBeanstalkEnvironment() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { diff --git a/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/DependencyValidationOptionSettings.cs b/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/DependencyValidationOptionSettings.cs index 2ceee49a4..d83bd19f9 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/DependencyValidationOptionSettings.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/DependencyValidationOptionSettings.cs @@ -15,6 +15,7 @@ using AWS.Deploy.CLI.IntegrationTests.Extensions; using AWS.Deploy.CLI.IntegrationTests.Utilities; using AWS.Deploy.ServerMode.Client; +using AWS.Deploy.ServerMode.Client.Utilities; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -50,7 +51,7 @@ public async Task DependentOptionSettingsGetInvalidated() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4022; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -61,7 +62,7 @@ public async Task DependentOptionSettingsGetInvalidated() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -141,7 +142,7 @@ public async Task SettingInvalidValue() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4022; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -152,7 +153,7 @@ public async Task SettingInvalidValue() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); diff --git a/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/GetApplyOptionSettings.cs b/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/GetApplyOptionSettings.cs index 2d1cf1d19..dc6efed82 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/GetApplyOptionSettings.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/ServerMode/GetApplyOptionSettings.cs @@ -25,6 +25,7 @@ using AWS.Deploy.Orchestration; using AWS.Deploy.Common.IO; using Newtonsoft.Json.Linq; +using AWS.Deploy.ServerMode.Client.Utilities; namespace AWS.Deploy.CLI.IntegrationTests.ServerMode { @@ -68,7 +69,7 @@ public async Task GetAndApplyAppRunnerSettings_RecipeValidatorsAreRun() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4026; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -79,7 +80,7 @@ public async Task GetAndApplyAppRunnerSettings_RecipeValidatorsAreRun() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -114,7 +115,7 @@ public async Task GetAndApplyAppRunnerSettings_FailedUpdatesReturnSettingId() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4027; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -125,7 +126,7 @@ public async Task GetAndApplyAppRunnerSettings_FailedUpdatesReturnSettingId() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -158,7 +159,7 @@ public async Task GetAndApplyAppRunnerSettings_VPCConnector() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4021; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -169,7 +170,7 @@ public async Task GetAndApplyAppRunnerSettings_VPCConnector() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -238,7 +239,7 @@ public async Task GetAppRunnerConfigSettings_TypeHintData() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4002; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -249,7 +250,7 @@ public async Task GetAppRunnerConfigSettings_TypeHintData() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -282,7 +283,7 @@ public async Task GetConfigSettingResources_VpcConnectorOptions() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4023; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -293,7 +294,7 @@ public async Task GetConfigSettingResources_VpcConnectorOptions() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); @@ -337,7 +338,7 @@ public async Task GetAndApplyECSFargateSettings_LoadBalancerSchemeConfig(string var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4024; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); // Running `cdk diff` to assert against the generated CloudFormation template // for this recipe takes longer than the default timeout @@ -352,7 +353,7 @@ public async Task GetAndApplyECSFargateSettings_LoadBalancerSchemeConfig(string var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var sessionId = await restClient.StartDeploymentSession(projectPath, _awsRegion); diff --git a/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs b/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs index 778879e3b..b8355ecc7 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs @@ -23,6 +23,7 @@ using AWS.Deploy.CLI.ServerMode; using AWS.Deploy.Orchestration.Utilities; using AWS.Deploy.ServerMode.Client; +using AWS.Deploy.ServerMode.Client.Utilities; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Xunit; @@ -74,8 +75,8 @@ public async Task ConfirmLocalhostOnly() _ = serverCommand.ExecuteAsync(cancelSource.Token); try { - var restClient = new RestAPIClient($"http://localhost:{portNumber}/", ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials)); - await restClient.WaitTillServerModeReady(); + var restClient = new RestAPIClient($"http://localhost:{portNumber}/", ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials)); + await restClient.WaitUntilServerModeReady(); using var client = new HttpClient(); @@ -97,7 +98,7 @@ public async Task GetRecommendations() { var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4000; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -106,7 +107,7 @@ public async Task GetRecommendations() try { var restClient = new RestAPIClient($"http://localhost:{portNumber}/", httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { @@ -144,7 +145,7 @@ public async Task GetRecommendationsWithEncryptedCredentials() aes.GenerateKey(); aes.GenerateIV(); - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials, aes); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials, aes); var keyInfo = new EncryptionKeyInfo { @@ -163,7 +164,7 @@ public async Task GetRecommendationsWithEncryptedCredentials() try { var restClient = new RestAPIClient($"http://localhost:{portNumber}/", httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { @@ -195,7 +196,7 @@ public async Task WebFargateDeploymentNoConfigChanges() var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4011; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -206,7 +207,7 @@ public async Task WebFargateDeploymentNoConfigChanges() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { @@ -317,7 +318,7 @@ public async Task RecommendationsForNewDeployments_DoesNotIncludeExistingBeansta { var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4002; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -329,7 +330,7 @@ public async Task RecommendationsForNewDeployments_DoesNotIncludeExistingBeansta var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { @@ -357,7 +358,7 @@ public async Task ShutdownViaRestClient() { var portNumber = 4003; var cancelSource = new CancellationTokenSource(); - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var serverTask = serverCommand.ExecuteAsync(cancelSource.Token); @@ -367,7 +368,7 @@ public async Task ShutdownViaRestClient() var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); await restClient.ShutdownAsync(); Thread.Sleep(100); @@ -390,7 +391,7 @@ public async Task InvalidStackName_ThrowsException(string invalidStackName) { var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); var portNumber = 4012; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -401,7 +402,7 @@ public async Task InvalidStackName_ThrowsException(string invalidStackName) var baseUrl = $"http://localhost:{portNumber}/"; var restClient = new RestAPIClient(baseUrl, httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { @@ -435,7 +436,7 @@ public async Task CheckCategories() { var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj")); var portNumber = 4200; - using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeExtensions.ResolveCredentials); + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); var cancelSource = new CancellationTokenSource(); @@ -444,7 +445,7 @@ public async Task CheckCategories() try { var restClient = new RestAPIClient($"http://localhost:{portNumber}/", httpClient); - await restClient.WaitTillServerModeReady(); + await restClient.WaitUntilServerModeReady(); var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput { diff --git a/test/AWS.Deploy.CLI.IntegrationTests/Utilities/ServerModeUtilities.cs b/test/AWS.Deploy.CLI.IntegrationTests/Utilities/ServerModeUtilities.cs index d7b1f7478..4dad736ec 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/Utilities/ServerModeUtilities.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/Utilities/ServerModeUtilities.cs @@ -21,23 +21,6 @@ namespace AWS.Deploy.CLI.IntegrationTests.Utilities { public static class ServerModeExtensions { - public static async Task WaitTillServerModeReady(this RestAPIClient restApiClient) - { - await Orchestration.Utilities.Helpers.WaitUntil(async () => - { - SystemStatus status = SystemStatus.Error; - try - { - status = (await restApiClient.HealthAsync()).Status; - } - catch (Exception) - { - } - - return status == SystemStatus.Ready; - }, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10)); - } - public static async Task StartDeploymentSession(this RestAPIClient restClient, string projectPath, string awsRegion) { var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput @@ -93,12 +76,6 @@ public static CloudFormationTemplateReader GetTemplateMetadataReader(Mock ResolveCredentials() - { - var testCredentials = FallbackCredentialsFactory.GetCredentials(); - return Task.FromResult(testCredentials); - } - public static async Task WaitForDeployment(this RestAPIClient restApiClient, string sessionId) { // Do an initial delay to avoid a race condition of the status being checked before the deployment has kicked off. diff --git a/test/AWS.Deploy.DocGenerator.UnitTests/AWS.Deploy.DocGenerator.UnitTests.csproj b/test/AWS.Deploy.DocGenerator.UnitTests/AWS.Deploy.DocGenerator.UnitTests.csproj new file mode 100644 index 000000000..e33bad108 --- /dev/null +++ b/test/AWS.Deploy.DocGenerator.UnitTests/AWS.Deploy.DocGenerator.UnitTests.csproj @@ -0,0 +1,39 @@ + + + + net6.0 + enable + enable + false + + + + + + + + + Always + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFileGeneratorTests.cs b/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFileGeneratorTests.cs new file mode 100644 index 000000000..0d3cfd841 --- /dev/null +++ b/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFileGeneratorTests.cs @@ -0,0 +1,77 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using AWS.Deploy.DocGenerator.Generators; +using AWS.Deploy.DocGenerator.UnitTests.Utilities; +using AWS.Deploy.ServerMode.Client; +using Moq; +using Xunit; + +namespace AWS.Deploy.DocGenerator.UnitTests +{ + public class DeploymentSettingsFileGeneratorTests + { + private readonly Mock _restClient; + private readonly TestFileManager _fileManager; + + public DeploymentSettingsFileGeneratorTests() + { + _restClient = new Mock(); + _fileManager = new TestFileManager(); + } + + /// + /// Checks if the generated documentation file is producing the same output as a local copy. + /// + [Fact] + public async Task GenerateTest() + { + var recipeSummary = new RecipeSummary { + Id = "AspNetAppAppRunner", + Name = "ASP.NET Core App to AWS App Runner", + Description = "This ASP.NET Core application will be built as a container image on Linux and deployed to AWS App Runner," + + " a fully managed service for web applications and APIs." + + " If your project does not contain a Dockerfile, it will be automatically generated," + + " otherwise an existing Dockerfile will be used. " + + "Recommended if you want to deploy your web application as a Linux container image on a fully managed environment." + }; + var recipeOptionSettingSummary1 = new RecipeOptionSettingSummary + { + Id = "ServiceName", + Name = "Service Name", + Description = "The name of the AWS App Runner service.", + Type = "String", + Settings = new List() + }; + var recipeOptionSettingSummary2 = new RecipeOptionSettingSummary + { + Id = "ApplicationIAMRole", + Name = "Application IAM Role", + Description = "The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services.", + Type = "Object", + Settings = new List + { + new RecipeOptionSettingSummary + { + Id = "CreateNew", + Name = "Create New Role", + Description = "Do you want to create a new role?", + Type = "Bool", + Settings = new List() + } + } + }; + + _restClient.Setup(x => x.ListAllRecipesAsync(It.IsAny())).ReturnsAsync(new ListAllRecipesOutput { Recipes = new List { recipeSummary } }); + _restClient.Setup(x => x.GetRecipeOptionSettingsAsync(It.IsAny(), It.IsAny())).ReturnsAsync(new List { recipeOptionSettingSummary1, recipeOptionSettingSummary2 }); + + var deploymentSettingsFileGenerator = new DeploymentSettingsFileGenerator(_restClient.Object, _fileManager); + await deploymentSettingsFileGenerator.Generate(); + + var filePath = _fileManager.InMemoryStore.Keys.First(); + var actualResult = _fileManager.InMemoryStore[filePath]; + + Assert.Equal(File.ReadAllText("./DeploymentSettingsFiles/AspNetAppAppRunner.md"), actualResult); + } + } +} diff --git a/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFiles/AspNetAppAppRunner.md b/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFiles/AspNetAppAppRunner.md new file mode 100644 index 000000000..293e1ad4c --- /dev/null +++ b/test/AWS.Deploy.DocGenerator.UnitTests/DeploymentSettingsFiles/AspNetAppAppRunner.md @@ -0,0 +1,19 @@ +**Recipe ID:** AspNetAppAppRunner + +**Recipe Description:** This ASP.NET Core application will be built as a container image on Linux and deployed to AWS App Runner, a fully managed service for web applications and APIs. If your project does not contain a Dockerfile, it will be automatically generated, otherwise an existing Dockerfile will be used. Recommended if you want to deploy your web application as a Linux container image on a fully managed environment. + +**Settings:** + +* **Service Name** + * ID: ServiceName + * Description: The name of the AWS App Runner service. + * Type: String +* **Application IAM Role** + * ID: ApplicationIAMRole + * Description: The Identity and Access Management (IAM) role that provides AWS credentials to the application to access AWS services. + * Type: Object + * Settings: + * **Create New Role** + * ID: CreateNew + * Description: Do you want to create a new role? + * Type: Bool diff --git a/test/AWS.Deploy.DocGenerator.UnitTests/Utilities/TestFileManager.cs b/test/AWS.Deploy.DocGenerator.UnitTests/Utilities/TestFileManager.cs new file mode 100644 index 000000000..15bee2eb2 --- /dev/null +++ b/test/AWS.Deploy.DocGenerator.UnitTests/Utilities/TestFileManager.cs @@ -0,0 +1,27 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using AWS.Deploy.Common.IO; + +namespace AWS.Deploy.DocGenerator.UnitTests.Utilities +{ + public class TestFileManager : IFileManager + { + public readonly Dictionary InMemoryStore = new Dictionary(); + + public bool Exists(string path) => throw new NotImplementedException(); + public bool Exists(string path, string directory) => throw new NotImplementedException(); + public string GetExtension(string filePath) => throw new NotImplementedException(); + public long GetSizeInBytes(string filePath) => throw new NotImplementedException(); + public bool IsFileValidPath(string filePath) => throw new NotImplementedException(); + public FileStream OpenRead(string filePath) => throw new NotImplementedException(); + public Task ReadAllLinesAsync(string path) => throw new NotImplementedException(); + public Task ReadAllTextAsync(string path) => throw new NotImplementedException(); + + public Task WriteAllTextAsync(string filePath, string contents, CancellationToken cancellationToken = default) + { + InMemoryStore[filePath] = contents; + return Task.CompletedTask; + } + } +}