From 18b2aff053d7b25c0ff17f52cdfa4e2c70ebad66 Mon Sep 17 00:00:00 2001 From: Pavel Bobov Date: Wed, 3 Apr 2024 13:45:13 -0700 Subject: [PATCH 1/2] #14 Updated test workflows --- aws/README.md | 2 +- .../enterprise-base-linux-aws-test.yaml | 20 ++---- .../enterprise-base-windows-aws-test.yaml | 20 ++---- aws/arcgis-enterprise-k8s/README.md | 18 ++---- aws/arcgis-enterprise-k8s/image/README.md | 25 +++++--- .../image/build-admin-cli-image.sh | 49 +++++++++++++++ .../image/copy-docker-hub-images.sh | 2 +- .../image/copy-public-ecr-images.sh | 58 ------------------ .../workflows/enterprise-k8s-aws-image.yaml | 29 +++++---- .../workflows/enterprise-k8s-aws-test.yaml | 28 ++++----- aws/arcgis-site-core/k8s-cluster/README.md | 2 +- aws/arcgis-site-core/k8s-cluster/main.tf | 1 + .../load-balancer-controller/README.md | 9 ++- .../copy-public-ecr-image.sh | 54 ++++++++++++++++ .../modules/load-balancer-controller/main.tf | 24 +++++++- .../load-balancer-controller/variables.tf | 18 +++++- aws/iam-policies/ArcGISEnterpriseK8s.json | 2 + enterprise-admin-cli/Dockerfile | 8 +++ enterprise-admin-cli/README.md | 23 +++++++ .../samples}/earthquakes.csv | 0 .../samples}/earthquakes.png | Bin .../tools/publish_csv.py | 6 +- 22 files changed, 252 insertions(+), 146 deletions(-) create mode 100644 aws/arcgis-enterprise-k8s/image/build-admin-cli-image.sh delete mode 100644 aws/arcgis-enterprise-k8s/image/copy-public-ecr-images.sh create mode 100644 aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/copy-public-ecr-image.sh create mode 100644 enterprise-admin-cli/Dockerfile create mode 100644 enterprise-admin-cli/README.md rename {aws/tests => enterprise-admin-cli/samples}/earthquakes.csv (100%) rename {aws/tests => enterprise-admin-cli/samples}/earthquakes.png (100%) rename aws/tests/arcgis-enterprise-base-test.py => enterprise-admin-cli/tools/publish_csv.py (94%) diff --git a/aws/README.md b/aws/README.md index 55e0334..900d240 100644 --- a/aws/README.md +++ b/aws/README.md @@ -38,7 +38,7 @@ Deployments configured to receive traffic from clients are referred to as *prima The following templates are available for AWS: * [arcgis-site-core](arcgis-site-core/README.md) - Provision core AWS resources for ArcGIS Enterprise site -* [arcgis-enterprise-base-windows](arcgis-enterprise-base-windows/README.md) - Base ArcGIS Enterprise on Windows deployment operations +* [arcgis-enterprise-base-windows](arcgis-enterprise-base-linux-windows/README.md) - Base ArcGIS Enterprise on Windows deployment operations * [arcgis-enterprise-base-linux](arcgis-enterprise-base-linux/README.md) - Base ArcGIS Enterprise on Linux deployment operations * [arcgis-enterprise-k8s](arcgis-enterprise-k8s/README.md) - ArcGIS Enterprise on Kubernetes deployment operations diff --git a/aws/arcgis-enterprise-base-linux/workflows/enterprise-base-linux-aws-test.yaml b/aws/arcgis-enterprise-base-linux/workflows/enterprise-base-linux-aws-test.yaml index c18b1e5..70f070d 100644 --- a/aws/arcgis-enterprise-base-linux/workflows/enterprise-base-linux-aws-test.yaml +++ b/aws/arcgis-enterprise-base-linux/workflows/enterprise-base-linux-aws-test.yaml @@ -4,7 +4,6 @@ on: workflow_dispatch: env: - PYTHONPATH: ${{ github.workspace }}/aws/tests CONFIG_FILE: ${{ github.workspace }}/config/aws/arcgis-enterprise-base-linux/application.tfvars.json jobs: @@ -13,7 +12,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ${{ github.workspace }}/aws/tests + working-directory: ${{ github.workspace }}/enterprise-admin-cli permissions: contents: read pull-requests: write @@ -22,20 +21,13 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.ref_name }} - - name: Setup Conda - uses: conda-incubator/setup-miniconda@v3 - with: - auto-activate-base: true - activate-environment: "" - - name: Install ArcGIS API for Python - id: install-arcgis + - name: Build Container Image run: | - conda install python=3.10 jupyter - conda install -c esri arcgis - - name: Run Test - id: test + docker build -t enterprise-admin-cli . + - name: Run Tests run: | DEPLOYMENT_FQDN=$(jq -r '.deployment_fqdn' $CONFIG_FILE) + ARCGIS_ENTERPRISE_CONTEXT=portal ADMIN_USERNAME=$(jq -r '.admin_username' $CONFIG_FILE) ADMIN_PASSWORD=$(jq -r '.admin_password' $CONFIG_FILE) - /usr/share/miniconda/bin/python arcgis-enterprise-base-test.py -a https://$DEPLOYMENT_FQDN/portal -u $ADMIN_USERNAME -p $ADMIN_PASSWORD + docker run enterprise-admin-cli python publish_csv.py -a https://$DEPLOYMENT_FQDN/$ARCGIS_ENTERPRISE_CONTEXT -u $ADMIN_USERNAME -p $ADMIN_PASSWORD diff --git a/aws/arcgis-enterprise-base-windows/workflows/enterprise-base-windows-aws-test.yaml b/aws/arcgis-enterprise-base-windows/workflows/enterprise-base-windows-aws-test.yaml index a94bcd3..885e518 100644 --- a/aws/arcgis-enterprise-base-windows/workflows/enterprise-base-windows-aws-test.yaml +++ b/aws/arcgis-enterprise-base-windows/workflows/enterprise-base-windows-aws-test.yaml @@ -4,7 +4,6 @@ on: workflow_dispatch: env: - PYTHONPATH: ${{ github.workspace }}/aws/tests CONFIG_FILE: ${{ github.workspace }}/config/aws/arcgis-enterprise-base-windows/application.tfvars.json jobs: @@ -13,7 +12,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ${{ github.workspace }}/aws/tests + working-directory: ${{ github.workspace }}/enterprise-admin-cli permissions: contents: read pull-requests: write @@ -22,20 +21,13 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.ref_name }} - - name: Setup Conda - uses: conda-incubator/setup-miniconda@v3 - with: - auto-activate-base: true - activate-environment: "" - - name: Install ArcGIS API for Python - id: install-arcgis + - name: Build Container Image run: | - conda install python=3.10 jupyter - conda install -c esri arcgis - - name: Run Test - id: test + docker build -t enterprise-admin-cli . + - name: Run Tests run: | DEPLOYMENT_FQDN=$(jq -r '.deployment_fqdn' $CONFIG_FILE) + ARCGIS_ENTERPRISE_CONTEXT=portal ADMIN_USERNAME=$(jq -r '.admin_username' $CONFIG_FILE) ADMIN_PASSWORD=$(jq -r '.admin_password' $CONFIG_FILE) - /usr/share/miniconda/bin/python arcgis-enterprise-base-test.py -a https://$DEPLOYMENT_FQDN/portal -u $ADMIN_USERNAME -p $ADMIN_PASSWORD + docker run enterprise-admin-cli python publish_csv.py -a https://$DEPLOYMENT_FQDN/$ARCGIS_ENTERPRISE_CONTEXT -u $ADMIN_USERNAME -p $ADMIN_PASSWORD diff --git a/aws/arcgis-enterprise-k8s/README.md b/aws/arcgis-enterprise-k8s/README.md index ebd04b7..bc3d48f 100644 --- a/aws/arcgis-enterprise-k8s/README.md +++ b/aws/arcgis-enterprise-k8s/README.md @@ -18,19 +18,15 @@ To enable the template's workflows, copy the .yaml files from the template's `wo ## Initial Deployment -Initial deployment of ArcGIS Enterprise on Kubernetes includes: creating ingress controller creating ArcGIS Enterprise organization, and testing the deployment web services. +Initial deployment of ArcGIS Enterprise on Kubernetes includes: provisioning container images, creating ingress controller creating ArcGIS Enterprise organization, and testing the deployment web services. -> If pull through cache rules are not configured for Amazon ECR, The container images must be copied to the Amazon ECR private repositories. +> The IAM principal used by the templates's workflows must have the EKS cluster administrator permissions. The IAM principal used to create the EKS cluster is granted the required permissions by site-k8s-cluster-aws workflow. -> The IAM principal used by the templates's workflows must have the EKS cluster administrator permissions. The IAM principal used to create the EKS cluster has the cluster administrator permissions by default. +### 1. Provisioning Container Images -### 1. Copy Container Images to Amazon ECR +GitHub Actions workflow **enterprise-k8s-aws-image** builds container image for [Enterprise Admin CLI](../../enterprise-admin-cli/README.md) and pushes it to private AWS Elastic Container Registry (ECR) repository. Optionally, if pull through cache is not enabled in the ECR, the workflow also copies container images of the ArcGIS Enterprise on Kubernetes version from DockerHub to the private ECR repositories. -GitHub Actions workflow **enterprise-k8s-aws-image** copies the ArcGIS Enterprise on Kubernetes container images from DockerHub to private AWS Elastic Container Registry (ECR) repositories. - -In advance copying of images is not required if [pull through cache rules](https://docs.aws.amazon.com/AmazonECR/latest/userguide/pull-through-cache.html) are configured for Amazon ECR private repositories. But for some AWS regions, such as AWS GovCloud and China, pull through cache rules are not supported. - -The workflow uses [image-copy-ecr](image/README.md) script with [image.vars.json](../../config/aws/arcgis-enterprise-k8s/image.vars.json) config file. +The workflow uses [shell scripts](image/README.md) with [image.vars.json](../../config/aws/arcgis-enterprise-k8s/image.vars.json) config file. Required IAM policies: @@ -106,14 +102,12 @@ Instructions: GitHub Actions workflow **enterprise-k8s-aws-test** tests the ArcGIS Enterprise deployment. -The python [test script](../tests/arcgis-enterprise-base-test.py) uses [ArcGIS API for Python](https://developers.arcgis.com/python/) to publish a CSV file to the Portal for ArcGIS URL. The portal domain name and admin credentials are retrieved from organization.tfvars.json properties file. +The workflow uses publish-csv.py tool from the [Enterprise Admin CLI](../../enterprise-admin-cli/README.md) container image to test the deployment's service. The deployment FQDN and admin credentials are retrieved from [organization.tfvars.json](../../config/aws/arcgis-enterprise-k8s/organization.tfvars.json) config file. Instructions: 1. Run enterprise-k8s-aws-test workflow using the branch. -> Note: enterprise-k8s-aws-test requires the ArcGIS Enterprise deployment to be accessible from the GitHub Actions runner. - ## Backups and Disaster Recovery TBD diff --git a/aws/arcgis-enterprise-k8s/image/README.md b/aws/arcgis-enterprise-k8s/image/README.md index 8f3173b..ea91c2a 100644 --- a/aws/arcgis-enterprise-k8s/image/README.md +++ b/aws/arcgis-enterprise-k8s/image/README.md @@ -1,25 +1,32 @@ -# Copy Container Images from DockerHub to Amazon ECR +# Scripts for Provisioning Container Images in Amazon ECR Amazon ECR is a fully managed container registry that provides a secure, scalable, and reliable registry for container images on AWS. -Script image-copy-ecr copies the ArcGIS Enterprise on Kubernetes container images from Docker Hub to AWS Elastic Container Registry (ECR) repositories in specific AWS account and region. - ## Requirements -On the machine where the script is run, the following tools must be installed: +On the machine where the scripts are run, the following tools must be installed: * [AWS CLI](https://aws.amazon.com/cli/) * [Docker](https://www.docker.com/) The AWS CLI must be configured with the appropriate AWS credentials and region must be set by AWS_DEFAULT_REGION environment variable. -The DockerHub credentials must be set by environment variables `CONTAINER_REGISTRY_USER` and `CONTAINER_REGISTRY_PASSWORD`. The DockerHub container registry organization must be set by environment variable `CONTAINER_REGISTRY_ORG`. +## build-admin-cli-image.sh -`ECR_REPOSITORY_PREFIX` environment variable must be set to the prefix of the ECR repository name that matches the value "of ecr_repository_prefix" setting used for the k8s-cluster configuration. +Builds container image for Enterprise Admin CLI and pushes it to private ECR repository in the AWS region. + +```bash +chmod +x ./build-admin-cli-image.sh +./build-admin-cli-image.sh +``` -The script requires at least 20GB of free disk space on the machine to temporary store the container images. +## copy-docker-hub-images.sh -## Usage +Copies ArcGIS Enterprise for Kubernetes images from DockerHub registry to private Amazon ECR repositories in the AWS region. + +The DockerHub credentials must be set by environment variables `CONTAINER_REGISTRY_USER` and `CONTAINER_REGISTRY_PASSWORD`. The DockerHub container registry organization must be set by environment variable `CONTAINER_REGISTRY_ORG`. + +`ECR_REPOSITORY_PREFIX` environment variable must be set to the prefix of the ECR repository name that matches the value "of ecr_repository_prefix" setting used for the k8s-cluster configuration. ```bash chmod +x ./copy-docker-hub-images.sh @@ -27,3 +34,5 @@ chmod +x ./copy-docker-hub-images.sh ``` The Esri-published version manifest is a JSON file that contains a list of images for a specific ArcGIS Enterprise on Kubernetes version, which are to be copied to ECR. This manifest file can be downloaded from a URL specified by the VERSION_MANIFEST_URL property in the `arcgis-enterprise//setup/.install/arcgis-enterprise/arcgis-enterprise.properties` file, located within the ArcGIS Enterprise on Kubernetes setup scripts for that particular version of ArcGIS Enterprise on Kubernetes. + +> The script requires at least 20GB of free disk space on the machine to temporary store the container images. diff --git a/aws/arcgis-enterprise-k8s/image/build-admin-cli-image.sh b/aws/arcgis-enterprise-k8s/image/build-admin-cli-image.sh new file mode 100644 index 0000000..15e6d2c --- /dev/null +++ b/aws/arcgis-enterprise-k8s/image/build-admin-cli-image.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# This script builds container image for Enterprise Admin CLI and pushes it to +# private ECR repository in the AWS region. +# +# On the machine where the script is executed: +# +# * AWS CLI and Docker must be installed +# * AWS credentials must be configured for AWS CLI +# * AWS region must be specified by AWS_DEFAULT_REGION environment variable + +set -e + +ECR_REPOSITORY_NAME=$1 +BUILD_CONTEXT_PATH=$2 +TAG=0.1.0 + +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +ECR_REGISTRY_URL=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com +IMAGE_TAG=$ECR_REGISTRY_URL/$ECR_REPOSITORY_NAME:$TAG + +aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY_URL + +set +e + +aws ecr describe-repositories --repository-names $ECR_REPOSITORY_NAME + +# Create ECR repository if it does not exist +if [ $? -ne 0 ] +then + aws ecr create-repository --repository-name $ECR_REPOSITORY_NAME --image-scanning-configuration scanOnPush=true --image-tag-mutability IMMUTABLE + echo "ECR repository '${ECR_REPOSITORY_NAME}' created." +else + echo "ECR repository '${ECR_REPOSITORY_NAME}' already exists." +fi + +aws ecr describe-images --repository-name $ECR_REPOSITORY_NAME --image-ids imageTag=$TAG + +# Copy image to the ECR repository if it does not exist +if [[ $? == 0 ]]; then + echo "Image $ECR_REPOSITORY_NAME:$TAG is already in the ECR repository" +else + set -e + + docker build -t $IMAGE_TAG $BUILD_CONTEXT_PATH + docker push $IMAGE_TAG + + echo "Image $ECR_REPOSITORY_NAME:$TAG copied." +fi \ No newline at end of file diff --git a/aws/arcgis-enterprise-k8s/image/copy-docker-hub-images.sh b/aws/arcgis-enterprise-k8s/image/copy-docker-hub-images.sh index 65603f5..075f868 100644 --- a/aws/arcgis-enterprise-k8s/image/copy-docker-hub-images.sh +++ b/aws/arcgis-enterprise-k8s/image/copy-docker-hub-images.sh @@ -1,7 +1,7 @@ #!/bin/bash # This script copies ArcGIS Enterprise for Kubernetes images from DockerHub -# registry to Amazon ECR. +# registry to private Amazon ECR repositories. # # Required environment variables: # CONTAINER_REGISTRY_ORG - The container registry organization diff --git a/aws/arcgis-enterprise-k8s/image/copy-public-ecr-images.sh b/aws/arcgis-enterprise-k8s/image/copy-public-ecr-images.sh deleted file mode 100644 index 46aaf39..0000000 --- a/aws/arcgis-enterprise-k8s/image/copy-public-ecr-images.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -# This script copies images from public to private Amazon ECR registries. -# -# Required environment variables: -# AWS_DEFAULT_REGION - The AWS default region - -set -e - -IMAGE_LIST=("eks/aws-load-balancer-controller:v2.7.1") -PUBLIC_REGISTRY_URL=public.ecr.aws -ECR_REPOSITORY_PREFIX=ecr-public -AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) -ECR_REGISTRY_URL=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com - -aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY_URL - -for REPO_WITH_TAG in $IMAGE_LIST -do - REPOSITORY_NAME=$(echo $REPO_WITH_TAG | cut -d: -f1) - TAG=$(echo $REPO_WITH_TAG | cut -d: -f2) - - PUBLIC_IMAGE=$PUBLIC_REGISTRY_URL/$REPOSITORY_NAME:$TAG - ECR_REPOSITORY_NAME=$ECR_REPOSITORY_PREFIX/$REPOSITORY_NAME - IMAGE=$ECR_REGISTRY_URL/$ECR_REPOSITORY_NAME:$TAG - - set +e - - aws ecr describe-repositories --repository-names "${ECR_REPOSITORY_NAME}" > /dev/null 2>&1 - - # Create ECR repository if it does not exist - if [ $? -ne 0 ] - then - aws ecr create-repository --repository-name "${ECR_REPOSITORY_NAME}" --image-scanning-configuration scanOnPush=true --image-tag-mutability IMMUTABLE - echo "ECR repository '${ECR_REPOSITORY_NAME}' created." - else - echo "ECR repository '${ECR_REPOSITORY_NAME}' already exists." - fi - - aws ecr describe-images --repository-name $ECR_REPOSITORY_NAME --image-ids imageTag=$TAG > /dev/null 2>&1 - - # Copy image to the ECR repository if it does not exist - if [[ $? == 0 ]]; then - echo "Image $ECR_REPOSITORY_NAME:$TAG is already in the ECR repository" - else - set -e - - docker pull -q $PUBLIC_IMAGE - - docker tag $PUBLIC_IMAGE $IMAGE - - docker push -q $IMAGE - - docker rmi $PUBLIC_IMAGE $IMAGE > /dev/null 2>&1 - - echo "Image $ECR_REPOSITORY_NAME:$TAG copied." - fi -done \ No newline at end of file diff --git a/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-image.yaml b/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-image.yaml index c787f04..4ebb2e2 100644 --- a/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-image.yaml +++ b/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-image.yaml @@ -36,17 +36,22 @@ jobs: docker rmi node:16 node:18 node:20 > /dev/null 2>&1 - name: Copy Docker Hub images run: | - ARCGIS_VERSION=$(jq -r '.arcgis_version' $CONFIG_FILE) - export CONTAINER_REGISTRY_ORG=$(jq -r '.container_registry_org' $CONFIG_FILE) - export ECR_REPOSITORY_PREFIX=$(jq -r '.ecr_repository_prefix' $CONFIG_FILE) - echo "ArcGIS Enterprise version: $ARCGIS_VERSION" - echo "Container registry org: $CONTAINER_REGISTRY_ORG" - echo "ECR repository prefix: $ECR_REPOSITORY_PREFIX" - MANIFEST_PATH=./manifests/$ARCGIS_VERSION.dat - chmod +x ./copy-docker-hub-images.sh - ./copy-docker-hub-images.sh $MANIFEST_PATH - - name: Copy Public ECR images + PULL_THROUGH_CACHE=$(jq -r '.pull_through_cache' $CONFIG_FILE) + if [ "$PULL_THROUGH_CACHE" == "true" ]; then + echo "Skip copying Docker Hub images because pull through cache is enabled." + else + ARCGIS_VERSION=$(jq -r '.arcgis_version' $CONFIG_FILE) + export CONTAINER_REGISTRY_ORG=$(jq -r '.container_registry_org' $CONFIG_FILE) + export ECR_REPOSITORY_PREFIX=$(jq -r '.ecr_repository_prefix' $CONFIG_FILE) + echo "ArcGIS Enterprise version: $ARCGIS_VERSION" + echo "Container registry org: $CONTAINER_REGISTRY_ORG" + echo "ECR repository prefix: $ECR_REPOSITORY_PREFIX" + MANIFEST_PATH=./manifests/$ARCGIS_VERSION.dat + chmod +x ./copy-docker-hub-images.sh + ./copy-docker-hub-images.sh $MANIFEST_PATH + fi + - name: Build Admin CLI Image run: | - chmod +x ./copy-public-ecr-images.sh - ./copy-public-ecr-images.sh + chmod +x ./build-admin-cli-image.sh + ./build-admin-cli-image.sh enterprise-admin-cli ${{ github.workspace }}/enterprise-admin-cli \ No newline at end of file diff --git a/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-test.yaml b/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-test.yaml index 8ad9c05..0d08e16 100644 --- a/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-test.yaml +++ b/aws/arcgis-enterprise-k8s/workflows/enterprise-k8s-aws-test.yaml @@ -4,7 +4,9 @@ on: workflow_dispatch: env: - PYTHONPATH: ${{ github.workspace }}/aws/tests + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }} CONFIG_FILE: ${{ github.workspace }}/config/aws/arcgis-enterprise-k8s/organization.tfvars.json jobs: @@ -13,7 +15,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ${{ github.workspace }}/aws/tests + working-directory: ${{ github.workspace }}/enterprise-admin-cli permissions: contents: read pull-requests: write @@ -22,21 +24,17 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.ref_name }} - - name: Setup Conda - uses: conda-incubator/setup-miniconda@v3 - with: - auto-activate-base: true - activate-environment: "" - - name: Install ArcGIS API for Python - id: install-arcgis - run: | - conda install python=3.10 jupyter - conda install -c esri arcgis - - name: Run Test - id: test + - name: Run Tests run: | + SITE_ID=$(jq -r '.site_id' $CONFIG_FILE) DEPLOYMENT_FQDN=$(jq -r '.deployment_fqdn' $CONFIG_FILE) ARCGIS_ENTERPRISE_CONTEXT=$(jq -r '.arcgis_enterprise_context' $CONFIG_FILE) ADMIN_USERNAME=$(jq -r '.admin_username' $CONFIG_FILE) ADMIN_PASSWORD=$(jq -r '.admin_password' $CONFIG_FILE) - /usr/share/miniconda/bin/python arcgis-enterprise-base-test.py -a https://$DEPLOYMENT_FQDN/$ARCGIS_ENTERPRISE_CONTEXT -u $ADMIN_USERNAME -p $ADMIN_PASSWORD + AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + ECR_REGISTRY_URL=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com + ECR_REPOSITORY_NAME=enterprise-admin-cli + TAG=0.1.0 + IMAGE_TAG=$ECR_REGISTRY_URL/$ECR_REPOSITORY_NAME:$TAG + aws eks update-kubeconfig --region $AWS_DEFAULT_REGION --name $SITE_ID + kubectl run -i --rm enterprise-k8s-aws-test --attach --image=$IMAGE_TAG --restart=Never --command -- python publish_csv.py -a https://$DEPLOYMENT_FQDN/$ARCGIS_ENTERPRISE_CONTEXT -u $ADMIN_USERNAME -p $ADMIN_PASSWORD diff --git a/aws/arcgis-site-core/k8s-cluster/README.md b/aws/arcgis-site-core/k8s-cluster/README.md index 372054a..3b51fae 100644 --- a/aws/arcgis-site-core/k8s-cluster/README.md +++ b/aws/arcgis-site-core/k8s-cluster/README.md @@ -72,7 +72,7 @@ thesubnet IDs are retrieved from the following SSM parameters: | container_registry_user | Source container registry user name | `string` | `null` | no | | ecr_repository_prefix | The repository name prefix to use when caching images from the source registry | `string` | `"docker-hub"` | no | | eks_version | The desired Kubernetes version for the EKS cluster | `string` | `"1.28"` | no | -| enable_waf | Enable WAF addons for ALB | `bool` | `true` | no | +| enable_waf | Enable WAF and Shield addons for ALB | `bool` | `true` | no | | key_name | EC2 key pair name | `string` | `null` | no | | node_groups |

