aws-annoying 0.8.0__tar.gz → 0.8.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/devcontainer.json +1 -1
  2. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.github/workflows/ci.yaml +11 -16
  3. aws_annoying-0.8.2/.github/workflows/prepare-release.yaml +51 -0
  4. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.github/workflows/release.yaml +24 -18
  5. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.vscode/extensions.json +0 -5
  6. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.vscode/settings.json +0 -8
  7. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/Makefile +2 -2
  8. aws_annoying-0.8.2/PKG-INFO +90 -0
  9. aws_annoying-0.8.2/README.md +72 -0
  10. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/pyproject.toml +8 -5
  11. aws_annoying-0.8.2/tests/cli/ecs/snapshots/test_task_definition_lifecycle/test_delete/stdout.txt +19 -0
  12. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/ecs/test_task_definition_lifecycle.py +60 -21
  13. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/test_load_variables.py +2 -1
  14. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/uv.lock +181 -158
  15. aws_annoying-0.8.0/PKG-INFO +0 -86
  16. aws_annoying-0.8.0/README.md +0 -51
  17. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/.env.example +0 -0
  18. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/Dockerfile +0 -0
  19. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/docker-compose.devcontainer.yaml +0 -0
  20. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/onCreateCommand.sh +0 -0
  21. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.devcontainer/postAttachCommand.sh +0 -0
  22. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.editorconfig +0 -0
  23. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.gitattributes +0 -0
  24. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.github/dependabot.yaml +0 -0
  25. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.gitignore +0 -0
  26. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.pre-commit-config.yaml +0 -0
  27. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.python-version +0 -0
  28. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/.vscode/launch.json +0 -0
  29. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/LICENSE +0 -0
  30. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/__init__.py +0 -0
  31. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/__init__.py +0 -0
  32. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/app.py +0 -0
  33. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/ecs/__init__.py +0 -0
  34. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/ecs/_app.py +0 -0
  35. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/ecs/task_definition_lifecycle.py +0 -0
  36. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/ecs/wait_for_deployment.py +0 -0
  37. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/load_variables.py +0 -0
  38. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/logging_handler.py +0 -0
  39. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/main.py +0 -0
  40. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/mfa/__init__.py +0 -0
  41. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/mfa/_app.py +0 -0
  42. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/mfa/configure.py +0 -0
  43. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/__init__.py +0 -0
  44. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/_app.py +0 -0
  45. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/_common.py +0 -0
  46. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/install.py +0 -0
  47. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/port_forward.py +0 -0
  48. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/start.py +0 -0
  49. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/cli/session_manager/stop.py +0 -0
  50. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/ecs/__init__.py +0 -0
  51. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/ecs/check.py +0 -0
  52. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/ecs/common.py +0 -0
  53. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/ecs/errors.py +0 -0
  54. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/ecs/wait_for.py +0 -0
  55. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/mfa_config.py +0 -0
  56. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/session_manager/__init__.py +0 -0
  57. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/session_manager/errors.py +0 -0
  58. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/session_manager/session_manager.py +0 -0
  59. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/session_manager/shortcuts.py +0 -0
  60. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/__init__.py +0 -0
  61. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/debugger.py +0 -0
  62. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/downloader.py +0 -0
  63. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/ec2.py +0 -0
  64. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/platform.py +0 -0
  65. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/utils/timeout.py +0 -0
  66. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/aws_annoying/variable_loader.py +0 -0
  67. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/console/ecs-exec/README.md +0 -0
  68. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/console/ecs-exec/ecs-console.png +0 -0
  69. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/console/ecs-exec/ecs-exec.user.js +0 -0
  70. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/console/ecs-exec/session-manager.png +0 -0
  71. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/examples/dbeaver/README.md +0 -0
  72. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/examples/dbeaver/after-disconnect.png +0 -0
  73. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/examples/dbeaver/before-connect.png +0 -0
  74. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/examples/dbeaver/new-connection.png +0 -0
  75. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/examples/dbeaver/test-connection.png +0 -0
  76. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/__init__.py +0 -0
  77. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/_helpers.py +0 -0
  78. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/__init__.py +0 -0
  79. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/__init__.py +0 -0
  80. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/boto3.py +0 -0
  81. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/command_builder.py +0 -0
  82. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/invoke.py +0 -0
  83. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/scripts/printenv.py +0 -0
  84. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/_helpers/string_.py +0 -0
  85. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/ecs/__init__.py +0 -0
  86. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/ecs/snapshots/test_task_definition_lifecycle/test_basic/stdout.txt +0 -0
  87. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/ecs/snapshots/test_task_definition_lifecycle/test_dry_run/stdout.txt +0 -0
  88. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/ecs/test_wait_for_deployment.py +0 -0
  89. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/__init__.py +0 -0
  90. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_basic/persist/aws_config.ini +0 -0
  91. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_basic/persist/stdout.txt +0 -0
  92. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_basic/skip_persist/stdout.txt +0 -0
  93. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_dry_run/stdout.txt +0 -0
  94. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_load_existing_config/aws_config.ini +0 -0
  95. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/snapshots/test_configure/test_load_existing_config/stdout.txt +0 -0
  96. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/mfa/test_configure.py +0 -0
  97. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/session_manager/__init__.py +0 -0
  98. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/session_manager/test_install.py +0 -0
  99. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/session_manager/test_port_forward.py +0 -0
  100. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/session_manager/test_start.py +0 -0
  101. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/session_manager/test_stop.py +0 -0
  102. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_basic/stdout.txt +0 -0
  103. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_env_prefix/stdout.txt +0 -0
  104. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_nothing/stdout.txt +0 -0
  105. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_overwrite_env/stdout.txt +0 -0
  106. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_replace_quiet/stdout.txt +0 -0
  107. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_resource_not_found/ssm/stdout.txt +0 -0
  108. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/snapshots/test_load_variables/test_unsupported_resource/stdout.txt +0 -0
  109. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/test_app.py +0 -0
  110. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/test_logging_handler.py +0 -0
  111. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/cli/test_main.py +0 -0
  112. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/conftest.py +0 -0
  113. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/ecs/__init__.py +0 -0
  114. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/ecs/test_check.py +0 -0
  115. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/ecs/test_common.py +0 -0
  116. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/ecs/test_errors.py +0 -0
  117. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/ecs/test_wait_for.py +0 -0
  118. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/session_manager/__init__.py +0 -0
  119. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/session_manager/test_errors.py +0 -0
  120. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/session_manager/test_session_manager.py +0 -0
  121. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/session_manager/test_shortcuts.py +0 -0
  122. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/test_mfa_config.py +0 -0
  123. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/test_variable_loader.py +0 -0
  124. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/utils/__init__.py +0 -0
  125. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/utils/test_downloader.py +0 -0
  126. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/utils/test_ec2.py +0 -0
  127. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/utils/test_platform.py +0 -0
  128. {aws_annoying-0.8.0 → aws_annoying-0.8.2}/tests/utils/test_timeout.py +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "lasuillard/aws-annoying",
