diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..adc1ec4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,99 @@ +name: Build and Push Lambda Container + +on: + workflow_dispatch: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + env: + PACKER_GITHUB_API_TOKEN: ${{ secrets.GH_TOKEN }} + AWS_ACCESS_KEY_ID: ${{ vars.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 + + steps: + - uses: actions/setup-node@v3 + with: + node-version: 16 + + - uses: actions/checkout@v4 + + - name: Setup HashiCorp Packer + uses: hashicorp/setup-packer@v3.1.0 + + - name: Download GTag + run: | + curl -sSL https://raw.githubusercontent.com/HappyPathway/centralized-actions/main/gtag.py -o gtag.py + curl -sSL https://raw.githubusercontent.com/HappyPathway/centralized-actions/main/gtag_requirements.txt -o requirements.txt + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.11' + cache: pip + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3.1.2 + with: + terraform_version: 1.9.1 + terraform_wrapper: false + + - name: terraform init + run: terraform init + + - name: terraform apply + run: terraform apply -auto-approve + + - name: terraform output + id: terraform_output + run: echo "repository_uri=$(terraform output -raw repository_uri)" >> $GITHUB_ENV + + - name: git fetch --unshallow --tags + run: git fetch --unshallow --tags + + - name: get tags + run: git tag --list + + - name: GTag + run: | + echo "next_tag=$(python gtag.py --${{ vars.increment_version }})" >> $GITHUB_ENV + + - name: Docker Login to ECR + uses: aws-actions/amazon-ecr-login@v2 + with: + mask-password: true + + - name: packer init + run: packer init packer.pkr.hcl + + - name: packer validate + run: | + packer validate \ + -var "repository_uri=${{ env.repository_uri }}" \ + -var "tag=${{ env.next_tag }}" \ + packer.pkr.hcl + + - name: set tag + run: | + remote_repo="https://${{ vars.gh_username }}:${{ secrets.GH_TOKEN }}@${{ vars.gh_server }}/${{ github.repository }}.git" + git remote add repo ${remote_repo} + git config --global user.email "${{ vars.gh_email }}" + git config --global user.name "${{ vars.gh_username }}" + git tag -a ${{ env.next_tag }} -m "Release ${{ env.next_tag }}" + git push --tags -u repo + + - name: packer build + run: | + packer build \ + -var "repository_uri=${{ env.repository_uri }}" \ + -var "tag=${{ env.next_tag }}" \ + packer.pkr.hcl \ No newline at end of file diff --git a/.github/workflows/gh-token.yaml b/.github/workflows/gh-token.yaml deleted file mode 100644 index f7e1c7c..0000000 --- a/.github/workflows/gh-token.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: GitHub Token Refresh - -on: - schedule: - - cron: '*/5 * * * *' # Runs every 5 minutes - workflow_dispatch: # Allows manual triggering - -jobs: - refresh-token: - name: Refresh GitHub Token - uses: CSVD/centralized-actions/.github/workflows/upload-github-token.yml@main - with: - aws_region: 'us-gov-west-1' - secret_name: '/eks-cluster-deployment/github_token' # This matches the SECRET_NAME in app.py - github_app_id: ${{ vars.GH_APP_ID }} - github_app_installation_id: ${{ vars.GH_APP_INSTALLATION_ID }} - use_ecs_credentials: true - secrets: - github_app_pem_file: ${{ secrets.GH_APP_PEM_FILE }} diff --git a/.github/workflows/tf-apply.yaml b/.github/workflows/tf-apply.yaml deleted file mode 100644 index 8be975f..0000000 --- a/.github/workflows/tf-apply.yaml +++ /dev/null @@ -1,117 +0,0 @@ -# This is a basic workflow to help you get started with Actions -name: Terraform Apply - -# Controls when the workflow will run -on: - push: - branches: - - main - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -concurrency: - group: ${{ github.repo }}-deployment-${{ vars.terraform_workspace }} - -permissions: write-all -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - Plan: - # The type of runner that the job will run on - runs-on: ["229685449397"] - - env: - TF_WORKSPACE: ${{ vars.terraform_workspace }} - TF_CLI_ARGS_plan: -lock-timeout=30m - TF_CLI_ARGS_apply: -lock-timeout=30m - NO_PROXY: ${{ vars.NO_PROXY }} - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - uses: CSVD/gh-actions-checkout@v4 - id: checkout - with: - persist-credentials: false - - - name: git show - id: git_show - run: | - echo "commit_sha=$(git show | grep commit | head -1 | awk '{ print $NF }')" >> $GITHUB_ENV - echo "commit_sha=$(git show | grep commit | head -1 | awk '{ print $NF }')" >> $GITHUB_OUTPUT - - - name: AWS Auth - id: aws_auth - uses: CSVD/aws-auth@main - with: - ecs: true - - - name: Setup GITHUB Credentials - id: github_credentials - uses: CSVD/gh-auth@main - with: - github_app_pem_file: ${{ secrets.GH_APP_PEM_FILE }} - github_app_installation_id: ${{ vars.GH_APP_INSTALLATION_ID }} - github_base_url: "${{ github.server_url }}/" - - - name: Terraform Init - uses: CSVD/terraform-init@main - id: terraform_init - with: - commit_sha: ${{ env.commit_sha }} - checkout: false - terraform_version: "1.9.1" - workspace: ${{ vars.terraform_workspace }} - setup_terraform: true - terraform_init: true - cache_bucket: github-actions-assets-us-gov-west-1-229685449397 - env: - GITHUB_TOKEN: ${{ steps.github_credentials.outputs.github_token }} - AWS_ACCESS_KEY_ID: ${{ steps.aws_auth.outputs.aws_access_key_id }} - AWS_SECRET_ACCESS_KEY: ${{ steps.aws_auth.outputs.aws_secret_access_key }} - AWS_SESSION_TOKEN: ${{ steps.aws_auth.outputs.aws_session_token }} - - - name: Terraform Plan - uses: CSVD/terraform-plan@main - with: - terraform_version: "1.9.1" - workspace: ${{ vars.terraform_workspace }} - commit_sha: ${{ steps.terraform_init.outputs.commit_sha }} - varfile: varfiles/${{ vars.terraform_workspace }}.tfvars - download_cache: true - setup_terraform: false - cache_key: ${{ steps.terraform_init.outputs.s3_upload_path }} - cache_bucket: github-actions-assets-us-gov-west-1-229685449397 - env: - AWS_ACCESS_KEY_ID: ${{ steps.aws_auth.outputs.aws_access_key_id }} - AWS_SECRET_ACCESS_KEY: ${{ steps.aws_auth.outputs.aws_secret_access_key }} - AWS_SESSION_TOKEN: ${{ steps.aws_auth.outputs.aws_session_token }} - GITHUB_TOKEN: ${{ steps.github_credentials.outputs.github_token }} - GITHUB_OWNER: ${{ github.repository_owner }} - GITHUB_BASE_URL: "${{ github.server_url }}/" - HTTP_PROXY: http://proxy.tco.census.gov:3128 - HTTPS_PROXY: http://proxy.tco.census.gov:3128 - NO_PROXY: ".census.gov,169.254.169.254,148.129.*,10.*,172.18.*,172.22.*,172.23.*,172.24.*,172.25.*,.eks.amazonaws.com,.s3.amazonaws.com,.amazonaws.com" - - - name: Terraform Apply - uses: CSVD/terraform-apply@main - with: - terraform_version: "1.9.1" - workspace: ${{ vars.terraform_workspace }} - commit_sha: ${{ env.commit_sha }} - download_cache: true - setup_terraform: true - terraform_wrapper: false - cache_key: ${{ steps.terraform_init.outputs.s3_upload_path }} - cache_bucket: github-actions-assets-us-gov-west-1-229685449397 - env: - AWS_ACCESS_KEY_ID: ${{ steps.aws_auth.outputs.aws_access_key_id }} - AWS_SECRET_ACCESS_KEY: ${{ steps.aws_auth.outputs.aws_secret_access_key }} - AWS_SESSION_TOKEN: ${{ steps.aws_auth.outputs.aws_session_token }} - GITHUB_TOKEN: ${{ steps.github_credentials.outputs.github_token }} - GITHUB_OWNER: ${{ github.repository_owner }} - GITHUB_BASE_URL: "${{ github.server_url }}/" - HTTP_PROXY: http://proxy.tco.census.gov:3128 - HTTPS_PROXY: http://proxy.tco.census.gov:3128 - NO_PROXY: ".census.gov,169.254.169.254,148.129.*,10.*,172.18.*,172.22.*,172.23.*,172.24.*,172.25.*,.eks.amazonaws.com,.s3.amazonaws.com,.amazonaws.com" - - diff --git a/.github/workflows/tf-validate.yaml b/.github/workflows/tf-validate.yaml deleted file mode 100644 index ac02202..0000000 --- a/.github/workflows/tf-validate.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Terraform Validate -on: - pull_request: - workflow_dispatch: - -jobs: - - terraform-validate: - runs-on: "229685449397" - permissions: - contents: write - steps: - - name: Checkout code - uses: CSVD/gh-actions-checkout@v4 - - - name: Setup Terraform - uses: CSVD/gh-actions-setup-terraform@v2 - with: - terraform_version: '1.7.3' - - - name: Validate Terraform Configuration - id: validate - uses: CSVD/terraform-validate@main - - - name: Check Validation/Test Results - if: always() - run: | - # Set default values if outputs are empty - IS_VALID="${{ steps.validate.outputs.is_valid }}" - TESTS_PASSED="${{ steps.validate.outputs.tests_passed }}" - - # If outputs are empty, set them to false - [ -z "$IS_VALID" ] && IS_VALID="false" - [ -z "$TESTS_PASSED" ] && TESTS_PASSED="false" - - if [[ "$IS_VALID" != "true" || "$TESTS_PASSED" != "true" ]]; then - echo "Validation or test errors found:" - echo "${{ steps.validate.outputs.stderr }}" - exit 1 - else - echo "All validations and tests passed successfully!" - fi diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a7ea870..0000000 --- a/.gitignore +++ /dev/null @@ -1,167 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -artifacts/ - -.aws-sam - -terraform_data_dirs -terraform.tfstate.d \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 4d07f26..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-added-large-files - - repo: https://github.com/psf/black - rev: 24.4.0 - hooks: - - id: black - - repo: local - hooks: - - id: pylint - name: pylint - entry: pylint - language: system - types: - - python diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 25e6537..0000000 --- a/.pylintrc +++ /dev/null @@ -1,549 +0,0 @@ -[MAIN] - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -init-hook='import sys; sys.path.append(".")' - -# Files or directories to be skipped. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the ignore-list. The -# regex matches against paths and can be in Posix or Windows format. -ignore-paths= - -# Files or directories matching the regex patterns are skipped. The regex -# matches against base names, not paths. -ignore-patterns=^\.# - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - pylint.extensions.check_elif, - pylint.extensions.bad_builtin, - pylint.extensions.docparams, - pylint.extensions.for_any_all, - pylint.extensions.set_membership, - pylint.extensions.code_style, - pylint.extensions.overlapping_exceptions, - pylint.extensions.typing, - pylint.extensions.redefined_variable_type, - pylint.extensions.comparison_placement, - pylint.extensions.broad_try_clause, - pylint.extensions.dict_init_mutate, - pylint.extensions.consider_refactoring_into_while_condition, - -# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the -# number of processors available to use. -jobs=1 - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages. -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-allow-list= - -# Minimum supported python version -py-version = 3.8.0 - -# Control the amount of potential inferred values when inferring a single -# object. This can help the performance when dealing with large functions or -# complex, nested conditions. -limit-inference-results=100 - -# Specify a score threshold under which the program will exit with error. -fail-under=10.0 - -# Return non-zero exit code if any of these messages/categories are detected, -# even if score is above --fail-under value. Syntax same as enable. Messages -# specified are enabled, while categories only check already-enabled messages. -fail-on= - -# Clear in-memory caches upon conclusion of linting. Useful if running pylint in -# a server-like mode. -clear-cache-post-run=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -# confidence= - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - use-symbolic-message-instead, - useless-suppression, - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then re-enable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" - -disable= - attribute-defined-outside-init, - invalid-name, - missing-docstring, - protected-access, - too-few-public-methods, - # handled by black - format, - # We anticipate #3512 where it will become optional - fixme, - consider-using-assignment-expr, - unspecified-encoding - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables 'fatal', 'error', 'warning', 'refactor', 'convention' -# and 'info', which contain the number of messages in each category, as -# well as 'statement', which is the total number of statements analyzed. This -# score is used by the global evaluation report (RP0004). -evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - -# Activate the evaluation score. -score=yes - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - -# The type of string formatting that logging methods do. `old` means using % -# formatting, `new` is for `{}` formatting. -logging-format-style=old - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - -# Regular expression of note tags to take in consideration. -#notes-rgx= - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=6 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=yes - -# Signatures are removed from the similarity computation -ignore-signatures=yes - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid defining new builtins when possible. -additional-builtins= - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of names allowed to shadow builtins -allowed-redefined-builtins= - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=100 - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Maximum number of lines in a module -max-module-lines=2000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - - -[BASIC] - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Good variable names regexes, separated by a comma. If names match any regex, -# they will always be accepted -good-names-rgxs= - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Bad variable names regexes, separated by a comma. If names match any regex, -# they will always be refused -bad-names-rgxs= - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Naming style matching correct function names. -function-naming-style=snake_case - -# Regular expression matching correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming style matching correct variable names. -variable-naming-style=snake_case - -# Regular expression matching correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming style matching correct constant names. -const-naming-style=UPPER_CASE - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Naming style matching correct attribute names. -attr-naming-style=snake_case - -# Regular expression matching correct attribute names -attr-rgx=[a-z_][a-z0-9_]{2,}$ - -# Naming style matching correct argument names. -argument-naming-style=snake_case - -# Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Naming style matching correct class attribute names. -class-attribute-naming-style=any - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Naming style matching correct class constant names. -class-const-naming-style=UPPER_CASE - -# Regular expression matching correct class constant names. Overrides class- -# const-naming-style. -#class-const-rgx= - -# Naming style matching correct inline iteration names. -inlinevar-naming-style=any - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Naming style matching correct class names. -class-naming-style=PascalCase - -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - - -# Naming style matching correct module names. -module-naming-style=snake_case - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - - -# Naming style matching correct method names. -method-naming-style=snake_case - -# Regular expression matching correct method names -method-rgx=[a-z_][a-z0-9_]{2,}$ - -# Regular expression matching correct type variable names -#typevar-rgx= - -# Regular expression which should only match function or class names that do -# not require a docstring. Use ^(?!__init__$)_ to also check __init__. -no-docstring-rgx=__.*__ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# List of decorators that define properties, such as abc.abstractproperty. -property-classes=abc.abstractproperty - - -[TYPECHECK] - -# Regex pattern to define which classes are considered mixins if ignore-mixin- -# members is set to 'yes' -mixin-class-rgx=.*MixIn - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis). It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=SQLObject, optparse.Values, thread._local, _thread._local - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent,argparse.Namespace - -# List of decorators that create context managers from functions, such as -# contextlib.contextmanager. -contextmanager-decorators=contextlib.contextmanager - -# Tells whether to warn about missing members when the owner of the attribute -# is inferred to be None. -ignore-none=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# List of comma separated words that should be considered directives if they -# appear and the beginning of a comment and should not be checked. -spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:,pragma:,# noinspection - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file=.pyenchant_pylint_custom_dict.txt - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - -# Limits count of emitted suggestions for spelling mistakes. -max-spelling-suggestions=2 - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args = 9 - -# Maximum number of locals for function / method body -max-locals = 19 - -# Maximum number of return / yield for function / method body -max-returns=11 - -# Maximum number of branch for function / method body -max-branches = 20 - -# Maximum number of statements in function / method body -max-statements = 50 - -# Maximum number of attributes for a class (see R0902). -max-attributes=11 - -# Maximum number of statements in a try-block -max-try-statements = 7 - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp,__post_init__ - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# Warn about protected attribute access inside special methods -check-protected-access-in-special-methods=no - -[IMPORTS] - -# List of modules that can be imported at any level, not just the top level -# one. -allow-any-import-level= - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Allow explicit reexports by alias from a package __init__. -allow-reexport-from-package=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - -# Couples of modules and preferred modules, separated by a comma. -preferred-modules= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=builtins.Exception - - -[TYPING] - -# Set to ``no`` if the app / library does **NOT** need to support runtime -# introspection of type annotations. If you use type annotations -# **exclusively** for type checking of an application, you're probably fine. -# For libraries, evaluate if some users what to access the type hints at -# runtime first, e.g., through ``typing.get_type_hints``. Applies to Python -# versions 3.7 - 3.9 -runtime-typing = no - - -[DEPRECATED_BUILTINS] - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,input - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=10 - -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=sys.exit,argparse.parse_error - - -[STRING] - -# This flag controls whether inconsistent-quotes generates a warning when the -# character used as a quote delimiter is used inconsistently within a module. -check-quote-consistency=no - -# This flag controls whether the implicit-str-concat should generate a warning -# on implicit string concatenation in sequences defined over several lines. -check-str-concat-over-line-jumps=no - - -[CODE_STYLE] - -# Max line length for which to sill emit suggestions. Used to prevent optional -# suggestions which would get split by a code formatter (e.g., black). Will -# default to the setting for ``max-line-length``. -#max-line-length-suggestions= diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl deleted file mode 100644 index 2c5d0fb..0000000 --- a/.terraform.lock.hcl +++ /dev/null @@ -1,25 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/aws" { - version = "5.94.1" - constraints = "~> 5.0" - hashes = [ - "h1:pm3uoaQYHaavwE83zsEzAFn/LKD1EWGiYRfzVxNCaIA=", - "zh:14fb41e50219660d5f02b977e6f786d8ce78766cce8c2f6b8131411b087ae945", - "zh:3bc5d12acd5e1a5f1cf78a7f05d0d63f988b57485e7d20c47e80a0b723a99d26", - "zh:4835e49377f80a37c6191a092f636e227a9f086e3cc3f0c9e1b554da8793cfe8", - "zh:605971275adae25096dca30a94e29931039133c667c1d9b38778a09594312964", - "zh:8ae46b4a9a67815facf59da0c56d74ef71bcc77ae79e8bfbac504fa43f267f8e", - "zh:913f3f371c3e6d1f040d6284406204b049977c13cb75aae71edb0ef8361da7dd", - "zh:91f85ae8c73932547ad7139ce0b047a6a7c7be2fd944e51db13231cc80ce6d8e", - "zh:96352ae4323ce137903b9fe879941f894a3ce9ef30df1018a0f29f285a448793", - "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9b51922c9201b1dc3d05b39f9972715db5f67297deee088793d02dea1832564b", - "zh:a689e82112aa71e15647b06502d5b585980cd9002c3cc8458f092e8c8a667696", - "zh:c3723fa3e6aff3c1cc0088bdcb1edee168fe60020f2f77161d135bf473f45ab2", - "zh:d6a2052b864dd394b01ad1bae32d0a7d257940ee47908d02df7fa7873981d619", - "zh:dda4c9c0406cc54ad8ee4f19173a32de7c6e73abb5a948ea0f342d567df26a1d", - "zh:f42e0fe592b97cbdf70612f0fbe2bab851835e2d1aaf8cbb87c3ab0f2c96bb27", - ] -} diff --git a/.terraform/providers/registry.terraform.io/hashicorp/aws/5.94.1/linux_amd64 b/.terraform/providers/registry.terraform.io/hashicorp/aws/5.94.1/linux_amd64 deleted file mode 120000 index 1263af3..0000000 --- a/.terraform/providers/registry.terraform.io/hashicorp/aws/5.94.1/linux_amd64 +++ /dev/null @@ -1 +0,0 @@ -/data/terraform/workspaces/arnol377/terraform-plugin-cache/registry.terraform.io/hashicorp/aws/5.94.1/linux_amd64 \ No newline at end of file diff --git a/.terraform_commits b/.terraform_commits deleted file mode 100644 index ebeee12..0000000 --- a/.terraform_commits +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T13:12:39.190090" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T13:13:33.377155" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T13:14:04.341717" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T13:46:26.319927" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T14:39:49.477391" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T14:41:30.994495" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T16:03:19.141297" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T16:06:13.577362" - }, - { - "commit_hash": "018399a6523b3c5c1d7503b2c0de8cd66eb8d8e5", - "commit_message": "Merge branch 'main' of github.e.it.census.gov:SCT-Engineering/eks-automation-lambda", - "author": "arnol377", - "timestamp": "2025-04-16T16:07:17.588493" - } -] \ No newline at end of file diff --git a/.tflog b/.tflog new file mode 100644 index 0000000..ded52c5 --- /dev/null +++ b/.tflog @@ -0,0 +1,91 @@ +2025-04-17T01:21:26.640-0700 [INFO] Terraform version: 1.10.5 +2025-04-17T01:21:26.640-0700 [DEBUG] using github.com/hashicorp/go-tfe v1.70.0 +2025-04-17T01:21:26.640-0700 [DEBUG] using github.com/hashicorp/hcl/v2 v2.23.0 +2025-04-17T01:21:26.640-0700 [DEBUG] using github.com/hashicorp/terraform-svchost v0.1.1 +2025-04-17T01:21:26.640-0700 [DEBUG] using github.com/zclconf/go-cty v1.16.2 +2025-04-17T01:21:26.640-0700 [INFO] Go runtime version: go1.23.3 +2025-04-17T01:21:26.640-0700 [INFO] CLI args: []string{"/usr/local/Cellar/tfenv/1.0.2/versions/1.10.5/terraform", "version", "-json"} +2025-04-17T01:21:26.640-0700 [TRACE] Stdout is not a terminal +2025-04-17T01:21:26.640-0700 [TRACE] Stderr is not a terminal +2025-04-17T01:21:26.640-0700 [TRACE] Stdin is not a terminal +2025-04-17T01:21:26.640-0700 [DEBUG] Attempting to open CLI config file: /Users/darnold/.terraformrc +2025-04-17T01:21:26.640-0700 [INFO] Loading CLI configuration from /Users/darnold/.terraformrc +2025-04-17T01:21:26.640-0700 [INFO] Loading CLI configuration from /Users/darnold/.terraform.d/credentials.tfrc.json +2025-04-17T01:21:26.641-0700 [DEBUG] checking for credentials in "/Users/darnold/.terraform.d/plugins" +2025-04-17T01:21:26.641-0700 [DEBUG] checking for credentials in "/Users/darnold/.terraform.d/plugins/darwin_amd64" +2025-04-17T01:21:26.641-0700 [DEBUG] Using modified User-Agent: HashiCorp Terraform/1.10.5 (+https://www.terraform.io) HashiCorp-terraform-exec/0.21.0 +2025-04-17T01:21:26.641-0700 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins +2025-04-17T01:21:26.641-0700 [DEBUG] will search for provider plugins in /Users/darnold/.terraform.d/plugins +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0/darwin_amd64" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0/darwin_amd64/terraform-provider-openai" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0/darwin_amd64" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0/darwin_amd64/terraform-provider-gigrack" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.641-0700 [WARN] Provider plugin search ignored symlink /Users/darnold/.terraform.d/plugins/darwin_amd64/terraform-provider-configstash: only the base directory /Users/darnold/.terraform.d/plugins may be a symlink +2025-04-17T01:21:26.642-0700 [TRACE] getproviders.SearchLocalDirectory: found hashicorp.com/edu/hashicups v0.3.1 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/hashicorp.com/edu/hashicups/0.3.1/darwin_amd64 +2025-04-17T01:21:26.643-0700 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/darnold/gigrack v0.1.0 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/gigrack/0.1.0/darwin_amd64 +2025-04-17T01:21:26.643-0700 [WARN] ignoring local provider path "/Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/openai/3b6fef8/darwin_amd64" with invalid version "3b6fef8": invalid characters "b6fef8" +2025-04-17T01:21:26.643-0700 [WARN] ignoring local provider path "/Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/openai/70f25a4/darwin_amd64" with invalid version "70f25a4": invalid characters "f25a4" +2025-04-17T01:21:26.643-0700 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/happypathway/openai v5.0.0 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/registry.terraform.io/happypathway/openai/5.0.0/darwin_amd64 +2025-04-17T01:21:26.643-0700 [DEBUG] ignoring non-existing provider search directory /Users/darnold/Library/Application Support/io.terraform/plugins +2025-04-17T01:21:26.643-0700 [DEBUG] ignoring non-existing provider search directory /Library/Application Support/io.terraform/plugins +2025-04-17T01:21:26.646-0700 [INFO] Checkpoint disabled. Not running. +2025-04-17T01:21:26.647-0700 [INFO] CLI command args: []string{"version", "-json"} +2025-04-17T01:21:26.786-0700 [INFO] Terraform version: 1.10.5 +2025-04-17T01:21:26.786-0700 [DEBUG] using github.com/hashicorp/go-tfe v1.70.0 +2025-04-17T01:21:26.786-0700 [DEBUG] using github.com/hashicorp/hcl/v2 v2.23.0 +2025-04-17T01:21:26.786-0700 [DEBUG] using github.com/hashicorp/terraform-svchost v0.1.1 +2025-04-17T01:21:26.786-0700 [DEBUG] using github.com/zclconf/go-cty v1.16.2 +2025-04-17T01:21:26.786-0700 [INFO] Go runtime version: go1.23.3 +2025-04-17T01:21:26.786-0700 [INFO] CLI args: []string{"/usr/local/Cellar/tfenv/1.0.2/versions/1.10.5/terraform", "providers", "schema", "-json", "-no-color"} +2025-04-17T01:21:26.786-0700 [TRACE] Stdout is not a terminal +2025-04-17T01:21:26.786-0700 [TRACE] Stderr is not a terminal +2025-04-17T01:21:26.786-0700 [TRACE] Stdin is not a terminal +2025-04-17T01:21:26.786-0700 [DEBUG] Attempting to open CLI config file: /Users/darnold/.terraformrc +2025-04-17T01:21:26.786-0700 [INFO] Loading CLI configuration from /Users/darnold/.terraformrc +2025-04-17T01:21:26.786-0700 [INFO] Loading CLI configuration from /Users/darnold/.terraform.d/credentials.tfrc.json +2025-04-17T01:21:26.786-0700 [DEBUG] checking for credentials in "/Users/darnold/.terraform.d/plugins" +2025-04-17T01:21:26.787-0700 [DEBUG] checking for credentials in "/Users/darnold/.terraform.d/plugins/darwin_amd64" +2025-04-17T01:21:26.787-0700 [DEBUG] Using modified User-Agent: HashiCorp Terraform/1.10.5 (+https://www.terraform.io) HashiCorp-terraform-exec/0.21.0 +2025-04-17T01:21:26.787-0700 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins +2025-04-17T01:21:26.787-0700 [DEBUG] will search for provider plugins in /Users/darnold/.terraform.d/plugins +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0/darwin_amd64" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/HappyPathway/openai/0.1.0/darwin_amd64/terraform-provider-openai" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0/darwin_amd64" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] local provider path "/Users/darnold/.terraform.d/plugins/darnold/gigrack/0.1.0/darwin_amd64/terraform-provider-gigrack" contains invalid type "0.1.0"; ignoring +2025-04-17T01:21:26.787-0700 [WARN] Provider plugin search ignored symlink /Users/darnold/.terraform.d/plugins/darwin_amd64/terraform-provider-configstash: only the base directory /Users/darnold/.terraform.d/plugins may be a symlink +2025-04-17T01:21:26.787-0700 [TRACE] getproviders.SearchLocalDirectory: found hashicorp.com/edu/hashicups v0.3.1 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/hashicorp.com/edu/hashicups/0.3.1/darwin_amd64 +2025-04-17T01:21:26.788-0700 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/darnold/gigrack v0.1.0 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/gigrack/0.1.0/darwin_amd64 +2025-04-17T01:21:26.788-0700 [WARN] ignoring local provider path "/Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/openai/3b6fef8/darwin_amd64" with invalid version "3b6fef8": invalid characters "b6fef8" +2025-04-17T01:21:26.788-0700 [WARN] ignoring local provider path "/Users/darnold/.terraform.d/plugins/registry.terraform.io/darnold/openai/70f25a4/darwin_amd64" with invalid version "70f25a4": invalid characters "f25a4" +2025-04-17T01:21:26.788-0700 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/happypathway/openai v5.0.0 for darwin_amd64 at /Users/darnold/.terraform.d/plugins/registry.terraform.io/happypathway/openai/5.0.0/darwin_amd64 +2025-04-17T01:21:26.788-0700 [DEBUG] ignoring non-existing provider search directory /Users/darnold/Library/Application Support/io.terraform/plugins +2025-04-17T01:21:26.788-0700 [DEBUG] ignoring non-existing provider search directory /Library/Application Support/io.terraform/plugins +2025-04-17T01:21:26.791-0700 [INFO] Checkpoint disabled. Not running. +2025-04-17T01:21:26.793-0700 [INFO] CLI command args: []string{"providers", "schema", "-json", "-no-color"} +2025-04-17T01:21:26.793-0700 [DEBUG] Using modified User-Agent: Terraform/1.10.5 HashiCorp-terraform-exec/0.21.0 +2025-04-17T01:21:26.793-0700 [DEBUG] Using modified User-Agent: HashiCorp Terraform/1.10.5 (+https://www.terraform.io) HashiCorp-terraform-exec/0.21.0 +2025-04-17T01:21:26.794-0700 [TRACE] Meta.Backend: no config given or present on disk, so returning nil config +2025-04-17T01:21:26.794-0700 [TRACE] Meta.Backend: backend has not previously been initialized in this working directory +2025-04-17T01:21:26.794-0700 [TRACE] Meta.Backend: using default local state only (no backend configuration, and no existing initialized backend) +2025-04-17T01:21:26.794-0700 [TRACE] Meta.Backend: instantiated backend of type +2025-04-17T01:21:26.794-0700 [DEBUG] checking for provisioner in "." +2025-04-17T01:21:26.794-0700 [DEBUG] checking for provisioner in "/usr/local/Cellar/tfenv/1.0.2/versions/1.10.5" +2025-04-17T01:21:26.794-0700 [DEBUG] checking for provisioner in "/Users/darnold/.terraform.d/plugins" +2025-04-17T01:21:26.794-0700 [DEBUG] checking for provisioner in "/Users/darnold/.terraform.d/plugins/darwin_amd64" +2025-04-17T01:21:26.794-0700 [TRACE] Meta.Backend: backend does not support operations, so wrapping it in a local backend +2025-04-17T01:21:26.794-0700 [TRACE] backend/local: requesting state manager for workspace "default" +2025-04-17T01:21:26.794-0700 [TRACE] backend/local: state manager for workspace "default" will: + - read initial snapshot from terraform.tfstate + - write new snapshots to terraform.tfstate + - create any backup at terraform.tfstate.backup +2025-04-17T01:21:26.794-0700 [TRACE] backend/local: requesting state lock for workspace "default" +2025-04-17T01:21:26.795-0700 [TRACE] backend/local: reading remote state for workspace "default" +2025-04-17T01:21:26.795-0700 [TRACE] statemgr.Filesystem: reading initial snapshot from terraform.tfstate +2025-04-17T01:21:26.795-0700 [TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay +2025-04-17T01:21:26.795-0700 [TRACE] statemgr.Filesystem: read nil snapshot +2025-04-17T01:21:26.795-0700 [TRACE] backend/local: populating backendrun.LocalRun for current working directory +2025-04-17T01:21:26.807-0700 [TRACE] Config.VerifyDependencySelections: provider registry.terraform.io/hashicorp/aws has no lock file entry to satisfy "" diff --git a/Makefile b/Makefile deleted file mode 100644 index 3834daf..0000000 --- a/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -.PHONY: init venv install-deps clean init plan apply destroy all invoke-lambda package-lambda - -PYTHON=python3 -PIP=pip3 -TERRAFORM=tf -VENV=.venv -VENV_BIN=$(VENV)/bin -VENV_PIP=$(VENV_BIN)/pip - -# Set PIP_CONFIG_FILE to use custom pip.conf -export PIP_CONFIG_FILE=$(CURDIR)/scripts/pip.conf - -all: venv install-deps apply - -venv: - test -d $(VENV) || $(PYTHON) -m venv $(VENV) - $(VENV_PIP) install --upgrade pip setuptools wheel - -install-deps: venv - source $(VENV_BIN)/activate && $(VENV_PIP) install -r scripts/requirements.txt - -clean: - rm -rf dist/ - rm -f *.zip - rm -rf __pycache__/ - rm -rf .terraform/ - rm -rf $(VENV) - -init: - $(TERRAFORM) init - -plan: init - $(TERRAFORM) plan - -apply: init - $(TERRAFORM) apply -auto-approve - -destroy: init - $(TERRAFORM) destroy -auto-approve - -invoke-lambda: - @echo "Invoking Lambda function via API Gateway..." - @source $(VENV_BIN)/activate && $(PYTHON) scripts/invoke_lambda.py $(ARGS) - @echo "For more options, run: make invoke-lambda ARGS='-h'" - -package-lambda: venv install-deps - @echo "Packaging Lambda function and dependencies..." - @mkdir -p dist - @source $(VENV_BIN)/activate && $(PYTHON) scripts/package_lambda.py $(CURDIR) - @echo "Tainting S3 objects to ensure they are recreated on next apply..." - -$(TERRAFORM) taint 'aws_s3_object.lambda_package' - -$(TERRAFORM) taint 'aws_s3_object.lambda_layer' - @echo "Lambda package created successfully in the dist/ directory" diff --git a/api_gateway.tf b/api_gateway.tf deleted file mode 100644 index bbbfbf0..0000000 --- a/api_gateway.tf +++ /dev/null @@ -1,63 +0,0 @@ -# API Gateway HTTP API without CORS (we'll add CORS separately) -resource "aws_apigatewayv2_api" "lambda_api" { - name = "${var.name}-api-gateway" - protocol_type = "HTTP" - cors_configuration { - allow_credentials = false - allow_headers = [ - "*", - ] - allow_methods = [ - "POST", - ] - allow_origins = [ - "*", - ] - expose_headers = [ - "*", - ] - max_age = 86400 - } - lifecycle { - ignore_changes = [ - cors_configuration - ] - } -} - -# API Gateway Integration with Lambda -resource "aws_apigatewayv2_integration" "lambda_integration" { - api_id = aws_apigatewayv2_api.lambda_api.id - integration_type = "AWS_PROXY" - integration_uri = aws_lambda_function.eks_automation.invoke_arn - payload_format_version = "2.0" -} - -# API Gateway Route for POST requests -resource "aws_apigatewayv2_route" "lambda_route" { - api_id = aws_apigatewayv2_api.lambda_api.id - route_key = "POST /" - target = "integrations/${aws_apigatewayv2_integration.lambda_integration.id}" -} - -# API Gateway Stage -resource "aws_apigatewayv2_stage" "lambda_stage" { - api_id = aws_apigatewayv2_api.lambda_api.id - name = "$default" - auto_deploy = true -} - -# Lambda Permission for API Gateway -resource "aws_lambda_permission" "api_gateway_permission" { - statement_id = "AllowAPIGatewayInvoke" - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.eks_automation.function_name - principal = "apigateway.amazonaws.com" - source_arn = "${aws_apigatewayv2_api.lambda_api.execution_arn}/*/*" -} - -# Add API Gateway URL to outputs -output "api_gateway_invoke_url" { - value = "${aws_apigatewayv2_stage.lambda_stage.invoke_url}" - description = "API Gateway URL for invoking the Lambda function" -} diff --git a/backend.tf.tmp b/backend.tf.tmp deleted file mode 100644 index eba3e91..0000000 --- a/backend.tf.tmp +++ /dev/null @@ -1,8 +0,0 @@ -terraform { - backend "s3" { - bucket = "inf-tfstate-us-gov-west-1-229685449397" - key = "csvd-dev-gov/common/apps/eks-automation/terraform.tfstate" - region = "us-gov-west-1" - dynamodb_table = "tf_remote_state" - } -} diff --git a/data.tf b/data.tf deleted file mode 100644 index 0b9fe53..0000000 --- a/data.tf +++ /dev/null @@ -1,5 +0,0 @@ -data aws_partition current {} - -data "aws_caller_identity" "current" {} - -data aws_region current {} \ No newline at end of file diff --git a/locals.tf b/locals.tf deleted file mode 100644 index a840973..0000000 --- a/locals.tf +++ /dev/null @@ -1,11 +0,0 @@ - -locals { - common_tags = { - environment = var.environment - environment_abbr = var.environment_abbr - organization = var.organization - finops_project_name = var.finops_project_name - finops_project_number = var.finops_project_number - finops_project_role = var.finops_project_role - } -} \ No newline at end of file diff --git a/main.tf b/main.tf index 17c2594..baf5863 100644 --- a/main.tf +++ b/main.tf @@ -1,246 +1,49 @@ -# S3 Bucket for Lambda artifacts - Only needed for zip deployments -resource "aws_s3_bucket" "lambda_artifacts" { - count = var.lambda_deployment_type == "zip" ? 1 : 0 - - bucket = "${var.name}-lambda-artifacts-${data.aws_caller_identity.current.account_id}" - - tags = local.common_tags - - # Package Lambda function and layer - provisioner "local-exec" { - command = "${path.module}/scripts/package_lambda.py ${path.module}" - environment = { - PIP_CONFIG_FILE = "${path.module}/scripts/pip.conf" - } - } -} - -resource "aws_s3_bucket_versioning" "lambda_artifacts" { - bucket = aws_s3_bucket.lambda_artifacts.id - versioning_configuration { - status = "Enabled" - } +provider "aws" { + region = "us-east-1" } -# Upload Lambda package to S3 - Only for zip deployments -resource "aws_s3_object" "lambda_package" { - count = var.lambda_deployment_type == "zip" ? 1 : 0 - - bucket = aws_s3_bucket.lambda_artifacts[0].id - key = "eks_automation.zip" - source = "${path.module}/dist/eks_automation.zip" - depends_on = [aws_s3_bucket.lambda_artifacts] -} - -# Upload Lambda layer to S3 - Only for zip deployments -resource "aws_s3_object" "lambda_layer" { - count = var.lambda_deployment_type == "zip" ? 1 : 0 - - bucket = aws_s3_bucket.lambda_artifacts[0].id - key = "layer.zip" - source = "${path.module}/dist/layer.zip" - depends_on = [aws_s3_bucket.lambda_artifacts] -} - -# Lambda Function URL feature is not available or not working properly in AWS GovCloud -# Using API Gateway as an alternative (defined in api_gateway.tf) - -# Lambda Layer - Only used for zip deployments -resource "aws_lambda_layer_version" "git" { - count = var.lambda_deployment_type == "zip" ? 1 : 0 - - s3_bucket = aws_s3_bucket.lambda_artifacts.id - s3_key = "layer.zip" - layer_name = "${var.name}-lambda-layer" - description = "${var.name} Lambda Layer" - compatible_runtimes = ["python3.9", "python3.10", "python3.11"] - depends_on = [aws_s3_object.lambda_layer] -} +data "aws_caller_identity" "current" {} -# Lambda Function -resource "aws_lambda_function" "eks_automation" { - function_name = "${var.name}-eks-automation" - role = aws_iam_role.lambda_role.arn - timeout = var.lambda_timeout - - # Conditional deployment based on deployment type - dynamic "image_config" { - for_each = var.lambda_deployment_type == "container" ? [1] : [] - content { - command = ["app.lambda_handler"] - } - } - - # Set package type based on deployment method - package_type = var.lambda_deployment_type == "container" ? "Image" : "Zip" - - # Container image configuration - image_uri = var.lambda_deployment_type == "container" ? var.container_image_uri : null - - # Zip deployment configuration - s3_bucket = var.lambda_deployment_type == "zip" ? aws_s3_bucket.lambda_artifacts[0].id : null - s3_key = var.lambda_deployment_type == "zip" ? "eks_automation.zip" : null - handler = var.lambda_deployment_type == "zip" ? "app.lambda_handler" : null - runtime = var.lambda_deployment_type == "zip" ? "python3.9" : null - layers = var.lambda_deployment_type == "zip" ? [aws_lambda_layer_version.git[0].arn] : null +resource "aws_ecrpublic_repository" "eks-automation-lambda" { + repository_name = "eks-automation-lambda" - vpc_config { - subnet_ids = var.vpc_subnet_ids - security_group_ids = var.vpc_security_group_ids + catalog_data { + about_text = "EKS Automation Lambda Image" + architectures = ["x86_64"] + description = "Lambda container image for EKS automation" + operating_systems = ["AmazonLinux2"] + usage_text = "Creates an EKS Automation Lambda container image" } - environment { - variables = { - ENVIRONMENT = var.environment - CENSUS_GITHUB_API = "https://github-instance.your-domain.com/api/v3" - GITHUB_ORG_NAME = "Your-Organization" - GITHUB_TOKEN_SECRET_NAME = "/path/to/github/token" - TEMPLATE_REPO_NAME = "your-template-repo" - TEMPLATE_FILE_NAME = "template.j2" - HCL_FILE_NAME = "config.hcl" - } + tags = { + env = "production" } - - tags = local.common_tags - depends_on = concat( - [ - aws_iam_role_policy_attachment.lambda_vpc_access, - aws_iam_role_policy.lambda_ssm_access, - ], - var.lambda_deployment_type == "zip" ? [ - aws_s3_object.lambda_package, - aws_s3_object.lambda_layer - ] : [] - ) } -# CloudWatch Log Group for Lambda Function -resource "aws_cloudwatch_log_group" "eks_automation" { - name = "/aws/lambda/${aws_lambda_function.eks_automation.function_name}" - retention_in_days = 14 # Or your desired retention period - - tags = local.common_tags +locals { + repository_uri = aws_ecrpublic_repository.eks-automation-lambda.repository_uri + repository_id = aws_ecrpublic_repository.eks-automation-lambda.id + aws_account_id = data.aws_caller_identity.current.account_id + region = "us-east-1" + arn = aws_ecrpublic_repository.eks-automation-lambda.arn } -# IAM Role for Lambda -resource "aws_iam_role" "lambda_role" { - name = "${var.name}-lambda-role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - } - ] - }) - - tags = local.common_tags +output "repository_uri" { + value = local.repository_uri } -# IAM Policies -resource "aws_iam_role_policy_attachment" "lambda_vpc_access" { - role = aws_iam_role.lambda_role.name - policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +output "repository_id" { + value = local.repository_id } -resource "aws_iam_role_policy" "lambda_ssm_access" { - name = "${var.name}-ssm-access" - role = aws_iam_role.lambda_role.id - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Sid = "SSMDescribeParametersPolicy" - Effect = "Allow" - Action = ["ssm:DescribeParameters"] - Resource = "*" - }, - { - Sid = "SSMGetParameterPolicy" - Effect = "Allow" - Action = [ - "ssm:GetParameters", - "ssm:GetParameter" - ] - Resource = "*" - } - ] - }) +output "aws_account_id" { + value = local.aws_account_id } -resource "aws_iam_role_policy" "lambda_function_url" { - name = "${var.name}-function-url-access" - role = aws_iam_role.lambda_role.id - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "lambda:CreateFunctionUrlConfig", - "lambda:UpdateFunctionUrlConfig", - "lambda:DeleteFunctionUrlConfig", - "lambda:GetFunctionUrlConfig", - "lambda:InvokeFunctionUrl", - "lambda:AddPermission", - "lambda:RemovePermission" - ] - Resource = [ - aws_lambda_function.eks_automation.arn, - "${aws_lambda_function.eks_automation.arn}/*" - ] - }, - { - Effect = "Allow" - Action = [ - "lambda:InvokeFunction" - ] - Resource = aws_lambda_function.eks_automation.arn - } - ] - }) +output "region" { + value = local.region } -# ECR Repository for Lambda container images -resource "aws_ecr_repository" "lambda_container" { - count = var.lambda_deployment_type == "container" && var.create_ecr_repository ? 1 : 0 - - name = coalesce(var.ecr_repository_name, "${var.name}-lambda-container") - image_tag_mutability = "MUTABLE" - - image_scanning_configuration { - scan_on_push = true - } - - tags = local.common_tags -} - -# ECR Repository Policy -resource "aws_ecr_repository_policy" "lambda_container_policy" { - count = var.lambda_deployment_type == "container" && var.create_ecr_repository ? 1 : 0 - - repository = aws_ecr_repository.lambda_container[0].name - policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Sid = "LambdaECRImageRetrievalPolicy", - Effect = "Allow", - Principal = { - Service = "lambda.amazonaws.com" - }, - Action = [ - "ecr:BatchGetImage", - "ecr:GetDownloadUrlForLayer" - ] - } - ] - }) -} +output "arn" { + value = local.arn +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf deleted file mode 100644 index aca3e2f..0000000 --- a/outputs.tf +++ /dev/null @@ -1,46 +0,0 @@ -# output "function_url" { -# description = "API Gateway URL for invoking the Lambda function" -# value = aws_apigatewayv2_stage.lambda_stage.invoke_url -# } - -# output "function_arn" { -# description = "Lambda function ARN" -# value = aws_lambda_function.eks_automation.arn -# } - -output user { - value = data.aws_caller_identity.current -} - -output log_group { - value = aws_cloudwatch_log_group.eks_automation.name -} - -output aws_region { - value = data.aws_region.current.name -} - -output "lambda_function_arn" { - description = "The ARN of the Lambda Function" - value = aws_lambda_function.eks_automation.arn -} - -output "lambda_function_name" { - description = "The name of the Lambda Function" - value = aws_lambda_function.eks_automation.function_name -} - -output "lambda_deployment_type" { - description = "The deployment type used for the Lambda function (zip or container)" - value = var.lambda_deployment_type -} - -output "ecr_repository_url" { - description = "The URL of the ECR repository (only applicable when using container deployment)" - value = var.lambda_deployment_type == "container" && var.create_ecr_repository ? aws_ecr_repository.lambda_container[0].repository_url : null -} - -output "container_image_uri" { - description = "The container image URI used for the Lambda function (only applicable when using container deployment)" - value = var.lambda_deployment_type == "container" ? var.container_image_uri : null -} \ No newline at end of file diff --git a/packer.pkr.hcl b/packer.pkr.hcl new file mode 100644 index 0000000..af8805f --- /dev/null +++ b/packer.pkr.hcl @@ -0,0 +1,58 @@ +packer { + required_plugins { + docker = { + source = "github.com/hashicorp/docker" + version = "~> 1" + } + } +} + +variable "repository_uri" { + type = string +} + +variable "tag" { + type = string + default = "latest" +} + +source "docker" "lambda" { + image = "public.ecr.aws/lambda/python:3.11" + commit = true + changes = [ + "WORKDIR /var/task", + "CMD [ \"app.handler\" ]" + ] +} + +build { + name = "eks-automation-lambda" + + sources = [ + "source.docker.lambda" + ] + + provisioner "file" { + source = "./eks_automation" + destination = "/var/task/" + } + + provisioner "shell" { + inline = [ + "cd /var/task", + "pip3 install -r requirements.txt -t ." + ] + } + + post-processors { + post-processor "docker-tag" { + repository = var.repository_uri + tags = [var.tag] + } + + post-processor "docker-push" { + ecr_login = true + login_server = var.repository_uri + } + } +} \ No newline at end of file diff --git a/providers.tf b/providers.tf deleted file mode 100644 index b79bf75..0000000 --- a/providers.tf +++ /dev/null @@ -1,6 +0,0 @@ -provider "aws" { - region = var.aws_region - default_tags { - tags = local.common_tags - } -} diff --git a/scripts/invoke_lambda.py b/scripts/invoke_lambda.py deleted file mode 100644 index e6f854b..0000000 --- a/scripts/invoke_lambda.py +++ /dev/null @@ -1,313 +0,0 @@ -#!/usr/bin/env python3 -""" -Script to invoke the EKS Automation Lambda function via API Gateway. -Parses Terraform outputs to get the API Gateway URL, log group name, and AWS region. -""" - -import json -import argparse -import subprocess -import sys -import requests -import os -import time -import boto3 -import datetime - - -class LambdaInvoker: - """Class for invoking Lambda functions and managing related operations.""" - - def __init__(self): - """Initialize the LambdaInvoker.""" - self.api_url = None - self.log_group_name = None - self.invocation_start_time = None - self.aws_region = None - self.session = None - - @staticmethod - def get_terraform_output(output_name): - """Get a specific Terraform output value by name.""" - try: - # Run Terraform output command - result = subprocess.run( - f"tf output -raw {output_name}", - shell=True, - capture_output=True, - text=True, - check=True, - ) - output_data = result.stdout - return output_data - except subprocess.CalledProcessError as e: - print(f"Error retrieving Terraform output '{output_name}': {e}") - print(f"stderr: {e.stderr}") - return None - except json.JSONDecodeError as e: - print(f"Error parsing Terraform output as JSON: {e}") - return None - - def initialize_from_terraform(self): - """Initialize API URL and log group name from Terraform outputs.""" - # Get API Gateway URL from Terraform output - output_name = "api_gateway_invoke_url" - self.api_url = self.get_terraform_output(output_name) - print(f"Found API Gateway URL in output: {output_name}. {self.api_url}") - if not self.api_url: - print("Error: Failed to find API Gateway URL in Terraform outputs") - return False - - # Get log group name from Terraform output - self.log_group_name = self.get_terraform_output("log_group") - if not self.log_group_name: - print("Warning: Failed to find CloudWatch log group in Terraform outputs") - print("CloudWatch logs will not be available") - else: - print(f"CloudWatch log group: {self.log_group_name}") - - # Get AWS region from Terraform output - self.aws_region = self.get_terraform_output("aws_region") - if not self.aws_region: - print("Warning: Failed to find AWS region in Terraform outputs") - print("Attempting to use default AWS region from environment or config") - else: - print(f"AWS Region: {self.aws_region}") - - print(f"API Gateway URL: {self.api_url}") - return True - - def initialize_aws_session(self, profile_name=None): - """ - Initialize AWS session for accessing AWS services - - Priority order for credentials: - 1. AWS environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) - 2. AWS profile if specified - 3. Default credential provider chain - - Args: - profile_name: Optional AWS profile name to use (lower priority than env vars) - - Returns: - True if successful, False otherwise - """ - try: - # Check if AWS environment variables are set - if os.environ.get('AWS_ACCESS_KEY_ID') and os.environ.get('AWS_SECRET_ACCESS_KEY'): - print("Using AWS credentials from environment variables") - # When using environment variables, boto3.Session() will automatically pick them up - self.session = boto3.Session(region_name=self.aws_region) - elif profile_name: - print(f"Using AWS profile: {profile_name}") - self.session = boto3.Session(profile_name=profile_name, region_name=self.aws_region) - else: - print("Using default AWS credentials") - self.session = boto3.Session(region_name=self.aws_region) - - # Test that credentials are valid - sts = self.session.client('sts') - identity = sts.get_caller_identity() - print(f"Using AWS account: {identity['Account']}") - print(f"Using IAM identity: {identity['Arn']}") - return True - except Exception as e: - print(f"Error initializing AWS session: {e}") - print("Make sure your AWS credentials are properly configured") - print("Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optionally AWS_SESSION_TOKEN environment variables") - return False - - def prepare_payload(self, args): - """Prepare the payload for Lambda invocation based on command-line arguments.""" - payload = None - if args.input: - try: - with open(args.input, 'r') as f: - payload = json.load(f) - except (IOError, json.JSONDecodeError) as e: - print(f"Error reading input file: {e}") - return None - elif args.payload: - try: - payload = json.loads(args.payload) - except json.JSONDecodeError as e: - print(f"Error parsing JSON payload: {e}") - return None - else: - # Default minimal payload if none provided - payload = {"message": "Test invocation"} - - print(f"Sending payload: {json.dumps(payload, indent=2)}") - return payload - - def invoke_lambda(self, payload, show_logs=False): - """ - Invoke the Lambda function via API Gateway and handle response - - Args: - payload: The payload to send to the Lambda function - show_logs: Whether to show CloudWatch logs regardless of success - - Returns: - 0 for success, 1 for failure - """ - # Record start time for log filtering - self.invocation_start_time = int(time.time() * 1000) - - try: - response = requests.post(self.api_url, json=payload) - print(f"Status code: {response.status_code}") - - try: - response_json = response.json() - print(f"Response: {json.dumps(response_json, indent=2)}") - except json.JSONDecodeError: - print(f"Response (raw): {response.text}") - - # Check if we need to display logs - should_show_logs = show_logs or not (200 <= response.status_code < 300) - print(f"Show logs: {should_show_logs}") - print(f"Log group name: {self.log_group_name}") - - # Fetch and display CloudWatch logs if needed - if should_show_logs and self.log_group_name: - # Wait a moment for logs to be available - time.sleep(2) - print("Fetching CloudWatch logs to help diagnose the issue...") - log_events = self.fetch_cloudwatch_logs(start_time=self.invocation_start_time) - self.display_cloudwatch_logs(log_events) - - # Return success if status code is 2xx - if 200 <= response.status_code < 300: - return 0 - else: - return 1 - except requests.RequestException as e: - print(f"Error invoking Lambda function: {e}") - - # Try to fetch logs on error - if self.log_group_name: - print("Fetching CloudWatch logs to help diagnose the issue...") - log_events = self.fetch_cloudwatch_logs(start_time=self.invocation_start_time) - self.display_cloudwatch_logs(log_events) - - return 1 - - def fetch_cloudwatch_logs(self, start_time=None, limit=20): - """ - Fetch recent logs from CloudWatch log group - - Args: - start_time: Start time for logs in Unix timestamp milliseconds - limit: Maximum number of log events to return - - Returns: - List of log events - """ - if not self.log_group_name: - return [] - - if start_time is None: - # Default to fetching logs from 5 minutes ago - start_time = int((datetime.datetime.now() - - datetime.timedelta(minutes=5)).timestamp() * 1000) - - try: - # Use the session to create a logs client with proper credentials - if self.session: - logs_client = self.session.client('logs') - else: - # Fallback to default client without session (uses environment credentials) - logs_client = boto3.client('logs', region_name=self.aws_region) - - response = logs_client.filter_log_events( - logGroupName=self.log_group_name, - startTime=start_time, - limit=limit, - interleaved=True, - ) - return response.get('events', []) - except Exception as e: - print(f"Error fetching CloudWatch logs: {e}") - print("This might be due to insufficient IAM permissions or invalid credentials") - return [] - - def display_cloudwatch_logs(self, log_events): - """ - Format and display CloudWatch log events - - Args: - log_events: List of CloudWatch log events - """ - if not log_events: - print("No recent CloudWatch logs found") - return - - print("\n=== Recent CloudWatch Logs ===") - for event in log_events: - timestamp = datetime.datetime.fromtimestamp( - event['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S') - message = event['message'].rstrip() - print(f"[{timestamp}] {message}") - print("=============================\n") - - -def main(): - """Main function to parse arguments and invoke the Lambda function.""" - parser = argparse.ArgumentParser( - description="Invoke EKS Automation Lambda function via API Gateway" - ) - parser.add_argument( - "-i", "--input", - help="Path to JSON file containing input payload", - default=os.path.join(os.path.dirname(__file__), "test_payload.json"), - required=False - ) - parser.add_argument( - "-p", "--payload", - help="JSON string payload to send to Lambda", - required=False - ) - parser.add_argument( - "--show-logs", - help="Always show CloudWatch logs, even on success", - action="store_true" - ) - parser.add_argument( - "--profile", - help="AWS profile name to use for credentials (environment variables take precedence if set)", - default=None - ) - - # Add an epilog message explaining credential options - parser.epilog = """ - AWS Authentication: - - Environment variables (preferred): AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN (optional) - - AWS profile (if specified with --profile) - - Default credential provider chain - """ - args = parser.parse_args() - - # Initialize the Lambda invoker - invoker = LambdaInvoker() - - # Initialize from Terraform outputs - if not invoker.initialize_from_terraform(): - sys.exit(1) - - # Initialize AWS session with credentials - if not invoker.initialize_aws_session(profile_name=args.profile): - print("Warning: Failed to initialize AWS session. Some features may not work.") - - # Prepare the payload - payload = invoker.prepare_payload(args) - if payload is None: - sys.exit(1) - - # Invoke the Lambda function - exit_code = invoker.invoke_lambda(payload, show_logs=args.show_logs) - return exit_code - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/scripts/package_lambda.py b/scripts/package_lambda.py deleted file mode 100755 index 37dd0ff..0000000 --- a/scripts/package_lambda.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python3 -""" -Lambda Function and Layer Packaging Script - -This script packages AWS Lambda function code and its dependencies into separate -zip files ready for deployment. It handles both the main function code and -a Lambda layer containing Python dependencies. -""" - -import asyncio -import logging -import os -import shutil -import sys -import zipfile -from dataclasses import dataclass -from pathlib import Path -from typing import Optional - -# Configure logging -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S' -) -logger = logging.getLogger("lambda_packager") - -@dataclass -class PackageConfig: - """Configuration for Lambda packaging.""" - workspace_dir: Path - dist_dir: Path - lambda_dir: Path - requirements_file: Path - - @classmethod - def from_workspace(cls, workspace_dir: Path) -> "PackageConfig": - """Create config from workspace directory.""" - return cls( - workspace_dir=workspace_dir, - dist_dir=workspace_dir / "dist", - lambda_dir=workspace_dir / "eks_automation", - requirements_file=workspace_dir / "eks_automation" / "requirements.txt" - ) - -class PackagingError(Exception): - """Base exception for packaging errors.""" - pass - -class DirectoryManager: - """Manages creation and cleanup of directories.""" - - def __init__(self, directory: Path): - self.directory = directory - - def __enter__(self) -> Path: - """Create clean directory.""" - if self.directory.exists(): - shutil.rmtree(self.directory) - self.directory.mkdir(parents=True) - return self.directory - - def __exit__(self, exc_type, exc_val, exc_tb): - """Handle cleanup if needed.""" - if exc_type is not None: - logger.error(f"Error occurred: {exc_val}") - return False - return True - -def create_zip(source_dir: Path, output_file: Path) -> None: - """Create a zip file from a directory.""" - logger.info(f"Creating zip file: {output_file}") - if not source_dir.exists(): - raise PackagingError(f"Source directory does not exist: {source_dir}") - - if not any(source_dir.iterdir()): - raise PackagingError(f"Source directory is empty: {source_dir}") - - output_file.parent.mkdir(parents=True, exist_ok=True) - if output_file.exists(): - output_file.unlink() - - try: - with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zf: - for root, _, files in os.walk(source_dir): - rel_dir = os.path.relpath(root, source_dir) - for file in files: - file_path = os.path.join(root, file) - arcname = os.path.join(rel_dir, file) - if rel_dir == '.': - arcname = file - zf.write(file_path, arcname) - - if not output_file.exists(): - raise PackagingError(f"Zip file was not created: {output_file}") - except Exception as e: - raise PackagingError(f"Failed to create zip file: {str(e)}") - -async def create_constraints_file(target_dir: Path) -> Path: - """Create a constraints file to ensure compatibility with Lambda runtime.""" - constraints_file = target_dir / "constraints.txt" - - logger.info("Creating constraints file for Lambda compatibility") - with open(constraints_file, "w") as f: - f.write("# Constraints for Lambda compatibility\n") - f.write("# Pin cryptography to version compatible with Lambda's GLIBC\n") - f.write("cryptography<38.0.0\n") - f.write("# Additional constraints for Lambda compatibility\n") - f.write("PyGithub<1.59.0\n") - f.write("GitPython<3.1.31\n") - - return constraints_file - -async def install_requirements(requirements_file: Path, target_dir: Path) -> None: - """Install Python requirements to target directory with constraints.""" - # Create constraints file - constraints_file = await create_constraints_file(target_dir.parent) - - logger.info(f"Installing requirements with constraints for Lambda compatibility") - process = await asyncio.create_subprocess_exec( - "pip", "install", "-r", str(requirements_file), "-t", str(target_dir), - "--constraint", str(constraints_file), - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE - ) - stdout, stderr = await process.communicate() - - if process.returncode != 0: - raise PackagingError(f"pip install failed: {stderr.decode()}") - -async def package_lambda(config: PackageConfig) -> None: - """Package Lambda function and layer.""" - try: - # Set up directories - logger.info("Setting up directories...") - lambda_dist = config.dist_dir / "lambda" - layer_dir = config.dist_dir / "layer" - layer_python_dir = layer_dir / "python" - - # Create directories - with DirectoryManager(lambda_dist): - # Copy Lambda function code - logger.info("Copying Lambda function code...") - shutil.copytree(config.lambda_dir, lambda_dist, dirs_exist_ok=True) - # Create function zip - create_zip(lambda_dist, config.dist_dir / "eks_automation.zip") - - # Create layer if requirements exist - if config.requirements_file.exists(): - with DirectoryManager(layer_python_dir): - logger.info("Installing Python requirements...") - await install_requirements(config.requirements_file, layer_python_dir) - # Create zip from the layer directory containing the python subdirectory - create_zip(layer_python_dir.parent, config.dist_dir / "layer.zip") - else: - raise PackagingError("requirements.txt not found") - except Exception as e: - logger.error(f"Packaging failed: {str(e)}") - raise PackagingError(f"Lambda packaging failed: {str(e)}") - - logger.info("Successfully created Lambda package and layer") - -def main() -> None: - """Main entry point.""" - try: - if len(sys.argv) != 2: - raise PackagingError("Usage: package_lambda.py ") - - workspace_dir = Path(sys.argv[1]) - if not workspace_dir.exists(): - raise PackagingError(f"Workspace directory not found: {workspace_dir}") - - config = PackageConfig.from_workspace(workspace_dir) - asyncio.run(package_lambda(config)) - - except PackagingError as e: - logger.error(f"Error: {e}") - sys.exit(1) - except Exception as e: - logger.exception("Unexpected error occurred") - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/scripts/pip.conf b/scripts/pip.conf deleted file mode 100644 index 3c3b843..0000000 --- a/scripts/pip.conf +++ /dev/null @@ -1,10 +0,0 @@ -[global] -cert = /etc/pki/ca-trust/source/anchors/katello-server-ca.pem -#proxy = http://proxy.tco.census.gov:3128 -index = https://nexus.it.census.gov:8443/repository/DataScience-Group/pypi -index-url = https://nexus.it.census.gov:8443/repository/DataScience-Group/simple -trusted-host = nexus.it.census.gov - pypi.python.org - pypi.org - files.pythonhosted.org - proxy.tco.census.gov \ No newline at end of file diff --git a/scripts/requirements.txt b/scripts/requirements.txt deleted file mode 100644 index fcad05a..0000000 --- a/scripts/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -rich>=10.0.0 diff --git a/scripts/test_payload.json b/scripts/test_payload.json deleted file mode 100644 index 9dea9e4..0000000 --- a/scripts/test_payload.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "project_name": "eks-automation-lambda-test1", - "eks_settings": { - "attrs": { - "account_name": "lab-dev-ew", - "aws_region": "us-gov-east-1", - "cluster_mailing_list": "matthew.c.morgan@census.gov", - "cluster_name": "csvd-platform-lab-mcm", - "eks_instance_disk_size": 100, - "eks_ng_desired_size": 2, - "eks_ng_max_size": 10, - "eks_ng_min_size": 2, - "environment": "development", - "environment_abbr": "dev", - "organization": "census:ocio:csvd", - "finops_project_name": "csvd_platformbaseline", - "finops_project_number": "fs0000000078", - "finops_project_role": "csvd_platformbaseline_app", - "vpc_domain_name": "dev.lab.csp2.census.gov", - "vpc_name": "vpc3-lab-dev" - }, - "tags" : { - "slim:schedule": "8:00-17:00" - } - } - } \ No newline at end of file diff --git a/varfiles/default.json b/varfiles/default.json deleted file mode 100644 index 9e26dfe..0000000 --- a/varfiles/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/varfiles/default.tfvars b/varfiles/default.tfvars deleted file mode 100644 index e69de29..0000000 diff --git a/varfiles/sct-engineering.json b/varfiles/sct-engineering.json deleted file mode 100644 index 9e26dfe..0000000 --- a/varfiles/sct-engineering.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/varfiles/sct-engineering.tfvars b/varfiles/sct-engineering.tfvars deleted file mode 100644 index 6453b5f..0000000 --- a/varfiles/sct-engineering.tfvars +++ /dev/null @@ -1,31 +0,0 @@ -name = "eks-repo-done-right" -# This file contains the variable values for the Terraform configuration. -# It is used to set up the AWS Lambda function and its associated resources. -# The values here are specific to the development environment and should be -# adjusted for production or other environments as needed. -# -# Environment variables -# These variables are used to configure the AWS Lambda function and its -# associated resources. They include the environment name, organization, -# FinOps project details, VPC security group IDs, subnet IDs, and Lambda -# timeout settings. -# The AWS region is set to "us-gov-west-1" for the development environment. -# The VPC security group IDs and subnet IDs are specific to the AWS -# infrastructure setup and should be verified before deployment. -# The Lambda timeout is set to 30 seconds, which should be sufficient for -# most operations. -environment = "development" -environment_abbr = "dev" -organization = "census:ocio:csvd" -finops_project_name = "csvd_platformbaseline" -finops_project_number = "fs0000000078" -finops_project_role = "csvd_platformbaseline_app" -vpc_security_group_ids = [ - "sg-03cbf2a626ed55c7e" -] -vpc_subnet_ids = [ - "subnet-05192178ac094f639", - "subnet-022370a5a03585376" -] -lambda_timeout = 30 -aws_region = "us-gov-east-1" \ No newline at end of file diff --git a/variables.tf b/variables.tf deleted file mode 100644 index e70eb40..0000000 --- a/variables.tf +++ /dev/null @@ -1,121 +0,0 @@ -variable "environment" { - description = "Environment name" - type = string -} - -variable "environment_abbr" { - description = "Environment abbreviation" - type = string -} - -variable "organization" { - description = "Organization name" - type = string -} - -variable "finops_project_name" { - description = "FinOps project name" - type = string -} - -variable "finops_project_number" { - description = "FinOps project number" - type = string -} - -variable "finops_project_role" { - description = "FinOps project role" - type = string -} - -variable "vpc_security_group_ids" { - description = "List of VPC security group IDs" - type = list(string) -} - -variable "vpc_subnet_ids" { - description = "List of VPC subnet IDs" - type = list(string) -} - -variable "lambda_timeout" { - description = "Lambda function timeout in seconds" - type = number -} - -variable "aws_region" { - description = "AWS region" - type = string - default = "us-gov-west-2" -} - -variable name { - description = "Name of the resource" - type = string - default = "eks-automation" -} - -variable "lambda_deployment_type" { - description = "Lambda deployment type: 'zip' or 'container'" - type = string - default = "zip" - validation { - condition = contains(["zip", "container"], var.lambda_deployment_type) - error_message = "Valid values for lambda_deployment_type are 'zip' or 'container'" - } -} - -variable "container_image_uri" { - description = "ECR container image URI for Lambda container (required if lambda_deployment_type is 'container')" - type = string - default = null -} - -variable "create_ecr_repository" { - description = "Whether to create an ECR repository for Lambda container images" - type = bool - default = true -} - -variable "ecr_repository_name" { - description = "Name of the ECR repository for Lambda container images" - type = string - default = null -} - -# Environment variables for EKS Automation Lambda -variable "census_github_api" { - description = "URL for the Census GitHub API" - type = string - default = "https://github.e.it.census.gov/api/v3" -} - -variable "github_org_name" { - description = "GitHub organization name" - type = string - default = "SCT-Engineering" -} - -variable "github_token_secret_name" { - description = "AWS SSM parameter name for the GitHub token" - type = string - default = "/eks-cluster-deployment/github_token" -} - -variable "template_repo_name" { - description = "GitHub repository name for the EKS template" - type = string - default = "template-eks-cluster" -} - -variable "template_file_name" { - description = "Template file name for the EKS configuration" - type = string - default = "eks.hcl.j2" -} - -variable "hcl_file_name" { - description = "Output file name for the rendered HCL configuration" - type = string - default = "eks.hcl" -} \ No newline at end of file diff --git a/versions.tf b/versions.tf deleted file mode 100644 index b36f3a4..0000000 --- a/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 1.0.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - } -}