nate2-scripts 1.0.0__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nate2_scripts-1.0.1/.github/workflows/publish.yml +64 -0
- nate2_scripts-1.0.1/.gitignore +3 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/PKG-INFO +1 -1
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/README.md +5 -1
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/pyproject.toml +1 -1
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/destitationResolver.py +14 -5
- nate2_scripts-1.0.1/src/nate2_scripts/console/nameResolver.py +99 -0
- nate2_scripts-1.0.0/.gitignore +0 -1
- nate2_scripts-1.0.0/testing.txt +0 -9
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/CONSOLE-NOTES.md +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/LICENSE +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/__init__.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/bing_wrapper.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/__init__.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/arnResolver.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/hashGrabber.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/regionCache.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/resourceIdResolver.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/sessionCache.py +0 -0
- {nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/test.py +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Trigger this workflow on every push to the main branch.
|
|
4
|
+
# To prevent unauthorized publishes, protect main with branch protection rules
|
|
5
|
+
# (require PRs + approvals) and add required reviewers to the "pypi" environment.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
# GitHub Actions run on fresh virtual machines that have no knowledge of your code.
|
|
18
|
+
# This step clones your repository into the runner so subsequent steps can access your files.
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.x"
|
|
25
|
+
|
|
26
|
+
- name: Install Hatch
|
|
27
|
+
run: pip install hatch
|
|
28
|
+
|
|
29
|
+
# Produces a source distribution (sdist) and a wheel in the dist/ directory.
|
|
30
|
+
# The version published is whatever is set in pyproject.toml — bump it before
|
|
31
|
+
# merging to main, otherwise PyPI will reject a duplicate version.
|
|
32
|
+
- name: Build package
|
|
33
|
+
run: hatch build
|
|
34
|
+
|
|
35
|
+
# Pass the built artifacts to the publish job via GitHub's artifact storage.
|
|
36
|
+
- name: Upload distribution artifacts
|
|
37
|
+
uses: actions/upload-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: dist
|
|
40
|
+
path: dist/
|
|
41
|
+
|
|
42
|
+
publish:
|
|
43
|
+
name: Publish to PyPI
|
|
44
|
+
needs: build # only runs after the build job succeeds
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
# The "pypi" environment can be configured in GitHub (Settings → Environments)
|
|
47
|
+
# to require manual approval before this job runs, adding an extra gate on publishing.
|
|
48
|
+
environment:
|
|
49
|
+
name: pypi
|
|
50
|
+
url: https://pypi.org/p/nate2-scripts
|
|
51
|
+
permissions:
|
|
52
|
+
id-token: write # required for Trusted Publishing (OIDC) — no API token needed
|
|
53
|
+
|
|
54
|
+
steps:
|
|
55
|
+
- name: Download distribution artifacts
|
|
56
|
+
uses: actions/download-artifact@v4
|
|
57
|
+
with:
|
|
58
|
+
name: dist
|
|
59
|
+
path: dist/
|
|
60
|
+
|
|
61
|
+
# Uses PyPA's official action with Trusted Publishing (OIDC).
|
|
62
|
+
# PyPI must be configured with a Trusted Publisher pointing at this repo/workflow.
|
|
63
|
+
- name: Publish to PyPI
|
|
64
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
[](https://pypi.org/project/nate2-scripts/)
|
|
3
|
+
[](https://github.com/tennex-nwestfall/nate2-scripts/blob/main/LICENSE)
|
|
4
|
+
|
|
1
5
|
# Nate2's Scripts
|
|
2
6
|
|
|
3
7
|
Utility scripts for AWS development on macOS.
|
|
@@ -5,7 +9,7 @@ Utility scripts for AWS development on macOS.
|
|
|
5
9
|
To install run:
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
pip install
|
|
12
|
+
pip install nate2-scripts
|
|
9
13
|
```
|
|
10
14
|
|
|
11
15
|
## Scripts
|
{nate2_scripts-1.0.0 → nate2_scripts-1.0.1}/src/nate2_scripts/console/destitationResolver.py
RENAMED
|
@@ -4,7 +4,8 @@ import sys
|
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
import boto3
|
|
6
6
|
from nate2_scripts.console.arnResolver import ArnResolver
|
|
7
|
-
from nate2_scripts.console.
|
|
7
|
+
from nate2_scripts.console.nameResolver import NameResolver
|
|
8
|
+
from nate2_scripts.console.regionCache import RegionCache
|
|
8
9
|
from botocore.exceptions import ClientError
|
|
9
10
|
import urllib.parse
|
|
10
11
|
|
|
@@ -36,6 +37,9 @@ class DestinationResolver:
|
|
|
36
37
|
if not service:
|
|
37
38
|
return f"https://{self.mdn}{default_region}.console.aws.amazon.com/"
|
|
38
39
|
|
|
40
|
+
if service.lower() in service_urls:
|
|
41
|
+
return service_urls[service.lower()]
|
|
42
|
+
|
|
39
43
|
arn_dest = ArnResolver(self.account,self.mdn).try_parse_arn(service)
|
|
40
44
|
if arn_dest:
|
|
41
45
|
return arn_dest
|
|
@@ -44,10 +48,13 @@ class DestinationResolver:
|
|
|
44
48
|
if id_dest:
|
|
45
49
|
return id_dest
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
name_dest = NameResolver(self.region_cache, self.mdn).resolve_name(service)
|
|
52
|
+
if name_dest:
|
|
53
|
+
return name_dest
|
|
54
|
+
|
|
55
|
+
print(f"Error: Unknown service '{service}'.", file=sys.stderr)
|
|
56
|
+
sys.exit(1)
|
|
57
|
+
|
|
51
58
|
|
|
52
59
|
@staticmethod
|
|
53
60
|
def _get_services(region: str, mdn: str = "") -> dict[str, str]:
|
|
@@ -98,6 +105,8 @@ class DestinationResolver:
|
|
|
98
105
|
"athena": f"https://{mdn}{region}.console.aws.amazon.com/athena/home#/query-editor",
|
|
99
106
|
"cloudtrail": f"https://{mdn}{region}.console.aws.amazon.com/cloudtrailv2/",
|
|
100
107
|
"ct": f"https://{mdn}{region}.console.aws.amazon.com/cloudtrailv2/",
|
|
108
|
+
"fsx": f"https://{mdn}{region}.console.aws.amazon.com/fsx/",
|
|
109
|
+
"subnet": f"https://{mdn}{region}.console.aws.amazon.com/vpcconsole/home#subnets:",
|
|
101
110
|
# unchecked
|
|
102
111
|
}
|
|
103
112
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import urllib.parse
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
4
|
+
|
|
5
|
+
import boto3
|
|
6
|
+
from botocore.exceptions import ClientError
|
|
7
|
+
|
|
8
|
+
from nate2_scripts.console.regionCache import RegionCache
|
|
9
|
+
|
|
10
|
+
MAX_THREADS = 10
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NameResolver:
|
|
14
|
+
region_cache: RegionCache
|
|
15
|
+
mdn: str
|
|
16
|
+
|
|
17
|
+
def __init__(self, region_cache: RegionCache, multisession_domain_name: str):
|
|
18
|
+
self.region_cache = region_cache
|
|
19
|
+
self.mdn = multisession_domain_name
|
|
20
|
+
|
|
21
|
+
def resolve_name(self, name: str) -> str | None:
|
|
22
|
+
regions = self.region_cache.get_regions()
|
|
23
|
+
|
|
24
|
+
# Priority: 0=logs, 1=ec2, 2=s3, 3=cloudformation
|
|
25
|
+
tasks: list[tuple] = []
|
|
26
|
+
for region in regions:
|
|
27
|
+
tasks.append((0, self._resolve_log_group, name, region))
|
|
28
|
+
tasks.append((1, self._resolve_ec2_instance, name, region))
|
|
29
|
+
tasks.append((3, self._resolve_cloudformation_stack, name, region))
|
|
30
|
+
tasks.append((2, self._resolve_s3_bucket, name))
|
|
31
|
+
|
|
32
|
+
results: dict[int, str] = {}
|
|
33
|
+
|
|
34
|
+
with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
|
|
35
|
+
future_to_priority = {
|
|
36
|
+
executor.submit(fn, *args): priority
|
|
37
|
+
for priority, fn, *args in tasks
|
|
38
|
+
}
|
|
39
|
+
for future in as_completed(future_to_priority):
|
|
40
|
+
priority = future_to_priority[future]
|
|
41
|
+
url = future.result()
|
|
42
|
+
if url is not None and priority not in results:
|
|
43
|
+
results[priority] = url
|
|
44
|
+
|
|
45
|
+
for priority in sorted(results):
|
|
46
|
+
return results[priority]
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def _resolve_log_group(self, name: str, region: str) -> str | None:
|
|
50
|
+
try:
|
|
51
|
+
result = boto3.client("logs", region_name=region).describe_log_groups(
|
|
52
|
+
logGroupNamePrefix=name
|
|
53
|
+
)
|
|
54
|
+
if any(lg["logGroupName"] == name for lg in result.get("logGroups", [])):
|
|
55
|
+
base = f"https://{self.mdn}{region}.console.aws.amazon.com"
|
|
56
|
+
encoded = urllib.parse.quote(name, safe="")
|
|
57
|
+
return f"{base}/cloudwatch/home?region={region}#logsV2:log-groups/log-group/{encoded}"
|
|
58
|
+
except ClientError:
|
|
59
|
+
pass
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
def _resolve_ec2_instance(self, name: str, region: str) -> str | None:
|
|
63
|
+
try:
|
|
64
|
+
result = boto3.client("ec2", region_name=region).describe_instances(
|
|
65
|
+
Filters=[{"Name": "tag:Name", "Values": [name]}]
|
|
66
|
+
)
|
|
67
|
+
reservations = result.get("Reservations", [])
|
|
68
|
+
if reservations:
|
|
69
|
+
base = f"https://{self.mdn}{region}.console.aws.amazon.com"
|
|
70
|
+
instance_id = reservations[0]["Instances"][0]["InstanceId"]
|
|
71
|
+
return f"{base}/ec2/v2/home?region={region}#InstanceDetails:instanceId={instance_id}"
|
|
72
|
+
except ClientError:
|
|
73
|
+
pass
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
def _resolve_cloudformation_stack(self, name: str, region: str) -> str | None:
|
|
77
|
+
try:
|
|
78
|
+
result = boto3.client("cloudformation", region_name=region).describe_stacks(
|
|
79
|
+
StackName=name
|
|
80
|
+
)
|
|
81
|
+
stacks = result.get("Stacks", [])
|
|
82
|
+
if stacks:
|
|
83
|
+
base = f"https://{self.mdn}{region}.console.aws.amazon.com"
|
|
84
|
+
stack_id = urllib.parse.quote(stacks[0]["StackId"], safe="")
|
|
85
|
+
return f"{base}/cloudformation/home?region={region}#/stacks/stackinfo?stackId={stack_id}"
|
|
86
|
+
except ClientError:
|
|
87
|
+
pass
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
def _resolve_s3_bucket(self, name: str) -> str | None:
|
|
91
|
+
try:
|
|
92
|
+
boto3.client("s3").head_bucket(Bucket=name)
|
|
93
|
+
return f"https://{self.mdn}us-east-1.console.aws.amazon.com/s3/buckets/{name}"
|
|
94
|
+
except Exception:
|
|
95
|
+
pass
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
nate2_scripts-1.0.0/.gitignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__pycache__
|
nate2_scripts-1.0.0/testing.txt
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
ec2
|
|
2
|
-
|
|
3
|
-
i-04338f521d58918dd
|
|
4
|
-
|
|
5
|
-
arn:aws:ec2:us-east-1:905502466771:instance/i-04338f521d58918dd
|
|
6
|
-
|
|
7
|
-
arn:aws:logs:us-east-1:905502466771:log-group:/aws/parallelcluster/pcluster-lab-nate2-202607062002:*
|
|
8
|
-
|
|
9
|
-
arn:aws:logs:us-west-2:905502466771:log-group:/aws/lambda/InternalTestingStack-1-TagBucketLambda1DCC2FF9-dwonHDanL8Xf:*
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|