2
+ "name": "lasuillard-s/aws-annoying",
3
3
  "dockerComposeFile": [
4
4
  "./docker-compose.devcontainer.yaml"
5
5
  ],
@@ -6,27 +6,24 @@ on:
6
6
  pull_request:
7
7
  branches: [main]
8
8
 
9
- permissions: read-all
10
-
11
9
  env:
12
10
  UV_FROZEN: 1
13
11
 
14
12
  jobs:
15
13
  lint:
16
- name: Lint
17
14
  runs-on: ubuntu-latest
15
+ timeout-minutes: 5
16
+ permissions:
17
+ contents: read
18
18
  steps:
19
- - name: Checkout
20
- uses: actions/checkout@v4
21
-
22
- - name: Set up uv
23
- uses: astral-sh/setup-uv@v6
19
+ - uses: actions/checkout@v5
20
+ - uses: astral-sh/setup-uv@v7
24
21
  with:
25
22
  version: latest
26
23
  enable-cache: true
27
24
 
28
25
  - name: Install deps
29
- run: uv sync --all-extras
26
+ run: uv sync
30
27
 
31
28
  - uses: pre-commit/action@v3.0.1
32
29
  env:
@@ -36,8 +33,9 @@ jobs:
36
33
  if: always()
37
34
 
