Coder Social home page Coder Social logo

terraform-aws-modules / terraform-aws-ecr Goto Github PK

View Code? Open in Web Editor NEW
48.0 4.0 102.0 84 KB

Terraform module to create AWS ECR resources πŸ‡ΊπŸ‡¦

Home Page: https://registry.terraform.io/modules/terraform-aws-modules/ecr/aws

License: Apache License 2.0

HCL 100.00%
aws aws-ecr ecr ecr-repositories terraform terraform-module

terraform-aws-ecr's Introduction

AWS ECR Terraform module

Terraform module which creates AWS ECR resources.

Usage

See examples directory for working examples to reference:

Private Repository

module "ecr" {
  source = "terraform-aws-modules/ecr/aws"

  repository_name = "private-example"

  repository_read_write_access_arns = ["arn:aws:iam::012345678901:role/terraform"]
  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 30 images",
        selection = {
          tagStatus     = "tagged",
          tagPrefixList = ["v"],
          countType     = "imageCountMoreThan",
          countNumber   = 30
        },
        action = {
          type = "expire"
        }
      }
    ]
  })

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Public Repository

module "public_ecr" {
  source = "terraform-aws-modules/ecr/aws"

  repository_name = "public-example"
  repository_type = "public"

  repository_read_write_access_arns = ["arn:aws:iam::012345678901:role/terraform"]

  public_repository_catalog_data = {
    description       = "Docker container for some things"
    about_text        = file("${path.module}/files/ABOUT.md")
    usage_text        = file("${path.module}/files/USAGE.md")
    operating_systems = ["Linux"]
    architectures     = ["x86"]
    logo_image_blob   = filebase64("${path.module}/files/clowd.png")
  }

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Registry Management

module "ecr_registry" {
  source = "terraform-aws-modules/ecr/aws"

  repository_name = "registry-example"

  create_repository = false

  # Registry Policy
  create_registry_policy = true
  registry_policy        = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Sid    = "testpolicy",
        Effect = "Allow",
        Principal = {
          "AWS" : "arn:aws:iam::012345678901:root"
        },
        Action = [
          "ecr:ReplicateImage"
        ],
        Resource = [
          "arn:aws:ecr:us-east-1:012345678901:repository/*"
        ]
      }, {
        Sid    = "dockerhub",
        Effect = "Allow",
        Principal = {
          "AWS" : "arn:aws:iam::012345678901:root"
        },
        Action = [
          "ecr:CreateRepository",
          "ecr:BatchImportUpstreamImage"
        ],
        Resource = [
          "arn:aws:ecr:us-east-1:012345678901:repository/dockerhub/*"
        ]
      }
    ]
  })

  # Registry Pull Through Cache Rules
  registry_pull_through_cache_rules = {
    pub = {
      ecr_repository_prefix = "ecr-public"
      upstream_registry_url = "public.ecr.aws"
    }
    dockerhub = {
      ecr_repository_prefix = "dockerhub"
      upstream_registry_url = "registry-1.docker.io"
      credential_arn        = "arn:aws:secretsmanager:us-east-1:123456789:secret:ecr-pullthroughcache/dockerhub"
    }
  }

  # Registry Scanning Configuration
  manage_registry_scanning_configuration = true
  registry_scan_type                     = "ENHANCED"
  registry_scan_rules = [
    {
      scan_frequency = "SCAN_ON_PUSH"
      filter = [
        {
          filter      = "example1"
          filter_type = "WILDCARD"
        },
        { filter      = "example2"
          filter_type = "WILDCARD"
        }
      ]
    }, {
      scan_frequency = "CONTINUOUS_SCAN"
      filter = [
        {
          filter      = "example"
          filter_type = "WILDCARD"
        }
      ]
    }
  ]

  # Registry Replication Configuration
  create_registry_replication_configuration = true
  registry_replication_rules = [
    {
      destinations = [{
        region      = "us-west-2"
        registry_id = "012345678901"
        }, {
        region      = "eu-west-1"
        registry_id = "012345678901"
      }]

      repository_filters = [{
        filter      = "prod-microservice"
        filter_type = "PREFIX_MATCH"
      }]
    }
  ]

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Module wrappers

Users of this Terraform module can create multiple similar resources by using for_each meta-argument within module block which became available in Terraform 0.13.

Users of Terragrunt can achieve similar results by using modules provided in the wrappers directory, if they prefer to reduce amount of configuration files.

Examples

Examples codified under the examples are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module. If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you!

Requirements

Name Version
terraform >= 1.0
aws >= 5.37

Providers

Name Version
aws >= 5.37

Modules

No modules.

Resources

Name Type
aws_ecr_lifecycle_policy.this resource
aws_ecr_pull_through_cache_rule.this resource
aws_ecr_registry_policy.this resource
aws_ecr_registry_scanning_configuration.this resource
aws_ecr_replication_configuration.this resource
aws_ecr_repository.this resource
aws_ecr_repository_policy.this resource
aws_ecrpublic_repository.this resource
aws_ecrpublic_repository_policy.example resource
aws_caller_identity.current data source
aws_iam_policy_document.repository data source
aws_partition.current data source

Inputs

