Skip to content

Commit

Permalink
Merge branch 'main' into feat/paths
Browse files Browse the repository at this point in the history
  • Loading branch information
kukushking authored Feb 10, 2025
2 parents f0cfcd4 + 7340ed6 commit 53d259b
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 9 deletions.
6 changes: 6 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ updates:
- dependency-name: "myst_parser"
versions:
- "4.0.0"
- dependency-name: "pydantic"
versions:
- "2.10.5"
- dependency-name: "pydantic-core"
versions:
- "2.27.2"

- package-ecosystem: "github-actions"
directory: "/"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Ch
## Unreleased

### New

- adding support for IAM paths
- adding support to taint modules to force a redeploy

### Changes

Expand Down
3 changes: 2 additions & 1 deletion seedfarmer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import seedfarmer
from seedfarmer import DEBUG_LOGGING_FORMAT, commands, config, enable_debug
from seedfarmer.cli_groups import bootstrap, bundle, init, list, metadata, projectpolicy, remove, store
from seedfarmer.cli_groups import bootstrap, bundle, init, list, metadata, projectpolicy, remove, store, taint
from seedfarmer.output_utils import print_bolded
from seedfarmer.utils import load_dotenv_files

Expand Down Expand Up @@ -312,5 +312,6 @@ def main() -> int:
cli.add_command(projectpolicy)
cli.add_command(metadata)
cli.add_command(bundle)
cli.add_command(taint)
cli()
return 0
3 changes: 2 additions & 1 deletion seedfarmer/cli_groups/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
from seedfarmer.cli_groups._project_group import projectpolicy
from seedfarmer.cli_groups._remove_group import remove
from seedfarmer.cli_groups._store_group import store
from seedfarmer.cli_groups._taint_group import taint