38
35
  test:
39
- name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
36
+ name: test (${{ matrix.os }}, py${{ matrix.python-version }})
40
37
  runs-on: ${{ matrix.os }}
38
+ timeout-minutes: 10
41
39
  permissions:
42
40
  contents: read
43
41
  id-token: write
@@ -48,11 +46,8 @@ jobs:
48
46
  python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
49
47
 
50
48
  steps:
51
- - name: Checkout
52
- uses: actions/checkout@v4
53
-
54
- - name: Set up uv
55
- uses: astral-sh/setup-uv@v6
49
+ - uses: actions/checkout@v5
50
+ - uses: astral-sh/setup-uv@v7
56
51
  with:
57
52
  version: latest
58
53
  enable-cache: true
@@ -61,7 +56,7 @@ jobs:
61
56
  run: uv python pin "${{ matrix.python-version }}"
62
57
 
63
58
  - name: Install deps
64
- run: uv sync --all-extras
59
+ run: uv sync
65
60
 
66
61
  - name: Run tests (Ubuntu)
67
62
  if: ${{ matrix.os == 'ubuntu-latest' }}
@@ -0,0 +1,51 @@
1
+ name: Prepare Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ tag:
7
+ description: Semver-style tag for release (e.g., v1.0.0)
8
+ required: true
9
+
10
+ jobs:
11
+ create-pr:
12
+ runs-on: ubuntu-latest
13
+ timeout-minutes: 5
14
+ permissions:
15
+ contents: write
16
+ pull-requests: write
17
+ steps:
18
+ - name: Check tag format
19
+ run: |
20
+ if [[ ! "${{ inputs.tag }}" =~ ^v ]]; then
21
+ echo "Tag must start with 'v'"
22
+ exit 1
23
+ fi
24
+
25
+ - uses: actions/checkout@v5
26
+ - uses: astral-sh/setup-uv@v7
27
+ with:
28
+ version: latest
29
+ enable-cache: true
30
+
31
+ - name: Set version
32
+ run: |
33
+ tag="${{ inputs.tag }}"
34
+ tag_no_v="${tag#v}"
35
+ uv version "${tag#v}"
36
+
37
+ - name: Generate GitHub App token
38
+ uses: actions/create-github-app-token@v2
39
+ id: generate-token
40
+ with:
41
+ app-id: ${{ vars.GH_APP_ID }}
42
+ private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
43
+
44
+ - name: Create pull request
45
+ uses: peter-evans/create-pull-request@v7.0.8
46
+ with:
47
+ token: ${{ steps.generate-token.outputs.token }}
48
+ sign-commits: true
49
+ title: Release ${{ inputs.tag }}
50
+ branch: release/${{ inputs.tag }}
51
+ delete-branch: true
@@ -1,59 +1,65 @@
1
1
  name: Release
2
2
 
3
3
  on:
4
- push:
5
- tags: [v*]
4
+ release:
5
+ types: [published]
6
6
 
7
- permissions: read-all
7
+ env:
8
+ UV_FROZEN: 1
8
9
 
9
10
  jobs:
10
11
  release:
11
- name: Release
12
12
  runs-on: ubuntu-latest
13
+ timeout-minutes: 5
13
14
  permissions:
14
15
  contents: write
15
16
  steps:
16
- - name: Checkout
17
- uses: actions/checkout@v4
18
-
19
- - name: Set up uv
20
- uses: astral-sh/setup-uv@v6
17
+ - uses: actions/checkout@v5
18
+ - uses: astral-sh/setup-uv@v7
21
19
  with:
22
20
  version: latest
23
21
  enable-cache: true
24
22
 
25
23
  - name: Install deps
26
- run: uv sync --frozen --all-extras
24
+ run: uv sync
27
25
 
28
26
  - name: Build package
29
27
  run: uv build
30
28
 
31
29
  - name: Create release
32
- uses: softprops/action-gh-release@v2
30
+ uses: softprops/action-gh-release@v2.4.1
33
31
  with:
32
+ tag_name: ${{ github.event.release.tag_name }}
34
33
  generate_release_notes: true
35
34
  files: dist/*
36
35
 
36
+ - name: Show files
37
+ run: ls -l --all --recursive dist
38
+
37
39
  - name: Upload release distributions
38
- uses: actions/upload-artifact@v4
40
+ uses: actions/upload-artifact@v5
39
41
  with:
40
42
  name: release-dists
41
43
  path: dist/
42
44
 
43
45
  publish-pypi:
44
- name: Publish to PyPI
46
+ needs: release
45
47
  runs-on: ubuntu-latest
46
- needs:
47
- - release
48
+ environment: pypi
49
+ timeout-minutes: 5
48
50
  permissions:
49
51
  id-token: write
50
- environment: pypi
51
52
  steps:
52
- - name: Retrieve release distributions
53
- uses: actions/download-artifact@v4
53
+ - name: Download release distributions
54
+ uses: actions/download-artifact@v6
54
55
  with:
55
56
  name: release-dists
56
57
  path: dist/
57
58
 
59
+ - name: Show artifacts
60
+ run: ls -l --all --recursive dist
61
+
58
62
  - name: Publish release distributions to PyPI
59
63
  uses: pypa/gh-action-pypi-publish@release/v1
64
+ with:
65
+ skip-existing: true
@@ -2,16 +2,11 @@
2
2
  "recommendations": [
3
3
  "ms-python.python",
4
4
  "ms-python.vscode-pylance",
5
- "ldez.ignore-files",
6
- "gruntfuggly.todo-tree",
7
- "redhat.vscode-yaml",
8
- "tamasfe.even-better-toml",
9
5
  "streetsidesoftware.code-spell-checker",
10
6
  "editorconfig.editorconfig",
11
7
  "visualstudioexptteam.vscodeintellicode",
12
8
  "charliermarsh.ruff",
13
9
  "ms-python.mypy-type-checker",
14
- "njpwerner.autodocstring",
15
10
  "ms-python.debugpy"
16
11
  ]
17
12
  }
@@ -6,7 +6,6 @@
6
6
  "editor.defaultFormatter": "charliermarsh.ruff",
7
7
  "editor.formatOnSave": true
8
8
  },
9
- "autoDocstring.docstringFormat": "google-notypes",
10
9
  "cSpell.words": [
11
10
  "Deregistering",
12
11
  "localstack",
@@ -17,13 +16,6 @@
17
16
  ],
18
17
  "editor.formatOnSave": true,
19
18
  "files.eol": "\n",
20
- "files.exclude": {
21
- ".mypy_cache": true,
22
- ".pytest_cache": true,
23
- ".ruff_cache": true,
24
- ".venv": true,
25
- "**/__pycache__": true
26
- },
27
19
  "files.insertFinalNewline": true,
28
20
  "json.format.enable": true,