Name Description Type Default Required
attach_repository_policy Determines whether a repository policy will be attached to the repository bool true no
create Determines whether resources will be created (affects all resources) bool true no
create_lifecycle_policy Determines whether a lifecycle policy will be created bool true no
create_registry_policy Determines whether a registry policy will be created bool false no
create_registry_replication_configuration Determines whether a registry replication configuration will be created bool false no
create_repository Determines whether a repository will be created bool true no
create_repository_policy Determines whether a repository policy will be created bool true no
manage_registry_scanning_configuration Determines whether the registry scanning configuration will be managed bool false no
public_repository_catalog_data Catalog data configuration for the repository any {} no
registry_policy The policy document. This is a JSON formatted string string null no
registry_pull_through_cache_rules List of pull through cache rules to create map(map(string)) {} no
registry_replication_rules The replication rules for a replication configuration. A maximum of 10 are allowed any [] no
registry_scan_rules One or multiple blocks specifying scanning rules to determine which repository filters are used and at what frequency scanning will occur any [] no
registry_scan_type the scanning type to set for the registry. Can be either ENHANCED or BASIC string "ENHANCED" no
repository_encryption_type The encryption type for the repository. Must be one of: KMS or AES256. Defaults to AES256 string null no
repository_force_delete If true, will delete the repository even if it contains images. Defaults to false bool null no
repository_image_scan_on_push Indicates whether images are scanned after being pushed to the repository (true) or not scanned (false) bool true no
repository_image_tag_mutability The tag mutability setting for the repository. Must be one of: MUTABLE or IMMUTABLE. Defaults to IMMUTABLE string "IMMUTABLE" no
repository_kms_key The ARN of the KMS key to use when encryption_type is KMS. If not specified, uses the default AWS managed key for ECR string null no
repository_lambda_read_access_arns The ARNs of the Lambda service roles that have read access to the repository list(string) [] no
repository_lifecycle_policy The policy document. This is a JSON formatted string. See more details about Policy Parameters in the official AWS docs string "" no
repository_name The name of the repository string "" no
repository_policy The JSON policy to apply to the repository. If not specified, uses the default policy string null no
repository_policy_statements A map of IAM policy statements for custom permission usage any {} no
repository_read_access_arns The ARNs of the IAM users/roles that have read access to the repository list(string) [] no
repository_read_write_access_arns The ARNs of the IAM users/roles that have read/write access to the repository list(string) [] no
repository_type The type of repository to create. Either public or private string "private" no
tags A map of tags to add to all resources map(string) {} no

Outputs

Name Description
repository_arn Full ARN of the repository
repository_name Name of the repository
repository_registry_id The registry ID where the repository was created
repository_url The URL of the repository

License

Apache-2.0 Licensed. See LICENSE.

terraform-aws-ecr's People

Contributors

antonbabenko avatar bryantbiggs avatar dev-slatto avatar good92 avatar gpdenny avatar josealvarezsonos avatar niroz89 avatar phr3nzii avatar semantic-release-bot avatar thepoppingone avatar vrnvikas avatar zahorniak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

terraform-aws-ecr's Issues

Wrappers not working

Description

I'm trying to use wrappers to create some repositories in ECR, currently I want to create just one.
My config:

terraform {
  source = "tfr:///terraform-aws-modules/ecr/aws//wrappers?version=1.4.0"
}

inputs = {
  defaults = {
    tags = {
      Terraform   = "true"
      Environment = "${local.environment}"
    }
  }

  items = {
    activity_sec = {
      repository_name = "foo"
      repository_lifecycle_policy = jsonencode({
        rules = [
          {
            rulePriority = 1,
            description  = "Keep last 30 images",
            selection = {
              tagStatus     = "tagged",
              tagPrefixList = ["v"],
              countType     = "imageCountMoreThan",
              countNumber   = 30
            },
            action = {
              type = "expire"
            }
          }
        ]
      })
    }
  }
}

Output when executing terragrunt plan:

Waiting for the plan to start...