__all__ = ["bootstrap", "init", "list", "remove", "store", "projectpolicy", "metadata", "bundle"]
__all__ = ["bootstrap", "init", "list", "remove", "store", "projectpolicy", "metadata", "bundle", "taint"]
12 changes: 6 additions & 6 deletions seedfarmer/cli_groups/_store_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def store() -> None:
@click.option(
"--target-account-id",
default=None,
help="""Account Id of the target accout to store deployspec, if specifed --target-region is required
help="""Account Id of the target account to store deployspec, if specified --target-region is required
You SHOULD NOT use this parameter as this command will leverage the SeedFarmer session manager!
It is meant for development purposes.
""",
Expand All @@ -119,7 +119,7 @@ def store() -> None:
@click.option(
"--target-region",
default=None,
help="""Region of the target accout to store deployspec, if specifed --target-account-id is required
help="""Region of the target account to store deployspec, if specified --target-account-id is required
You SHOULD NOT use this parameter as this command will leverage the SeedFarmer session manager!
It is meant for development purposes.
""",
Expand Down Expand Up @@ -228,13 +228,13 @@ def store_deployspec(
@click.option(
"--target-account-id",
default=None,
help="Account Id of the target accout to store module metadata, if specifed --target-region is required",
help="Account Id of the target account to store module metadata, if specified --target-region is required",
show_default=True,
)
@click.option(
"--target-region",
default=None,
help="Region of the target accout to store module metadata, if specifed --target-account-id is required",
help="Region of the target account to store module metadata, if specified --target-account-id is required",
show_default=True,
)
@click.option(
Expand Down Expand Up @@ -344,13 +344,13 @@ def store_module_metadata(
@click.option(
"--target-account-id",
default=None,
help="Account Id of the target accout to store md5, if specifed --target-region is required",
help="Account Id of the target account to store md5, if specified --target-region is required",
show_default=True,
)
@click.option(
"--target-region",
default=None,
help="Region of the target accout to store md5, if specifed --target-account-id is required",
help="Region of the target account to store md5, if specified --target-account-id is required",
show_default=True,
)
@click.option(
Expand Down
167 changes: 167 additions & 0 deletions seedfarmer/cli_groups/_taint_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
from typing import List, Optional

import click

import seedfarmer.mgmt.deploy_utils as du
import seedfarmer.mgmt.module_info as mi
from seedfarmer import DEBUG_LOGGING_FORMAT, config, enable_debug
from seedfarmer.output_utils import print_bolded
from seedfarmer.services.session_manager import ISessionManager, SessionManager
from seedfarmer.utils import load_dotenv_files

_logger: logging.Logger = logging.getLogger(__name__)


def _load_project() -> str:
try:
_logger.info("No --project provided, attempting load from seedfarmer.yaml")
return config.PROJECT
except FileNotFoundError:
print_bolded("Unable to determine project to bootstrap, one of --project or a seedfarmer.yaml is required")
raise click.ClickException("Failed to determine project identifier")


def _error_messaging(deployment: str, group: Optional[str] = None, module: Optional[str] = None) -> None:
if group and module:
print(f"No module info found for {deployment}-{group}-{module}")
print_bolded(f"To see all deployed modules in {deployment}, run seedfarmer list modules -d {deployment}")
else:
print(f"No module info found for {deployment}")
print_bolded("To see all deployments, run seedfarmer list deployments")


@click.group(name="taint", help="Top Level command to support adding a taint to a deployed module")
def taint() -> None:
"""Taint module"""
pass


@taint.command(
name="module",
help="""This command will mark a module as needing
redeploy of a module on the next deployment.
Do not use this unless you are sure of the ramifications!
""",
)
@click.option(
"--deployment",
"-d",
type=str,
help="The Deployment Name",
required=True,
)
@click.option(
"--group",
"-g",
type=str,
help="The Group Name",
required=True,
)
@click.option(
"--module",
"-m",
type=str,
help="The Module Name",
required=True,
)
@click.option(
"--project",
"-p",
help="Project identifier",
required=False,
default=None,
)
@click.option(
"--profile",
default=None,
help="The AWS profile used to create a session to assume the toolchain role",
required=False,
)
@click.option(
"--region",
default=None,
help="The AWS region used to create a session to assume the toolchain role",
required=False,
)
@click.option(
"--qualifier",
default=None,
help="""A qualifier to use with the seedfarmer roles.
Use only if bootstrapped with this qualifier""",
required=False,
)
@click.option(
"--env-file",
"env_files",
default=[".env"],
help="""A relative path to the .env file to load environment variables from.
Multple files can be passed in by repeating this flag, and the order will be
preserved when overriding duplicate values.
""",
multiple=True,
required=False,
)
@click.option(
"--debug/--no-debug",
default=False,
help="Enable detailed logging.",
show_default=True,
)
def taint_module(
deployment: str,
group: str,
module: str,
project: Optional[str],
profile: Optional[str],
region: Optional[str],
qualifier: Optional[str],
env_files: List[str],
debug: bool,
) -> None:
if debug:
enable_debug(format=DEBUG_LOGGING_FORMAT)
_logger.debug("We are removing module data for %s of group %s in %s", module, group, deployment)

if project is None:
project = _load_project()

load_dotenv_files(config.OPS_ROOT, env_files=env_files)

session_manager: ISessionManager = SessionManager().get_or_create(
project_name=project, profile=profile, region_name=region, qualifier=qualifier
)

try:
dep_manifest = du.generate_deployed_manifest(deployment_name=deployment, skip_deploy_spec=True)
dep_manifest.validate_and_set_module_defaults() # type: ignore
session = session_manager.get_deployment_session(
account_id=dep_manifest.get_module(group=group, module=module).get_target_account_id(), # type: ignore
region_name=dep_manifest.get_module(group=group, module=module).target_region, # type: ignore
)
except Exception:
_error_messaging(deployment, group, module)
return

mi.remove_module_md5(
deployment=deployment,
group=group,
module=module,
type=mi.ModuleConst.BUNDLE,
session=session,
)
_logger.debug("Module %s-%s-%s marked for redeploy", module, group, deployment)
36 changes: 35 additions & 1 deletion test/unit-test/test_cli_arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from moto import mock_aws

from seedfarmer import config
from seedfarmer.__main__ import apply, bootstrap, destroy, init, metadata, projectpolicy, remove, store, version
from seedfarmer.__main__ import apply, bootstrap, destroy, init, metadata, projectpolicy, remove, store, taint, version
from seedfarmer.__main__ import list as list
from seedfarmer.models._deploy_spec import DeploySpec
from seedfarmer.models.manifests import DeploymentManifest
Expand Down Expand Up @@ -1555,3 +1555,37 @@ def test_metadata_add_kv_missing_value(mocker):
mocker.patch("seedfarmer.cli_groups._manage_metadata_group.metadata_support.add_kv_output", return_value=None)
mocker.patch("seedfarmer.cli_groups._manage_metadata_group.metadata_support.add_json_output", return_value=None)
_test_command(sub_command=metadata, options=["add", "--key", "adfdf"], exit_code=1)


@pytest.mark.metadata
def test_taint(mocker):
mocker.patch("seedfarmer.cli_groups._taint_group.mi.remove_module_md5", return_value=None)
_test_command(
sub_command=taint,
options=[
"module",
"-d",
"deployment_name",
"-g",
"test_group",
"-m",
"test_module",
],
exit_code=0,
)


@pytest.mark.metadata
def test_taint_missing_param(mocker):
mocker.patch("seedfarmer.cli_groups._taint_group.mi.remove_module_md5", return_value=None)
_test_command(
sub_command=taint,
options=[
"module",
"-d",
"deployment-name",
"-g",
"test-group",
],
exit_code=2,
)

0 comments on commit 53d259b

Please sign in to comment.