29
21
  "mypy-type-checker.path": [
@@ -19,12 +19,12 @@ help: Makefile ## Show help
19
19
  # =============================================================================
20
20
  install: ## Install the app locally
21
21
  uv python install
22
- uv sync --frozen --all-extras
22
+ uv sync --frozen
23
23
  pre-commit install --install-hooks
24
24
  .PHONY: install
25
25
 
26
26
  update: ## Update deps and tools
27
- uv sync --upgrade --all-extras
27
+ uv sync --upgrade
28
28
  pre-commit autoupdate
29
29
  .PHONY: update
30
30
 
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: aws-annoying
3
+ Version: 0.8.2
4
+ Summary: Utils to handle some annoying AWS tasks.
5
+ Project-URL: Homepage, https://github.com/lasuillard/aws-annoying
6
+ Project-URL: Repository, https://github.com/lasuillard/aws-annoying.git
7
+ Project-URL: Issues, https://github.com/lasuillard/aws-annoying/issues
8
+ Author-email: Yuchan Lee <lasuillard@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: <4.0,>=3.9
12
+ Requires-Dist: boto3<2,>=1
13
+ Requires-Dist: pydantic<3,>=2
14
+ Requires-Dist: requests<3,>=2
15
+ Requires-Dist: tqdm<5,>=4
16
+ Requires-Dist: typer<1,>=0
17
+ Description-Content-Type: text/markdown
18
+
19
+ # aws-annoying
20
+
21
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
22
+ [![codecov](https://codecov.io/gh/lasuillard-s/aws-annoying/graph/badge.svg?token=gbcHMVVz2k)](https://codecov.io/gh/lasuillard-s/aws-annoying)
23
+ [![PyPI - Version](https://img.shields.io/pypi/v/aws-annoying)](https://pypi.org/project/aws-annoying/)
24
+
25
+ Utils to handle some annoying AWS tasks.
26
+
27
+ ## ❓ About
28
+
29
+ This project aims to provide a set of utilities and examples to help with some annoying tasks when working with AWS.
30
+
31
+ Major directories of the project:
32
+
33
+ - **aws_annoying** Python package containing CLI and utility functions.
34
+ - **console** Utilities to help working with AWS Console.
35
+ - **examples** Examples of how to use the package.
36
+
37
+ ## 🚀 Installation
38
+
39
+ It is recommended to use [pipx](https://pipx.pypa.io/stable/) to install `aws-annoying` CLI:
40
+
41
+ ```bash
42
+ $ pipx install aws-annoying
43
+ $ aws-annoying --help
44
+
45
+ Usage: aws-annoying [OPTIONS] COMMAND [ARGS]...
46
+
47
+ ...
48
+ ```
49
+
50
+ As the package also provides some utility functions, you can install `aws-annoying` via pip, if you are going to use those utils.
51
+
52
+ ## 💡 Usage
53
+
54
+ Below are brief explanation of available commands. For more detailed information about commands, please refer to the CLI help.
55
+
56
+ ### `ecs task-definition-lifecycle`
57
+
58
+ Expire and delete ECS task definitions based on criteria.
59
+
60
+ ### `ecs wait-for-deployment`
61
+
62
+ Wait for ECS deployment to start, complete or fail, and stabilize.
63
+
64
+ ### `load-variables`
65
+
66
+ Wrapper command to run command with variables from various AWS resources (SSM Parameter Store, Secrets Manager, etc.) injected as environment variables.
67
+
68
+ ### `mfa configure`
69
+
70
+ Configure AWS profile or refresh session for MFA.
71
+
72
+ ### `session-manager install`
73
+
74
+ Install AWS Session Manager plugin.
75
+
76
+ ### `session-manager port-forward`
77
+
78
+ Start a port forwarding session using AWS Session Manager.
79
+
80
+ ### `session-manager start`
81
+
82
+ Start new session via Session Manager.
83
+
84
+ ### `session-manager stop`
85
+
86
+ Stop running port forwarding session for PID file.
87
+
88
+ ## 💖 Contributing
89
+
90
+ Any feedback, suggestions or contributions are welcome! Feel free to open an issue or a pull request.
@@ -0,0 +1,72 @@
1
+ # aws-annoying
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![codecov](https://codecov.io/gh/lasuillard-s/aws-annoying/graph/badge.svg?token=gbcHMVVz2k)](https://codecov.io/gh/lasuillard-s/aws-annoying)
5
+ [![PyPI - Version](https://img.shields.io/pypi/v/aws-annoying)](https://pypi.org/project/aws-annoying/)
6
+
7
+ Utils to handle some annoying AWS tasks.
8
+
9
+ ## ❓ About
10
+
11
+ This project aims to provide a set of utilities and examples to help with some annoying tasks when working with AWS.
12
+
13
+ Major directories of the project:
14
+
15
+ - **aws_annoying** Python package containing CLI and utility functions.
16
+ - **console** Utilities to help working with AWS Console.
17
+ - **examples** Examples of how to use the package.
18
+
19
+ ## 🚀 Installation
20
+
21
+ It is recommended to use [pipx](https://pipx.pypa.io/stable/) to install `aws-annoying` CLI:
22
+
23
+ ```bash
24
+ $ pipx install aws-annoying
25
+ $ aws-annoying --help
26
+
27
+ Usage: aws-annoying [OPTIONS] COMMAND [ARGS]...
28
+
29
+ ...
30
+ ```
31
+
32
+ As the package also provides some utility functions, you can install `aws-annoying` via pip, if you are going to use those utils.
33
+
34
+ ## 💡 Usage
35
+
36
+ Below are brief explanation of available commands. For more detailed information about commands, please refer to the CLI help.
37
+
38
+ ### `ecs task-definition-lifecycle`
39
+
40
+ Expire and delete ECS task definitions based on criteria.
41
+
42
+ ### `ecs wait-for-deployment`
43
+
44
+ Wait for ECS deployment to start, complete or fail, and stabilize.
45
+
46
+ ### `load-variables`
47
+
48
+ Wrapper command to run command with variables from various AWS resources (SSM Parameter Store, Secrets Manager, etc.) injected as environment variables.
49
+
50
+ ### `mfa configure`
51
+
52
+ Configure AWS profile or refresh session for MFA.
53
+
54
+ ### `session-manager install`
55
+
56
+ Install AWS Session Manager plugin.
57
+
58
+ ### `session-manager port-forward`
59
+
60
+ Start a port forwarding session using AWS Session Manager.
61
+
62
+ ### `session-manager start`
63
+
64
+ Start new session via Session Manager.
65
+
66
+ ### `session-manager stop`
67
+
68
+ Stop running port forwarding session for PID file.
69
+
70
+ ## 💖 Contributing
71
+
72
+ Any feedback, suggestions or contributions are welcome! Feel free to open an issue or a pull request.
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "aws-annoying"
3
3
  description = "Utils to handle some annoying AWS tasks."
4
- version = "0.8.0"
4
+ version = "0.8.2"
5
5
  authors = [{ name = "Yuchan Lee", email = "lasuillard@gmail.com" }]
6
6
  readme = "README.md"
7
7
  license = "MIT"
@@ -17,7 +17,7 @@ dependencies = [
17
17
  [project.scripts]
18
18
  "aws-annoying" = "aws_annoying.cli.main:entrypoint"
19
19
 
20
- [project.optional-dependencies]
20
+ [dependency-groups]
21
21
  dev = [
22
22
  "boto3-stubs[ecs,secretsmanager,ssm,sts,ec2]>=1.37.1",
23
23
  "mypy>=1.15,<1.17",
@@ -26,12 +26,12 @@ dev = [
26
26
  ]
27
27
  test = [
28
28
  "coverage>=7.6,<7.9",
29
- "moto[secretsmanager,server,ssm,ecs]~=5.1.1",
30
- "pytest~=8.3.2",
29
+ "moto[secretsmanager,server,ssm,ecs]~=5.1.8",
30
+ "pytest>=8.3.2,<8.5.0",
31
31
  "pytest-cov>=6.0,<6.2",
32
32
  "pytest-env~=1.1.1",
33
33
  "pytest-snapshot>=0.9.0",
34
- "pytest-sugar~=1.0.0",
34
+ "pytest-sugar>=1.0,<1.2",
35
35
  "pytest-xdist>=3.6.1",
36
36
  "testcontainers[localstack]>=4.9.2",
37
37
  "toml>=0.10.2",
@@ -47,6 +47,9 @@ Issues = "https://github.com/lasuillard/aws-annoying/issues"
47
47
  requires = ["hatchling"]
48
48
  build-backend = "hatchling.build"
49
49
 
50
+ [tool.uv]
51
+ default-groups = ["dev", "test"]
52
+
50
53
  [tool.hatch.build.targets.wheel]
51
54
  packages = ["aws_annoying"]
52
55
 
@@ -0,0 +1,19 @@
1
+ ⚠️ Deregistering 15 task definitions...
2
+ ⚠️ Deregistered task definition 'my-task:1'
3
+ ⚠️ Deregistered task definition 'my-task:2'
4
+ ⚠️ Deregistered task definition 'my-task:3'
5
+ ⚠️ Deregistered task definition 'my-task:4'
6
+ ⚠️ Deregistered task definition 'my-task:5'
7
+ ⚠️ Deregistered task definition 'my-task:6'
8
+ ⚠️ Deregistered task definition 'my-task:7'
9
+ ⚠️ Deregistered task definition 'my-task:8'
10
+ ⚠️ Deregistered task definition 'my-task:9'
11
+ ⚠️ Deregistered task definition 'my-task:10'
12
+ ⚠️ Deregistered task definition 'my-task:11'
13
+ ⚠️ Deregistered task definition 'my-task:12'
14
+ ⚠️ Deregistered task definition 'my-task:13'
15
+ ⚠️ Deregistered task definition 'my-task:14'
16
+ ⚠️ Deregistered task definition 'my-task:15'
17
+ ⚠️ Deleting 15 task definitions in chunks of size 10...
18
+ ⚠️ Deleted 10 task definitions in 0-th batch.
19
+ ⚠️ Deleted 5 task definitions in 1-th batch.
@@ -50,28 +50,70 @@ def test_basic(snapshot: Snapshot) -> None:
50
50
  family,
51
51
  "--keep-latest",
52
52
  str(keep_latest),
53
- # ? `delete_task_definitions` not implemented in moto yet
54
- # "--delete",
55
53
  ],
56
54
  )
57
- task_definitions = [
58
- ecs.describe_task_definition(taskDefinition=f"{family}:{i}")["taskDefinition"]
59
- for i in range(1, num_task_defs + 1)
60
- ]
61
55
 
62
56
  # Assert
63
57
  assert result.exit_code == 0
64
58
  snapshot.assert_match(normalize_console_output(result.stdout), "stdout.txt")
65
59
 
66
- # ?: Moto (v5.1.1) `ecs.list_task_definitions` does not handle `status` filter properly
67
- # ?: + sorting also does not work (current behavior is ASC)
68
- assert [td["revision"] for td in task_definitions if td["status"] == "INACTIVE"] == list(
69
- range(1, num_task_defs - keep_latest + 1), # 1..15
70
- )
71
- assert [td["revision"] for td in task_definitions if td["status"] == "ACTIVE"] == list(
72
- range(num_task_defs - keep_latest + 1, num_task_defs + 1), # 16..25
60
+ active_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="ACTIVE")
61
+ assert active_task_definitions["taskDefinitionArns"] == [
62
+ f"arn:aws:ecs:us-east-1:123456789012:task-definition/{family}:{i}" for i in range(16, 26)
63
+ ]
64
+
65
+ inactive_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="INACTIVE")
66
+ assert inactive_task_definitions["taskDefinitionArns"] == [
67
+ f"arn:aws:ecs:us-east-1:123456789012:task-definition/{family}:{i}" for i in range(1, 16)
68
+ ]
69
+
70
+
71
+ def test_delete(snapshot: Snapshot) -> None:
72
+ """The command should deregister the oldest task definitions."""
73
+ # Arrange
74
+ ecs = boto3.client("ecs")
75
+ family = "my-task"
76
+ num_task_defs = 25
77
+ for i in range(1, num_task_defs + 1):
78
+ ecs.register_task_definition(
79
+ family=family,
80
+ containerDefinitions=[
81
+ {
82
+ "name": "my-container",
83
+ "image": f"my-image:{i}",
84
+ "cpu": 0,
85
+ "memory": 0,
86
+ },
87
+ ],
88
+ )
89
+
90
+ # Act
91
+ keep_latest = 10
92
+ result = runner.invoke(
93
+ app,
94
+ [
95
+ "ecs",
96
+ "task-definition-lifecycle",
97
+ "--family",
98
+ family,
99
+ "--keep-latest",
100
+ str(keep_latest),
101
+ "--delete",
102
+ ],
73
103
  )
74
104
 
105
+ # Assert
106
+ assert result.exit_code == 0
107
+ snapshot.assert_match(normalize_console_output(result.stdout), "stdout.txt")
108
+
109
+ active_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="ACTIVE")
110
+ assert active_task_definitions["taskDefinitionArns"] == [
111
+ f"arn:aws:ecs:us-east-1:123456789012:task-definition/{family}:{i}" for i in range(16, 26)
112
+ ]
113
+
114
+ inactive_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="INACTIVE")
115
+ assert inactive_task_definitions["taskDefinitionArns"] == []
116
+
75
117
 
76
118
  def test_dry_run(snapshot: Snapshot) -> None:
77
119
  """If `--dry-run` option given, the command should not perform any changes."""
@@ -107,16 +149,13 @@ def test_dry_run(snapshot: Snapshot) -> None:
107
149
  "--delete",
108
150
  ],
109
151
  )
110
- task_definitions = [
111
- ecs.describe_task_definition(taskDefinition=f"{family}:{i}")["taskDefinition"]
112
- for i in range(1, num_task_defs + 1)
113
- ]
114
152
 
115
153
  # Assert
116
154
  assert result.exit_code == 0
117
155
  snapshot.assert_match(normalize_console_output(result.stdout), "stdout.txt")
118
156
 
119
- # ?: Moto (v5.1.1) `ecs.list_task_definitions` does not handle `status` filter properly
120
- # ?: + sorting also does not work (current behavior is ASC)
121
- assert [td["revision"] for td in task_definitions if td["status"] == "INACTIVE"] == []
122
- assert len([td["revision"] for td in task_definitions if td["status"] == "ACTIVE"]) == num_task_defs
157
+ active_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="ACTIVE")
158
+ assert len(active_task_definitions["taskDefinitionArns"]) == 25
159
+
160
+ inactive_task_definitions = ecs.list_task_definitions(familyPrefix=family, status="INACTIVE")
161
+ assert len(inactive_task_definitions["taskDefinitionArns"]) == 0
@@ -221,7 +221,8 @@ def test_unsupported_resource(snapshot: Snapshot) -> None:
221
221
  @pytest.mark.parametrize(
222
222
  argnames="arn",
223
223
  argvalues=[
224
- # TODO(lasuillard): Moto Secrets Manager does not respond with error for non-existing resources
224
+ # TODO(lasuillard): `batch_get_secret_value` does not raise an error if secret does not exist.
225
+ # Consider implementing new flag for strict mode (e.g. `--if-not-exists={error,ignore}`)
225
226
  # "arn:aws:secretsmanager:us-east-1:123456789012:secret:unknown-secret", # noqa: ERA001
226
227
  "arn:aws:ssm:us-east-1:123456789012:parameter/unknown-parameter",
227
228
  ],