Terraform v1.3.3
on linux_amd64
Initializing plugins and modules...
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 6, in module "wrapper":
β”‚    6:   create                                    = try(each.value.create, var.defaults.create, true)
β”‚
β”‚ An argument named "create" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 7, in module "wrapper":
β”‚    7:   tags                                      = try(each.value.tags, var.defaults.tags, {})
β”‚
β”‚ An argument named "tags" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 8, in module "wrapper":
β”‚    8:   repository_type                           = try(each.value.repository_type, var.defaults.repository_type, "private")
β”‚
β”‚ An argument named "repository_type" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 9, in module "wrapper":
β”‚    9:   create_repository                         = try(each.value.create_repository, var.defaults.create_repository, true)
β”‚
β”‚ An argument named "create_repository" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 10, in module "wrapper":
β”‚   10:   repository_name                           = try(each.value.repository_name, var.defaults.repository_name, "")
β”‚
β”‚ An argument named "repository_name" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 11, in module "wrapper":
β”‚   11:   repository_image_tag_mutability           = try(each.value.repository_image_tag_mutability, var.defaults.repository_image_tag_mutability, "IMMUTABLE")
β”‚
β”‚ An argument named "repository_image_tag_mutability" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 12, in module "wrapper":
β”‚   12:   repository_encryption_type                = try(each.value.repository_encryption_type, var.defaults.repository_encryption_type, null)
β”‚
β”‚ An argument named "repository_encryption_type" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 13, in module "wrapper":
β”‚   13:   repository_kms_key                        = try(each.value.repository_kms_key, var.defaults.repository_kms_key, null)
β”‚
β”‚ An argument named "repository_kms_key" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 14, in module "wrapper":
β”‚   14:   repository_image_scan_on_push             = try(each.value.repository_image_scan_on_push, var.defaults.repository_image_scan_on_push, true)
β”‚
β”‚ An argument named "repository_image_scan_on_push" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 15, in module "wrapper":
β”‚   15:   repository_policy                         = try(each.value.repository_policy, var.defaults.repository_policy, null)
β”‚
β”‚ An argument named "repository_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 16, in module "wrapper":
β”‚   16:   repository_force_delete                   = try(each.value.repository_force_delete, var.defaults.repository_force_delete, null)
β”‚
β”‚ An argument named "repository_force_delete" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 17, in module "wrapper":
β”‚   17:   attach_repository_policy                  = try(each.value.attach_repository_policy, var.defaults.attach_repository_policy, true)
β”‚
β”‚ An argument named "attach_repository_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 18, in module "wrapper":
β”‚   18:   create_repository_policy                  = try(each.value.create_repository_policy, var.defaults.create_repository_policy, true)
β”‚
β”‚ An argument named "create_repository_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 19, in module "wrapper":
β”‚   19:   repository_read_access_arns               = try(each.value.repository_read_access_arns, var.defaults.repository_read_access_arns, [])
β”‚
β”‚ An argument named "repository_read_access_arns" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 20, in module "wrapper":
β”‚   20:   repository_read_write_access_arns         = try(each.value.repository_read_write_access_arns, var.defaults.repository_read_write_access_arns, [])
β”‚
β”‚ An argument named "repository_read_write_access_arns" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 21, in module "wrapper":
β”‚   21:   create_lifecycle_policy                   = try(each.value.create_lifecycle_policy, var.defaults.create_lifecycle_policy, true)
β”‚
β”‚ An argument named "create_lifecycle_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 22, in module "wrapper":
β”‚   22:   repository_lifecycle_policy               = try(each.value.repository_lifecycle_policy, var.defaults.repository_lifecycle_policy, "")
β”‚
β”‚ An argument named "repository_lifecycle_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 23, in module "wrapper":
β”‚   23:   public_repository_catalog_data            = try(each.value.public_repository_catalog_data, var.defaults.public_repository_catalog_data, {})
β”‚
β”‚ An argument named "public_repository_catalog_data" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 24, in module "wrapper":
β”‚   24:   create_registry_policy                    = try(each.value.create_registry_policy, var.defaults.create_registry_policy, false)
β”‚
β”‚ An argument named "create_registry_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 25, in module "wrapper":
β”‚   25:   registry_policy                           = try(each.value.registry_policy, var.defaults.registry_policy, null)
β”‚
β”‚ An argument named "registry_policy" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 26, in module "wrapper":
β”‚   26:   registry_pull_through_cache_rules         = try(each.value.registry_pull_through_cache_rules, var.defaults.registry_pull_through_cache_rules, {})
β”‚
β”‚ An argument named "registry_pull_through_cache_rules" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 27, in module "wrapper":
β”‚   27:   manage_registry_scanning_configuration    = try(each.value.manage_registry_scanning_configuration, var.defaults.manage_registry_scanning_configuration, false)
β”‚
β”‚ An argument named "manage_registry_scanning_configuration" is not expected
β”‚ here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 28, in module "wrapper":
β”‚   28:   registry_scan_type                        = try(each.value.registry_scan_type, var.defaults.registry_scan_type, "ENHANCED")
β”‚
β”‚ An argument named "registry_scan_type" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 29, in module "wrapper":
β”‚   29:   registry_scan_rules                       = try(each.value.registry_scan_rules, var.defaults.registry_scan_rules, [])
β”‚
β”‚ An argument named "registry_scan_rules" is not expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 30, in module "wrapper":
β”‚   30:   create_registry_replication_configuration = try(each.value.create_registry_replication_configuration, var.defaults.create_registry_replication_configuration, false)
β”‚
β”‚ An argument named "create_registry_replication_configuration" is not
β”‚ expected here.
β•΅
β•·
β”‚ Error: Unsupported argument
β”‚
β”‚   on main.tf line 31, in module "wrapper":
β”‚   31:   registry_replication_rules                = try(each.value.registry_replication_rules, var.defaults.registry_replication_rules, [])
β”‚
β”‚ An argument named "registry_replication_rules" is not expected here.
β•΅
Operation failed: failed running terraform plan (exit 1)
ERRO[0031] Terraform invocation failed in /Users/XXX/XXX/XXX/XXX/XXX/.terragrunt-cache/lNn_BUItOxjt46sMF85eiWlKVAc/eWDEKADBpIQ7X8Dom0nJ14Prazg/wrappers  prefix=[/Users/XXX/XXX/XXX/XXX/XXX]
ERRO[0031] 1 error occurred:
	* exit status 1
  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]: 1.4.0

  • Terraform version: Terraform v1.3.3

  • Provider version(s): registry.terraform.io/hashicorp/aws v4.36.1