EKS node groups configuration properties:

  • name - Name of the node group
  • instance_type -Type of EC2 instance to use for the node group
  • root_volume_size - Size of the root volume in GB
  • desired_size - Number of nodes to start with
  • max_size - Maximum number of nodes in the node group
  • min_size - Minimum number of nodes in the node group
  • subnet_ids - List of subnet IDs to use for the node group (the first two private subnets are used by default)
| ```list(object({ name = string instance_type = string root_volume_size = number desired_size = number max_size = number min_size = number subnet_ids = list(string) }))``` | ```[ { "desired_size": 4, "instance_type": "m6i.2xlarge", "max_size": 8, "min_size": 4, "name": "default", "root_volume_size": 1024, "subnet_ids": [] } ]``` | no | | pull_through_cache | Configure ECR pull through cache rules | `bool` | `true` | no | diff --git a/aws/arcgis-site-core/k8s-cluster/main.tf b/aws/arcgis-site-core/k8s-cluster/main.tf index e6a8364..8d06afa 100644 --- a/aws/arcgis-site-core/k8s-cluster/main.tf +++ b/aws/arcgis-site-core/k8s-cluster/main.tf @@ -186,6 +186,7 @@ module "load_balancer_controller" { cluster_name = aws_eks_cluster.cluster.name oidc_arn = aws_iam_openid_connect_provider.eks_oidc.arn enable_waf = var.enable_waf + copy_image = !var.pull_through_cache depends_on = [ aws_eks_cluster.cluster diff --git a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/README.md b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/README.md index acc641e..6d96995 100644 --- a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/README.md +++ b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/README.md @@ -7,7 +7,7 @@ See: https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controll ## Requirements -On the machine where terraform is executed must be installed AWS CLI, kubectl, and helm. +On the machine where terraform is executed must be installed AWS CLI, kubectl, helm, and Docker. ## Providers @@ -25,6 +25,7 @@ On the machine where terraform is executed must be installed AWS CLI, kubectl, a | [aws_iam_role.aws_eks_load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.aws_eks_load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [local_file.service_account](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [null_resource.copy_public_ecr_image](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.helm_install](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.service_account](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.update_kubeconfig](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | @@ -35,7 +36,9 @@ On the machine where terraform is executed must be installed AWS CLI, kubectl, a | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| cluster_name | The name of the EKS cluster | `string` | n/a | yes | +| cluster_name | Name of the EKS cluster | `string` | n/a | yes | +| controller_version | Version of the AWS Load Balancer Controller | `string` | `"2.7.0"` | no | +| copy_image | If set to true, the controller's image is copied to the private ECR repository | `bool` | `false` | no | | enable_waf | Enable WAF and Shield addons for ALB | `bool` | `true` | no | -| oidc_arn | The OIDC provider ARN for the EKS cluster | `string` | n/a | yes | +| oidc_arn | OIDC provider ARN for the EKS cluster | `string` | n/a | yes | \ No newline at end of file diff --git a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/copy-public-ecr-image.sh b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/copy-public-ecr-image.sh new file mode 100644 index 0000000..1e2e88e --- /dev/null +++ b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/copy-public-ecr-image.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# This script copies image from public to private Amazon ECR registries. +# +# Required environment variables: +# AWS_DEFAULT_REGION - The AWS default region + +set -e + +REPO_WITH_TAG=$1 + +PUBLIC_REGISTRY_URL=public.ecr.aws +ECR_REPOSITORY_PREFIX=ecr-public +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +ECR_REGISTRY_URL=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com +REPOSITORY_NAME=$(echo $REPO_WITH_TAG | cut -d: -f1) +TAG=$(echo $REPO_WITH_TAG | cut -d: -f2) +PUBLIC_IMAGE=$PUBLIC_REGISTRY_URL/$REPOSITORY_NAME:$TAG +ECR_REPOSITORY_NAME=$ECR_REPOSITORY_PREFIX/$REPOSITORY_NAME +IMAGE=$ECR_REGISTRY_URL/$ECR_REPOSITORY_NAME:$TAG + +aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY_URL + +set +e + +aws ecr describe-repositories --repository-names "${ECR_REPOSITORY_NAME}" > /dev/null 2>&1 + +# Create ECR repository if it does not exist +if [ $? -ne 0 ] +then + aws ecr create-repository --repository-name "${ECR_REPOSITORY_NAME}" --image-scanning-configuration scanOnPush=true --image-tag-mutability IMMUTABLE + echo "ECR repository '${ECR_REPOSITORY_NAME}' created." +else + echo "ECR repository '${ECR_REPOSITORY_NAME}' already exists." +fi + +aws ecr describe-images --repository-name $ECR_REPOSITORY_NAME --image-ids imageTag=$TAG > /dev/null 2>&1 + +# Copy image to the ECR repository if it does not exist +if [[ $? == 0 ]]; then + echo "Image $ECR_REPOSITORY_NAME:$TAG is already in the ECR repository" +else + set -e + + docker pull -q $PUBLIC_IMAGE + + docker tag $PUBLIC_IMAGE $IMAGE + + docker push -q $IMAGE + + docker rmi $PUBLIC_IMAGE $IMAGE > /dev/null 2>&1 + + echo "Image $ECR_REPOSITORY_NAME:$TAG copied." +fi diff --git a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/main.tf b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/main.tf index 67d0910..ce35723 100644 --- a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/main.tf +++ b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/main.tf @@ -7,7 +7,7 @@ * * ## Requirements * - * On the machine where terraform is executed must be installed AWS CLI, kubectl, and helm. + * On the machine where terraform is executed must be installed AWS CLI, kubectl, helm, and Docker. */ data "aws_caller_identity" "current" {} @@ -15,11 +15,14 @@ data "aws_region" "current" {} locals { oidc_provider = "oidc.eks.${data.aws_region.current.name}.amazonaws.com/id/${split("/", var.oidc_arn)[3]}" + image_repo = "eks/aws-load-balancer-controller" + image_tag = "v${var.controller_version}" helm_values = { "clusterName" = var.cluster_name "serviceAccount.create" = false "serviceAccount.name" = "aws-load-balancer-controller" - "image.repository" = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/ecr-public/eks/aws-load-balancer-controller" + "image.repository" = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/ecr-public/${local.image_repo}" + "image.tag" = local.image_tag "enableShield" = var.enable_waf "enableWaf" = var.enable_waf "enableWafv2" = var.enable_waf @@ -77,6 +80,22 @@ resource "local_file" "service_account" { ] } +resource "null_resource" "copy_public_ecr_image" { + count = var.copy_image ? 1 : 0 + + triggers = { + always_run = "${timestamp()}" + } + + provisioner "local-exec" { + command = "chmod +x ${path.module}/copy-public-ecr-image.sh" + } + + provisioner "local-exec" { + command = "${path.module}/copy-public-ecr-image.sh ${local.image_repo}:${local.image_tag}" + } +} + # Ideally, instead of local-exec provisioner, the module should use kubernetes and helm terraform providers, # but the providers do not support initialization of k8s credentials after initialization of the providers. @@ -127,6 +146,7 @@ resource "null_resource" "helm_install" { } depends_on = [ + null_resource.copy_public_ecr_image, null_resource.service_account ] } diff --git a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/variables.tf b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/variables.tf index 6794534..455a92f 100644 --- a/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/variables.tf +++ b/aws/arcgis-site-core/k8s-cluster/modules/load-balancer-controller/variables.tf @@ -1,10 +1,16 @@ +variable "controller_version" { + description = "Version of the AWS Load Balancer Controller" + type = string + default = "2.7.0" +} + variable "cluster_name" { - description = "The name of the EKS cluster" + description = "Name of the EKS cluster" type = string } variable "oidc_arn" { - description = "The OIDC provider ARN for the EKS cluster" + description = "OIDC provider ARN for the EKS cluster" type = string } @@ -12,4 +18,10 @@ variable "enable_waf" { description = "Enable WAF and Shield addons for ALB" type = bool default = true -} \ No newline at end of file +} + +variable "copy_image" { + description = "If set to true, the controller's image is copied to the private ECR repository" + type = bool + default = false +} diff --git a/aws/iam-policies/ArcGISEnterpriseK8s.json b/aws/iam-policies/ArcGISEnterpriseK8s.json index ca712ba..445bf13 100644 --- a/aws/iam-policies/ArcGISEnterpriseK8s.json +++ b/aws/iam-policies/ArcGISEnterpriseK8s.json @@ -5,12 +5,14 @@ "Effect": "Allow", "Action": [ "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", "ecr:CompleteLayerUpload", "ecr:CreateRepository", "ecr:DeleteRepository", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:GetAuthorizationToken", + "ecr:GetDownloadUrlForLayer", "ecr:InitiateLayerUpload", "ecr:ListTagsForResource", "ecr:PutImage", diff --git a/enterprise-admin-cli/Dockerfile b/enterprise-admin-cli/Dockerfile new file mode 100644 index 0000000..7a04493 --- /dev/null +++ b/enterprise-admin-cli/Dockerfile @@ -0,0 +1,8 @@ +FROM ghcr.io/esri/arcgis-python-api-notebook:latest + +ADD tools/ /cli/tools/ +ADD samples/ /cli/samples/ + +WORKDIR /cli/tools + +CMD ["python", "publish_csv.py"] diff --git a/enterprise-admin-cli/README.md b/enterprise-admin-cli/README.md new file mode 100644 index 0000000..79c356a --- /dev/null +++ b/enterprise-admin-cli/README.md @@ -0,0 +1,23 @@ +# Enterprise Admin CLI + +Enterprise Admin CLI is a command line interface for ArcGIS Enterprise configuration management. + +The CLI uses [ArcGIS API for Python](https://developers.arcgis.com/python/) as well as standalone Python modules to call ArcGIS Enterprise web services. + +## publish_csv + +Tests ArcGIS Enterprise portal by publishing a feature service from CSV file. + +Usage: + +```shell +python -m publish_csv -a -u -p +``` + +Options: + +```text +-a (string) Portal for ArcGIS URL +-u (string) Portal for ArcGIS user name +-p (string) Portal for ArcGIS user password +``` diff --git a/aws/tests/earthquakes.csv b/enterprise-admin-cli/samples/earthquakes.csv similarity index 100% rename from aws/tests/earthquakes.csv rename to enterprise-admin-cli/samples/earthquakes.csv diff --git a/aws/tests/earthquakes.png b/enterprise-admin-cli/samples/earthquakes.png similarity index 100% rename from aws/tests/earthquakes.png rename to enterprise-admin-cli/samples/earthquakes.png diff --git a/aws/tests/arcgis-enterprise-base-test.py b/enterprise-admin-cli/tools/publish_csv.py similarity index 94% rename from aws/tests/arcgis-enterprise-base-test.py rename to enterprise-admin-cli/tools/publish_csv.py index 5407ac2..d395320 100644 --- a/aws/tests/arcgis-enterprise-base-test.py +++ b/enterprise-admin-cli/tools/publish_csv.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Tests the service endpoint by publishing a feature service import os @@ -21,7 +23,7 @@ def wait_for_portal(portal_url): def publish_csv(portal_url, username, password): gis = GIS(url=portal_url, username=username, password=password) - data_path = os.path.dirname(os.path.realpath(__file__)) + data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "samples") # csv_path = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv' csv_path = os.path.join(data_path, "earthquakes.csv") @@ -53,7 +55,7 @@ def publish_csv(portal_url, username, password): if __name__ == '__main__': parser = argparse.ArgumentParser( - prog='arcgis-enterprise-base-test.py', + prog='publish_csv.py', description='Tests base ArcGIS Enterprise deployment by publishing a feature service.') parser.add_argument('-a', dest='url', required=True, help='Portal for ArcGIS URL') From 0aa11a12f6d2593c9180e8316f0de9e2250ecc27 Mon Sep 17 00:00:00 2001 From: Pavel Bobov Date: Wed, 3 Apr 2024 13:49:16 -0700 Subject: [PATCH 2/2] #14 Updated config files --- config/aws/arcgis-enterprise-k8s/image.vars.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/aws/arcgis-enterprise-k8s/image.vars.json b/config/aws/arcgis-enterprise-k8s/image.vars.json index 65e0581..c4db2b1 100644 --- a/config/aws/arcgis-enterprise-k8s/image.vars.json +++ b/config/aws/arcgis-enterprise-k8s/image.vars.json @@ -1,5 +1,6 @@ { "arcgis_version": "11.2.0", "container_registry_org": "esridocker", - "ecr_repository_prefix": "docker-hub" + "ecr_repository_prefix": "docker-hub", + "pull_through_cache": true } \ No newline at end of file