Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding npm_mirror_secret to manifest and module deploy objects #672

Merged
merged 11 commits into from
Aug 13, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Ch
### New

### Changes
- adds support for npm mirrors to be set

### Fixes

Expand Down
2 changes: 1 addition & 1 deletion seedfarmer/commands/_bootstrap_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def bootstrap_toolchain_account(
raise seedfarmer.errors.InvalidConfigurationError("The Qualifier must be alphanumeric and 6 characters or less")

for arn in principal_arns:
if not re.match(r"arn:aws:(sts|iam)::(\d{12}|\*):.*$", arn):
if not re.match(r"arn:aws.*:(sts|iam)::(\d{12}|\*):.*$", arn):
raise seedfarmer.errors.InvalidConfigurationError(f"Trusted principal: {arn} is not a valid principal arn")

role_stack_name = get_toolchain_role_name(project_name=project_name, qualifier=cast(str, qualifier))
Expand Down
9 changes: 9 additions & 0 deletions seedfarmer/commands/_module_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def _env_vars(
session: Optional[Session] = None,
use_project_prefix: Optional[bool] = True,
pypi_mirror_secret: Optional[str] = None,
npm_mirror_secret: Optional[str] = None,
) -> Dict[str, str]:
env_vars = (
{
Expand All @@ -80,6 +81,8 @@ def _env_vars(
env_vars[_param("PERMISSIONS_BOUNDARY_ARN", use_project_prefix)] = permissions_boundary_arn
if pypi_mirror_secret is not None:
env_vars["AWS_CODESEEDER_MIRROR_SECRET"] = pypi_mirror_secret
if npm_mirror_secret is not None:
env_vars["AWS_CODESEEDER_MIRROR_SECRET"] = npm_mirror_secret
malachi-constant marked this conversation as resolved.
Show resolved Hide resolved
# Add the partition to env for ease of fetching
env_vars["AWS_PARTITION"] = deployment_partition
env_vars["AWS_CODESEEDER_VERSION"] = aws_codeseeder.__version__
Expand Down Expand Up @@ -127,6 +130,9 @@ def deploy_module(mdo: ModuleDeployObject) -> ModuleDeploymentResponse:
pypi_mirror_secret=(
module_manifest.pypi_mirror_secret if module_manifest.pypi_mirror_secret else mdo.pypi_mirror_secret
),
npm_mirror_secret=(
module_manifest.npm_mirror_secret if module_manifest.npm_mirror_secret else mdo.npm_mirror_secret
),
)
env_vars[_param("MODULE_MD5", use_project_prefix)] = (
module_manifest.bundle_md5 if module_manifest.bundle_md5 is not None else ""
Expand Down Expand Up @@ -248,6 +254,9 @@ def destroy_module(mdo: ModuleDeployObject) -> ModuleDeploymentResponse:
pypi_mirror_secret=(
module_manifest.pypi_mirror_secret if module_manifest.pypi_mirror_secret else mdo.pypi_mirror_secret
),
npm_mirror_secret=(
module_manifest.npm_mirror_secret if module_manifest.npm_mirror_secret else mdo.npm_mirror_secret
),
)

remove_ssm = [
Expand Down
30 changes: 22 additions & 8 deletions seedfarmer/models/manifests/_deployment_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class RegionMapping(CamelModel):
npm_mirror: Optional[str] = None
pypi_mirror: Optional[str] = None
pypi_mirror_secret: Optional[str] = None
npm_mirror_secret: Optional[str] = None
seedkit_metadata: Optional[Dict[str, Any]] = None
seedfarmer_artifact_bucket: Optional[str] = None

Expand All @@ -77,6 +78,7 @@ class TargetAccountMapping(CamelModel):
region_mappings: List[RegionMapping] = []
codebuild_image: Optional[str] = None
npm_mirror: Optional[str] = None
npm_mirror_secret: Optional[str] = None
pypi_mirror: Optional[str] = None
pypi_mirror_secret: Optional[str] = None
_default_region: Optional[RegionMapping] = PrivateAttr(default=None)
Expand Down Expand Up @@ -372,16 +374,20 @@ def get_region_pypi_mirror(
else:
return None

def get_region_pypi_mirror_secret(
def get_region_mirror_secret(
self,
*,
mirror_type: Optional[str] = "pypi",
account_alias: Optional[str] = None,
account_id: Optional[str] = None,
region: Optional[str] = None,
) -> Optional[str]:
if account_alias is not None and account_id is not None:
raise seedfarmer.errors.InvalidManifestError("Only one of 'account_alias' and 'account_id' is allowed")

if mirror_type not in ["pypi", "npm"]:
raise seedfarmer.errors.InvalidManifestError("Mirror type must be of type 'npm' or 'pypi'")

use_default_account = account_alias is None and account_id is None
use_default_region = region is None
for target_account in self.target_account_mappings:
Expand All @@ -390,15 +396,23 @@ def get_region_pypi_mirror_secret(
or account_id == target_account.actual_account_id
or (use_default_account and target_account.default)
):
# Search the region_mappings for the region, if the pypi_mirror_secret is in region
# Search the region_mappings for the region, if the [pypi|npm]_mirror_secret is in region
for region_mapping in target_account.region_mappings:
if region == region_mapping.region or (use_default_region and region_mapping.default):
pypi_mirror_secret = (
region_mapping.pypi_mirror_secret
if region_mapping.pypi_mirror_secret is not None
else target_account.pypi_mirror_secret
)
return pypi_mirror_secret
if mirror_type == "pypi":
pypi_mirror_secret = (
region_mapping.pypi_mirror_secret
if region_mapping.pypi_mirror_secret is not None
else target_account.pypi_mirror_secret
)
return pypi_mirror_secret
elif mirror_type == "npm":
npm_mirror_secret = (
region_mapping.npm_mirror_secret
if region_mapping.npm_mirror_secret is not None
else target_account.npm_mirror_secret
)
return npm_mirror_secret
else:
return None

Expand Down
1 change: 1 addition & 0 deletions seedfarmer/models/manifests/_module_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class ModuleManifest(CamelModel):
data_files: Optional[List[DataFile]] = None
commit_hash: SkipJsonSchema[Optional[str]] = None
npm_mirror: Optional[str] = None
npm_mirror_secret: Optional[str] = None
pypi_mirror: Optional[str] = None
pypi_mirror_secret: Optional[str] = None
_target_account_id: Optional[str] = PrivateAttr(default=None)
Expand Down
10 changes: 8 additions & 2 deletions seedfarmer/models/transfer/_module_deploy_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ModuleDeployObject(CamelModel):
module_role_name: Optional[str] = None
codebuild_image: Optional[str] = None
npm_mirror: Optional[str] = None
npm_mirror_secret: Optional[str] = None
pypi_mirror: Optional[str] = None
pypi_mirror_secret: Optional[str] = None
seedfarmer_bucket: Optional[str] = None
Expand Down Expand Up @@ -52,12 +53,16 @@ def __init__(self, **kwargs: Any) -> None:
account_alias=_module.target_account, region=_module.target_region
)

npm_mirror_secret = self.deployment_manifest.get_region_mirror_secret(
account_alias=_module.target_account, region=_module.target_region, mirror_type="npm"
)

pypi_mirror = self.deployment_manifest.get_region_pypi_mirror(
account_alias=_module.target_account, region=_module.target_region
)

pypi_mirror_secret = self.deployment_manifest.get_region_pypi_mirror_secret(
account_alias=_module.target_account, region=_module.target_region
pypi_mirror_secret = self.deployment_manifest.get_region_mirror_secret(
account_alias=_module.target_account, region=_module.target_region, mirror_type="pypi"
)

sf_bucket = self.deployment_manifest.get_region_seedfarmer_bucket(
Expand All @@ -68,6 +73,7 @@ def __init__(self, **kwargs: Any) -> None:
self.codebuild_image = codebuild_image if codebuild_image is not None else None
self.docker_credentials_secret = dcs if dcs else None
self.npm_mirror = npm_mirror if npm_mirror is not None else None
self.npm_mirror_secret = npm_mirror_secret if npm_mirror_secret is not None else None
self.pypi_mirror = pypi_mirror if pypi_mirror is not None else None
self.pypi_mirror_secret = pypi_mirror_secret if pypi_mirror_secret is not None else None
self.seedfarmer_bucket = sf_bucket if sf_bucket is not None else None
4 changes: 4 additions & 0 deletions test/unit-test/test_commands_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ def test_deploy_modules(session_manager, mocker):
mdo.permissions_boundary_arn = ("arn:aws:iam::123456789012:policy/boundary",)
mdo.module_role_name = ("mlops-optionals-efs",)
mdo.docker_credentials_secret = ("aws-addf-docker-credentials",)
mdo.pypi_mirror = "https://mypypimirror.com/here"
mdo.pypi_mirror_secret = "user-mirror-credentials"
mdo.npm_mirror = "https://mynpmmirror.com/here"
mdo.npm_mirror_secret = "user-mirror-credentials"
mdo.module_metadata = (json.dumps(dummy_list_params),)
mc.deploy_module(mdo)

Expand Down
28 changes: 28 additions & 0 deletions test/unit-test/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,34 @@ def test_deserialize_deployment_manifest():
assert manifest.name == "test"


@pytest.mark.models
@pytest.mark.models_deployment_manifest
def test_deployment_manifest_with_custom_mirrors():
deployment_yaml["targetAccountMappings"][0]["npmMirror"] = "https://mynpmmirror.com/here"
deployment_yaml["targetAccountMappings"][0]["npmMirrorSecret"] = "user-mirror-credentials"
deployment_yaml["targetAccountMappings"][0]["pypiMirror"] = "https://mypypimirror.com/here"
deployment_yaml["targetAccountMappings"][0]["pypiMirrorSecret"] = "user-mirror-credentials"
manifest = DeploymentManifest(**deployment_yaml)
assert manifest.target_account_mappings[0].npm_mirror == "https://mynpmmirror.com/here"
assert manifest.target_account_mappings[0].npm_mirror_secret == "user-mirror-credentials"
assert manifest.target_account_mappings[0].pypi_mirror == "https://mypypimirror.com/here"
assert manifest.target_account_mappings[0].pypi_mirror_secret == "user-mirror-credentials"


@pytest.mark.models
@pytest.mark.models_deployment_manifest
def test_get_region_mirror_secret():
secret_name = "user-mirror-credentials"
deployment_yaml["targetAccountMappings"][0]["npmMirror"] = "https://mynpmmirror.com/here"
deployment_yaml["targetAccountMappings"][0]["npmMirrorSecret"] = secret_name
deployment_yaml["targetAccountMappings"][0]["pypiMirror"] = "https://mypypimirror.com/here"
deployment_yaml["targetAccountMappings"][0]["pypiMirrorSecret"] = secret_name
manifest = DeploymentManifest(**deployment_yaml)
assert manifest.get_region_mirror_secret() == secret_name
assert manifest.get_region_npm_mirror() == "https://mynpmmirror.com/here"
assert manifest.get_region_pypi_mirror() == "https://mypypimirror.com/here"


@pytest.mark.models
@pytest.mark.models_deployment_manifest
def test_deployment_manifest_get_parameter_with_defaults():
Expand Down