Reproduction Code [Required]

Steps to reproduce the behavior:

Yes Yes In description

Expected behavior

terragrunt plan passes successfully

Actual behavior

In description

Terminal Output Screenshot(s)

Additional context

Can this module be used as ECR for lambda image code?

Description

I want to use this module, if possible, to host local AWS account lambda ECR code images. I am having trouble with the policies however. Could the examples be updated if possible to reflect how appropriate policies would be set for lambda to consume the ECR images as code? For that matter could any example show how to set a custom policy, or to ignore changes to policy (made by other AWS services - lambda)?
I can see input: repository_lambda_read_access_arns will result in a policy of:

{
  "Sid": "PrivateLambdaReadOnly",
  "Effect": "Allow",
  "Principal": {
    "Service": "lambda.amazonaws.com"
  },
  "Action": [
    "ecr:BatchGetImage",
    "ecr:GetDownloadUrlForLayer"
  ],
  "Condition": {
    "StringLike": {
      "aws:sourceArn": "arn:aws:iam::<account>:role/<ecr_name>"
    }
  }
}

this is almost a match on what lambda itself seems to want to set on the ECR, this permission appears after lambda is set to grab the ECR image:

{
  "Sid": "LambdaECRImageRetrievalPolicy",
  "Effect": "Allow",
  "Principal": {
    "Service": "lambda.amazonaws.com"
  },
  "Action": [
    "ecr:BatchGetImage",
    "ecr:DeleteRepositoryPolicy",
    "ecr:GetDownloadUrlForLayer",
    "ecr:GetRepositoryPolicy",
    "ecr:SetRepositoryPolicy"
  ],
  "Condition": {
    "StringLike": {
      "aws:sourceArn": "arn:aws:lambda:<region>:<account>:function:*"
    }
  }
}

I am unsure if this is just a user error my end or a feature request sorry.
I should also add that an initial build of the ECR with this module and then a lambda build to reference the ECR as code image does work at first. Where things go awry is any future terraform apply will look to strip the added policy that lambda has added, and this results in permissions errors for Lambda then not being allowed to access the ECR.

If your request is for a new feature, please use the Feature request template.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]:

  • Terraform version:

  • Provider version(s):

Reproduction Code [Required]

Steps to reproduce the behavior:

Expected behavior

Actual behavior

Terminal Output Screenshot(s)

Additional context

new feature: add roles to the repository policy

Is your request related to a problem? Please describe.

We are currently using our own module to create ECR repositories. It might be good to use and contribute to a more versatile and popular module. A feature that is missing from this fine module is the ability to add roles to the repository policy.

Describe the solution you'd like.

Add a new variable repository_role_arns that accepts one or more IAM role ARNs. If this feature is compatible with this project's design objectives, I could work on a pull request to add this.

Describe alternatives you've considered.

The alternative is to continue using our own module. An alternative implementation would be to add a repository_policy variable that accepts a full policy instead of building in inside the module.

Additional context

This is the policy we use today:

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "ECS Pull Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "${ecsInstanceRole_arn}",
                    "${ecsServiceRole_arn}"
                ]
            },
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability"
            ]
        },
        {
            "Sid": "CD push/pull",
            "Effect": "Allow",
            "Principal": {
                "AWS": "${cd_user_arn}"
            },
            "Action": [
                "ecr:PutImage",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability"
            ]
        }
    ]
}

For reference, the above file is here

Module version 1.3.0 no longer allows creating a custom repository policy for private repositories

Description

The changes to version 1.3.0 result in private repository custom policies no longer working, though it worked in version 1.2.0.

Sample

The following sample code illustrates the issue. Module with version 1.2.0 creates 3 resources, module 1.3.0 only 2.

Sample Code
data "aws_iam_policy_document" "repository_read_access_policy" {
  version = "2012-10-17"

  statement {
    sid    = "OrgStuff"
    effect = "Allow"
    actions = [
      "ecr:*",
    ]
    principals {
      type        = "AWS"
      identifiers = ["*"]
    }
    condition {
      test     = "StringEquals"
      values   = ["o-dummy"]
      variable = "aws:PrincipalOrgID"
    }
  }
}

module "_1_2_0" {
  source  = "registry.terraform.io/terraform-aws-modules/ecr/aws"
  version = "= 1.2.0"
  repository_name = "1_2_0"

  create_repository_policy = false
  repository_policy        = data.aws_iam_policy_document.repository_read_access_policy.json

  repository_image_tag_mutability = "MUTABLE"

  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 10 images",
        selection = {
          tagStatus   = "any",
          countType   = "imageCountMoreThan",
          countNumber = 1000
        },
        action = {
          type = "expire"
        }
      }
    ]
  })
}

module "_1_3_0" {
  source  = "registry.terraform.io/terraform-aws-modules/ecr/aws"
  version = "= 1.3.0"

  repository_name = "1_3_0"

  create_repository_policy = false
  repository_policy        = data.aws_iam_policy_document.repository_read_access_policy.json

