-
Notifications
You must be signed in to change notification settings - Fork 0
Add CLI Command to Check Deployment Prerequisites #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
BenCodeOcean
wants to merge
16
commits into
main
Choose a base branch
from
prerequisites-script-sc-97879
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,383
−2
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
74168e3
First commit
BenCodeOcean bf89674
Refactor project structure: rename to co-support, update requirements…
BenCodeOcean 46aa399
Add __init__.py to prerequisites module
BenCodeOcean 4952630
Add __init__.py files to checks and core modules
BenCodeOcean 1968a92
Update README.md: enhance installation instructions and usage examples
BenCodeOcean 09292fd
Rename run_checks to check_prerequisites for clarity and update refer…
BenCodeOcean 5da5458
short url
BenCodeOcean a33dd9d
syle fixes
BenCodeOcean 95a6c78
style fixes
BenCodeOcean c5e4e3f
role arn
BenCodeOcean 9d3def6
Improve clarity in vCPU and EIP quota checks by enhancing return mess…
BenCodeOcean 745021d
Update README and code to include role option and improve messaging f…
BenCodeOcean b262eab
Refactor argument parsing and enhance YAML handling; improve help mes…
BenCodeOcean b86ef3d
Enhance .gitignore for macOS, Linux, and Windows system files; improv…
BenCodeOcean 9330bdc
Update README and code to rename 'hosted-zone' to 'zone'; enhance rol…
BenCodeOcean 8cbf069
Copilot review
BenCodeOcean File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# macOS system files | ||
.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Thumbnails | ||
._* | ||
|
||
# Files that might appear on external disks | ||
.Spotlight-V100 | ||
.Trashes | ||
|
||
# Linux system files | ||
*~ | ||
.nfs* | ||
|
||
# Windows system files | ||
Thumbs.db | ||
ehthumbs.db | ||
Desktop.ini | ||
$RECYCLE.BIN/ | ||
|
||
# Python bytecode | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
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 | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyderworkspace | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,63 @@ | ||
# co-assistant | ||
Code Ocean Command-Line Assistant | ||
# Code Ocean Support Command-Line | ||
|
||
## Installation | ||
|
||
### pip | ||
To install or upgrade the co-support, run the following command: | ||
```bash | ||
pip install --upgrade git+https://github.com/codeocean/co-support.git | ||
``` | ||
|
||
### virtualenv | ||
To install for development purposes using a virtual environment: | ||
```bash | ||
python3 -m venv .venv | ||
source .venv/bin/activate | ||
pip install -e . | ||
``` | ||
|
||
## Usage | ||
```bash | ||
usage: co-support check-prerequisites [-h] [-s | --silent | --no-silent] [-f {table,yaml}] [-o OUTPUT] [--version VERSION] [--role ROLE] [--domain DOMAIN] [--zone HOSTED_ZONE] [--cert CERT] | ||
[--private-ca | --no-private-ca] [--vpc VPC] [--internet-facing | --no-internet-facing] | ||
|
||
options: | ||
-h, --help show this help message and exit | ||
-s, --silent, --no-silent | ||
Run the script in silent mode (default: False) | ||
-f, --format {table,yaml} | ||
Output format: table or yaml (default: table) | ||
-o, --output OUTPUT Path to the directory where the output file will be saved (default: None) | ||
--version VERSION Version of Code Ocean to deploy (e.g., v3.4.1) (default: None) | ||
--role ROLE ARN of the IAM role to deploy the Code Ocean template (e.g., arn:aws:iam::account-id:role/role-name) (default: None) | ||
--domain DOMAIN Domain for the deployment (e.g., codeocean.company.com) (default: None) | ||
--zone HOSTED_ZONE | ||
Hosted zone ID for the deployment (e.g., Z3P5QSUBK4POTI) (default: None) | ||
--cert CERT ARN of the SSL/TLS certificate (e.g., arn:aws:acm:region:account:certificate/certificate-id) (default: None) | ||
--private-ca, --no-private-ca | ||
Indicate if the certificate is signed by a private CA (default: False) | ||
--vpc VPC ID of the existing VPC (e.g., vpc-0bb1c79de3fd22e7d) (default: None) | ||
--internet-facing, --no-internet-facing | ||
Indicate if the deployment is internet-facing (default: True) | ||
``` | ||
|
||
### Interactive Example | ||
```bash | ||
co-support check-prerequisites | ||
``` | ||
|
||
### Silent Example | ||
```bash | ||
co-support check-prerequisites -s \ | ||
--version v3.4.1 \ | ||
--internet-facing \ | ||
--domain codeocean.acmecorp.com \ | ||
--zone A0B1C2D3E4F5G6H7I8J9 \ | ||
--cert arn:aws:acm:us-east-1:000000000000:certificate/01234567-890a-bcde-f012-3456789000 \ | ||
--vpc vpc-0123456789abcdeff \ | ||
--role arn:aws:iam::000000000000:role/Administrator | ||
--private-ca \ | ||
``` | ||
|
||
## Notes | ||
Currently, this tool only checks prerequisites for Code Ocean deployment. |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from abc import ABC, abstractmethod | ||
from argparse import ArgumentDefaultsHelpFormatter | ||
|
||
|
||
class BaseCommand(ABC): | ||
""" | ||
Base class for commands. | ||
""" | ||
|
||
def __init__(self, subparsers, name, format_map=None): | ||
self.parser = subparsers.add_parser( | ||
name=name.format_map(format_map), | ||
help=self.__doc__.strip().format_map(format_map), | ||
formatter_class=ArgumentDefaultsHelpFormatter, | ||
) | ||
self.parser.set_defaults(cmd=self.cmd) | ||
|
||
@abstractmethod | ||
def cmd(args): | ||
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
|
||
from .prerequisites.main import commands as prerequisites_commands | ||
|
||
|
||
def parse_args(): | ||
parser = argparse.ArgumentParser() | ||
subparsers = parser.add_subparsers() | ||
prerequisites_commands(subparsers) | ||
|
||
return parser.parse_args(), parser | ||
|
||
|
||
def main(): | ||
args, parser = parse_args() | ||
if hasattr(args, 'cmd'): | ||
response = args.cmd(args) | ||
if response: | ||
print(response) | ||
else: | ||
parser.print_help() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Empty file.
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import boto3 | ||
import requests | ||
import yaml | ||
|
||
from botocore.exceptions import ClientError | ||
from typing import Dict, Set, Tuple | ||
|
||
from ..core.constants import get_account, get_region | ||
|
||
|
||
def check_linked_roles(params: Dict[str, Set[str]]) -> Tuple[bool, str]: | ||
""" | ||
Verifies the existence of required service-linked roles. | ||
""" | ||
iam_client = boto3.client("iam") | ||
existing_roles: Set[str] = set() | ||
roles_set: Set[str] = set(params.get("roles", set())) | ||
|
||
try: | ||
for role in iam_client.list_roles()["Roles"]: | ||
if not role.get("Path", "").startswith("/aws-service-role/") and \ | ||
not role.get("AssumeRolePolicyDocument"): | ||
continue | ||
statements = role["AssumeRolePolicyDocument"].get("Statement", []) | ||
for statement in statements: | ||
principal = statement.get("Principal", {}) | ||
service = principal.get("Service", "") | ||
existing_roles.add(service) | ||
except ClientError as e: | ||
return False, f"Error fetching roles: {e}" | ||
|
||
missing_roles = roles_set - existing_roles | ||
if missing_roles: | ||
return False, ( | ||
f"Missing service-linked roles: {', '.join(missing_roles)}." | ||
) | ||
|
||
return True, "All required service-linked roles exist." | ||
|
||
|
||
def check_admin_access(params: Dict[str, str]) -> Tuple[bool, str]: | ||
""" | ||
Determines whether the current user or a given role | ||
has administrator access. | ||
""" | ||
iam_client = boto3.client("iam") | ||
sts_client = boto3.client("sts") | ||
|
||
try: | ||
role_arn = params.get("role_arn") | ||
if not role_arn: | ||
role_arn = sts_client.get_caller_identity()["Arn"] | ||
|
||
role_name = role_arn.split("/")[-1] | ||
if ":assumed-role/" in role_arn: | ||
role_name = role_arn.split("/")[-2] | ||
|
||
if ":user/" in role_arn: | ||
policies = iam_client.list_attached_user_policies( | ||
UserName=role_name | ||
) | ||
else: | ||
policies = iam_client.list_attached_role_policies( | ||
RoleName=role_name | ||
) | ||
|
||
if any( | ||
p["PolicyArn"] == "arn:aws:iam::aws:policy/AdministratorAccess" | ||
for p in policies["AttachedPolicies"] | ||
): | ||
return True, ( | ||
f"{role_name} has AdministratorAccess policy attached." | ||
) | ||
|
||
return False, ( | ||
f"{role_name} does not have the AdministratorAccess policy. " | ||
"This is acceptable if a least-privileged role is " | ||
"intentionally being used." | ||
) | ||
|
||
except ClientError as e: | ||
return False, f"Error checking admin access: {e}" | ||
|
||
|
||
def check_shared_ami(params: Dict[str, str]) -> Tuple[bool, str]: | ||
""" | ||
Checks if the AMI is shared with the current account | ||
in the specified region. | ||
""" | ||
yaml_url = ( | ||
"https://codeocean-vpc.s3.amazonaws.com/templates/" | ||
f"{params.get('version', '')}/codeocean.template.yaml" | ||
) | ||
|
||
try: | ||
yaml_content = yaml.safe_load(requests.get(yaml_url, "").text) | ||
mappings = yaml_content.get("Mappings", {}) | ||
ami_id = mappings.get("AMIs", {}).get(get_region(), {}).get("id", "") | ||
if not ami_id: | ||
return False, ( | ||
f"The current region {get_region()} " | ||
"is not supported in this version" | ||
) | ||
|
||
ec2_client = boto3.client("ec2") | ||
try: | ||
response = ec2_client.describe_images( | ||
ImageIds=[ami_id], | ||
) | ||
if response.get("Images"): | ||
return True, ( | ||
f"AMI {ami_id} in region {get_region()} " | ||
f"is shared with account {get_account()}" | ||
) | ||
except ClientError as e: | ||
return False, f"Error checking AMI permissions: {e}" | ||
|
||
return False, ( | ||
f"AMI {ami_id} is not shared with account {get_account()}" | ||
) | ||
except requests.RequestException as e: | ||
return False, f"Error fetching YAML file: {e}" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The abstract method 'cmd' is missing the 'self' parameter. Change it to 'def cmd(self, args):' to correctly define an instance method.
Copilot is powered by AI, so mistakes are possible. Review output carefully before use.