  repository_image_tag_mutability = "MUTABLE"

  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 10 images",
        selection = {
          tagStatus   = "any",
          countType   = "imageCountMoreThan",
          countNumber = 1000
        },
        action = {
          type = "expire"
        }
      }
    ]
  })
}
Sample Plan
  # module._1_2_0.aws_ecr_lifecycle_policy.this[0] will be created
  + resource "aws_ecr_lifecycle_policy" "this" {
      + id          = (known after apply)
      + policy      = jsonencode(
            {
              + rules = [
                  + {
                      + action       = {
                          + type = "expire"
                        }
                      + description  = "Keep last 10 images"
                      + rulePriority = 1
                      + selection    = {
                          + countNumber = 1000
                          + countType   = "imageCountMoreThan"
                          + tagStatus   = "any"
                        }
                    },
                ]
            }
        )
      + registry_id = (known after apply)
      + repository  = "1_2_0"
    }

  # module._1_2_0.aws_ecr_repository.this[0] will be created
  + resource "aws_ecr_repository" "this" {
      + arn                  = (known after apply)
      + id                   = (known after apply)
      + image_tag_mutability = "MUTABLE"
      + name                 = "1_2_0"
      + registry_id          = (known after apply)
      + repository_url       = (known after apply)
      + tags_all             = (known after apply)

      + encryption_configuration {
          + encryption_type = "AES256"
          + kms_key         = (known after apply)
        }

      + image_scanning_configuration {
          + scan_on_push = true
        }
    }

  # module._1_2_0.aws_ecr_repository_policy.this[0] will be created
  + resource "aws_ecr_repository_policy" "this" {
      + id          = (known after apply)
      + policy      = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "ecr:*"
                      + Condition = {
                          + StringEquals = {
                              + "aws:PrincipalOrgID" = "o-dummy"
                            }
                        }
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "*"
                        }
                      + Sid       = "PrivateReadOnly"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + registry_id = (known after apply)
      + repository  = "1_2_0"
    }

  # module._1_3_0.aws_ecr_lifecycle_policy.this[0] will be created
  + resource "aws_ecr_lifecycle_policy" "this" {
      + id          = (known after apply)
      + policy      = jsonencode(
            {
              + rules = [
                  + {
                      + action       = {
                          + type = "expire"
                        }
                      + description  = "Keep last 10 images"
                      + rulePriority = 1
                      + selection    = {
                          + countNumber = 1000
                          + countType   = "imageCountMoreThan"
                          + tagStatus   = "any"
                        }
                    },
                ]
            }
        )
      + registry_id = (known after apply)
      + repository  = "1_3_0"
    }

  # module._1_3_0.aws_ecr_repository.this[0] will be created
  + resource "aws_ecr_repository" "this" {
      + arn                  = (known after apply)
      + id                   = (known after apply)
      + image_tag_mutability = "MUTABLE"
      + name                 = "1_3_0"
      + registry_id          = (known after apply)
      + repository_url       = (known after apply)
      + tags_all             = (known after apply)

      + encryption_configuration {
          + encryption_type = "AES256"
          + kms_key         = (known after apply)
        }

      + image_scanning_configuration {
          + scan_on_push = true
        }
    }

Findings

The changes to the aws_ecr_repository_policy result in a user only being able to use the default policy or no policy at all but not a custom policy. The count expression enforces var.create_repository_policy being true and thus the policy can only be the new created policy.

resource "aws_ecr_repository_policy" "this" {
  count = local.create_private_repository && var.create_repository_policy ? 1 : 0

  repository = aws_ecr_repository.this[0].name
  policy     = var.create_repository_policy ? data.aws_iam_policy_document.repository[0].json : var.repository_policy
}

Source:

resource "aws_ecr_repository_policy" "this" {

repository_lifecycle_policy returns an error if omitted

Description

Creating a private repository with repository_lifecycle_policy omitted or set to a value of "" results in a validation error being thrown.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:
    1.1.1 (latest)
  • Terraform version:
    1.2.1
  • Provider version(s):
    aws v4.16.0

Reproduction Code [Required]

module "base_images" {
  source  = "terraform-aws-modules/ecr/aws"
  version = "1.1.1"

  repository_name                 = "foo/base-images"
  repository_image_scan_on_push   = true
  repository_image_tag_mutability = "MUTABLE"
}

Steps to reproduce the behavior:

Run a plan against the above. This results in successful completion.

Running apply against the plan then creates the requested resources but also returns the following:

Error: InvalidParameter: 1 validation error(s) found.
- minimum field size of 100, PutLifecyclePolicyInput.LifecyclePolicyText.

with module.base_images.aws_ecr_lifecycle_policy.this[0],
on .terraform-management/modules/base_images/main.tf line 122, in resource "aws_ecr_lifecycle_policy" "this":
122: resource "aws_ecr_lifecycle_policy" "this" {

Upon closer inspection of the plan, the following unexpected resource is listed.

# module.base_images.aws_ecr_lifecycle_policy.this[0] will be created
  + resource "aws_ecr_lifecycle_policy" "this" {
      + id          = (known after apply)
      + registry_id = (known after apply)
      + repository  = "cronofy/base-images"
    }

Expected behavior

Empty ECR repository created with no lifecycle policy.

Actual behavior

Empty ECR repository is created as expected but with a validation error thrown for lifecycle policy creation that wasn't requested.

Additional context

Not a huge issue from our point of view as we're working around the validation error by adding a policy that won't be triggered by anything in the repository but thought it worth mentioning.

Addendum. A colleague has advised that the same behaviour is observed even if create_repository_policy = false is set.

ECR public repo doesn't support lifecycle policy

Description

The public ecr repo doesn't support lifecycle so the example is wrong, when you terraform apply on the below sample code it will not give you any error or warning but the policy section is not valid.

module "public_ecr" {
  source = "terraform-aws-modules/ecr/aws"

  repository_name = "public-example"
  repository_type = "public"

  repository_read_write_access_arns = ["arn:aws:iam::012345678901:role/terraform"]
  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 30 images",
        selection = {
          tagStatus     = "tagged",
          tagPrefixList = ["v"],
          countType     = "imageCountMoreThan",
          countNumber   = 30
        },
        action = {
          type = "expire"
        }
      }
    ]
  })

  public_repository_catalog_data = {
    description       = "Docker container for some things"
    about_text        = file("${path.module}/files/ABOUT.md")
    usage_text        = file("${path.module}/files/USAGE.md")
    operating_systems = ["Linux"]
    architectures     = ["x86"]
    logo_image_blob   = filebase64("${path.module}/files/clowd.png")
  }

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

This is not valid code for public ecr so it should be removed

  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 30 images",
        selection = {
          tagStatus     = "tagged",
          tagPrefixList = ["v"],
          countType     = "imageCountMoreThan",
          countNumber   = 30
        },
        action = {
          type = "expire"
        }
      }
    ]
  })

If your request is for a new feature, please use the Feature request template.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]:

  • Terraform version: v1.5 and above

  • Provider version(s): v1.6.0

Reproduction Code [Required]

Steps to reproduce the behavior:

Expected behavior

Actual behavior

Terminal Output Screenshot(s)

Additional context

Permission problem

Description

When I create a repository and add role to repository_read_write_access_arns that role doesn't have access to repository.

I need create role policy to add access to repository. Looks like ECR policy is omitted. Also when I create IAM role for access to repo looks like ECR policy doesn't restrict access. I think default DENY policy is missing, or I'm doing sth wrong.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:

  • Terraform version: 1.5.1

  • Provider version(s):

Reproduction Code [Required]

Steps to reproduce the behavior:

Create repository and add role arn to repository_read_write_access_arns.
Role doesn't have configured policy other than stsAssumeRole.
Permission denied when access to registry.

Expected behavior

Access to registry to roles provides to repository_read_write_access_arns

Actual behavior

Permission denied for role.

add support for more flexible repository policy

Describe the solution you'd like.

add option to accept policy as a variable in order to allow more flexible policies. for example: access for all the account in an organization.

Describe alternatives you've considered.

add support for Conditions

Creating ECR Repository Policy: InvalidParameterException: Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided'

Description

Please provide a clear and concise description of the issue you are encountering, and a reproduction of your configuration (see the examples/* directory for references that you can copy+paste and tailor to match your configs if you are unable to copy your exact configuration). The reproduction MUST be executable by running terraform init && terraform apply without any further changes.

If your request is for a new feature, please use the Feature request template.

  • [x ] βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: 1.6.0

  • Terraform version:
    1.5.5

  • Provider version(s):
    5.12.0

module "ecr" {
  source                            = "code.siemens.com/mc-gmc-deep/terraform-aws-ecr/aws"
  version                           = "1.6.0"
  for_each                          = toset(var.ecr-repositories)
  repository_name                   = each.key
  repository_encryption_type        = "KMS"
  repository_read_write_access_arns = [var.terraform_account_arn]
  repository_image_tag_mutability   = "MUTABLE"
  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        rulePriority = 1,
        description  = "Keep last 30 images",
        selection = {
          tagStatus     = "tagged",
          tagPrefixList = ["v"],
          countType     = "imageCountMoreThan",
          countNumber   = 30
        },
        action = {
          type = "expire"
        }
      }
    ]
  })
  # Registry Policy
  create_registry_policy = false
}```

<!-- REQUIRED -->

Steps to reproduce the behavior:

<!-- Are you using workspaces? --> No
<!-- Have you cleared the local cache (see Notice section above)? --> We use gitlab runners that are destroyed after each execution
<!-- List steps in order that led up to the issue you encountered --> Was using the module for several runs, no error. Resource was unchanged. Then the plan started to show:

```hcl
# module.ecr["XXXXX"].aws_ecr_repository_policy.this[0] will be updated in-place
  ~ resource "aws_ecr_repository_policy" "this" {
        id          = "viewer-backend"
      ~ policy      = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Principal = {
                          ~ AWS = "XXXXXX" -> "arn:aws:iam::[MASKED]:user/[MASKED]"
                        }
                        # (3 unchanged attributes hidden)
                    },
                  ~ {
                      ~ Principal = {
                          ~ AWS = "XXXXXX" -> "arn:aws:iam::[MASKED]:user/[MASKED]"
                        }
                        # (3 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        # (2 unchanged attributes hidden)
    }

Expected behavior

Resource should be unchanged after creation.

I have replaced the module with the code bellow just to be able to bypass the issues I'm having:

resource "aws_ecr_repository" "ecr" {
  for_each             = toset(var.ecr-repositories)
  name                 = each.key
  image_tag_mutability = "MUTABLE"
  encryption_configuration {
    encryption_type = "KMS"
  }

  image_scanning_configuration {
    scan_on_push = true
  }
  tags = local.tags
}

Public ECR Resource is missing TAG attribute

Description

When creating a public repository it is not supplied the var.tags variable value

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version 2.2.0

Reproduction Code [Required]

module "ecr_public" {
source = "terraform-aws-modules/ecr/aws"

repository_name = "my-ecr"
repository_type = "public"

tags = { Name = "my-ecr" }
}

Expected behavior

Terraform Plan SHOULD show

resource "aws_ecrpublic_repository" "this" {
....
tags = { Name = "my-ecr" }
....
}

Actual behavior

resource "aws_ecrpublic_repository" "this" {
....
tags = {}
....
}

Solution

in main.tf on line 240 add

tags = var.tags

Error: creating ECR Public repository: RequestError: send request failed

Description

Creating resources against us-east-2 fails with the following log.

β”‚ Error: creating ECR Public repository: RequestError: send request failed
β”‚ caused by: Post "https://api.ecr-public.us-east-2.amazonaws.com/": dial tcp: lookup api.ecr-public.us-east-2.amazonaws.com on 10.2.0.2:53: no such host
  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:

1.6.0

  • Terraform version:
    v1.2.9
  • Provider version(s):
    registry.terraform.io/hashicorp/aws v5.17.0

Reproduction Code [Required]

provider "aws" {
  region = "us-east-2"
}

module "public_ecr" {
  source = "terraform-aws-modules/ecr/aws"

  repository_name = "public-image"
  repository_type = "public"

  public_repository_catalog_data = {
    description       = "public docker image"
    operating_systems = ["Linux"]
    architectures     = ["x86"]
  }
}

the latest module version on the terraform registry is 1.6.0

Description

When publishing a module release here, it is not making its way over to the terraform registry
https://registry.terraform.io/modules/terraform-aws-modules/ecr/aws/

If your request is for a new feature, please use the Feature request template.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]:

  • Terraform version:

  • Provider version(s):

Reproduction Code [Required]

Steps to reproduce the behavior:

Expected behavior

Actual behavior

Terminal Output Screenshot(s)

Additional context

the latest module version on the terraform registry is 2.0.0

Description

When publishing a module release here, it is not making its way over to the terraform registry
https://registry.terraform.io/modules/terraform-aws-modules/ecr/aws/

If your request is for a new feature, please use the Feature request template.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version [Required]:

  • Terraform version:

  • Provider version(s):

Reproduction Code [Required]

Steps to reproduce the behavior:

Expected behavior

Actual behavior

Terminal Output Screenshot(s)

Additional context

First apply attempt of registry policy creation fails

Description

I am trying to create a repository + registry configuration at the same time, and Terraform complains says "RegistryPolicyNotFoundException" when it tries to attach the policy to the registry.

  • βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: 1.6.0
  • Terraform version: 1.5.5
  • Provider version(s):
    • provider registry.terraform.io/hashicorp/aws v5.31.0

Reproduction Code [Required]

code:

locals {
  registry_replication_rules = [for rule in var.ecr_registry.replication_rules : {
    destinations = [for destination in rule.destinations : {
      region      = destination
      registry_id = data.aws_caller_identity.current.account_id
    }]
    repository_filters = rule.repository_filters
  }]
}

data "aws_caller_identity" "current" {}
data "aws_partition" "current" {}

module "ecr" {
  count   = var.ecr.create ? 1 : 0
  source  = "terraform-aws-modules/ecr/aws"
  version = "1.6.0"

  repository_name = var.ecr.name
  repository_type = var.ecr.type

  create_lifecycle_policy  = var.ecr.lifecycle_policy != null ? true : false
  create_repository_policy = var.ecr.policy != null ? true : false
  attach_repository_policy = var.ecr.policy != null ? true : false

  repository_read_write_access_arns = var.ecr.read_write_access_arns
  repository_policy                 = var.ecr.policy
  repository_lifecycle_policy       = var.ecr.lifecycle_policy
  repository_image_scan_on_push     = var.ecr.image_scan_on_push
  repository_image_tag_mutability   = var.ecr.image_tag_mutability
  repository_encryption_type        = var.ecr.kms_arn != null ? "KMS" : null
  repository_kms_key                = var.ecr.kms_arn

  tags = var.tags
}

data "aws_iam_policy_document" "registry" {
  statement {
    principals {
      type        = "AWS"
      identifiers = ["arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:root"]
    }

    actions = [
      "ecr:ReplicateImage",
    ]

    resources = [
      module.ecr[0].repository_arn,
    ]
  }
}

module "ecr_registry" {
  count   = var.ecr_registry.create ? 1 : 0
  source  = "terraform-aws-modules/ecr/aws"
  version = "1.6.0"

  create_repository = false

  create_registry_policy = true
  registry_policy        = data.aws_iam_policy_document.registry.json

  manage_registry_scanning_configuration = length(var.ecr_registry.scan_rules) > 0 ? true : false
  registry_scan_type                     = var.ecr_registry.scan_type
  registry_scan_rules                    = var.ecr_registry.scan_rules

  create_registry_replication_configuration = length(var.ecr_registry.replication_rules) > 0 ? true : false
  registry_replication_rules                = local.registry_replication_rules

  tags = var.tags
}

variables:

ecr = {
  create = true
  name = "test-ecr-repo"
  type = "private"
  read_write_access_arns = ["arn-censored"]
  image_scan_on_push = true
  kms_arn = "kms-arn-censored"
}

ecr_registry = {
  create = true
  replication_rules = [{
    destinations = ["eu-west-2", "us-east-1"]
  }]
}

Steps to reproduce the behavior:

  • Simply run terraform apply the first time and it will fail, the second time it will go through properly.

Expected behavior

The first apply should work immediatly.

Actual behavior

module.ecr_registry[0].aws_ecr_registry_policy.this[0]: Creating...
β•·
β”‚ Error: reading ECR Registry Policy (account-id-censored): RegistryPolicyNotFoundException: Registry policy does not exist in the registry with id 'account-id-censored'
β”‚ 
β”‚   with module.ecr_registry[0].aws_ecr_registry_policy.this[0],
β”‚   on .terraform/modules/ecr_registry/main.tf line 218, in resource "aws_ecr_registry_policy" "this":
β”‚  218: resource "aws_ecr_registry_policy" "this" {
β”‚ 

Terminal Output Screenshot(s)

image

Additional context

Policy changes on every plan

Description

Every time I plan with this module, the policy block has pending changes. I apply them, and then the next plan, still has changes pending.

I've tried removing the policy and creating it again. Still, pending changes.

  • [ x] βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: 1.6.0

  • Terraform version: v1.7.3

  • Provider version(s): + provider registry.terraform.io/hashicorp/aws v5.38.0

Reproduction Code [Required]

module "gsal_proxy" {
  source = "terraform-aws-modules/ecr/aws"
  version = "1.6.0"

  repository_name = "gs/al-proxy"

  repository_read_write_access_arns = var.read_write_arns
  repository_read_access_arns       = var.read_only_arns
  create_lifecycle_policy           = false
}


vars:
  "read_only_arns": [
    "arn:aws-us-gov:iam::xxx:role/prd-1-20231005055232381500000001",
    "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231005055232381500000001/i-zzz",
    "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231206195128453200000003/i-zzz",
    "arn:aws-us-gov:sts::xxx:assumed-role/test-1-20231015185902248100000003/i-zzz",
    "arn:aws-us-gov:iam::xxx:role/dev-01-1-20230526030206003600000002",
    "arn:aws-us-gov:sts::xxx:assumed-role/stg-01-1-20231102031159343200000001/i-zzz",
    "arn:aws-us-gov:iam::xxx:assumed-role/stg-01-1-20231122212759304500000001/i-zzz"
  ],
  "read_write_arns": [
    "arn:aws-us-gov:iam::xxx:role/gitlab_runner_role"
  ]

Expected behavior

After applying this, a plan results in 0 changes detected.

Actual behavior

After applying, a subsequent plan results in changes It seems like it just wants to re-order them, removing and adding the same entries:

 # module.gsal.proxy.aws_ecr_repository_policy.this[0] will be updated in-place
  ~ resource "aws_ecr_repository_policy" "this" {
        id          = "gs/al-proxy"
      ~ policy      = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Principal = {
                          ~ AWS = [
                              - "arn:aws-us-gov:iam::xxx:role/dev-01-1-20230526030206003600000002",
                              + "arn:aws-us-gov:sts::xxx:assumed-role/test-01-test-1-20231015185902248100000003/i-zzz",
                              + "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231005055232381500000001/i-zzz",
                              + "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231206195128453200000003/i-zzz",
                                "arn:aws-us-gov:sts::xxx:assumed-role/stg-01-1-20231102031159343200000001/i-zzz",
                                "arn:aws-us-gov:iam::xxx:role/prd-1-20231005055232381500000001",
                              - "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231206195128453200000003/i-zzz",
                              - "arn:aws-us-gov:sts::xxx:assumed-role/prd-1-20231005055232381500000001/i-zzz",
                              + "arn:aws-us-gov:iam::xxx:role/dev-01-20230526030206003600000002",
                                "arn:aws-us-gov:iam::xxx:role/gitlab_runner_role",
                              - "arn:aws-us-gov:sts::xxx:assumed-role/test-01-test-1-20231015185902248100000003/i-zzz",
                              - "arn:aws-us-gov:sts::xxx:assumed-role/stg-01-1-20231122212759304500000001/i-zzz",
                              + "arn:aws-us-gov:iam::xxx:assumed-role/stg-01-1-20231122212759304500000001/i-zzz",
                            ]
                        }
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action    = [
                            "ecr:UploadLayerPart",
                            "ecr:PutImage",
                            "ecr:InitiateLayerUpload",
                            "ecr:CompleteLayerUpload",
                        ]
                        Effect    = "Allow"
                        Principal = {
                            AWS = "arn:aws-us-gov:iam::xxx:role/gitlab_runner_role"
                        }
                        Sid       = "ReadWrite"
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        # (2 unchanged attributes hidden)
    }

Plan: 0 to add, 2 to change, 0 to destroy.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.