├── .gitignore ├── examples ├── simple │ ├── go │ │ ├── includes │ │ │ ├── include_me.txt │ │ │ ├── infra.yaml │ │ │ ├── main.go │ │ │ └── test.py │ │ ├── ecr │ │ │ ├── infra.yaml │ │ │ └── main.go │ │ ├── websocket │ │ │ ├── infra.yaml │ │ │ ├── main.go │ │ │ └── test.py │ │ ├── api_and_stream │ │ │ ├── infra.yaml │ │ │ └── main.go │ │ ├── api │ │ │ ├── infra.yaml │ │ │ └── main.go │ │ ├── schedule │ │ │ ├── infra.yaml │ │ │ ├── main.go │ │ │ └── test.py │ │ ├── s3 │ │ │ ├── infra.yaml │ │ │ └── main.go │ │ ├── sqs │ │ │ ├── main.go │ │ │ └── infra.yaml │ │ └── dynamodb │ │ │ ├── infra.yaml │ │ │ └── main.go │ ├── python │ │ ├── includes │ │ │ ├── include_me.txt │ │ │ ├── main.py │ │ │ ├── infra.yaml │ │ │ └── test.py │ │ ├── dependencies │ │ │ ├── adep │ │ │ │ ├── foo.py │ │ │ │ ├── build │ │ │ │ │ └── lib │ │ │ │ │ │ └── foo.py │ │ │ │ └── setup.py │ │ │ ├── main.py │ │ │ ├── infra.yaml │ │ │ └── test.py │ │ ├── ecr │ │ │ ├── main.py │ │ │ └── infra.yaml │ │ ├── schedule │ │ │ ├── main.py │ │ │ └── infra.yaml │ │ ├── s3 │ │ │ ├── main.py │ │ │ └── infra.yaml │ │ ├── sqs │ │ │ ├── main.py │ │ │ └── infra.yaml │ │ ├── websocket │ │ │ ├── main.py │ │ │ ├── infra.yaml │ │ │ └── test.py │ │ ├── api │ │ │ ├── infra.yaml │ │ │ └── main.py │ │ └── dynamodb │ │ │ ├── main.py │ │ │ └── infra.yaml │ └── docker │ │ ├── s3 │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── main.js │ │ └── infra.yaml │ │ ├── api │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── main.js │ │ └── infra.yaml │ │ ├── ecr │ │ ├── Dockerfile │ │ ├── main.js │ │ ├── package.json │ │ └── infra.yaml │ │ ├── sqs │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── main.js │ │ └── infra.yaml │ │ ├── dynamodb │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── infra.yaml │ │ └── main.js │ │ ├── schedule │ │ ├── Dockerfile │ │ ├── main.js │ │ ├── package.json │ │ └── infra.yaml │ │ └── websocket │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── infra.yaml │ │ └── main.js ├── misc │ ├── basic │ │ ├── main.py │ │ └── infra.yaml │ ├── api_binary │ │ ├── infra.yaml │ │ └── main.py │ └── api_deep_routes │ │ ├── infra.yaml │ │ └── main.py └── complex │ └── s3-ec2 │ └── infra.yaml ├── gif ├── ls.gif ├── rm.gif ├── ensure.gif ├── trigger.gif └── update.gif ├── lib ├── data.go ├── ecs.go ├── cost.go ├── lib_test.go ├── acm.go └── codecommit.go ├── Dockerfile ├── test_one.sh ├── tox.ini ├── cmd ├── aws │ ├── region.go │ ├── user.go │ ├── account.go │ └── regions.go ├── ecr │ ├── url.go │ ├── ls.go │ ├── ensure.go │ ├── rm_repo.go │ ├── rm.go │ ├── rm_tag.go │ ├── login.go │ └── ls_tags.go ├── vpc │ ├── id.go │ ├── rm.go │ ├── ls.go │ ├── ensure.go │ └── ls_subnets.go ├── api │ ├── ls.go │ ├── url.go │ ├── ls_domains.go │ └── url_domain.go ├── sqs │ ├── ls.go │ ├── url.go │ ├── stats.go │ ├── purge.go │ ├── send.go │ ├── rm.go │ └── ensure.go ├── logs │ ├── rm.go │ ├── recent.go │ ├── ls.go │ ├── set_retention.go │ ├── tail.go │ ├── set_retention_all.go │ └── near.go ├── ec2 │ ├── ls_sgs.go │ ├── id_sg.go │ ├── ami_user.go │ ├── rm_keypair.go │ ├── rm_sg.go │ ├── ensure_keypair.go │ ├── rm_snapshot.go │ ├── ls_keypairs.go │ ├── new_ami.go │ ├── ls_instance_zones.go │ ├── ami_base.go │ ├── ensure_sg.go │ ├── ip.go │ ├── dns.go │ ├── dns_private.go │ ├── ip_private.go │ ├── id.go │ ├── price_ondemand.go │ ├── ls_amis.go │ ├── ssh_user.go │ ├── ami_latest.go │ └── ls_snapshots.go ├── lambda │ ├── arn.go │ ├── rm.go │ ├── vars.go │ ├── permissions.go │ ├── describe.go │ ├── ls.go │ └── set_var.go ├── iam │ ├── ls_users.go │ ├── ls_roles.go │ ├── rm_role.go │ ├── rm_user.go │ ├── ensure_ec2_spot_roles.go │ ├── rm_instance_profile.go │ ├── ls_instance_profiles.go │ ├── ls_policies.go │ ├── ls_ssh_keys.go │ ├── ensure_instance_profile.go │ ├── reset_user_login_password.go │ ├── ensure_role.go │ ├── get_policy.go │ ├── ensure_user_api.go │ └── ensure_managed_policy.go ├── s3 │ ├── rm_bucket.go │ ├── describe.go │ ├── presign_put.go │ ├── presign_get.go │ ├── rm.go │ ├── get.go │ ├── get_version.go │ ├── ensure.go │ ├── head.go │ └── put.go ├── events │ ├── ls_buses.go │ ├── ls_rules.go │ └── ls_targets.go ├── codecommit │ ├── ls.go │ ├── describe.go │ ├── rm.go │ └── ensure.go ├── ses │ ├── rm_receipt_rule.go │ ├── ensure_receipt_rule.go │ ├── ls_receipt_rules.go │ └── send.go ├── route53 │ ├── rm_zone.go │ ├── ensure_zone.go │ ├── describe_records.go │ ├── ns.go │ ├── describe_zone.go │ ├── rm_record.go │ ├── ensure_record.go │ └── ls.go ├── dynamodb │ ├── rm.go │ ├── item_rm_all.go │ ├── ls.go │ ├── describe.go │ ├── item_rm.go │ ├── item_scan.go │ └── item_put.go ├── cloudwatch │ ├── ls_alarms.go │ ├── ls_alarms_billing.go │ ├── ls_namespaces.go │ ├── ls_dimensions.go │ └── ls_metrics.go ├── infra │ ├── parse.go │ ├── rm.go │ ├── ls.go │ ├── url_api.go │ ├── url_func.go │ ├── url_websocket.go │ └── ensure.go ├── ssh │ ├── keygen_rsa.go │ └── keygen_ed25519.go ├── organizations │ ├── ensure.go │ └── ls.go ├── acm │ └── ls.go └── creds │ ├── ls.go │ └── set.go ├── test.sh └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | libaws 2 | .tox 3 | __pycache__ 4 | -------------------------------------------------------------------------------- /examples/simple/go/includes/include_me.txt: -------------------------------------------------------------------------------- 1 | data123 2 | -------------------------------------------------------------------------------- /examples/simple/python/includes/include_me.txt: -------------------------------------------------------------------------------- 1 | data123 2 | -------------------------------------------------------------------------------- /gif/ls.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathants/libaws/HEAD/gif/ls.gif -------------------------------------------------------------------------------- /gif/rm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathants/libaws/HEAD/gif/rm.gif -------------------------------------------------------------------------------- /gif/ensure.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathants/libaws/HEAD/gif/ensure.gif -------------------------------------------------------------------------------- /gif/trigger.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathants/libaws/HEAD/gif/trigger.gif -------------------------------------------------------------------------------- /gif/update.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathants/libaws/HEAD/gif/update.gif -------------------------------------------------------------------------------- /examples/simple/python/dependencies/adep/foo.py: -------------------------------------------------------------------------------- 1 | def bar(x): 2 | return f'hello: {x}' 3 | -------------------------------------------------------------------------------- /examples/simple/python/dependencies/adep/build/lib/foo.py: -------------------------------------------------------------------------------- 1 | def bar(x): 2 | return f'hello: {x}' 3 | -------------------------------------------------------------------------------- /examples/simple/python/ecr/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(event, context): 4 | print(event) 5 | -------------------------------------------------------------------------------- /examples/simple/python/schedule/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | 5 | def main(event, context): 6 | print(os.environ['uid']) 7 | -------------------------------------------------------------------------------- /examples/simple/docker/s3/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/ecr/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/sqs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/dynamodb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/schedule/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/websocket/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/nodejs:16 2 | COPY package*.json ./ 3 | RUN npm install 4 | COPY main.js ./ 5 | CMD ["main.handler"] 6 | -------------------------------------------------------------------------------- /examples/simple/docker/schedule/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | console.log(process.env['uid']); 5 | context.succeed(); 6 | } 7 | -------------------------------------------------------------------------------- /examples/simple/python/includes/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(event, context): 4 | with open('include_me.txt') as f: 5 | return f.read().strip() 6 | -------------------------------------------------------------------------------- /examples/simple/docker/ecr/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | console.log('got:', JSON.stringify(event)); 5 | context.succeed(); 6 | } 7 | -------------------------------------------------------------------------------- /examples/simple/python/dependencies/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | 5 | def main(event, context): 6 | import foo 7 | print(foo.bar(os.environ['uid'])) 8 | -------------------------------------------------------------------------------- /examples/simple/python/s3/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(event, context): 4 | for record in event['Records']: 5 | print(record['s3']['object']['key']) 6 | -------------------------------------------------------------------------------- /examples/simple/python/sqs/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(event, context): 4 | for record in event['Records']: 5 | print('thanks for:', record['body']) 6 | -------------------------------------------------------------------------------- /lib/data.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import "os" 4 | 5 | const ( 6 | ErrPrefixDidntFindExactlyOne = "didn't find exactly one" 7 | ) 8 | 9 | var doDebug = os.Getenv("DEBUG") != "" 10 | -------------------------------------------------------------------------------- /examples/simple/docker/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/ecr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/s3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/sqs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/schedule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/websocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": {}, 7 | "license": "MIT" 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/s3/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | for (const record of event['Records']) { 5 | console.log(record['s3']['object']['key']); 6 | } 7 | context.succeed(); 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/sqs/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | for (const record of event['Records']) { 5 | console.log('thanks for:', JSON.stringify(record)); 6 | } 7 | context.succeed(); 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple/docker/api/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | let response = { 5 | statusCode: '200', 6 | body: 'ok\n', 7 | headers: {} 8 | }; 9 | context.succeed(response); 10 | } 11 | -------------------------------------------------------------------------------- /examples/simple/docker/dynamodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libaws", 3 | "version": "0.0.0", 4 | "main": "main.js", 5 | "author": "me@nathants.com", 6 | "dependencies": { 7 | "@aws-sdk/client-dynamodb": "3.782.0" 8 | }, 9 | "license": "MIT" 10 | } 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge 2 | 3 | RUN apk update && apk upgrade -a 4 | 5 | RUN apk add --no-cache bash go coreutils ca-certificates 6 | 7 | RUN go install github.com/nathants/libaws@latest && \ 8 | mv /root/go/bin/libaws /usr/local/bin && \ 9 | rm -rf /root/go 10 | -------------------------------------------------------------------------------- /examples/simple/go/ecr/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: ecr 14 | -------------------------------------------------------------------------------- /examples/simple/python/websocket/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def main(event, context): 4 | """ 5 | TODO 6 | 7 | this test currently just checks that the websocket trigger can be successfully deployed. 8 | 9 | for websocket example see: https://github.com/nathants/aws-gocljs 10 | """ 11 | -------------------------------------------------------------------------------- /examples/simple/python/ecr/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: ecr 14 | -------------------------------------------------------------------------------- /examples/simple/go/includes/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | include: 13 | - include_me.txt 14 | -------------------------------------------------------------------------------- /examples/simple/go/websocket/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: websocket 14 | -------------------------------------------------------------------------------- /examples/simple/python/includes/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | include: 13 | - include_me.txt 14 | -------------------------------------------------------------------------------- /examples/simple/python/websocket/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: websocket 14 | -------------------------------------------------------------------------------- /examples/simple/go/api_and_stream/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: url 15 | -------------------------------------------------------------------------------- /examples/misc/basic/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import util.colors 5 | import os 6 | 7 | def main(event, context): 8 | print('log some stuff about requests:', requests.get) 9 | print(util.colors.green('green means go')) 10 | print(os.environ['uid']) 11 | return ' '.join(f'{k}=>{v}' for k, v in event.items()) 12 | -------------------------------------------------------------------------------- /examples/simple/python/dependencies/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | require: 11 | - ./adep 12 | env: 13 | - uid=${uid} 14 | policy: 15 | - AWSLambdaBasicExecutionRole 16 | -------------------------------------------------------------------------------- /test_one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eou pipefail 3 | name=$1 4 | ( 5 | cd lib 6 | nontest=$(ls *.go | grep -v _test.go) 7 | for test in $(ls *_test.go | grep -v lib_test.go | grep "${name}_test.go"); do 8 | go test lib_test.go $nontest $test -o /tmp/libaws.test -c 9 | timeout 600 /tmp/libaws.test -test.v -test.failfast 10 | done 11 | ) 12 | -------------------------------------------------------------------------------- /examples/simple/docker/ecr/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: ecr 14 | -------------------------------------------------------------------------------- /examples/simple/docker/websocket/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: websocket 14 | -------------------------------------------------------------------------------- /examples/misc/api_binary/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: schedule 15 | attr: 16 | - rate(15 minutes) 17 | -------------------------------------------------------------------------------- /examples/simple/go/api/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: schedule 15 | attr: 16 | - rate(15 minutes) 17 | -------------------------------------------------------------------------------- /examples/simple/python/dependencies/adep/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | import os 3 | 4 | parent = os.path.dirname(os.path.abspath(__file__)) 5 | 6 | setuptools.setup( 7 | version="0.0.1", 8 | name='adep', 9 | py_modules=[x.split('.py')[0] 10 | for x in os.listdir(parent) 11 | if x.endswith('.py') 12 | and not x == 'setup.py'], 13 | ) 14 | -------------------------------------------------------------------------------- /examples/misc/api_deep_routes/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: schedule 15 | attr: 16 | - rate(15 minutes) 17 | -------------------------------------------------------------------------------- /examples/simple/python/api/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: schedule 15 | attr: 16 | - rate(15 minutes) 17 | -------------------------------------------------------------------------------- /examples/simple/go/schedule/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.go 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: schedule 14 | attr: 15 | - rate(1 minute) 16 | env: 17 | - uid=${uid} 18 | -------------------------------------------------------------------------------- /examples/simple/python/schedule/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: schedule 14 | attr: 15 | - rate(1 minute) 16 | env: 17 | - uid=${uid} 18 | -------------------------------------------------------------------------------- /examples/simple/go/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/aws/aws-lambda-go/events" 7 | "github.com/aws/aws-lambda-go/lambda" 8 | ) 9 | 10 | func handleRequest(_ context.Context, _ events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 11 | return events.APIGatewayProxyResponse{Body: "hi\n", StatusCode: 200}, nil 12 | } 13 | 14 | func main() { 15 | lambda.Start(handleRequest) 16 | } 17 | -------------------------------------------------------------------------------- /examples/misc/basic/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: main.py 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | require: 11 | - git+https://github.com/nathants/py-util@6844917fb51e9d24de130fd4728053d62c7946da 12 | - requests >2, <3 13 | env: 14 | - uid=${uid} 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | -------------------------------------------------------------------------------- /examples/simple/go/s3/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | s3: 4 | test-bucket-${uid}: 5 | attr: 6 | - acl=private 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: main.go 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | trigger: 18 | - type: s3 19 | attr: 20 | - test-bucket-${uid} 21 | -------------------------------------------------------------------------------- /examples/simple/python/s3/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | s3: 4 | test-bucket-${uid}: 5 | attr: 6 | - acl=private 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: main.py 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | trigger: 18 | - type: s3 19 | attr: 20 | - test-bucket-${uid} 21 | -------------------------------------------------------------------------------- /examples/simple/docker/api/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: api 14 | - type: schedule 15 | attr: 16 | - rate(15 minutes) 17 | -------------------------------------------------------------------------------- /examples/simple/python/api/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import base64 5 | 6 | def main(event, context): 7 | body = event['body'] 8 | if body: 9 | body = base64.b64decode(bytes(body, 'utf-8')).decode() 10 | return {'statusCode': '200', 11 | 'isBase64Encoded': False, 12 | 'headers': {'Content-Type': 'application/json'}, 13 | 'body': json.dumps([event['httpMethod'], event['path'], body])} 14 | -------------------------------------------------------------------------------- /examples/misc/api_deep_routes/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import base64 5 | 6 | def main(event, context): 7 | body = event['body'] 8 | if body: 9 | body = base64.b64decode(bytes(body, 'utf-8')).decode() 10 | return {'statusCode': '200', 11 | 'isBase64Encoded': False, 12 | 'headers': {'Content-Type': 'application/json'}, 13 | 'body': json.dumps([event['httpMethod'], event['path'], body])} 14 | -------------------------------------------------------------------------------- /examples/simple/docker/schedule/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | lambda: 4 | test-lambda-${uid}: 5 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 6 | attr: 7 | - concurrency=0 8 | - memory=128 9 | - timeout=60 10 | policy: 11 | - AWSLambdaBasicExecutionRole 12 | trigger: 13 | - type: schedule 14 | attr: 15 | - rate(1 minute) 16 | env: 17 | - uid=${uid} 18 | -------------------------------------------------------------------------------- /examples/simple/docker/websocket/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.handler = async (event, context) => { 4 | // 5 | // TODO 6 | // 7 | // this test currently just checks that the websocket trigger can be successfully deployed. 8 | // 9 | // for websocket example see: https://github.com/nathants/aws-gocljs 10 | // 11 | let response = { 12 | statusCode: '200', 13 | body: 'ok\n', 14 | headers: {} 15 | }; 16 | context.succeed(response); 17 | } 18 | -------------------------------------------------------------------------------- /examples/simple/go/ecr/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/aws/aws-lambda-go/events" 7 | "github.com/aws/aws-lambda-go/lambda" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func handleRequest(_ context.Context, event any) (events.APIGatewayProxyResponse, error) { 12 | lib.Logger.Println(lib.Pformat(event)) 13 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 14 | } 15 | 16 | func main() { 17 | lambda.Start(handleRequest) 18 | } 19 | -------------------------------------------------------------------------------- /examples/simple/go/schedule/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/aws/aws-lambda-go/events" 9 | "github.com/aws/aws-lambda-go/lambda" 10 | ) 11 | 12 | func handleRequest(_ context.Context, _ events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 13 | fmt.Println(os.Getenv("uid")) 14 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 15 | } 16 | 17 | func main() { 18 | lambda.Start(handleRequest) 19 | } 20 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py3 3 | 4 | [testenv] 5 | usedevelop = True 6 | allowlist_externals = bash 7 | skip_install = True 8 | passenv = * 9 | commands = {posargs:bash test.sh} 10 | deps = 11 | git+https://github.com/nathants/py-util@115c1302c49c15ed5c46d5421f73022b5406096b 12 | git+https://github.com/nathants/py-pool@27b31ec18b326366c8c405076963e2934dd7b134 13 | git+https://github.com/nathants/py-shell@dacb4922e13f947998ae31e40aec441c54471b36 14 | pytest==8.3.5 15 | pyyaml==6.0.2 16 | -------------------------------------------------------------------------------- /examples/simple/docker/s3/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | s3: 4 | test-bucket-${uid}: 5 | attr: 6 | - acl=private 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | trigger: 18 | - type: s3 19 | attr: 20 | - test-bucket-${uid} 21 | -------------------------------------------------------------------------------- /cmd/aws/region.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["aws-region"] = region 12 | lib.Args["aws-region"] = regionArgs{} 13 | } 14 | 15 | type regionArgs struct { 16 | } 17 | 18 | func (regionArgs) Description() string { 19 | return "\ncurrent region id\n" 20 | } 21 | 22 | func region() { 23 | var args regionArgs 24 | arg.MustParse(&args) 25 | fmt.Println(lib.Region()) 26 | } 27 | -------------------------------------------------------------------------------- /examples/simple/go/s3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/aws/aws-lambda-go/events" 8 | "github.com/aws/aws-lambda-go/lambda" 9 | ) 10 | 11 | func handleRequest(_ context.Context, event events.S3Event) (events.APIGatewayProxyResponse, error) { 12 | for _, record := range event.Records { 13 | fmt.Println(record.S3.Object.Key) 14 | } 15 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 16 | } 17 | 18 | func main() { 19 | lambda.Start(handleRequest) 20 | } 21 | -------------------------------------------------------------------------------- /examples/simple/go/sqs/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/aws/aws-lambda-go/events" 8 | "github.com/aws/aws-lambda-go/lambda" 9 | ) 10 | 11 | func handleRequest(_ context.Context, event events.SQSEvent) (events.APIGatewayProxyResponse, error) { 12 | for _, record := range event.Records { 13 | fmt.Println("thanks for:", record.Body) 14 | } 15 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 16 | } 17 | 18 | func main() { 19 | lambda.Start(handleRequest) 20 | } 21 | -------------------------------------------------------------------------------- /examples/simple/go/includes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "strings" 7 | 8 | "github.com/aws/aws-lambda-go/lambda" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func handleRequest(_ context.Context, _ any) (any, error) { 13 | data, err := os.ReadFile("include_me.txt") 14 | if err != nil { 15 | lib.Logger.Println("error:", err) 16 | return nil, err 17 | } 18 | return strings.TrimRight(string(data), "\n"), nil 19 | } 20 | 21 | func main() { 22 | lambda.Start(handleRequest) 23 | } 24 | -------------------------------------------------------------------------------- /examples/simple/go/sqs/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | sqs: 4 | test-queue-${uid}: 5 | attr: 6 | - timeout=60 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: main.go 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | - AWSLambdaSQSQueueExecutionRole 18 | trigger: 19 | - type: sqs 20 | attr: 21 | - test-queue-${uid} 22 | - batch=1 23 | - window=1 24 | -------------------------------------------------------------------------------- /examples/simple/python/sqs/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | sqs: 4 | test-queue-${uid}: 5 | attr: 6 | - timeout=60 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: main.py 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | - AWSLambdaSQSQueueExecutionRole 18 | trigger: 19 | - type: sqs 20 | attr: 21 | - test-queue-${uid} 22 | - batch=1 23 | - window=1 24 | -------------------------------------------------------------------------------- /examples/simple/python/dynamodb/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import boto3 4 | 5 | dynamodb = boto3.client('dynamodb') 6 | 7 | uid = os.environ['uid'] 8 | 9 | def main(event, context): 10 | for record in event['Records']: 11 | source_arn = record['eventSourceARN'] 12 | _, table, *_ = source_arn.split('/') 13 | keys = record['dynamodb']['Keys'] 14 | item = dynamodb.get_item(TableName=table, Key=keys)['Item'] 15 | dynamodb.put_item(TableName=f'test-other-table-{uid}', Item=item) 16 | print('put:', item) 17 | -------------------------------------------------------------------------------- /lib/ecs.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/aws/aws-sdk-go-v2/service/ecs" 7 | ) 8 | 9 | var ecsClient *ecs.Client 10 | var ecsClientLock sync.Mutex 11 | 12 | func ECSClientExplicit(accessKeyID, accessKeySecret, region string) *ecs.Client { 13 | return ecs.NewFromConfig(*SessionExplicit(accessKeyID, accessKeySecret, region)) 14 | } 15 | 16 | func ECSClient() *ecs.Client { 17 | ecsClientLock.Lock() 18 | defer ecsClientLock.Unlock() 19 | if ecsClient == nil { 20 | ecsClient = ecs.NewFromConfig(*Session()) 21 | } 22 | return ecsClient 23 | } 24 | -------------------------------------------------------------------------------- /examples/simple/docker/sqs/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | sqs: 4 | test-queue-${uid}: 5 | attr: 6 | - timeout=60 7 | 8 | lambda: 9 | test-lambda-${uid}: 10 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 11 | attr: 12 | - concurrency=0 13 | - memory=128 14 | - timeout=60 15 | policy: 16 | - AWSLambdaBasicExecutionRole 17 | - AWSLambdaSQSQueueExecutionRole 18 | trigger: 19 | - type: sqs 20 | attr: 21 | - test-queue-${uid} 22 | - batch=1 23 | - window=1 24 | -------------------------------------------------------------------------------- /examples/misc/api_binary/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import base64 4 | 5 | def main(event, context): 6 | body = event.get('body') 7 | if body: 8 | # binary request body, when available, must be decoded 9 | body = base64.b64decode(body) 10 | assert len(body) == 64 11 | return {'statusCode': '200', 12 | 'isBase64Encoded': True, 13 | 'headers': {'Content-Type': 'application/octet-stream'}, 14 | # binary response body, when returned, must be encoded 15 | 'body': base64.b64encode(body).decode() if body else None} 16 | -------------------------------------------------------------------------------- /cmd/aws/user.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["aws-user"] = user 13 | lib.Args["aws-user"] = userArgs{} 14 | } 15 | 16 | type userArgs struct { 17 | } 18 | 19 | func (userArgs) Description() string { 20 | return "\ncurrent iam user name\n" 21 | } 22 | 23 | func user() { 24 | var args userArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | user, err := lib.StsUser(ctx) 28 | if err != nil { 29 | panic(err) 30 | } 31 | fmt.Println(user) 32 | } 33 | -------------------------------------------------------------------------------- /cmd/ecr/url.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ecr-url"] = ecrUrl 13 | lib.Args["ecr-url"] = ecrUrlArgs{} 14 | } 15 | 16 | type ecrUrlArgs struct { 17 | } 18 | 19 | func (ecrUrlArgs) Description() string { 20 | return "\nlist ecr containers\n" 21 | } 22 | 23 | func ecrUrl() { 24 | var args ecrUrlArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | url, err := lib.EcrUrl(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | fmt.Println(url) 32 | } 33 | -------------------------------------------------------------------------------- /examples/simple/go/websocket/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/aws/aws-lambda-go/events" 7 | "github.com/aws/aws-lambda-go/lambda" 8 | ) 9 | 10 | func handleRequest(_ context.Context, _ events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 11 | // TODO 12 | // 13 | // this test currently just checks that the websocket trigger can be successfully deployed. 14 | // 15 | // for websocket example see: https://github.com/nathants/aws-gocljs 16 | // 17 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 18 | } 19 | 20 | func main() { 21 | lambda.Start(handleRequest) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/aws/account.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["aws-account"] = account 13 | lib.Args["aws-account"] = accountArgs{} 14 | } 15 | 16 | type accountArgs struct { 17 | } 18 | 19 | func (accountArgs) Description() string { 20 | return "\ncurrent account id\n" 21 | } 22 | 23 | func account() { 24 | var args accountArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | account, err := lib.StsAccount(ctx) 28 | if err != nil { 29 | panic(err) 30 | } 31 | fmt.Println(account) 32 | } 33 | -------------------------------------------------------------------------------- /cmd/aws/regions.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["aws-regions"] = regions 12 | lib.Args["aws-regions"] = regionsArgs{} 13 | } 14 | 15 | type regionsArgs struct { 16 | } 17 | 18 | func (regionsArgs) Description() string { 19 | return "\nregion ids\n" 20 | } 21 | 22 | func regions() { 23 | var args regionArgs 24 | arg.MustParse(&args) 25 | awsRegions, err := lib.Regions() 26 | if err != nil { 27 | lib.Logger.Fatal("error: ", err) 28 | } 29 | for _, region := range awsRegions { 30 | fmt.Println(region) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/vpc/id.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["vpc-id"] = vpcId 13 | lib.Args["vpc-id"] = vpcIdArgs{} 14 | } 15 | 16 | type vpcIdArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (vpcIdArgs) Description() string { 21 | return "\nget vpc id\n" 22 | } 23 | 24 | func vpcId() { 25 | var args vpcIdArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | id, err := lib.VpcID(ctx, args.Name) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | fmt.Println(id) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/api/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | 6 | "context" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["api-ls"] = apiLs 14 | lib.Args["api-ls"] = apiLsArgs{} 15 | } 16 | 17 | type apiLsArgs struct { 18 | } 19 | 20 | func (apiLsArgs) Description() string { 21 | return "\nlist apis\n" 22 | } 23 | 24 | func apiLs() { 25 | var args apiLsArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | apis, err := lib.ApiList(ctx) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | for _, api := range apis { 33 | fmt.Println(*api.Name) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cmd/sqs/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["sqs-ls"] = sqsLs 13 | lib.Args["sqs-ls"] = sqsLsArgs{} 14 | } 15 | 16 | type sqsLsArgs struct { 17 | } 18 | 19 | func (sqsLsArgs) Description() string { 20 | return "\nlist sqs queues\n" 21 | } 22 | 23 | func sqsLs() { 24 | var args sqsLsArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | queues, err := lib.SQSListQueues(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, queue := range queues { 32 | fmt.Println(queue) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/api/url.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["api-url"] = apiUrl 13 | lib.Args["api-url"] = apiUrlArgs{} 14 | } 15 | 16 | type apiUrlArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (apiUrlArgs) Description() string { 21 | return "\nget api url\n" 22 | } 23 | 24 | func apiUrl() { 25 | var args apiUrlArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | url, err := lib.ApiUrl(ctx, args.Name) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | fmt.Println(url) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/vpc/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["vpc-rm"] = vpcRm 12 | lib.Args["vpc-rm"] = vpcRmArgs{} 13 | } 14 | 15 | type vpcRmArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (vpcRmArgs) Description() string { 21 | return `rm a vpc` 22 | } 23 | 24 | func vpcRm() { 25 | var args vpcRmArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.VpcRm(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/vpc/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["vpc-ls"] = vpcLs 13 | lib.Args["vpc-ls"] = vpcLsArgs{} 14 | } 15 | 16 | type vpcLsArgs struct { 17 | } 18 | 19 | func (vpcLsArgs) Description() string { 20 | return "\nls vpcs\n" 21 | } 22 | 23 | func vpcLs() { 24 | var args vpcLsArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | vpcs, err := lib.VpcList(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, vpc := range vpcs { 32 | fmt.Println(lib.EC2Name(vpc.Tags), *vpc.VpcId) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/ecr/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ecr-ls"] = ecrLs 13 | lib.Args["ecr-ls"] = ecrLsArgs{} 14 | } 15 | 16 | type ecrLsArgs struct { 17 | } 18 | 19 | func (ecrLsArgs) Description() string { 20 | return "\nlist ecr containers\n" 21 | } 22 | 23 | func ecrLs() { 24 | var args ecrLsArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | repos, err := lib.EcrDescribeRepos(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, repo := range repos { 32 | fmt.Println(*repo.RepositoryName) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/cost.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/aws/aws-sdk-go-v2/service/costexplorer" 7 | ) 8 | 9 | var costExplorerClient *costexplorer.Client 10 | var costExplorerClientLock sync.Mutex 11 | 12 | func CostExplorerClientExplicit(accessKeyID, accessKeySecret, region string) *costexplorer.Client { 13 | return costexplorer.NewFromConfig(*SessionExplicit(accessKeyID, accessKeySecret, region)) 14 | } 15 | 16 | func CostExplorerClient() *costexplorer.Client { 17 | costExplorerClientLock.Lock() 18 | defer costExplorerClientLock.Unlock() 19 | if costExplorerClient == nil { 20 | costExplorerClient = costexplorer.NewFromConfig(*Session()) 21 | } 22 | return costExplorerClient 23 | } 24 | -------------------------------------------------------------------------------- /cmd/logs/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["logs-rm"] = logsRm 12 | lib.Args["logs-rm"] = logsRmArgs{} 13 | } 14 | 15 | type logsRmArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (logsRmArgs) Description() string { 21 | return "\nrm log group\n" 22 | } 23 | 24 | func logsRm() { 25 | var args logsRmArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.LogsDeleteGroup(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/ec2/ls_sgs.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ec2-ls-sgs"] = ec2LsSgs 13 | lib.Args["ec2-ls-sgs"] = ec2LsSgsArgs{} 14 | } 15 | 16 | type ec2LsSgsArgs struct { 17 | } 18 | 19 | func (ec2LsSgsArgs) Description() string { 20 | return "\nls sgs\n" 21 | } 22 | 23 | func ec2LsSgs() { 24 | var args ec2LsSgsArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | out, err := lib.EC2ListSgs(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, sg := range out { 32 | fmt.Println(*sg.GroupName, *sg.GroupId, *sg.VpcId) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/lambda/arn.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["lambda-arn"] = lambdaArn 13 | lib.Args["lambda-arn"] = lambdaArnArgs{} 14 | } 15 | 16 | type lambdaArnArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (lambdaArnArgs) Description() string { 21 | return "\nget lambda arn\n" 22 | } 23 | 24 | func lambdaArn() { 25 | var args lambdaArnArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | arn, err := lib.LambdaArn(ctx, args.Name) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | fmt.Println(arn) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/lambda/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["lambda-rm"] = lambdaRm 12 | lib.Args["lambda-rm"] = lambdaRmArgs{} 13 | } 14 | 15 | type lambdaRmArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (lambdaRmArgs) Description() string { 21 | return "\nlambda rm\n" 22 | } 23 | 24 | func lambdaRm() { 25 | var args lambdaRmArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.LambdaDelete(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/iam/ls_users.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ls-users"] = iamLsUsers 13 | lib.Args["iam-ls-users"] = iamLsUsersArgs{} 14 | } 15 | 16 | type iamLsUsersArgs struct { 17 | } 18 | 19 | func (iamLsUsersArgs) Description() string { 20 | return "\nlist iam users\n" 21 | } 22 | 23 | func iamLsUsers() { 24 | var args iamLsUsersArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | users, err := lib.IamListUsers(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, role := range users { 32 | fmt.Println(lib.Pformat(role)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/ecr/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ecr-ensure"] = ecrEnsure 12 | lib.Args["ecr-ensure"] = ecrEnsureArgs{} 13 | } 14 | 15 | type ecrEnsureArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (ecrEnsureArgs) Description() string { 21 | return "\nensure ecr image\n" 22 | } 23 | 24 | func ecrEnsure() { 25 | var args ecrEnsureArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.EcrEnsure(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/iam/ls_roles.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ls-roles"] = iamLsRoles 13 | lib.Args["iam-ls-roles"] = iamLsRolesArgs{} 14 | } 15 | 16 | type iamLsRolesArgs struct { 17 | } 18 | 19 | func (iamLsRolesArgs) Description() string { 20 | return "\nlist iam roles\n" 21 | } 22 | 23 | func iamLsRoles() { 24 | var args iamLsRolesArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | roles, err := lib.IamListRoles(ctx, nil) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, role := range roles { 32 | fmt.Println(lib.Pformat(role)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/iam/rm_role.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-rm-role"] = iamRmRole 12 | lib.Args["iam-rm-role"] = iamRmRoleArgs{} 13 | } 14 | 15 | type iamRmRoleArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (iamRmRoleArgs) Description() string { 21 | return "\nrm iam role\n" 22 | } 23 | 24 | func iamRmRole() { 25 | var args iamRmRoleArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.IamDeleteRole(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/iam/rm_user.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-rm-user"] = iamRmUser 12 | lib.Args["iam-rm-user"] = iamRmUserArgs{} 13 | } 14 | 15 | type iamRmUserArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (iamRmUserArgs) Description() string { 21 | return "\nrm iam user\n" 22 | } 23 | 24 | func iamRmUser() { 25 | var args iamRmUserArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.IamDeleteUser(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/s3/rm_bucket.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["s3-rm-bucket"] = s3RmBucket 12 | lib.Args["s3-rm-bucket"] = s3RmBucketArgs{} 13 | } 14 | 15 | type s3RmBucketArgs struct { 16 | Bucket string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (s3RmBucketArgs) Description() string { 21 | return "\nrm s3 bucket\n" 22 | } 23 | 24 | func s3RmBucket() { 25 | var args s3RmBucketArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.S3DeleteBucket(ctx, args.Bucket, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/ec2/id_sg.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ec2-id-sg"] = ec2IdSg 13 | lib.Args["ec2-id-sg"] = ec2IdSgArgs{} 14 | } 15 | 16 | type ec2IdSgArgs struct { 17 | VpcName string `arg:"positional,required"` 18 | SgName string `arg:"positional,required"` 19 | } 20 | 21 | func (ec2IdSgArgs) Description() string { 22 | return "\nsg id\n" 23 | } 24 | 25 | func ec2IdSg() { 26 | var args ec2IdSgArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | id, err := lib.EC2SgID(ctx, args.VpcName, args.SgName) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | fmt.Println(id) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/events/ls_buses.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["events-ls-buses"] = eventsLsBuses 13 | lib.Args["events-ls-buses"] = eventsLsBusesArgs{} 14 | } 15 | 16 | type eventsLsBusesArgs struct { 17 | } 18 | 19 | func (eventsLsBusesArgs) Description() string { 20 | return "\nlist event buses\n" 21 | } 22 | 23 | func eventsLsBuses() { 24 | var args eventsLsBusesArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | buses, err := lib.EventsListBuses(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, bus := range buses { 32 | fmt.Println(*bus.Name) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/sqs/url.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["sqs-url"] = sqsUrl 13 | lib.Args["sqs-url"] = sqsUrlArgs{} 14 | } 15 | 16 | type sqsUrlArgs struct { 17 | QueueName string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (sqsUrlArgs) Description() string { 22 | return "\ndelete an sqs queue\n" 23 | } 24 | 25 | func sqsUrl() { 26 | var args sqsUrlArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | queueUrl, err := lib.SQSQueueUrl(ctx, args.QueueName) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | fmt.Println(queueUrl) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/ec2/ami_user.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ec2-ami-user"] = ec2AmiUser 13 | lib.Args["ec2-ami-user"] = ec2AmiUserArgs{} 14 | } 15 | 16 | type ec2AmiUserArgs struct { 17 | AmiID string `arg:"positional,required"` 18 | } 19 | 20 | func (ec2AmiUserArgs) Description() string { 21 | return "\nget the latest ami-id for a given user ami name\n" 22 | } 23 | 24 | func ec2AmiUser() { 25 | var args ec2AmiUserArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | amiID, err := lib.EC2AmiUser(ctx, args.AmiID) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | fmt.Println(amiID) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/ec2/rm_keypair.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ec2-rm-keypair"] = ec2RmKeypair 12 | lib.Args["ec2-rm-keypair"] = ec2RmKeypairArgs{} 13 | } 14 | 15 | type ec2RmKeypairArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (ec2RmKeypairArgs) Description() string { 21 | return "\ndelete a keypair\n" 22 | } 23 | 24 | func ec2RmKeypair() { 25 | var args ec2RmKeypairArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.EC2DeleteKeypair(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/codecommit/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["codecommit-ls"] = codeCommitLs 13 | lib.Args["codecommit-ls"] = codeCommitLsArgs{} 14 | } 15 | 16 | type codeCommitLsArgs struct { 17 | } 18 | 19 | func (codeCommitLsArgs) Description() string { 20 | return ` 21 | ls codecommit repositories 22 | ` 23 | } 24 | 25 | func codeCommitLs() { 26 | var args codeCommitLsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | repos, err := lib.CodeCommitListRepos(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, repo := range repos { 34 | fmt.Println(*repo.RepositoryName) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cmd/s3/describe.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["s3-describe"] = s3Describe 13 | lib.Args["s3-describe"] = s3DescribeArgs{} 14 | } 15 | 16 | type s3DescribeArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (s3DescribeArgs) Description() string { 21 | return "\ndescribe a s3 bucket\n" 22 | } 23 | 24 | func s3Describe() { 25 | var args s3DescribeArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | bucket := args.Name 29 | descr, err := lib.S3GetBucketDescription(ctx, bucket) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | fmt.Println(lib.Pformat(descr)) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/ses/rm_receipt_rule.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ses-rm-receipt-rule"] = sesRmReceiptRule 12 | lib.Args["ses-rm-receipt-rule"] = sesRmReceiptRulesArg{} 13 | } 14 | 15 | type sesRmReceiptRulesArg struct { 16 | Domain string `arg:"positional"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (sesRmReceiptRulesArg) Description() string { 21 | return "\n \n" 22 | } 23 | 24 | func sesRmReceiptRule() { 25 | var args sesRmReceiptRulesArg 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.SesRmReceiptRuleset(ctx, args.Domain, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/ec2/rm_sg.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ec2-rm-sg"] = ec2RmSg 12 | lib.Args["ec2-rm-sg"] = ec2RmSgArgs{} 13 | } 14 | 15 | type ec2RmSgArgs struct { 16 | VpcName string `arg:"positional,required"` 17 | SgName string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (ec2RmSgArgs) Description() string { 22 | return "\ndelete a security-group\n" 23 | } 24 | 25 | func ec2RmSg() { 26 | var args ec2RmSgArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | err := lib.EC2DeleteSg(ctx, args.VpcName, args.SgName, args.Preview) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/route53/rm_zone.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "github.com/alexflint/go-arg" 6 | "github.com/nathants/libaws/lib" 7 | ) 8 | 9 | func init() { 10 | lib.Commands["route53-rm-zone"] = route53DeleteZone 11 | lib.Args["route53-rm-zone"] = route53DeleteZoneArgs{} 12 | } 13 | 14 | type route53DeleteZoneArgs struct { 15 | Name string `arg:"positional,required"` 16 | Preview bool `arg:"-p,--preview"` 17 | } 18 | 19 | func (route53DeleteZoneArgs) Description() string { 20 | return "\ndelete hosted zone\n" 21 | } 22 | 23 | func route53DeleteZone() { 24 | var args route53DeleteZoneArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | err := lib.Route53DeleteZone(ctx, args.Name, args.Preview) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cmd/dynamodb/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["dynamodb-rm"] = dynamodbRm 12 | lib.Args["dynamodb-rm"] = dynamodbRmArgs{} 13 | } 14 | 15 | type dynamodbRmArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | NoWait bool `arg:"-n,--no-wait"` 19 | } 20 | 21 | func (dynamodbRmArgs) Description() string { 22 | return "\nlist dynamodb tables\n" 23 | } 24 | 25 | func dynamodbRm() { 26 | var args dynamodbRmArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | err := lib.DynamoDBDeleteTable(ctx, args.Name, args.Preview, args.NoWait) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/route53/ensure_zone.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "github.com/alexflint/go-arg" 6 | "github.com/nathants/libaws/lib" 7 | ) 8 | 9 | func init() { 10 | lib.Commands["route53-ensure-zone"] = route53EnsureZone 11 | lib.Args["route53-ensure-zone"] = route53EnsureZoneArgs{} 12 | } 13 | 14 | type route53EnsureZoneArgs struct { 15 | Name string `arg:"positional,required"` 16 | Preview bool `arg:"-p,--preview"` 17 | } 18 | 19 | func (route53EnsureZoneArgs) Description() string { 20 | return "\nensure hosted zone\n" 21 | } 22 | 23 | func route53EnsureZone() { 24 | var args route53EnsureZoneArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | err := lib.Route53EnsureZone(ctx, args.Name, args.Preview) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eou pipefail 3 | make check 4 | make 5 | (cd examples/simple/python; for name in *; do (cd $name && timeout 600 python test.py); done) 6 | (cd examples/simple/go; for name in *; do (cd $name && timeout 600 python test.py); done) 7 | (cd examples/simple/docker; for name in *; do (cd $name && timeout 600 python test.py); done) 8 | (cd examples/complex; for name in *; do (cd $name && timeout 600 python test.py); done) 9 | (cd examples/misc; for name in *; do (cd $name && timeout 600 python test.py); done) 10 | ( 11 | cd lib 12 | nontest=$(ls *.go | grep -v _test.go) 13 | for test in $(ls *_test.go | grep -v lib_test.go); do 14 | go test lib_test.go $nontest $test -o /tmp/libaws.test -c 15 | timeout 600 /tmp/libaws.test -test.v -test.failfast 16 | done 17 | ) 18 | -------------------------------------------------------------------------------- /cmd/cloudwatch/ls_alarms.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["cloudwatch-ls-alarms"] = cloudwatchLsAlarms 13 | lib.Args["cloudwatch-ls-alarms"] = cloudwatchLsAlarmsArgs{} 14 | } 15 | 16 | type cloudwatchLsAlarmsArgs struct { 17 | } 18 | 19 | func (cloudwatchLsAlarmsArgs) Description() string { 20 | return "\nlist cloudwatch alarms\n" 21 | } 22 | 23 | func cloudwatchLsAlarms() { 24 | var args cloudwatchLsAlarmsArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | alarms, err := lib.CloudwatchListAlarms(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, alarm := range alarms { 32 | fmt.Println(lib.Pformat(alarm)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/vpc/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["vpc-ensure"] = vpcEnsure 13 | lib.Args["vpc-ensure"] = vpcEnsureArgs{} 14 | } 15 | 16 | type vpcEnsureArgs struct { 17 | Name string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (vpcEnsureArgs) Description() string { 22 | return "\nensure a default-like vpc with an internet gateway and public access\n" 23 | } 24 | 25 | func vpcEnsure() { 26 | var args vpcEnsureArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | vpc, err := lib.VpcEnsure(ctx, "", args.Name, args.Preview) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | fmt.Println(vpc) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/infra/parse.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | "gopkg.in/yaml.v3" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["infra-parse"] = infraParse 13 | lib.Args["infra-parse"] = infraParseArgs{} 14 | } 15 | 16 | type infraParseArgs struct { 17 | YamlPath string `arg:"positional"` 18 | } 19 | 20 | func (infraParseArgs) Description() string { 21 | return "\nparse and validate an infra.yaml file\n" 22 | } 23 | 24 | func infraParse() { 25 | var args infraParseArgs 26 | arg.MustParse(&args) 27 | infra, err := lib.InfraParse(args.YamlPath) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | data, err := yaml.Marshal(infra) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | fmt.Println(string(data)) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/infra/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["infra-rm"] = infraRm 12 | lib.Args["infra-rm"] = infraRmArgs{} 13 | } 14 | 15 | type infraRmArgs struct { 16 | YamlPath string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (infraRmArgs) Description() string { 21 | return "\ninfra rm\n" 22 | } 23 | 24 | func infraRm() { 25 | var args infraRmArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | infraSet, err := lib.InfraParse(args.YamlPath) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | err = lib.InfraDelete(ctx, infraSet, args.Preview) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cmd/iam/ensure_ec2_spot_roles.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-ensure-ec2-spot-roles"] = iamEnsureEC2SpotRoles 12 | lib.Args["iam-ensure-ec2-spot-roles"] = iamEnsureEC2SpotRolesArgs{} 13 | } 14 | 15 | type iamEnsureEC2SpotRolesArgs struct { 16 | Preview bool `arg:"-p,--preview"` 17 | } 18 | 19 | func (iamEnsureEC2SpotRolesArgs) Description() string { 20 | return "\nensure iam ec2 spot roles that are needed to use ec2 spot\n" 21 | } 22 | 23 | func iamEnsureEC2SpotRoles() { 24 | var args iamEnsureEC2SpotRolesArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | err := lib.IamEnsureEC2SpotRoles(ctx, args.Preview) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cmd/iam/rm_instance_profile.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-rm-instance-profile"] = iamRmInstanceProfile 12 | lib.Args["iam-rm-instance-profile"] = iamRmInstanceProfileArgs{} 13 | } 14 | 15 | type iamRmInstanceProfileArgs struct { 16 | Name string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | } 19 | 20 | func (iamRmInstanceProfileArgs) Description() string { 21 | return "\nrm iam instance profile\n" 22 | } 23 | 24 | func iamRmInstanceProfile() { 25 | var args iamRmInstanceProfileArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.IamDeleteInstanceProfile(ctx, args.Name, args.Preview) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/sqs/stats.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["sqs-stats"] = sqsStats 13 | lib.Args["sqs-stats"] = sqsStatsArgs{} 14 | } 15 | 16 | type sqsStatsArgs struct { 17 | QueueName string `arg:"positional,required"` 18 | } 19 | 20 | func (sqsStatsArgs) Description() string { 21 | return "\nsqs queues stats\n" 22 | } 23 | 24 | func sqsStats() { 25 | var args sqsStatsArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | queueUrl, err := lib.SQSQueueUrl(ctx, args.QueueName) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | out, err := lib.SQSNumMessages(ctx, queueUrl) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | fmt.Println(lib.Pformat(out)) 37 | } 38 | -------------------------------------------------------------------------------- /cmd/iam/ls_instance_profiles.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ls-instance-profiles"] = iamLsInstanceProfiles 13 | lib.Args["iam-ls-instance-profiles"] = iamLsInstanceProfilesArgs{} 14 | } 15 | 16 | type iamLsInstanceProfilesArgs struct { 17 | } 18 | 19 | func (iamLsInstanceProfilesArgs) Description() string { 20 | return "\nlist iam instance profiles\n" 21 | } 22 | 23 | func iamLsInstanceProfiles() { 24 | var args iamLsInstanceProfilesArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | profiles, err := lib.IamListInstanceProfiles(ctx, nil) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, profile := range profiles { 32 | fmt.Println(lib.Pformat(profile)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/dynamodb/item_rm_all.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["dynamodb-item-rm-all"] = dynamodbItemRmAll 12 | lib.Args["dynamodb-item-rm-all"] = dynamodbItemRmAllArgs{} 13 | } 14 | 15 | type dynamodbItemRmAllArgs struct { 16 | Table string `arg:"positional"` 17 | Keys []string `arg:"positional,required" help:"should be user_id, not user_id:s:hash"` 18 | } 19 | 20 | func (dynamodbItemRmAllArgs) Description() string { 21 | return "\nrm all items in dynamodb table\n" 22 | } 23 | 24 | func dynamodbItemRmAll() { 25 | var args dynamodbItemRmAllArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := lib.DynamoDBItemDeleteAll(ctx, args.Table, args.Keys) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cmd/ec2/ensure_keypair.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ec2-ensure-keypair"] = ec2EnsureKeypair 12 | lib.Args["ec2-ensure-keypair"] = ec2EnsureKeypairArgs{} 13 | } 14 | 15 | type ec2EnsureKeypairArgs struct { 16 | Name string `arg:"positional,required"` 17 | PubkeyContent string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (ec2EnsureKeypairArgs) Description() string { 22 | return "\nensure a keypair\n" 23 | } 24 | 25 | func ec2EnsureKeypair() { 26 | var args ec2EnsureKeypairArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | err := lib.EC2EnsureKeypair(ctx, "", args.Name, args.PubkeyContent, args.Preview) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/logs/recent.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["logs-recent"] = logsRecent 13 | lib.Args["logs-recent"] = logsRecentArgs{} 14 | } 15 | 16 | type logsRecentArgs struct { 17 | Name string `arg:"positional,required"` 18 | NumLines int `arg:"positional,required" help:"number of recent log lines to show"` 19 | } 20 | 21 | func (logsRecentArgs) Description() string { 22 | return "\nshow the N most recent log lines\n" 23 | } 24 | 25 | func logsRecent() { 26 | var args logsRecentArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | lines, err := lib.LogsRecent(ctx, args.Name, args.NumLines) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, line := range lines { 34 | fmt.Println(line) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cmd/iam/ls_policies.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ls-policies"] = iamLsPolicies 13 | lib.Args["iam-ls-policies"] = iamLsPoliciesArgs{} 14 | } 15 | 16 | type iamLsPoliciesArgs struct { 17 | } 18 | 19 | func (iamLsPoliciesArgs) Description() string { 20 | return "\nlist iam policies\n" 21 | } 22 | 23 | func iamLsPolicies() { 24 | var args iamLsPoliciesArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | policies, err := lib.IamListPolicies(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, policy := range policies { 32 | p := &lib.IamPolicy{} 33 | err := p.FromPolicy(ctx, policy, false) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | fmt.Println(lib.Pformat(p)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/vpc/ls_subnets.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["vpc-ls-subnets"] = vpcLsSubnets 13 | lib.Args["vpc-ls-subnets"] = vpcLsSubnetsArgs{} 14 | } 15 | 16 | type vpcLsSubnetsArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (vpcLsSubnetsArgs) Description() string { 21 | return "\nls vpc subnets\n" 22 | } 23 | 24 | func vpcLsSubnets() { 25 | var args vpcLsSubnetsArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | id, err := lib.VpcID(ctx, args.Name) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | subnets, err := lib.VpcListSubnets(ctx, id) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | for _, subnet := range subnets { 37 | fmt.Println(*subnet.SubnetId, *subnet.AvailabilityZone) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/s3/presign_put.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["s3-presign-put"] = s3PresignPut 14 | lib.Args["s3-presign-put"] = s3PresignPutArgs{} 15 | } 16 | 17 | type s3PresignPutArgs struct { 18 | Path string `arg:"positional"` 19 | ExpirationMinutes int `arg:"-e,--expiration-minutes" default:"20"` 20 | } 21 | 22 | func (s3PresignPutArgs) Description() string { 23 | return "\npresign a s3 put url\n" 24 | } 25 | 26 | func s3PresignPut() { 27 | var args s3PresignPutArgs 28 | arg.MustParse(&args) 29 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 30 | bucket, key, err := lib.SplitOnce(args.Path, "/") 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | fmt.Println(lib.S3PresignPut(bucket, key, time.Duration(args.ExpirationMinutes)*time.Minute)) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/ec2/rm_snapshot.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/ec2" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["ec2-rm-snapshot"] = ec2RmSnapshot 14 | lib.Args["ec2-rm-snapshot"] = ec2RmSnapshotArgs{} 15 | } 16 | 17 | type ec2RmSnapshotArgs struct { 18 | SnapshotID string `arg:"positional"` 19 | } 20 | 21 | func (ec2RmSnapshotArgs) Description() string { 22 | return "\ndelete an snapshot\n" 23 | } 24 | 25 | func ec2RmSnapshot() { 26 | var args ec2RmSnapshotArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | _, err := lib.EC2Client().DeleteSnapshot(ctx, &ec2.DeleteSnapshotInput{ 30 | SnapshotId: aws.String(args.SnapshotID), 31 | }) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | lib.Logger.Println("deleted snapshot:", args.SnapshotID) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/iam/ls_ssh_keys.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ls-ssh-keys"] = iamLsSSHKeys 13 | lib.Args["iam-ls-ssh-keys"] = iamLsSSHKeysArgs{} 14 | } 15 | 16 | type iamLsSSHKeysArgs struct { 17 | } 18 | 19 | func (iamLsSSHKeysArgs) Description() string { 20 | return "\nlist iam ssh keys for the caller's iam user\n" 21 | } 22 | 23 | func iamLsSSHKeys() { 24 | var args iamLsSSHKeysArgs 25 | arg.MustParse(&args) 26 | ctx := context.Background() 27 | keys, err := lib.IamListSSHPublicKeys(ctx) 28 | if err != nil { 29 | lib.Logger.Fatal("error: ", err) 30 | } 31 | for _, key := range keys { 32 | data, err := lib.IamGetSSHPublicKey(ctx, *key.SSHPublicKeyId) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | fmt.Println(key.Status, *key.SSHPublicKeyId, *data.Fingerprint) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/ssh/keygen_rsa.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ssh-keygen-rsa"] = sshKeygenRsa 12 | lib.Args["ssh-keygen-rsa"] = sshKeygenRsaArgs{} 13 | } 14 | 15 | type sshKeygenRsaArgs struct { 16 | } 17 | 18 | func (sshKeygenRsaArgs) Description() string { 19 | return "\ngenerate new rsa ssh keypair and write id_rsa and id_rsa.pub to current working directory\n" 20 | } 21 | 22 | func sshKeygenRsa() { 23 | var args sshKeygenRsaArgs 24 | arg.MustParse(&args) 25 | pubKey, privKey, err := lib.SshKeygenRsa() 26 | if err != nil { 27 | lib.Logger.Fatal("error: ", err) 28 | } 29 | err = os.WriteFile("id_rsa.pub", []byte(pubKey), 0600) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | err = os.WriteFile("id_rsa", []byte(privKey), 0600) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/sqs/purge.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/sqs" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["sqs-purge"] = sqsPurge 14 | lib.Args["sqs-purge"] = sqsPurgeArgs{} 15 | } 16 | 17 | type sqsPurgeArgs struct { 18 | QueueName string `arg:"positional,required"` 19 | } 20 | 21 | func (sqsPurgeArgs) Description() string { 22 | return "\nsqs queues purge\n" 23 | } 24 | 25 | func sqsPurge() { 26 | var args sqsPurgeArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | queueUrl, err := lib.SQSQueueUrl(ctx, args.QueueName) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | _, err = lib.SQSClient().PurgeQueue(ctx, &sqs.PurgeQueueInput{ 34 | QueueUrl: aws.String(queueUrl), 35 | }) 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/ec2/ls_keypairs.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/service/ec2" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-ls-keypairs"] = ec2LsKeypairs 15 | lib.Args["ec2-ls-keypairs"] = ec2LsKeypairsArgs{} 16 | } 17 | 18 | type ec2LsKeypairsArgs struct { 19 | } 20 | 21 | func (ec2LsKeypairsArgs) Description() string { 22 | return "\nlist keypairs\n" 23 | } 24 | 25 | func ec2LsKeypairs() { 26 | var args ec2LsKeypairsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | out, err := lib.EC2Client().DescribeKeyPairs(ctx, &ec2.DescribeKeyPairsInput{}) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | fmt.Fprintln(os.Stderr, "name", "id", "fingerprint", "type") 34 | for _, key := range out.KeyPairs { 35 | fmt.Println(*key.KeyName, *key.KeyPairId, *key.KeyFingerprint, key.KeyType) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/ec2/new_ami.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ec2-new-ami"] = ec2NewAmi 13 | lib.Args["ec2-new-ami"] = ec2NewAmiArgs{} 14 | } 15 | 16 | type ec2NewAmiArgs struct { 17 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 18 | Wait bool `arg:"-w,--wait" default:"false"` 19 | } 20 | 21 | func (ec2NewAmiArgs) Description() string { 22 | return "\nnew ami\n" 23 | } 24 | 25 | func ec2NewAmi() { 26 | var args ec2NewAmiArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | amiID, err := lib.EC2NewAmi(ctx, &lib.EC2NewAmiInput{ 30 | Selectors: args.Selectors, 31 | Wait: args.Wait, 32 | }) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | fmt.Println(amiID) 37 | } 38 | -------------------------------------------------------------------------------- /cmd/lambda/vars.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/lambda" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["lambda-vars"] = lambdaVars 15 | lib.Args["lambda-vars"] = lambdaVarsArgs{} 16 | } 17 | 18 | type lambdaVarsArgs struct { 19 | Name string `arg:"positional"` 20 | } 21 | 22 | func (lambdaVarsArgs) Description() string { 23 | return "\nget lambda vars\n" 24 | } 25 | 26 | func lambdaVars() { 27 | var args lambdaVarsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | out, err := lib.LambdaClient().GetFunction(ctx, &lambda.GetFunctionInput{ 31 | FunctionName: aws.String(args.Name), 32 | }) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | for k, v := range out.Configuration.Environment.Variables { 37 | fmt.Printf("%s=%s\n", k, v) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/route53/describe_records.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["route53-describe-records"] = route53DescribeRecords 13 | lib.Args["route53-describe-records"] = route53DescribeRecordsArgs{} 14 | } 15 | 16 | type route53DescribeRecordsArgs struct { 17 | Name string `arg:"positional,required"` 18 | } 19 | 20 | func (route53DescribeRecordsArgs) Description() string { 21 | return "\ndescribe records\n" 22 | } 23 | 24 | func route53DescribeRecords() { 25 | var args route53DescribeRecordsArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | id, err := lib.Route53ZoneID(ctx, args.Name) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | records, err := lib.Route53ListRecords(ctx, id) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | fmt.Println(lib.Pformat(records)) 37 | } 38 | -------------------------------------------------------------------------------- /examples/simple/go/dynamodb/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | dynamodb: 4 | test-table-${uid}: 5 | key: 6 | - userid:s:hash 7 | - version:n:range 8 | attr: 9 | - stream=keys_only 10 | test-other-table-${uid}: 11 | key: 12 | - userid:s:hash 13 | 14 | lambda: 15 | test-lambda-${uid}: 16 | entrypoint: main.go 17 | attr: 18 | - concurrency=0 19 | - memory=128 20 | - timeout=60 21 | policy: 22 | - AWSLambdaBasicExecutionRole 23 | - AWSLambdaDynamoDBExecutionRole 24 | allow: 25 | - dynamodb:GetItem arn:aws:dynamodb:*:*:table/test-table-${uid} 26 | - dynamodb:PutItem arn:aws:dynamodb:*:*:table/test-other-table-${uid} 27 | trigger: 28 | - type: dynamodb 29 | attr: 30 | - test-table-${uid} 31 | - start=trim_horizon 32 | - batch=1 33 | - parallel=10 34 | - retry=0 35 | - window=1 36 | env: 37 | - uid=${uid} 38 | -------------------------------------------------------------------------------- /examples/simple/python/dynamodb/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | dynamodb: 4 | test-table-${uid}: 5 | key: 6 | - userid:s:hash 7 | - version:n:range 8 | attr: 9 | - stream=keys_only 10 | test-other-table-${uid}: 11 | key: 12 | - userid:s:hash 13 | 14 | lambda: 15 | test-lambda-${uid}: 16 | entrypoint: main.py 17 | attr: 18 | - concurrency=0 19 | - memory=128 20 | - timeout=60 21 | policy: 22 | - AWSLambdaBasicExecutionRole 23 | - AWSLambdaDynamoDBExecutionRole 24 | allow: 25 | - dynamodb:GetItem arn:aws:dynamodb:*:*:table/test-table-${uid} 26 | - dynamodb:PutItem arn:aws:dynamodb:*:*:table/test-other-table-${uid} 27 | trigger: 28 | - type: dynamodb 29 | attr: 30 | - test-table-${uid} 31 | - start=trim_horizon 32 | - batch=1 33 | - parallel=10 34 | - retry=0 35 | - window=1 36 | env: 37 | - uid=${uid} 38 | -------------------------------------------------------------------------------- /cmd/ec2/ls_instance_zones.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/alexflint/go-arg" 7 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["ec2-ls-instance-zones"] = ec2LsInstanceZones 13 | lib.Args["ec2-ls-instance-zones"] = ec2LsInstanceZonesArgs{} 14 | } 15 | 16 | type ec2LsInstanceZonesArgs struct { 17 | Type string `arg:"positional,required" help:"instance type"` 18 | } 19 | 20 | func (ec2LsInstanceZonesArgs) Description() string { 21 | return "\nlist zones which support this instance type\n" 22 | } 23 | 24 | func ec2LsInstanceZones() { 25 | var args ec2LsInstanceZonesArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | 29 | zones, err := lib.EC2ZonesWithInstance(ctx, ec2types.InstanceType(args.Type)) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, zone := range zones { 34 | fmt.Println(zone) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cmd/ecr/rm_repo.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/ecr" 10 | 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["ecr-rm-repo"] = ecrRmRepo 16 | lib.Args["ecr-rm-repo"] = ecrRmRepoArgs{} 17 | } 18 | 19 | type ecrRmRepoArgs struct { 20 | Name string `arg:"positional,required"` 21 | } 22 | 23 | func (ecrRmRepoArgs) Description() string { 24 | return "\ndelete ecr repository\n" 25 | } 26 | 27 | func ecrRmRepo() { 28 | var args ecrRmRepoArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | _, err := lib.EcrClient().DeleteRepository(ctx, &ecr.DeleteRepositoryInput{ 32 | RepositoryName: aws.String(args.Name), 33 | Force: true, 34 | }) 35 | if err != nil { 36 | if !strings.Contains(err.Error(), "RepositoryNotFoundException") { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cmd/ec2/ami_base.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ec2-ami-base"] = ec2AmiBase 12 | lib.Args["ec2-ami-base"] = ec2AmiBaseArgs{} 13 | } 14 | 15 | type ec2AmiBaseArgs struct { 16 | Name string `arg:"positional,required" help:"ami-ID | amzn2 | amzn2023 | deeplearning | bionic | xenial | trusty | focal | jammy | bookworm | trixie | bullseye | buster | stretch | alpine-xx.yy.zz"` 17 | Arch string `arg:"-a,--arch" default:"x86_64" help:"arm64 | x86_64"` 18 | } 19 | 20 | func (ec2AmiBaseArgs) Description() string { 21 | return "\nget the latest ami-id for a given base ami name\n" 22 | } 23 | 24 | func ec2AmiBase() { 25 | var args ec2AmiBaseArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | amiID, _, err := lib.EC2AmiBase(ctx, args.Name, args.Arch) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | fmt.Println(amiID) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/ecr/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/ecr" 10 | 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["ecr-rm"] = ecrRm 16 | lib.Args["ecr-rm"] = ecrRmArgs{} 17 | } 18 | 19 | type ecrRmArgs struct { 20 | Name string `arg:"positional,required"` 21 | // Preview bool `arg:"-p,--preview"` 22 | } 23 | 24 | func (ecrRmArgs) Description() string { 25 | return "\nrm ecr container\n" 26 | } 27 | 28 | func ecrRm() { 29 | var args ecrRmArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | _, err := lib.EcrClient().DeleteRepository(ctx, &ecr.DeleteRepositoryInput{ 33 | RepositoryName: aws.String(args.Name), 34 | Force: true, 35 | }) 36 | if err != nil { 37 | if !strings.Contains(err.Error(), "RepositoryNotFoundException") { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cmd/ses/ensure_receipt_rule.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ses-ensure-receipt-rule"] = sesEnsureReceiptRule 12 | lib.Args["ses-ensure-receipt-rule"] = sesEnsureReceiptRulesArg{} 13 | } 14 | 15 | type sesEnsureReceiptRulesArg struct { 16 | Domain string `arg:"positional"` 17 | LambdaArn string `arg:"positional"` 18 | Bucket string `arg:"positional"` 19 | Prefix string `arg:"positional"` 20 | Preview bool `arg:"-p,--preview"` 21 | } 22 | 23 | func (sesEnsureReceiptRulesArg) Description() string { 24 | return "\n \n" 25 | } 26 | 27 | func sesEnsureReceiptRule() { 28 | var args sesEnsureReceiptRulesArg 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | _, err := lib.SesEnsureReceiptRuleset(ctx, args.Domain, args.LambdaArn, args.Bucket, args.Prefix, args.Preview) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cmd/infra/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | "gopkg.in/yaml.v3" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["infra-ls"] = infraLs 14 | lib.Args["infra-ls"] = infraLsArgs{} 15 | } 16 | 17 | type infraLsArgs struct { 18 | Filter string `arg:"positional" help:"filter by name substring"` 19 | ShowEnvVarValues bool `arg:"-v,--env-values" help:"show environment variable values instead of their hash"` 20 | } 21 | 22 | func (infraLsArgs) Description() string { 23 | return "\nls infra\n" 24 | } 25 | 26 | func infraLs() { 27 | var args infraLsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | infra, err := lib.InfraList(ctx, args.Filter, args.ShowEnvVarValues) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | bytes, err := yaml.Marshal(infra) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | fmt.Println(string(bytes)) 39 | } 40 | -------------------------------------------------------------------------------- /cmd/ssh/keygen_ed25519.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ssh-keygen-ed25519"] = sshKeygenEd25519 12 | lib.Args["ssh-keygen-ed25519"] = sshKeygenEd25519Args{} 13 | } 14 | 15 | type sshKeygenEd25519Args struct { 16 | } 17 | 18 | func (sshKeygenEd25519Args) Description() string { 19 | return "\ngenerate new ed25519 ssh keypair and write id_ed25519 and id_ed25519.pub to current working directory\n" 20 | } 21 | 22 | func sshKeygenEd25519() { 23 | var args sshKeygenEd25519Args 24 | arg.MustParse(&args) 25 | pubKey, privKey, err := lib.SshKeygenEd25519() 26 | if err != nil { 27 | lib.Logger.Fatal("error: ", err) 28 | } 29 | err = os.WriteFile("id_ed25519.pub", []byte(pubKey), 0600) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | err = os.WriteFile("id_ed25519", []byte(privKey), 0600) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/events/ls_rules.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["events-ls-rules"] = eventsLsRules 14 | lib.Args["events-ls-rules"] = eventsLsRulesArgs{} 15 | } 16 | 17 | type eventsLsRulesArgs struct { 18 | BusName string `arg:"positional" help:"specify name to target a bus other than the default bus"` 19 | } 20 | 21 | func (eventsLsRulesArgs) Description() string { 22 | return "\nlist events rules\n" 23 | } 24 | 25 | func eventsLsRules() { 26 | var args eventsLsRulesArgs 27 | arg.MustParse(&args) 28 | var busName *string 29 | if args.BusName != "" { 30 | busName = aws.String(args.BusName) 31 | } 32 | ctx := context.Background() 33 | rules, err := lib.EventsListRules(ctx, busName) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | for _, rule := range rules { 38 | fmt.Println(lib.Pformat(rule)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cmd/s3/presign_get.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["s3-presign-get"] = s3PresignGet 14 | lib.Args["s3-presign-get"] = s3PresignGetArgs{} 15 | } 16 | 17 | type s3PresignGetArgs struct { 18 | Path string `arg:"positional"` 19 | ExpirationMinutes int `arg:"-e,--expiration-minutes" default:"20"` 20 | Range string `arg:"-r,--range" help:"bytes=0-10"` 21 | } 22 | 23 | func (s3PresignGetArgs) Description() string { 24 | return "\npresign a s3 get url\n" 25 | } 26 | 27 | func s3PresignGet() { 28 | var args s3PresignGetArgs 29 | arg.MustParse(&args) 30 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 31 | bucket, key, err := lib.SplitOnce(args.Path, "/") 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | fmt.Println(lib.S3PresignGet(bucket, key, args.Range, time.Duration(args.ExpirationMinutes)*time.Minute)) 36 | } 37 | -------------------------------------------------------------------------------- /examples/simple/docker/dynamodb/infra.yaml: -------------------------------------------------------------------------------- 1 | name: test-infraset-${uid} 2 | 3 | dynamodb: 4 | test-table-${uid}: 5 | key: 6 | - userid:s:hash 7 | - version:n:range 8 | attr: 9 | - stream=keys_only 10 | test-other-table-${uid}: 11 | key: 12 | - userid:s:hash 13 | 14 | lambda: 15 | test-lambda-${uid}: 16 | entrypoint: ${account}.dkr.ecr.${region}.amazonaws.com/test-container@${digest} 17 | attr: 18 | - concurrency=0 19 | - memory=128 20 | - timeout=60 21 | policy: 22 | - AWSLambdaBasicExecutionRole 23 | - AWSLambdaDynamoDBExecutionRole 24 | allow: 25 | - dynamodb:GetItem arn:aws:dynamodb:*:*:table/test-table-${uid} 26 | - dynamodb:PutItem arn:aws:dynamodb:*:*:table/test-other-table-${uid} 27 | trigger: 28 | - type: dynamodb 29 | attr: 30 | - test-table-${uid} 31 | - start=trim_horizon 32 | - batch=1 33 | - parallel=10 34 | - retry=0 35 | - window=1 36 | env: 37 | - uid=${uid} 38 | -------------------------------------------------------------------------------- /cmd/sqs/send.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/sqs" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["sqs-send"] = sqsSend 14 | lib.Args["sqs-send"] = sqsSendArgs{} 15 | } 16 | 17 | type sqsSendArgs struct { 18 | Name string `arg:"positional,required"` 19 | Message string `arg:"positional,required"` 20 | } 21 | 22 | func (sqsSendArgs) Description() string { 23 | return "\nsend a message to a sqs queue\n" 24 | } 25 | 26 | func sqsSend() { 27 | var args sqsSendArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | url, err := lib.SQSQueueUrl(ctx, args.Name) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | _, err = lib.SQSClient().SendMessage(ctx, &sqs.SendMessageInput{ 35 | QueueUrl: aws.String(url), 36 | MessageBody: aws.String(args.Message), 37 | }) 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cmd/codecommit/describe.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/codecommit" 10 | 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["codecommit-describe"] = codeCommitDescribe 16 | lib.Args["codecommit-describe"] = codeCommitDescribeArgs{} 17 | } 18 | 19 | type codeCommitDescribeArgs struct { 20 | Name string `arg:"positional,required"` 21 | } 22 | 23 | func (codeCommitDescribeArgs) Description() string { 24 | return ` 25 | describe codecommit repository 26 | ` 27 | } 28 | 29 | func codeCommitDescribe() { 30 | var args codeCommitDescribeArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | getOut, err := lib.CodeCommitClient().GetRepository(ctx, &codecommit.GetRepositoryInput{ 34 | RepositoryName: aws.String(args.Name), 35 | }) 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | fmt.Println(lib.Pformat(getOut.RepositoryMetadata)) 40 | } 41 | -------------------------------------------------------------------------------- /cmd/infra/url_api.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["infra-url-api"] = infraUrlApi 14 | lib.Args["infra-url-api"] = infraUrlApiArgs{} 15 | } 16 | 17 | type infraUrlApiArgs struct { 18 | YamlPath string `arg:"positional,required"` 19 | LambdaName string `arg:"positional,required"` 20 | } 21 | 22 | func (infraUrlApiArgs) Description() string { 23 | return "\nget infra api url\n" 24 | } 25 | 26 | func infraUrlApi() { 27 | var args infraUrlApiArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | infraSet, err := lib.InfraParse(args.YamlPath) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | for name := range infraSet.Lambda { 35 | if name == args.LambdaName { 36 | url, err := lib.ApiUrl(ctx, name) 37 | if err != nil { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | fmt.Println(url) 41 | os.Exit(0) 42 | } 43 | } 44 | os.Exit(1) 45 | } 46 | -------------------------------------------------------------------------------- /lib/lib_test.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "reflect" 5 | "slices" 6 | "testing" 7 | ) 8 | 9 | func TestDropLinesWithAny(t *testing.T) { 10 | type test struct { 11 | input string 12 | output string 13 | tokens []string 14 | } 15 | tests := []test{ 16 | {"a\nb\nc\n", "a\nb\nc\n", []string{"foo"}}, 17 | {"a\nb\nc\n", "b\nc\n", []string{"a"}}, 18 | {"a\nb\nc\n", "b\n", []string{"a", "c"}}, 19 | } 20 | for _, test := range tests { 21 | output := DropLinesWithAny(test.input, test.tokens...) 22 | if output != test.output { 23 | t.Errorf("\ngot:\n%s\nwant:\n%s\n", output, test.output) 24 | } 25 | } 26 | } 27 | 28 | func TestChunk(t *testing.T) { 29 | type test struct { 30 | input []string 31 | output [][]string 32 | } 33 | tests := []test{ 34 | {[]string{"a", "b", "c", "d"}, [][]string{{"a", "b", "c"}, {"d"}}}, 35 | } 36 | for _, test := range tests { 37 | output := slices.Chunk(test.input, 3) 38 | if !reflect.DeepEqual(output, test.output) { 39 | t.Errorf("\ngot:\n%v\nwant:\n%v\n", output, test.output) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/simple/docker/dynamodb/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const { DynamoDBClient, GetItemCommand, PutItemCommand } = require("@aws-sdk/client-dynamodb"); 4 | 5 | exports.handler = async (event, context) => { 6 | try { 7 | const client = new DynamoDBClient({ region: process.env.AWS_DEFAULT_REGION }); 8 | for (const record of event['Records']) { 9 | const source_arn = record['eventSourceARN']; 10 | const table = source_arn.split('/')[1]; 11 | const getCommand = new GetItemCommand({ 12 | TableName: 'test-table-' + process.env.uid, 13 | Key: record['dynamodb']['Keys'] 14 | }); 15 | const res = await client.send(getCommand); 16 | const item = res['Item']; 17 | const putCommand = new PutItemCommand({ 18 | TableName: 'test-other-table-' + process.env.uid, 19 | Item: item 20 | }); 21 | const putRes = await client.send(putCommand); 22 | console.log('put:', JSON.stringify(item)); 23 | } 24 | } catch (err) { 25 | console.error(err); 26 | } 27 | context.succeed(); 28 | } 29 | -------------------------------------------------------------------------------- /cmd/infra/url_func.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["infra-url-func"] = infraUrlFunc 14 | lib.Args["infra-url-func"] = infraUrlFuncArgs{} 15 | } 16 | 17 | type infraUrlFuncArgs struct { 18 | YamlPath string `arg:"positional,required"` 19 | LambdaName string `arg:"positional,required"` 20 | } 21 | 22 | func (infraUrlFuncArgs) Description() string { 23 | return "\nget infra function url\n" 24 | } 25 | 26 | func infraUrlFunc() { 27 | var args infraUrlFuncArgs 28 | arg.MustParse(&args) 29 | 30 | ctx := context.Background() 31 | 32 | infraSet, err := lib.InfraParse(args.YamlPath) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | 37 | for name := range infraSet.Lambda { 38 | if name == args.LambdaName { 39 | url, err := lib.FuncUrl(ctx, name) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | fmt.Println(url) 44 | os.Exit(0) 45 | } 46 | } 47 | os.Exit(1) 48 | } 49 | -------------------------------------------------------------------------------- /cmd/route53/ns.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/route53" 10 | 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["route53-ns"] = route53NS 16 | lib.Args["route53-ns"] = route53NSArgs{} 17 | } 18 | 19 | type route53NSArgs struct { 20 | ZoneName string `arg:"positional,required"` 21 | } 22 | 23 | func (route53NSArgs) Description() string { 24 | return "\nlist name servers for zone\n" 25 | } 26 | 27 | func route53NS() { 28 | var args route53NSArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | id, err := lib.Route53ZoneID(ctx, args.ZoneName) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | out, err := lib.Route53Client().GetHostedZone(ctx, &route53.GetHostedZoneInput{ 36 | Id: aws.String(id), 37 | }) 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | for _, ns := range out.DelegationSet.NameServers { 42 | fmt.Println(ns) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmd/cloudwatch/ls_alarms_billing.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["cloudwatch-ls-alarms-billing"] = cloudwatchLsAlarmsBilling 14 | lib.Args["cloudwatch-ls-alarms-billing"] = cloudwatchLsAlarmsBillingArgs{} 15 | } 16 | 17 | type cloudwatchLsAlarmsBillingArgs struct { 18 | } 19 | 20 | func (cloudwatchLsAlarmsBillingArgs) Description() string { 21 | return "\nlist cloudwatch billing alarms in us-east-1\n" 22 | } 23 | 24 | func cloudwatchLsAlarmsBilling() { 25 | var args cloudwatchLsAlarmsBillingArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | err := os.Setenv("AWS_DEFAULT_REGION", "us-east-1") 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | out, err := lib.CloudwatchListAlarms(ctx) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | for _, alarm := range out { 37 | if *alarm.Namespace == "AWS/Billing" { 38 | fmt.Println(lib.Pformat(alarm)) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cmd/ec2/ensure_sg.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["ec2-ensure-sg"] = ec2EnsureSg 12 | lib.Args["ec2-ensure-sg"] = ec2EnsureSgArgs{} 13 | } 14 | 15 | type ec2EnsureSgArgs struct { 16 | VpcName string `arg:"positional,required"` 17 | SgName string `arg:"positional,required"` 18 | Rules []string `arg:"positional"` 19 | Preview bool `arg:"-p,--preview"` 20 | } 21 | 22 | func (ec2EnsureSgArgs) Description() string { 23 | return "\nensure a security-group\n" + ` 24 | libaws ec2-ensure-sg $vpc $sg tcp:22:0.0.0.0/0 tcp:443:0.0.0.0/0 ::sg-XXXX 25 | ` 26 | } 27 | 28 | func ec2EnsureSg() { 29 | var args ec2EnsureSgArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | input, err := lib.EC2EnsureSgInput("", args.VpcName, args.SgName, args.Rules) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | err = lib.EC2EnsureSg(ctx, input, args.Preview) 37 | if err != nil { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cmd/organizations/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["organizations-ensure"] = organizationsEnsure 13 | lib.Args["organizations-ensure"] = organizationsEnsureArgs{} 14 | } 15 | 16 | type organizationsEnsureArgs struct { 17 | Name string `arg:"positional,required"` 18 | Email string `arg:"positional,required"` 19 | Preview bool `arg:"-p,--preview"` 20 | } 21 | 22 | func (organizationsEnsureArgs) Description() string { 23 | return "\nensure a sub account\n" 24 | } 25 | 26 | func organizationsEnsure() { 27 | var args organizationsEnsureArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | accountID, err := lib.OrganizationsEnsure(ctx, args.Name, args.Email, args.Preview) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | fmt.Println("account-id:", accountID) 35 | fmt.Println("setup root user login for account via password reset at https://console.aws.amazon.com/ with email:", args.Email) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/route53/describe_zone.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/route53" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["route53-describe-zone"] = route53DescribeZone 15 | lib.Args["route53-describe-zone"] = route53DescribeZoneArgs{} 16 | } 17 | 18 | type route53DescribeZoneArgs struct { 19 | Name string `arg:"positional,required"` 20 | } 21 | 22 | func (route53DescribeZoneArgs) Description() string { 23 | return "\ndescribe zone\n" 24 | } 25 | 26 | func route53DescribeZone() { 27 | var args route53DescribeZoneArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | id, err := lib.Route53ZoneID(ctx, args.Name) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | out, err := lib.Route53Client().GetHostedZone(ctx, &route53.GetHostedZoneInput{ 35 | Id: aws.String(id), 36 | }) 37 | if err != nil { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | fmt.Println(lib.Pformat(out)) 41 | } 42 | -------------------------------------------------------------------------------- /cmd/s3/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["s3-rm"] = s3Rm 13 | lib.Args["s3-rm"] = s3RmArgs{} 14 | } 15 | 16 | type s3RmArgs struct { 17 | Path string `arg:"positional,required"` 18 | Recursive bool `arg:"-r,--recursive"` 19 | Preview bool `arg:"-p,--preview"` 20 | } 21 | 22 | func (s3RmArgs) Description() string { 23 | return "\nrm s3 content \n" 24 | } 25 | 26 | func s3Rm() { 27 | var args s3RmArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | 31 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 32 | bucket, key, err := lib.SplitOnce(args.Path, "/") 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | 37 | deleteInput := &lib.S3DeleteInput{ 38 | Bucket: bucket, 39 | Prefix: key, 40 | Recursive: args.Recursive, 41 | Preview: args.Preview, 42 | } 43 | 44 | err = lib.S3Delete(ctx, deleteInput) 45 | if err != nil { 46 | lib.Logger.Fatal("error: ", err) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cmd/ec2/ip.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-ip"] = ec2Ip 15 | lib.Args["ec2-ip"] = ec2IpArgs{} 16 | } 17 | 18 | type ec2IpArgs struct { 19 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 20 | } 21 | 22 | func (ec2IpArgs) Description() string { 23 | return "\nlist ec2 ipv4\n" 24 | } 25 | 26 | func ec2Ip() { 27 | var args ec2IpArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, ec2types.InstanceStateNameRunning) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | if len(instances) == 0 { 35 | os.Exit(1) 36 | } 37 | for _, instance := range instances { 38 | if instance.PublicIpAddress != nil { 39 | fmt.Println(*instance.PublicIpAddress) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmd/ec2/dns.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-dns"] = ec2Dns 15 | lib.Args["ec2-dns"] = ec2DnsArgs{} 16 | } 17 | 18 | type ec2DnsArgs struct { 19 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 20 | } 21 | 22 | func (ec2DnsArgs) Description() string { 23 | return "\nlist ec2 dns\n" 24 | } 25 | 26 | func ec2Dns() { 27 | var args ec2DnsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, ec2types.InstanceStateNameRunning) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | if len(instances) == 0 { 35 | os.Exit(1) 36 | } 37 | for _, instance := range instances { 38 | if instance.PrivateDnsName != nil { 39 | fmt.Println(*instance.PublicDnsName) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmd/ses/ls_receipt_rules.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/service/ses" 9 | 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ses-ls-receipt-rules"] = sesLsReceiptRules 15 | lib.Args["ses-ls-receipt-rules"] = sesLsReceiptRulesArgs{} 16 | } 17 | 18 | type sesLsReceiptRulesArgs struct { 19 | } 20 | 21 | func (sesLsReceiptRulesArgs) Description() string { 22 | return "\n \n" 23 | } 24 | 25 | func sesLsReceiptRules() { 26 | var args sesLsReceiptRulesArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | rules, err := lib.SesListReceiptRulesets(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, rule := range rules { 34 | fmt.Println() 35 | fmt.Println(*rule.Name) 36 | out, err := lib.SesClient().DescribeReceiptRuleSet(ctx, &ses.DescribeReceiptRuleSetInput{ 37 | RuleSetName: rule.Name, 38 | }) 39 | if err != nil { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | fmt.Println(lib.PformatAlways(out)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmd/sqs/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/sqs" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["sqs-rm"] = sqsRm 15 | lib.Args["sqs-rm"] = sqsRmArgs{} 16 | } 17 | 18 | type sqsRmArgs struct { 19 | QueueName string `arg:"positional,required"` 20 | Preview bool `arg:"-p,--preview"` 21 | } 22 | 23 | func (sqsRmArgs) Description() string { 24 | return "\ndelete an sqs queue\n" 25 | } 26 | 27 | func sqsRm() { 28 | var args sqsRmArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | queueUrl, err := lib.SQSQueueUrl(ctx, args.QueueName) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | lib.Logger.Println(lib.PreviewString(args.Preview)+"deleted:", queueUrl) 36 | if args.Preview { 37 | os.Exit(0) 38 | } 39 | _, err = lib.SQSClient().DeleteQueue(ctx, &sqs.DeleteQueueInput{ 40 | QueueUrl: aws.String(queueUrl), 41 | }) 42 | if err != nil { 43 | lib.Logger.Fatal("error: ", err) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cmd/ecr/rm_tag.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/ecr" 10 | ecrtypes "github.com/aws/aws-sdk-go-v2/service/ecr/types" 11 | 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | func init() { 16 | lib.Commands["ecr-rm-tag"] = ecrRmTag 17 | lib.Args["ecr-rm-tag"] = ecrRmTagArgs{} 18 | } 19 | 20 | type ecrRmTagArgs struct { 21 | Name string `arg:"positional,required"` 22 | } 23 | 24 | func (ecrRmTagArgs) Description() string { 25 | return "\nrm ecr tag\n" 26 | } 27 | 28 | func ecrRmTag() { 29 | var args ecrRmTagArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | parts := strings.Split(args.Name, ":") 33 | name := parts[0] 34 | tag := parts[1] 35 | _, err := lib.EcrClient().BatchDeleteImage(ctx, &ecr.BatchDeleteImageInput{ 36 | RepositoryName: aws.String(name), 37 | ImageIds: []ecrtypes.ImageIdentifier{ 38 | { 39 | ImageTag: aws.String(tag), 40 | }, 41 | }, 42 | }) 43 | if err != nil { 44 | lib.Logger.Fatal("error: ", err) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cmd/events/ls_targets.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["events-ls-targets"] = eventsLsTargets 14 | lib.Args["events-ls-targets"] = eventsLsTargetsArgs{} 15 | } 16 | 17 | type eventsLsTargetsArgs struct { 18 | RuleName string `arg:"positional,required"` 19 | BusName string `arg:"positional" default:"" help:"specify name to target a bus other than the default bus"` 20 | } 21 | 22 | func (eventsLsTargetsArgs) Description() string { 23 | return "\nlist event targets\n" 24 | } 25 | 26 | func eventsLsTargets() { 27 | var args eventsLsTargetsArgs 28 | arg.MustParse(&args) 29 | var busName *string 30 | if args.BusName != "" { 31 | busName = aws.String(args.BusName) 32 | } 33 | ctx := context.Background() 34 | targets, err := lib.EventsListRuleTargets(ctx, args.RuleName, busName) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | for _, target := range targets { 39 | fmt.Println(lib.Pformat(target)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cmd/cloudwatch/ls_namespaces.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["cloudwatch-ls-namespaces"] = cloudwatchLsNamespaces 14 | lib.Args["cloudwatch-ls-namespaces"] = cloudwatchLsNamespacesArgs{} 15 | } 16 | 17 | type cloudwatchLsNamespacesArgs struct { 18 | } 19 | 20 | func (cloudwatchLsNamespacesArgs) Description() string { 21 | return "\nlist cloudwatch namespaces\n" 22 | } 23 | 24 | func cloudwatchLsNamespaces() { 25 | var args cloudwatchLsNamespacesArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | metrics, err := lib.CloudwatchListMetrics(ctx, nil, nil) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | namespacesMap := map[string]any{} 33 | for _, m := range metrics { 34 | namespacesMap[*m.Namespace] = nil 35 | } 36 | var namespaces []string 37 | for n := range namespacesMap { 38 | namespaces = append(namespaces, n) 39 | } 40 | sort.Strings(namespaces) 41 | for _, n := range namespaces { 42 | fmt.Println(n) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmd/iam/ensure_instance_profile.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-ensure-instance-profile"] = iamEnsureInstanceProfile 12 | lib.Args["iam-ensure-instance-profile"] = iamEnsureInstanceProfileArgs{} 13 | } 14 | 15 | type iamEnsureInstanceProfileArgs struct { 16 | Name string `arg:"positional,required"` 17 | Policy []string `arg:"--policy" help:"policy name, can specify multiple values"` 18 | Allow []string `arg:"--allow" help:"\"$service:$action $arn\", example: \"s3:* *\", can specify multiple values"` 19 | Preview bool `arg:"-p,--preview"` 20 | } 21 | 22 | func (iamEnsureInstanceProfileArgs) Description() string { 23 | return "\nensure an iam instance-profile\n" 24 | } 25 | 26 | func iamEnsureInstanceProfile() { 27 | var args iamEnsureInstanceProfileArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | err := lib.IamEnsureInstanceProfile(ctx, "", args.Name, args.Policy, args.Allow, args.Preview) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/infra/url_websocket.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["infra-url-websocket"] = infraUrlWebsocket 14 | lib.Args["infra-url-websocket"] = infraUrlWebsocketArgs{} 15 | } 16 | 17 | type infraUrlWebsocketArgs struct { 18 | YamlPath string `arg:"positional,required"` 19 | LambdaName string `arg:"positional,required"` 20 | } 21 | 22 | func (infraUrlWebsocketArgs) Description() string { 23 | return "\nget infra websocket url\n" 24 | } 25 | 26 | func infraUrlWebsocket() { 27 | var args infraUrlWebsocketArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | infraSet, err := lib.InfraParse(args.YamlPath) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | for name := range infraSet.Lambda { 35 | if name == args.LambdaName { 36 | url, err := lib.ApiUrl(ctx, name+lib.LambdaWebsocketSuffix) 37 | if err != nil { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | fmt.Println(url) 41 | os.Exit(0) 42 | } 43 | } 44 | os.Exit(1) 45 | } 46 | -------------------------------------------------------------------------------- /cmd/infra/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["infra-ensure"] = infraEnsure 12 | lib.Args["infra-ensure"] = infraEnsureArgs{} 13 | } 14 | 15 | type infraEnsureArgs struct { 16 | YamlPath string `arg:"positional,required"` 17 | Preview bool `arg:"-p,--preview"` 18 | Quick string `arg:"-q,--quick" help:"patch this lambda's code without updating infrastructure"` 19 | ShowEnvVarValues bool `arg:"-v,--env-values" help:"show environment variable values instead of their hash"` 20 | } 21 | 22 | func (infraEnsureArgs) Description() string { 23 | return "\nensure infra\nsee " 24 | } 25 | 26 | func infraEnsure() { 27 | var args infraEnsureArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | infraSet, err := lib.InfraParse(args.YamlPath) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | err = lib.InfraEnsure(ctx, infraSet, args.Quick, args.Preview, args.ShowEnvVarValues) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cmd/lambda/permissions.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/service/lambda" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["lambda-permissions"] = lambdaPermissions 16 | lib.Args["lambda-permissions"] = lambdaPermissionsArgs{} 17 | } 18 | 19 | type lambdaPermissionsArgs struct { 20 | Name string `arg:"positional"` 21 | } 22 | 23 | func (lambdaPermissionsArgs) Description() string { 24 | return "\nget lambda permissions\n" 25 | } 26 | 27 | func lambdaPermissions() { 28 | var args lambdaPermissionsArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | out, err := lib.LambdaClient().GetPolicy(ctx, &lambda.GetPolicyInput{ 32 | FunctionName: aws.String(args.Name), 33 | }) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | val := map[string]any{} 38 | err = json.Unmarshal([]byte(*out.Policy), &val) 39 | if err != nil { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | fmt.Println(lib.PformatAlways(val)) 43 | } 44 | -------------------------------------------------------------------------------- /cmd/logs/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/dustin/go-humanize" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["logs-ls"] = logsLs 16 | lib.Args["logs-ls"] = logsLsArgs{} 17 | } 18 | 19 | type logsLsArgs struct { 20 | } 21 | 22 | func (logsLsArgs) Description() string { 23 | return "\nlist logs\n" 24 | } 25 | 26 | func zeroOnNil(x *int32) int32 { 27 | if x == nil { 28 | return 0 29 | } 30 | return *x 31 | } 32 | 33 | func logsLs() { 34 | var args logsLsArgs 35 | arg.MustParse(&args) 36 | ctx := context.Background() 37 | logs, err := lib.LogsListLogGroups(ctx) 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | sort.Slice(logs, func(i, j int) bool { return *logs[i].StoredBytes < *logs[j].StoredBytes }) 42 | for _, log := range logs { 43 | fmt.Println( 44 | *log.LogGroupName, 45 | fmt.Sprintf("retention-days=%d", zeroOnNil(log.RetentionInDays)), 46 | fmt.Sprintf("stored=%s", strings.ReplaceAll(humanize.Bytes(uint64(*log.StoredBytes)), " ", "")), 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present Nathan Todd-Stone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd/logs/set_retention.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["logs-set-retention"] = logsSetRetention 14 | lib.Args["logs-set-retention"] = logsSetRetentionArgs{} 15 | } 16 | 17 | type logsSetRetentionArgs struct { 18 | Name string `arg:"positional,required" help:"log group name"` 19 | Days int32 `arg:"positional,required" help:"days to retain log data"` 20 | } 21 | 22 | func (logsSetRetentionArgs) Description() string { 23 | return "\nset log retention days\n" 24 | } 25 | 26 | func logsSetRetention() { 27 | var args logsSetRetentionArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | _, err := lib.LogsClient().PutRetentionPolicy(ctx, &cloudwatchlogs.PutRetentionPolicyInput{ 31 | LogGroupName: aws.String(args.Name), 32 | RetentionInDays: aws.Int32(args.Days), 33 | }) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | lib.Logger.Printf("set retention to %d days for %s\n", args.Days, args.Name) 38 | } 39 | -------------------------------------------------------------------------------- /cmd/ec2/dns_private.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-dns-private"] = ec2DnsPrivate 15 | lib.Args["ec2-dns-private"] = ec2DnsPrivateArgs{} 16 | } 17 | 18 | type ec2DnsPrivateArgs struct { 19 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 20 | } 21 | 22 | func (ec2DnsPrivateArgs) Description() string { 23 | return "\nlist ec2 private dns\n" 24 | } 25 | 26 | func ec2DnsPrivate() { 27 | var args ec2DnsPrivateArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, ec2types.InstanceStateNameRunning) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | if len(instances) == 0 { 35 | os.Exit(1) 36 | } 37 | for _, instance := range instances { 38 | if instance.PrivateDnsName != nil { 39 | fmt.Println(*instance.PrivateDnsName) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmd/ec2/ip_private.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-ip-private"] = ec2IpPrivate 15 | lib.Args["ec2-ip-private"] = ec2IpPrivateArgs{} 16 | } 17 | 18 | type ec2IpPrivateArgs struct { 19 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 20 | } 21 | 22 | func (ec2IpPrivateArgs) Description() string { 23 | return "\nlist ec2 private ipv4\n" 24 | } 25 | 26 | func ec2IpPrivate() { 27 | var args ec2IpPrivateArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, ec2types.InstanceStateNameRunning) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | if len(instances) == 0 { 35 | os.Exit(1) 36 | } 37 | for _, instance := range instances { 38 | if instance.PrivateIpAddress != nil { 39 | fmt.Println(*instance.PrivateIpAddress) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmd/acm/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | "time" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/service/acm" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["acm-ls"] = acmLs 16 | lib.Args["acm-ls"] = acmLsArgs{} 17 | } 18 | 19 | type acmLsArgs struct { 20 | } 21 | 22 | func (acmLsArgs) Description() string { 23 | return "\nlist acm certificates\n" 24 | } 25 | 26 | func acmLs() { 27 | var args acmLsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | certs, err := lib.AcmListCertificates(ctx) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | for _, cert := range certs { 35 | out, err := lib.AcmClient().DescribeCertificate(ctx, &acm.DescribeCertificateInput{ 36 | CertificateArn: cert.CertificateArn, 37 | }) 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | 42 | fmt.Println( 43 | strings.Join(out.Certificate.SubjectAlternativeNames, " "), 44 | "renewal="+out.Certificate.RenewalEligibility, 45 | "status="+out.Certificate.Status, 46 | "expires="+out.Certificate.NotAfter.Format(time.RFC3339), 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cmd/ec2/id.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ec2-id"] = ec2Id 15 | lib.Args["ec2-id"] = ec2IdArgs{} 16 | } 17 | 18 | type ec2IdArgs struct { 19 | Selectors []string `arg:"positional" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 20 | State string `arg:"-s,--state" help:"running | pending | terminated | stopped" default:"running"` 21 | } 22 | 23 | func (ec2IdArgs) Description() string { 24 | return "\nlist ec2 id\n" 25 | } 26 | 27 | func ec2Id() { 28 | var args ec2IdArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, ec2types.InstanceStateName(args.State)) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | if len(instances) == 0 { 36 | os.Exit(1) 37 | } 38 | for _, instance := range instances { 39 | if instance.InstanceId != nil { 40 | fmt.Println(*instance.InstanceId) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cmd/dynamodb/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["dynamodb-ls"] = dynamodbLs 15 | lib.Args["dynamodb-ls"] = dynamodbLsArgs{} 16 | } 17 | 18 | type dynamodbLsArgs struct { 19 | Status bool `arg:"-s,--status" help:"show table status"` 20 | } 21 | 22 | func (dynamodbLsArgs) Description() string { 23 | return "\nlist dynamodb tables\n" 24 | } 25 | 26 | func dynamodbLs() { 27 | var args dynamodbLsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | tables, err := lib.DynamoDBListTables(ctx) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | for _, table := range tables { 35 | if args.Status { 36 | description, err := lib.DynamoDBClient().DescribeTable(ctx, &dynamodb.DescribeTableInput{ 37 | TableName: aws.String(table), 38 | }) 39 | if err != nil { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | fmt.Println(table, string(description.Table.TableStatus)) 43 | } else { 44 | fmt.Println(table) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cmd/creds/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/user" 7 | "path" 8 | "strings" 9 | 10 | "github.com/alexflint/go-arg" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["creds-ls"] = credsLs 16 | lib.Args["creds-ls"] = credsLsArgs{} 17 | } 18 | 19 | type credsLsArgs struct { 20 | } 21 | 22 | func (credsLsArgs) Description() string { 23 | return "\nlist aws creds\n" 24 | } 25 | 26 | func credsLs() { 27 | var args credsLsArgs 28 | arg.MustParse(&args) 29 | usr, err := user.Current() 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | home := usr.HomeDir 34 | dir := os.Getenv("LIBAWS_CREDS_DIR") 35 | if dir == "" { 36 | dir = "secure/aws_creds" 37 | } 38 | root := path.Join(home, dir) 39 | if err != nil { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | entries, err := os.ReadDir(root) 43 | if err != nil { 44 | lib.Logger.Fatal("error: ", err) 45 | } 46 | for _, entry := range entries { 47 | if !entry.Type().IsRegular() { 48 | continue 49 | } 50 | if !strings.HasSuffix(entry.Name(), ".creds") { 51 | continue 52 | } 53 | name := strings.Split(entry.Name(), ".")[0] 54 | fmt.Println(name) 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /cmd/ec2/price_ondemand.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["ec2-price-ondemand"] = ec2PriceOndemand 14 | lib.Args["ec2-price-ondemand"] = ec2PriceOndemandArgs{} 15 | } 16 | 17 | type ec2PriceOndemandArgs struct { 18 | InstanceType string `arg:"positional" help:"optional instance type, e.g. m6i.large"` 19 | } 20 | 21 | func (ec2PriceOndemandArgs) Description() string { 22 | return "\nshow EC2 on-demand prices\n" 23 | } 24 | 25 | func ec2PriceOndemand() { 26 | var args ec2PriceOndemandArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | region := lib.Region() 30 | prices, err := lib.EC2OnDemandPrices(ctx, region, args.InstanceType) 31 | if err != nil { 32 | lib.Logger.Println("error:", err) 33 | os.Exit(1) 34 | } 35 | if len(prices) == 0 { 36 | os.Exit(1) 37 | } 38 | if args.InstanceType != "" { 39 | price, ok := prices[args.InstanceType] 40 | if !ok { 41 | os.Exit(1) 42 | } 43 | fmt.Println(price) 44 | return 45 | } 46 | for _, t := range lib.SortedInstanceTypes(prices) { 47 | fmt.Printf("%s %g\n", t, prices[t]) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cmd/organizations/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/service/organizations" 9 | orgtypes "github.com/aws/aws-sdk-go-v2/service/organizations/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["organizations-ls"] = organizationsLs 15 | lib.Args["organizations-ls"] = organizationsLsArgs{} 16 | } 17 | 18 | type organizationsLsArgs struct { 19 | } 20 | 21 | func (organizationsLsArgs) Description() string { 22 | return "\nlist sub accounts\n" 23 | } 24 | 25 | func organizationsLs() { 26 | var args organizationsLsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | var token *string 30 | var accounts []orgtypes.Account 31 | for { 32 | out, err := lib.OrganizationsClient().ListAccounts(ctx, &organizations.ListAccountsInput{ 33 | NextToken: token, 34 | }) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | accounts = append(accounts, out.Accounts...) 39 | if out.NextToken == nil { 40 | break 41 | } 42 | token = out.NextToken 43 | } 44 | 45 | for _, account := range accounts { 46 | fmt.Println(lib.Pformat(account)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cmd/lambda/describe.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/lambda" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["lambda-describe"] = lambdaDescribe 15 | lib.Args["lambda-describe"] = lambdaDescribeArgs{} 16 | } 17 | 18 | type lambdaDescribeArgs struct { 19 | Name string `arg:"positional,required"` 20 | } 21 | 22 | func (lambdaDescribeArgs) Description() string { 23 | return "\nget lambda describe\n" 24 | } 25 | 26 | func lambdaDescribe() { 27 | var args lambdaDescribeArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | out, err := lib.LambdaClient().GetFunction(ctx, &lambda.GetFunctionInput{ 31 | FunctionName: aws.String(args.Name), 32 | }) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | fmt.Println(lib.PformatAlways(out)) 37 | confOut, err := lib.LambdaClient().GetFunctionConfiguration(ctx, &lambda.GetFunctionConfigurationInput{ 38 | FunctionName: aws.String(args.Name), 39 | }) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | fmt.Println(lib.PformatAlways(confOut)) 44 | } 45 | -------------------------------------------------------------------------------- /cmd/ec2/ls_amis.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/service/ec2" 8 | "github.com/nathants/libaws/lib" 9 | "sort" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["ec2-ls-amis"] = ec2LsAmis 14 | lib.Args["ec2-ls-amis"] = ec2LsAmisArgs{} 15 | } 16 | 17 | type ec2LsAmisArgs struct { 18 | } 19 | 20 | func (ec2LsAmisArgs) Description() string { 21 | return "\nlist amis\n" 22 | } 23 | 24 | func ec2LsAmis() { 25 | var args ec2LsAmisArgs 26 | arg.MustParse(&args) 27 | ctx := context.Background() 28 | account, err := lib.StsAccount(ctx) 29 | if err != nil { 30 | lib.Logger.Fatal("error: ", err) 31 | } 32 | images, err := lib.EC2Client().DescribeImages(ctx, &ec2.DescribeImagesInput{ 33 | Owners: []string{account}, 34 | }) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | sort.Slice(images.Images, func(i, j int) bool { return *images.Images[i].CreationDate > *images.Images[j].CreationDate }) 39 | for _, image := range images.Images { 40 | fmt.Println( 41 | *image.ImageId, 42 | *image.CreationDate, 43 | lib.StringOr(image.Description, "-"), 44 | lib.EC2Tags(image.Tags), 45 | string(image.State)) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/complex/s3-ec2/infra.yaml: -------------------------------------------------------------------------------- 1 | # workflow: 2 | # - write to s3 in-bucket 3 | # - which triggers lambda 4 | # - which launches ec2 spot 5 | # - which reads from in-bucket, writes to out-bucket, and shutdown 6 | 7 | name: test-infraset-${uid} 8 | 9 | instance-profile: 10 | test-profile-${uid}: 11 | allow: 12 | - s3:List* arn:aws:s3:::in-bucket-${uid}/* 13 | - s3:GetObject arn:aws:s3:::in-bucket-${uid}/* 14 | - s3:PutObject arn:aws:s3:::out-bucket-${uid}/* 15 | 16 | keypair: 17 | test-keypair-${uid}: 18 | pubkey-content: ${pubkey} 19 | 20 | vpc: 21 | test-vpc-${uid}: 22 | security-group: 23 | test-sg-${uid}: 24 | rule: 25 | - tcp:22:0.0.0.0/0 26 | 27 | s3: 28 | in-bucket-${uid}: {} 29 | out-bucket-${uid}: {} 30 | 31 | lambda: 32 | test-lambda-${uid}: 33 | entrypoint: main.go 34 | allow: 35 | - ec2:* * 36 | - iam:GetRole * 37 | - iam:PassRole arn:aws:iam::*:role/aws-ec2-spot-fleet-tagging-role 38 | - iam:PassRole arn:aws:iam::*:role/ec2/test-profile-${uid}-path/test-profile-${uid} 39 | policy: 40 | - AWSLambdaBasicExecutionRole 41 | trigger: 42 | - type: s3 43 | attr: 44 | - in-bucket-${uid} 45 | env: 46 | - uid=${uid} 47 | -------------------------------------------------------------------------------- /cmd/ec2/ssh_user.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["ec2-ssh-user"] = ec2SshUser 14 | lib.Args["ec2-ssh-user"] = ec2SshUserArgs{} 15 | } 16 | 17 | type ec2SshUserArgs struct { 18 | Selectors []string `arg:"positional,required" help:"instance-id | dns-name | private-dns-name | tag | vpc-id | subnet-id | security-group-id | ip-address | private-ip-address"` 19 | } 20 | 21 | func (ec2SshUserArgs) Description() string { 22 | return "\nprint the ssh-user for ec2 instance\n" 23 | } 24 | 25 | func ec2SshUser() { 26 | var args ec2SshUserArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | instances, err := lib.EC2ListInstances(ctx, args.Selectors, "running") 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | users := map[string]any{} 34 | for _, instance := range instances { 35 | users[lib.EC2GetTag(instance.Tags, "user", "")] = nil 36 | } 37 | if len(users) > 1 { 38 | lib.Logger.Fatal("error: too many users ", lib.Pformat(instances)) 39 | } 40 | for user := range users { 41 | fmt.Println(user) 42 | os.Exit(0) 43 | } 44 | lib.Logger.Fatal("no user tag found") 45 | } 46 | -------------------------------------------------------------------------------- /cmd/iam/reset_user_login_password.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | "github.com/sethvargo/go-password/password" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["iam-reset-user-login-password"] = iamResetUserLoginPassword 14 | lib.Args["iam-reset-user-login-password"] = iamResetUserLoginPasswordArgs{} 15 | } 16 | 17 | type iamResetUserLoginPasswordArgs struct { 18 | User string `arg:"positional,required"` 19 | } 20 | 21 | func (iamResetUserLoginPasswordArgs) Description() string { 22 | return "\nreset an iam user login password\n" 23 | } 24 | 25 | func iamResetUserLoginPassword() { 26 | var args iamResetUserLoginPasswordArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | account, err := lib.StsAccount(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | password, err := password.Generate(24, 4, 4, false, false) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | err = lib.IamResetUserLoginTempPassword(ctx, args.User, password) 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | fmt.Println("password:", password) 42 | fmt.Printf("url: https://%s.signin.aws.amazon.com/console\n", account) 43 | } 44 | -------------------------------------------------------------------------------- /cmd/route53/rm_record.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "github.com/alexflint/go-arg" 6 | "github.com/nathants/libaws/lib" 7 | ) 8 | 9 | func init() { 10 | lib.Commands["route53-rm-record"] = route53DeleteRecord 11 | lib.Args["route53-rm-record"] = route53DeleteRecordArgs{} 12 | } 13 | 14 | type route53DeleteRecordArgs struct { 15 | ZoneName string `arg:"positional,required"` 16 | RecordName string `arg:"positional,required"` 17 | Attr []string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (route53DeleteRecordArgs) Description() string { 22 | return `delete a route53 record 23 | 24 | example: 25 | - libaws route53-rm-record example.com domain.example.com Type=A TTL=60 Value=1.1.1.1 Value=2.2.2.2 26 | 27 | required attrs: 28 | - TTL=VALUE 29 | - Type=VALUE 30 | - Value=VALUE 31 | ` 32 | } 33 | 34 | func route53DeleteRecord() { 35 | var args route53DeleteRecordArgs 36 | arg.MustParse(&args) 37 | ctx := context.Background() 38 | input, err := lib.Route53EnsureRecordInput(args.ZoneName, args.RecordName, args.Attr) 39 | if err != nil { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | err = lib.Route53DeleteRecord(ctx, input, args.Preview) 43 | if err != nil { 44 | lib.Logger.Fatal("error: ", err) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cmd/logs/tail.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "strings" 8 | "time" 9 | 10 | "github.com/alexflint/go-arg" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["logs-tail"] = logsTail 16 | lib.Args["logs-tail"] = logsTailArgs{} 17 | } 18 | 19 | type logsTailArgs struct { 20 | Name string `arg:"positional,required"` 21 | FromHours int `arg:"-f,--from-hours" default:"0" help:"get data no older than this"` 22 | Timestamps bool `arg:"-t,--timestamps" help:"show timestamps"` 23 | ExitAfter string `arg:"-e,--exit-after" help:"when tailing, after this substring is seen in a log line, exit"` 24 | } 25 | 26 | func (logsTailArgs) Description() string { 27 | return "\ntail logs\n" 28 | } 29 | 30 | func logsTail() { 31 | var args logsTailArgs 32 | arg.MustParse(&args) 33 | ctx := context.Background() 34 | minAge := time.Now().Add(-1 * time.Hour * time.Duration(args.FromHours)) 35 | err := lib.LogsTail(ctx, args.Name, minAge, func(timestamp time.Time, line string) { 36 | if args.Timestamps { 37 | fmt.Println(timestamp, line) 38 | } else { 39 | fmt.Println(line) 40 | } 41 | if args.ExitAfter != "" && strings.Contains(line, args.ExitAfter) { 42 | os.Exit(0) 43 | } 44 | }) 45 | if err != nil { 46 | lib.Logger.Fatal("error: ", err) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cmd/codecommit/rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/codecommit" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["codecommit-rm"] = codeCommitRm 15 | lib.Args["codecommit-rm"] = codeCommitRmArgs{} 16 | } 17 | 18 | type codeCommitRmArgs struct { 19 | Name string `arg:"positional,required"` 20 | Preview bool `arg:"-p,--preview"` 21 | } 22 | 23 | func (codeCommitRmArgs) Description() string { 24 | return ` 25 | rm a codecommit repository 26 | ` 27 | } 28 | 29 | func codeCommitRm() { 30 | var args codeCommitRmArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | out, err := lib.CodeCommitClient().GetRepository(ctx, &codecommit.GetRepositoryInput{ 34 | RepositoryName: aws.String(args.Name), 35 | }) 36 | if err != nil { 37 | fmt.Println("repository not found") 38 | return 39 | } 40 | if !args.Preview { 41 | _, err = lib.CodeCommitClient().DeleteRepository(ctx, &codecommit.DeleteRepositoryInput{ 42 | RepositoryName: aws.String(args.Name), 43 | }) 44 | } 45 | lib.Logger.Println(lib.PreviewString(args.Preview), "deleted: "+lib.Pformat(out.RepositoryMetadata)) 46 | if err != nil { 47 | lib.Logger.Fatal("error: ", err) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cmd/s3/get.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "os" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/s3" 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | func init() { 16 | lib.Commands["s3-get"] = s3Get 17 | lib.Args["s3-get"] = s3GetArgs{} 18 | } 19 | 20 | type s3GetArgs struct { 21 | Path string `arg:"positional"` 22 | } 23 | 24 | func (s3GetArgs) Description() string { 25 | return "\nget an object and write it to stdout\n" 26 | } 27 | 28 | func s3Get() { 29 | var args s3GetArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | 33 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 34 | bucket, key, err := lib.SplitOnce(args.Path, "/") 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | 39 | s3Client, err := lib.S3ClientBucketRegion(bucket) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | out, err := s3Client.GetObject(ctx, &s3.GetObjectInput{ 44 | Bucket: aws.String(bucket), 45 | Key: aws.String(key), 46 | }) 47 | if err != nil { 48 | lib.Logger.Fatal("error: ", err) 49 | } 50 | defer func() { _ = out.Body.Close() }() 51 | 52 | _, err = io.Copy(os.Stdout, out.Body) 53 | if err != nil { 54 | lib.Logger.Fatal("error: ", err) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/acm.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | "time" 7 | 8 | "github.com/aws/aws-sdk-go-v2/service/acm" 9 | acmtypes "github.com/aws/aws-sdk-go-v2/service/acm/types" 10 | ) 11 | 12 | var acmClient *acm.Client 13 | var acmClientLock sync.Mutex 14 | 15 | func AcmClientExplicit(accessKeyID, accessKeySecret, region string) *acm.Client { 16 | return acm.NewFromConfig(*SessionExplicit(accessKeyID, accessKeySecret, region)) 17 | } 18 | 19 | func AcmClient() *acm.Client { 20 | acmClientLock.Lock() 21 | defer acmClientLock.Unlock() 22 | if acmClient == nil { 23 | acmClient = acm.NewFromConfig(*Session()) 24 | } 25 | return acmClient 26 | } 27 | 28 | func AcmListCertificates(ctx context.Context) ([]acmtypes.CertificateSummary, error) { 29 | if doDebug { 30 | d := &Debug{start: time.Now(), name: "AcmListCertificates"} 31 | d.Start() 32 | defer d.End() 33 | } 34 | var token *string 35 | var result []acmtypes.CertificateSummary 36 | for { 37 | out, err := AcmClient().ListCertificates(ctx, &acm.ListCertificatesInput{ 38 | NextToken: token, 39 | }) 40 | if err != nil { 41 | Logger.Println("error:", err) 42 | return nil, err 43 | } 44 | result = append(result, out.CertificateSummaryList...) 45 | if out.NextToken == nil { 46 | break 47 | } 48 | token = out.NextToken 49 | } 50 | return result, nil 51 | } 52 | -------------------------------------------------------------------------------- /cmd/iam/ensure_role.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["iam-ensure-role"] = iamEnsureRole 12 | lib.Args["iam-ensure-role"] = iamEnsureRoleArgs{} 13 | } 14 | 15 | type iamEnsureRoleArgs struct { 16 | Name string `arg:"positional,required"` 17 | Principal string `arg:"positional,required"` 18 | Policy []string `arg:"--policy" help:"policy name, can specify multiple values"` 19 | Allow []string `arg:"--allow" help:"\"$service:$action $arn\", example: \"s3:* *\", can specify multiple values"` 20 | Preview bool `arg:"-p,--preview"` 21 | } 22 | 23 | func (iamEnsureRoleArgs) Description() string { 24 | return "\nensure an iam role\n" 25 | } 26 | 27 | func iamEnsureRole() { 28 | var args iamEnsureRoleArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | err := lib.IamEnsureRole(ctx, "", args.Name, args.Principal, args.Preview) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | err = lib.IamEnsureRolePolicies(ctx, args.Name, args.Policy, args.Preview) 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | err = lib.IamEnsureRoleAllows(ctx, args.Name, args.Allow, args.Preview) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cmd/cloudwatch/ls_dimensions.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["cloudwatch-ls-dimensions"] = cloudwatchLsDimensions 15 | lib.Args["cloudwatch-ls-dimensions"] = cloudwatchLsDimensionsArgs{} 16 | } 17 | 18 | type cloudwatchLsDimensionsArgs struct { 19 | Namespace string `arg:"positional,required"` 20 | Metric string `arg:"positional,required"` 21 | } 22 | 23 | func (cloudwatchLsDimensionsArgs) Description() string { 24 | return "\nlist cloudwatch dimensions\n" 25 | } 26 | 27 | func cloudwatchLsDimensions() { 28 | var args cloudwatchLsDimensionsArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | metrics, err := lib.CloudwatchListMetrics(ctx, aws.String(args.Namespace), aws.String(args.Metric)) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | dimensionsMap := map[string]any{} 36 | for _, m := range metrics { 37 | for _, d := range m.Dimensions { 38 | dimensionsMap[*d.Name+"="+*d.Value] = nil 39 | } 40 | } 41 | var dimensions []string 42 | for n := range dimensionsMap { 43 | dimensions = append(dimensions, n) 44 | } 45 | sort.Strings(dimensions) 46 | for _, d := range dimensions { 47 | fmt.Println(d) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cmd/cloudwatch/ls_metrics.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "sort" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["cloudwatch-ls-metrics"] = cloudwatchLsMetrics 16 | lib.Args["cloudwatch-ls-metrics"] = cloudwatchLsMetricsArgs{} 17 | } 18 | 19 | type cloudwatchLsMetricsArgs struct { 20 | Namespace string `arg:"positional,required"` 21 | } 22 | 23 | func (cloudwatchLsMetricsArgs) Description() string { 24 | return "\nlist cloudwatch metrics\n" 25 | } 26 | 27 | func cloudwatchLsMetrics() { 28 | var args cloudwatchLsMetricsArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | metrics, err := lib.CloudwatchListMetrics(ctx, aws.String(args.Namespace), nil) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | metricsMap := map[string]int{} 36 | for _, m := range metrics { 37 | metricsMap[*m.MetricName] = 0 38 | for range m.Dimensions { 39 | metricsMap[*m.MetricName]++ 40 | } 41 | } 42 | var metricsNames []string 43 | for m := range metricsMap { 44 | metricsNames = append(metricsNames, m) 45 | } 46 | sort.Strings(metricsNames) 47 | fmt.Fprintln(os.Stderr, "name", "dimensions") 48 | for _, m := range metricsNames { 49 | fmt.Println(m, metricsMap[m]) 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /examples/simple/go/api_and_stream/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "time" 9 | 10 | "github.com/aws/aws-lambda-go/events" 11 | "github.com/aws/aws-lambda-go/lambda" 12 | ) 13 | 14 | func streamHandler(_ context.Context, _ *events.LambdaFunctionURLRequest) (*events.LambdaFunctionURLStreamingResponse, error) { 15 | pr, pw := io.Pipe() 16 | go func() { 17 | defer func() { _ = pw.Close() }() 18 | for _, v := range []string{"a\n", "b\n", "c\n", "d\n"} { 19 | _, _ = pw.Write([]byte(v)) 20 | time.Sleep(2 * time.Second) 21 | } 22 | }() 23 | return &events.LambdaFunctionURLStreamingResponse{ 24 | StatusCode: 200, 25 | Headers: map[string]string{ 26 | "Content-Type": "text/plain", 27 | }, 28 | Body: pr, 29 | }, nil 30 | } 31 | 32 | func dispatch(ctx context.Context, raw json.RawMessage) (any, error) { 33 | var urlReq events.LambdaFunctionURLRequest 34 | if json.Unmarshal(raw, &urlReq) == nil && urlReq.RequestContext.HTTP.Method != "" { 35 | return streamHandler(ctx, &urlReq) 36 | } 37 | var apiReq events.APIGatewayProxyRequest 38 | if json.Unmarshal(raw, &apiReq) == nil && apiReq.HTTPMethod != "" { 39 | return events.APIGatewayProxyResponse{StatusCode: 200, Body: "ok\n"}, nil 40 | } 41 | return nil, fmt.Errorf("unknown event") 42 | } 43 | 44 | func main() { 45 | lambda.Start(dispatch) 46 | } 47 | -------------------------------------------------------------------------------- /cmd/iam/get_policy.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/alexflint/go-arg" 7 | iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" 8 | "github.com/nathants/libaws/lib" 9 | "strings" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["iam-get-policy"] = iamGetPolicy 14 | lib.Args["iam-get-policy"] = iamGetPolicyArgs{} 15 | } 16 | 17 | type iamGetPolicyArgs struct { 18 | Name string `arg:"positional,required"` 19 | } 20 | 21 | func (iamGetPolicyArgs) Description() string { 22 | return "\nget iam policy\n" 23 | } 24 | 25 | func iamGetPolicy() { 26 | var args iamGetPolicyArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | policies, err := lib.IamListPolicies(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | var matches []iamtypes.Policy 34 | for _, policy := range policies { 35 | if strings.EqualFold(lib.Last(strings.Split(*policy.Arn, "/")), args.Name) { 36 | matches = append(matches, policy) 37 | } 38 | } 39 | switch len(matches) { 40 | case 0: 41 | lib.Logger.Fatal("error: ", "no policy found") 42 | case 1: 43 | p := &lib.IamPolicy{} 44 | err := p.FromPolicy(ctx, matches[0], true) 45 | if err != nil { 46 | lib.Logger.Fatal("error: ", err) 47 | } 48 | fmt.Println(lib.Pformat(p)) 49 | default: 50 | lib.Logger.Fatal("error: ", "more than 1 policy found:", lib.Pformat(matches)) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cmd/codecommit/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "os" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/codecommit" 12 | cctypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["codecommit-ensure"] = codeCommitEnsure 18 | lib.Args["codecommit-ensure"] = codeCommitEnsureArgs{} 19 | } 20 | 21 | type codeCommitEnsureArgs struct { 22 | Name string `arg:"positional,required"` 23 | Descr string `arg:"-d,--description"` 24 | } 25 | 26 | func (codeCommitEnsureArgs) Description() string { 27 | return ` 28 | ensure a codecommit repository 29 | ` 30 | } 31 | 32 | func codeCommitEnsure() { 33 | var args codeCommitEnsureArgs 34 | arg.MustParse(&args) 35 | ctx := context.Background() 36 | createOut, err := lib.CodeCommitClient().CreateRepository(ctx, &codecommit.CreateRepositoryInput{ 37 | RepositoryName: aws.String(args.Name), 38 | RepositoryDescription: aws.String(args.Descr), 39 | }) 40 | if err == nil { 41 | fmt.Fprintln(os.Stderr, "created:", args.Name) 42 | fmt.Println(lib.Pformat(createOut.RepositoryMetadata)) 43 | return 44 | } 45 | var rne *cctypes.RepositoryNameExistsException 46 | if errors.As(err, &rne) { 47 | } else { 48 | lib.Logger.Fatal("error: ", err) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cmd/logs/set_retention_all.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["logs-set-retention-all"] = logsSetRetentionALl 14 | lib.Args["logs-set-retention-all"] = logsSetRetentionALlArgs{} 15 | } 16 | 17 | type logsSetRetentionALlArgs struct { 18 | Days int32 `arg:"positional,required" help:"days to retain log data"` 19 | } 20 | 21 | func (logsSetRetentionALlArgs) Description() string { 22 | return "\nset log retention days for all log groups\n" 23 | } 24 | 25 | func logsSetRetentionALl() { 26 | var args logsSetRetentionALlArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | logs, err := lib.LogsListLogGroups(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, log := range logs { 34 | old := 0 35 | if log.RetentionInDays != nil { 36 | old = int(*log.RetentionInDays) 37 | } 38 | _, err := lib.LogsClient().PutRetentionPolicy(ctx, &cloudwatchlogs.PutRetentionPolicyInput{ 39 | LogGroupName: log.LogGroupName, 40 | RetentionInDays: aws.Int32(args.Days), 41 | }) 42 | if err != nil { 43 | lib.Logger.Fatal("error: ", err) 44 | } 45 | lib.Logger.Printf("set retention from %d to %d days for %s\n", old, args.Days, *log.LogGroupName) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cmd/sqs/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["sqs-ensure"] = sqsEnsure 12 | lib.Args["sqs-ensure"] = sqsEnsureArgs{} 13 | } 14 | 15 | type sqsEnsureArgs struct { 16 | Name string `arg:"positional,required"` 17 | Attr []string `arg:"positional"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (sqsEnsureArgs) Description() string { 22 | return ` 23 | ensure a sqs queue 24 | 25 | example: 26 | - libaws sqs-ensure test-queue delay=30 timeout=60 27 | 28 | optional attrs: 29 | - DelaySeconds=VALUE, shortcut: delay=VALUE, default: 0 30 | - MaximumMessageSize=VALUE, shortcut: size=VALUE, default: 262144 31 | - MessageRetentionPeriod=VALUE, shortcut: retention=VALUE default: 345600 32 | - ReceiveMessageWaitTimeSeconds=VALUE, shortcut: wait=VALUE default: 0 33 | - VisibilityTimeout=VALUE, shortcut: timeout=VALUE default: 30 34 | 35 | ` 36 | } 37 | 38 | func sqsEnsure() { 39 | var args sqsEnsureArgs 40 | arg.MustParse(&args) 41 | ctx := context.Background() 42 | input, err := lib.SQSEnsureInput("", args.Name, args.Attr) 43 | if err != nil { 44 | lib.Logger.Fatal("error: ", err) 45 | } 46 | err = lib.SQSEnsure(ctx, input, args.Preview) 47 | if err != nil { 48 | lib.Logger.Fatal("error: ", err) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cmd/lambda/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["lambda-ls"] = lambdaLs 15 | lib.Args["lambda-ls"] = lambdaLsArgs{} 16 | } 17 | 18 | type lambdaLsArgs struct { 19 | } 20 | 21 | func (lambdaLsArgs) Description() string { 22 | return "\nget lambda ls\n" 23 | } 24 | 25 | func lambdaLs() { 26 | var args lambdaLsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | fns, err := lib.LambdaListFunctions(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | sort.Slice(fns, func(i, j int) bool { 34 | return *fns[i].FunctionName < *fns[j].FunctionName 35 | }) 36 | for _, fn := range fns { 37 | name := "-" 38 | if fn.FunctionName != nil { 39 | name = *fn.FunctionName 40 | } 41 | runtime := "-" 42 | if fn.Runtime != "" { 43 | runtime = string(fn.Runtime) 44 | } 45 | timeout := "-" 46 | if fn.Timeout != nil { 47 | timeout = fmt.Sprintf("%ds", *fn.Timeout) 48 | } 49 | memory := "-" 50 | if fn.MemorySize != nil { 51 | memory = fmt.Sprintf("%dmb", *fn.MemorySize) 52 | } 53 | lastmodified := "-" 54 | if fn.LastModified != nil { 55 | lastmodified = strings.Join(strings.Split(*fn.LastModified, ":")[:2], ":") + "Z" 56 | } 57 | fmt.Println(lib.Green(name), runtime, timeout, memory, lastmodified) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cmd/ecr/login.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "encoding/base64" 6 | "fmt" 7 | "os" 8 | "os/exec" 9 | "strings" 10 | 11 | "github.com/alexflint/go-arg" 12 | "github.com/aws/aws-sdk-go-v2/service/ecr" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["ecr-login"] = ecrLogin 18 | lib.Args["ecr-login"] = ecrLoginArgs{} 19 | } 20 | 21 | type ecrLoginArgs struct { 22 | } 23 | 24 | func (ecrLoginArgs) Description() string { 25 | return "\nlogin to docker\n" 26 | } 27 | 28 | func ecrLogin() { 29 | var args ecrLoginArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | token, err := lib.EcrClient().GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenInput{}) 33 | if err != nil { 34 | lib.Logger.Fatal("error: ", err) 35 | } 36 | bytes, err := base64.StdEncoding.DecodeString(*token.AuthorizationData[0].AuthorizationToken) 37 | if err != nil { 38 | lib.Logger.Fatal("error: ", err) 39 | } 40 | parts := strings.Split(string(bytes), ":") 41 | if len(parts) != 2 { 42 | err := fmt.Errorf("expected two parts") 43 | lib.Logger.Fatal("error: ", err) 44 | } 45 | password := parts[1] 46 | endpoint := *token.AuthorizationData[0].ProxyEndpoint 47 | cmd := exec.Command("docker", "login", "--username", "AWS", "--password", password, endpoint) 48 | cmd.Stdout = os.Stdout 49 | cmd.Stderr = os.Stderr 50 | err = cmd.Run() 51 | if err != nil { 52 | lib.Logger.Fatal("error: ", err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/codecommit.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | "time" 7 | 8 | "github.com/aws/aws-sdk-go-v2/service/codecommit" 9 | codecommittypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types" 10 | ) 11 | 12 | var codeCommitClient *codecommit.Client 13 | var codeCommitClientLock sync.Mutex 14 | 15 | func CodeCommitClientExplicit(accessKeyID, accessKeySecret, region string) *codecommit.Client { 16 | return codecommit.NewFromConfig(*SessionExplicit(accessKeyID, accessKeySecret, region)) 17 | } 18 | 19 | func CodeCommitClient() *codecommit.Client { 20 | codeCommitClientLock.Lock() 21 | defer codeCommitClientLock.Unlock() 22 | if codeCommitClient == nil { 23 | codeCommitClient = codecommit.NewFromConfig(*Session()) 24 | } 25 | return codeCommitClient 26 | } 27 | 28 | func CodeCommitListRepos(ctx context.Context) ([]codecommittypes.RepositoryNameIdPair, error) { 29 | if doDebug { 30 | d := &Debug{start: time.Now(), name: "CodeCommitListRepos"} 31 | d.Start() 32 | defer d.End() 33 | } 34 | var token *string 35 | var repos []codecommittypes.RepositoryNameIdPair 36 | for { 37 | out, err := CodeCommitClient().ListRepositories(ctx, &codecommit.ListRepositoriesInput{ 38 | NextToken: token, 39 | }) 40 | if err != nil { 41 | Logger.Println("error:", err) 42 | return nil, err 43 | } 44 | repos = append(repos, out.Repositories...) 45 | if out.NextToken == nil { 46 | break 47 | } 48 | } 49 | return repos, nil 50 | } 51 | -------------------------------------------------------------------------------- /cmd/dynamodb/describe.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 11 | ddbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | func init() { 16 | lib.Commands["dynamodb-describe"] = dynamodbDescribe 17 | lib.Args["dynamodb-describe"] = dynamodbDescribeArgs{} 18 | } 19 | 20 | type dynamodbDescribeArgs struct { 21 | Table string `arg:"positional,required" help:"table name"` 22 | } 23 | 24 | func (dynamodbDescribeArgs) Description() string { 25 | return "\ndescribe dynamodb table\n" 26 | } 27 | 28 | func dynamodbDescribe() { 29 | var args dynamodbDescribeArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | out, err := lib.DynamoDBClient().DescribeTable(ctx, &dynamodb.DescribeTableInput{ 33 | TableName: aws.String(args.Table), 34 | }) 35 | if err != nil { 36 | lib.Logger.Fatal("error: ", err) 37 | } 38 | attrs := map[string]ddbtypes.ScalarAttributeType{} 39 | for _, attr := range out.Table.AttributeDefinitions { 40 | attrs[*attr.AttributeName] = attr.AttributeType 41 | } 42 | for _, key := range out.Table.KeySchema { 43 | vals := []string{ 44 | *key.AttributeName, 45 | string(attrs[*key.AttributeName]), 46 | string(key.KeyType), 47 | } 48 | fmt.Println(strings.ToLower(strings.Join(vals, ":"))) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cmd/iam/ensure_user_api.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/nathants/libaws/lib" 9 | ) 10 | 11 | func init() { 12 | lib.Commands["iam-ensure-user-api"] = iamEnsureUserApi 13 | lib.Args["iam-ensure-user-api"] = iamEnsureUserApiArgs{} 14 | } 15 | 16 | type iamEnsureUserApiArgs struct { 17 | Name string `arg:"positional,required"` 18 | Policy []string `arg:"--policy" help:"policy name, can specify multiple values"` 19 | Allow []string `arg:"--allow" help:"\"$service:$action $arn\", example: \"s3:* *\", can specify multiple values"` 20 | Preview bool `arg:"-p,--preview"` 21 | } 22 | 23 | func (iamEnsureUserApiArgs) Description() string { 24 | return "\nensure an iam user with api key\n" 25 | } 26 | 27 | func iamEnsureUserApi() { 28 | var args iamEnsureUserApiArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | out, err := lib.IamEnsureUserApi(ctx, args.Name, args.Preview) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | err = lib.IamEnsureUserPolicies(ctx, args.Name, args.Policy, args.Preview) 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | err = lib.IamEnsureUserAllows(ctx, args.Name, args.Allow, args.Preview) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | if out.AccessKeyId != nil { 44 | fmt.Println("access key id:", *out.AccessKeyId) 45 | fmt.Println("access key secret:", *out.SecretAccessKey) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cmd/api/ls_domains.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["api-ls-domains"] = apiLsDomains 15 | lib.Args["api-ls-domains"] = apiLsDomainsArgs{} 16 | } 17 | 18 | type apiLsDomainsArgs struct { 19 | } 20 | 21 | func (apiLsDomainsArgs) Description() string { 22 | return "\nlist api custom domains\n" 23 | } 24 | 25 | func apiLsDomains() { 26 | var args apiLsDomainsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | domains, err := lib.ApiListDomains(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal("error: ", err) 32 | } 33 | for _, domain := range domains { 34 | api := "" 35 | mappings, err := lib.ApiClient().GetApiMappings(ctx, &apigatewayv2.GetApiMappingsInput{ 36 | DomainName: domain.DomainName, 37 | MaxResults: aws.String(fmt.Sprint(500)), 38 | }) 39 | if err != nil || len(mappings.Items) == 500 { 40 | lib.Logger.Fatal("error: ", err) 41 | } 42 | for _, mapping := range mappings.Items { 43 | if *mapping.Stage == "$default" { 44 | out, err := lib.ApiClient().GetApi(ctx, &apigatewayv2.GetApiInput{ 45 | ApiId: mapping.ApiId, 46 | }) 47 | if err != nil { 48 | lib.Logger.Fatal("error: ", err) 49 | } 50 | api = "api=" + *out.Name 51 | } 52 | } 53 | fmt.Println(*domain.DomainName, api) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /cmd/lambda/set_var.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/lambda" 9 | lambdatypes "github.com/aws/aws-sdk-go-v2/service/lambda/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["lambda-set-var"] = lambdaSetVar 15 | lib.Args["lambda-set-var"] = lambdaSetVarArgs{} 16 | } 17 | 18 | type lambdaSetVarArgs struct { 19 | Name string `arg:"positional,required"` 20 | Val string `arg:"positional" help:"KEY=VALUE"` 21 | } 22 | 23 | func (lambdaSetVarArgs) Description() string { 24 | return "\nset lambda env var\n" 25 | } 26 | 27 | func lambdaSetVar() { 28 | var args lambdaSetVarArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | out, err := lib.LambdaClient().GetFunction(ctx, &lambda.GetFunctionInput{ 32 | FunctionName: aws.String(args.Name), 33 | }) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | k, v, err := lib.SplitOnce(args.Val, "=") 38 | if err != nil { 39 | lib.Logger.Fatal("error: ", err) 40 | } 41 | out.Configuration.Environment.Variables[k] = v 42 | _, err = lib.LambdaClient().UpdateFunctionConfiguration(ctx, &lambda.UpdateFunctionConfigurationInput{ 43 | FunctionName: aws.String(args.Name), 44 | Environment: &lambdatypes.Environment{ 45 | Variables: out.Configuration.Environment.Variables, 46 | }, 47 | }) 48 | if err != nil { 49 | lib.Logger.Fatal("error: ", err) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cmd/ses/send.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/aws/aws-sdk-go-v2/aws" 8 | "github.com/aws/aws-sdk-go-v2/service/ses" 9 | sestypes "github.com/aws/aws-sdk-go-v2/service/ses/types" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["ses-send"] = sesSend 15 | lib.Args["ses-send"] = sesSendArgs{} 16 | } 17 | 18 | type sesSendArgs struct { 19 | ConfigurationSet string `arg:"-c,--conf-set" help:"configuration set name"` 20 | From string `arg:"-f,--from"` 21 | To string `arg:"-t,--to"` 22 | Subject string `arg:"-s,--subject"` 23 | Body string `arg:"-b,--body"` 24 | } 25 | 26 | func (sesSendArgs) Description() string { 27 | return "\n \n" 28 | } 29 | 30 | func sesSend() { 31 | var args sesSendArgs 32 | arg.MustParse(&args) 33 | ctx := context.Background() 34 | _, err := lib.SesClient().SendEmail(ctx, &ses.SendEmailInput{ 35 | ConfigurationSetName: aws.String(args.ConfigurationSet), 36 | Destination: &sestypes.Destination{ 37 | ToAddresses: []string{ 38 | args.To, 39 | }, 40 | }, 41 | Message: &sestypes.Message{ 42 | Subject: &sestypes.Content{ 43 | Data: aws.String(args.Subject), 44 | }, 45 | Body: &sestypes.Body{ 46 | Text: &sestypes.Content{ 47 | Data: aws.String(args.Body), 48 | }, 49 | }, 50 | }, 51 | Source: aws.String(args.From), 52 | }) 53 | if err != nil { 54 | lib.Logger.Fatal("error: ", err) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cmd/s3/get_version.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "os" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/s3" 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | func init() { 16 | lib.Commands["s3-get-version"] = s3Getversion 17 | lib.Args["s3-get-version"] = s3GetVersionArgs{} 18 | } 19 | 20 | type s3GetVersionArgs struct { 21 | Path string `arg:"positional"` 22 | Version string `arg:"-v,--version,required"` 23 | } 24 | 25 | func (s3GetVersionArgs) Description() string { 26 | return "\nget an object version and write it to stdout\n" 27 | } 28 | 29 | func s3Getversion() { 30 | var args s3GetVersionArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | 34 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 35 | bucket, key, err := lib.SplitOnce(args.Path, "/") 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | 40 | s3Client, err := lib.S3ClientBucketRegion(bucket) 41 | if err != nil { 42 | lib.Logger.Fatal("error: ", err) 43 | } 44 | out, err := s3Client.GetObject(ctx, &s3.GetObjectInput{ 45 | Bucket: aws.String(bucket), 46 | Key: aws.String(key), 47 | VersionId: aws.String(args.Version), 48 | }) 49 | if err != nil { 50 | lib.Logger.Fatal("error: ", err) 51 | } 52 | defer func() { _ = out.Body.Close() }() 53 | 54 | _, err = io.Copy(os.Stdout, out.Body) 55 | if err != nil { 56 | lib.Logger.Fatal("error: ", err) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cmd/iam/ensure_managed_policy.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/nathants/libaws/lib" 10 | ) 11 | 12 | func init() { 13 | lib.Commands["iam-ensure-managed-policy"] = iamEnsureManagedPolicy 14 | lib.Args["iam-ensure-managed-policy"] = iamEnsureManagedPolicyArgs{} 15 | } 16 | 17 | type iamEnsureManagedPolicyArgs struct { 18 | Name string `arg:"positional,required"` 19 | PolicyDescription string `arg:"--description,required"` 20 | Document string `arg:"--document,required" help:"inline JSON policy document or path to file"` 21 | Preview bool `arg:"-p,--preview"` 22 | } 23 | 24 | func (iamEnsureManagedPolicyArgs) Description() string { 25 | return "\nensure a managed iam policy exists with the given document and description\n" 26 | } 27 | 28 | func iamEnsureManagedPolicy() { 29 | var args iamEnsureManagedPolicyArgs 30 | arg.MustParse(&args) 31 | ctx := context.Background() 32 | 33 | policyDoc := args.Document 34 | if args.Document == "-" { 35 | bytes, err := io.ReadAll(os.Stdin) 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | policyDoc = string(bytes) 40 | } else if lib.Exists(args.Document) { 41 | data, err := os.ReadFile(args.Document) 42 | if err != nil { 43 | lib.Logger.Fatal("error: ", err) 44 | } 45 | policyDoc = string(data) 46 | } 47 | 48 | _, err := lib.IamEnsureManagedPolicy(ctx, args.Name, args.PolicyDescription, policyDoc, args.Preview) 49 | if err != nil { 50 | lib.Logger.Fatal("error: ", err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cmd/ecr/ls_tags.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | "time" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/ecr" 12 | ecrtypes "github.com/aws/aws-sdk-go-v2/service/ecr/types" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["ecr-ls-tags"] = ecrLsTags 18 | lib.Args["ecr-ls-tags"] = ecrLsTagsArgs{} 19 | } 20 | 21 | type ecrLsTagsArgs struct { 22 | Image string `arg:"positional,required" help:"image name"` 23 | } 24 | 25 | func (ecrLsTagsArgs) Description() string { 26 | return "\nlist ecr tags for an image\n" 27 | } 28 | 29 | func ecrLsTags() { 30 | var args ecrLsTagsArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | var imageDetails []ecrtypes.ImageDetail 34 | var token *string 35 | for { 36 | out, err := lib.EcrClient().DescribeImages(ctx, &ecr.DescribeImagesInput{ 37 | RepositoryName: aws.String(args.Image), 38 | NextToken: token, 39 | }) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | imageDetails = append(imageDetails, out.ImageDetails...) 44 | if out.NextToken == nil { 45 | break 46 | } 47 | token = out.NextToken 48 | } 49 | sort.Slice(imageDetails, func(a, b int) bool { 50 | return imageDetails[a].ImagePushedAt.After(*imageDetails[b].ImagePushedAt) 51 | }) 52 | for _, image := range imageDetails { 53 | for _, tag := range image.ImageTags { 54 | fmt.Println(args.Image+":"+tag, *image.ImageDigest, image.ImagePushedAt.Format(time.RFC3339)) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cmd/ec2/ami_latest.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "sort" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/ec2" 12 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["ec2-ami-latest"] = ec2LatestAmi 18 | lib.Args["ec2-ami-latest"] = ec2LatestAmiArgs{} 19 | } 20 | 21 | type ec2LatestAmiArgs struct { 22 | Name string `arg:"positional,required"` 23 | } 24 | 25 | func (ec2LatestAmiArgs) Description() string { 26 | return "\nlatest ami\n" 27 | } 28 | 29 | func ec2LatestAmi() { 30 | var args ec2LatestAmiArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | account, err := lib.StsAccount(ctx) 34 | if err != nil { 35 | lib.Logger.Fatal("error: ", err) 36 | } 37 | images, err := lib.EC2Client().DescribeImages(ctx, &ec2.DescribeImagesInput{ 38 | Owners: []string{account}, 39 | Filters: []ec2types.Filter{ 40 | { 41 | Name: aws.String("description"), 42 | Values: []string{ 43 | args.Name, 44 | }, 45 | }, 46 | { 47 | Name: aws.String("state"), 48 | Values: []string{ 49 | "available", 50 | }, 51 | }, 52 | }, 53 | }) 54 | if err != nil { 55 | lib.Logger.Fatal("error: ", err) 56 | } 57 | if len(images.Images) == 0 { 58 | os.Exit(1) 59 | } 60 | sort.Slice(images.Images, func(i, j int) bool { return *images.Images[i].CreationDate > *images.Images[j].CreationDate }) 61 | image := images.Images[0] 62 | fmt.Println(*image.ImageId) 63 | } 64 | -------------------------------------------------------------------------------- /cmd/dynamodb/item_rm.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 10 | ddbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["dynamodb-item-rm"] = dynamodbItemRm 16 | lib.Args["dynamodb-item-rm"] = dynamodbItemRmArgs{} 17 | } 18 | 19 | type dynamodbItemRmArgs struct { 20 | Table string `arg:"positional,required"` 21 | Keys []string `arg:"positional,required"` 22 | } 23 | 24 | func (dynamodbItemRmArgs) Description() string { 25 | return ` 26 | 27 | delete item 28 | describe keys like: $name:s|n:$value 29 | 30 | >> libaws dynamodb-item-rm test-table user:s:john 31 | 32 | ` 33 | } 34 | 35 | func dynamodbItemRm() { 36 | var args dynamodbItemRmArgs 37 | arg.MustParse(&args) 38 | ctx := context.Background() 39 | item := map[string]ddbtypes.AttributeValue{} 40 | for _, key := range args.Keys { 41 | name, kind, val, err := lib.SplitTwice(key, ":") 42 | if err != nil { 43 | lib.Logger.Fatal("error: ", err) 44 | } 45 | switch strings.ToUpper(kind) { 46 | case "S": 47 | item[name] = &ddbtypes.AttributeValueMemberS{Value: val} 48 | case "N": 49 | item[name] = &ddbtypes.AttributeValueMemberN{Value: val} 50 | default: 51 | panic(kind) 52 | } 53 | } 54 | _, err := lib.DynamoDBClient().DeleteItem(ctx, &dynamodb.DeleteItemInput{ 55 | TableName: aws.String(args.Table), 56 | Key: item, 57 | }) 58 | if err != nil { 59 | lib.Logger.Fatal("error: ", err) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /cmd/ec2/ls_snapshots.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/service/ec2" 10 | ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["ec2-ls-snapshots"] = ec2LsSnapshots 16 | lib.Args["ec2-ls-snapshots"] = ec2LsSnapshotsArgs{} 17 | } 18 | 19 | type ec2LsSnapshotsArgs struct { 20 | } 21 | 22 | func (ec2LsSnapshotsArgs) Description() string { 23 | return "\nlist snapshots\n" 24 | } 25 | 26 | func ec2LsSnapshots() { 27 | var args ec2LsSnapshotsArgs 28 | arg.MustParse(&args) 29 | ctx := context.Background() 30 | account, err := lib.StsAccount(ctx) 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | var nextToken *string 35 | var snapshots []ec2types.Snapshot 36 | for { 37 | out, err := lib.EC2Client().DescribeSnapshots(ctx, &ec2.DescribeSnapshotsInput{ 38 | OwnerIds: []string{account}, 39 | NextToken: nextToken, 40 | }) 41 | if err != nil { 42 | lib.Logger.Fatal("error: ", err) 43 | } 44 | snapshots = append(snapshots, out.Snapshots...) 45 | if out.NextToken == nil { 46 | break 47 | } 48 | nextToken = out.NextToken 49 | } 50 | for _, snapshot := range snapshots { 51 | amiID := "-" 52 | if snapshot.Description != nil { 53 | for _, part := range strings.Split(*snapshot.Description, " ") { 54 | if strings.HasPrefix(part, "ami-") { 55 | amiID = part 56 | break 57 | } 58 | } 59 | } 60 | fmt.Println(*snapshot.SnapshotId, amiID, lib.EC2Tags(snapshot.Tags)) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /cmd/s3/ensure.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/alexflint/go-arg" 7 | "github.com/nathants/libaws/lib" 8 | ) 9 | 10 | func init() { 11 | lib.Commands["s3-ensure"] = s3Ensure 12 | lib.Args["s3-ensure"] = s3EnsureArgs{} 13 | } 14 | 15 | type s3EnsureArgs struct { 16 | Name string `arg:"positional,required"` 17 | Attr []string `arg:"positional"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (s3EnsureArgs) Description() string { 22 | return ` 23 | ensure a s3 bucket 24 | 25 | example: 26 | - libaws s3-ensure test-bucket acl=public versioning=true 27 | 28 | optional attrs: 29 | - acl=VALUE (values = public | private, default = private) 30 | - versioning=VALUE (values = true | false, default = false) 31 | - metrics=VALUE (values = true | false, default = false) 32 | - cors=VALUE (values = true | false, default = false) 33 | - ttldays=VALUE (values = 0 | n, default = 0) 34 | - allow_put=VALUE (values = $principal.amazonaws.com) 35 | 36 | setting 'cors=true' uses '*' for allowed origins. to specify one or more explicit origins, do this instead: 37 | - corsorigin=http://localhost:8080 38 | - corsorigin=https://example.com 39 | 40 | note: bucket acl can only be set at bucket creation time 41 | 42 | ` 43 | } 44 | 45 | func s3Ensure() { 46 | var args s3EnsureArgs 47 | arg.MustParse(&args) 48 | ctx := context.Background() 49 | input, err := lib.S3EnsureInput("", args.Name, args.Attr) 50 | if err != nil { 51 | lib.Logger.Fatal("error: ", err) 52 | } 53 | err = lib.S3Ensure(ctx, input, args.Preview) 54 | if err != nil { 55 | lib.Logger.Fatal("error: ", err) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cmd/s3/head.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/s3" 12 | s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["s3-head"] = s3Head 18 | lib.Args["s3-head"] = s3HeadArgs{} 19 | } 20 | 21 | type s3HeadArgs struct { 22 | Path string `arg:"positional"` 23 | } 24 | 25 | func (s3HeadArgs) Description() string { 26 | return "\nhead an object\n" 27 | } 28 | 29 | func s3Head() { 30 | var args s3HeadArgs 31 | arg.MustParse(&args) 32 | ctx := context.Background() 33 | 34 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 35 | bucket, key, err := lib.SplitOnce(args.Path, "/") 36 | if err != nil { 37 | lib.Logger.Fatal("error: ", err) 38 | } 39 | 40 | s3Client, err := lib.S3ClientBucketRegion(bucket) 41 | if err != nil { 42 | lib.Logger.Fatal("error: ", err) 43 | } 44 | out, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{ 45 | Bucket: aws.String(bucket), 46 | Key: aws.String(key), 47 | ChecksumMode: s3types.ChecksumModeEnabled, 48 | }) 49 | if err != nil { 50 | lib.Logger.Fatal("error: ", err) 51 | } 52 | 53 | data, err := json.Marshal(out) 54 | if err != nil { 55 | lib.Logger.Fatal("error: ", err) 56 | } 57 | var outMap map[string]any 58 | err = json.Unmarshal(data, &outMap) 59 | if err != nil { 60 | lib.Logger.Fatal("error: ", err) 61 | } 62 | 63 | val := map[string]any{} 64 | for k, v := range outMap { 65 | if v != nil { 66 | val[k] = v 67 | } 68 | } 69 | fmt.Println(lib.Pformat(val)) 70 | } 71 | -------------------------------------------------------------------------------- /cmd/s3/put.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "crypto/sha256" 7 | "encoding/base64" 8 | "io" 9 | "os" 10 | "strings" 11 | 12 | "github.com/alexflint/go-arg" 13 | "github.com/aws/aws-sdk-go-v2/aws" 14 | "github.com/aws/aws-sdk-go-v2/service/s3" 15 | s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" 16 | "github.com/nathants/libaws/lib" 17 | ) 18 | 19 | func init() { 20 | lib.Commands["s3-put"] = s3Put 21 | lib.Args["s3-put"] = s3PutArgs{} 22 | } 23 | 24 | type s3PutArgs struct { 25 | Path string `arg:"positional"` 26 | Sha256 bool `arg:"-s,--sha256" help:"add sha256 checksum"` 27 | } 28 | 29 | func (s3PutArgs) Description() string { 30 | return "\nput an object from stdin\n" 31 | } 32 | 33 | func s3Put() { 34 | var args s3PutArgs 35 | arg.MustParse(&args) 36 | ctx := context.Background() 37 | 38 | args.Path = strings.ReplaceAll(args.Path, "s3://", "") 39 | bucket, key, err := lib.SplitOnce(args.Path, "/") 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | 44 | s3Client, err := lib.S3ClientBucketRegion(bucket) 45 | if err != nil { 46 | lib.Logger.Fatal("error: ", err) 47 | } 48 | 49 | val, err := io.ReadAll(os.Stdin) 50 | if err != nil { 51 | lib.Logger.Fatal("error: ", err) 52 | } 53 | 54 | input := &s3.PutObjectInput{ 55 | Bucket: aws.String(bucket), 56 | Key: aws.String(key), 57 | Body: bytes.NewReader(val), 58 | } 59 | 60 | if args.Sha256 { 61 | hash := sha256.Sum256(val) 62 | input.ChecksumAlgorithm = s3types.ChecksumAlgorithmSha256 63 | input.ChecksumSHA256 = aws.String(base64.StdEncoding.EncodeToString(hash[:])) 64 | } 65 | _, err = s3Client.PutObject(ctx, input) 66 | if err != nil { 67 | lib.Logger.Fatal("error: ", err) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cmd/dynamodb/item_scan.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue" 11 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 12 | ddbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" 13 | "github.com/nathants/libaws/lib" 14 | ) 15 | 16 | func init() { 17 | lib.Commands["dynamodb-item-scan"] = dynamodbItemScan 18 | lib.Args["dynamodb-item-scan"] = dynamodbItemScanArgs{} 19 | } 20 | 21 | type dynamodbItemScanArgs struct { 22 | Table string `arg:"positional"` 23 | Limit int `arg:"-l,--limit" default:"0"` 24 | } 25 | 26 | func (dynamodbItemScanArgs) Description() string { 27 | return "\nscan dynamodb table\n" 28 | } 29 | 30 | func dynamodbItemScan() { 31 | var args dynamodbItemScanArgs 32 | arg.MustParse(&args) 33 | ctx := context.Background() 34 | var start map[string]ddbtypes.AttributeValue 35 | count := 0 36 | for { 37 | out, err := lib.DynamoDBClient().Scan(ctx, &dynamodb.ScanInput{ 38 | TableName: aws.String(args.Table), 39 | ExclusiveStartKey: start, 40 | Limit: aws.Int32(1000), 41 | }) 42 | if err != nil { 43 | panic(err) 44 | } 45 | for _, item := range out.Items { 46 | if args.Limit != 0 && args.Limit < count { 47 | break 48 | } 49 | count++ 50 | val := map[string]any{} 51 | err = attributevalue.UnmarshalMap(item, &val) 52 | if err != nil { 53 | panic(err) 54 | } 55 | bytes, err := json.Marshal(val) 56 | if err != nil { 57 | panic(err) 58 | } 59 | fmt.Println(string(bytes)) 60 | } 61 | if out.LastEvaluatedKey == nil { 62 | break 63 | } 64 | start = out.LastEvaluatedKey 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /cmd/route53/ensure_record.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "github.com/alexflint/go-arg" 6 | "github.com/nathants/libaws/lib" 7 | ) 8 | 9 | func init() { 10 | lib.Commands["route53-ensure-record"] = route53EnsureRecord 11 | lib.Args["route53-ensure-record"] = route53EnsureRecordArgs{} 12 | } 13 | 14 | type route53EnsureRecordArgs struct { 15 | ZoneName string `arg:"positional,required"` 16 | RecordName string `arg:"positional,required"` 17 | Attr []string `arg:"positional,required"` 18 | Preview bool `arg:"-p,--preview"` 19 | } 20 | 21 | func (route53EnsureRecordArgs) Description() string { 22 | return ` 23 | ensure a route53 record 24 | 25 | examples: 26 | - libaws route53-ensure-record example.com example.com Type=A TTL=60 Value=1.1.1.1 Value=2.2.2.2 27 | - libaws route53-ensure-record example.com cname.example.com Type=CNAME TTL=60 Value=about.us-west-2.domain.example.com 28 | - libaws route53-ensure-record example.com alias.example.com Type=Alias Value=d-XXX.execute-api.us-west-2.amazonaws.com HostedZoneId=XXX 29 | 30 | required attrs for standard dns records: 31 | - TTL=VALUE 32 | - Type=VALUE 33 | - Value=VALUE 34 | 35 | required attrs for aws alias records: 36 | - Type=Alias 37 | - Value=VALUE 38 | - HostedZoneId=VALUE 39 | 40 | for complex values, quote them like this: 41 | - 'Value=complex value' 42 | 43 | ` 44 | } 45 | 46 | func route53EnsureRecord() { 47 | var args route53EnsureRecordArgs 48 | arg.MustParse(&args) 49 | ctx := context.Background() 50 | input, err := lib.Route53EnsureRecordInput(args.ZoneName, args.RecordName, args.Attr) 51 | if err != nil { 52 | lib.Logger.Fatal("error: ", err) 53 | } 54 | err = lib.Route53EnsureRecord(ctx, input, args.Preview) 55 | if err != nil { 56 | lib.Logger.Fatal("error: ", err) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/simple/go/includes/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import uuid 3 | import pytest 4 | import sys 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ['uid'] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | expected = { 26 | "infraset": { 27 | f"test-infraset-{uid}": { 28 | "lambda": { 29 | f"test-lambda-{uid}": { 30 | "attr": ["timeout=60"], 31 | "policy": ["AWSLambdaBasicExecutionRole"], 32 | } 33 | } 34 | } 35 | } 36 | } 37 | assert infra == expected, infra 38 | assert '"data123"' == run(f"libaws lambda-invoke test-lambda-{uid}") 39 | run("libaws infra-rm infra.yaml --preview") 40 | run("libaws infra-rm infra.yaml") 41 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 42 | assert sorted(infra["infraset"].keys()) == ["none"], infra 43 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 44 | 45 | 46 | if __name__ == "__main__": 47 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 48 | -------------------------------------------------------------------------------- /examples/simple/python/includes/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import uuid 3 | import pytest 4 | import sys 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ['uid'] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | expected = { 26 | "infraset": { 27 | f"test-infraset-{uid}": { 28 | "lambda": { 29 | f"test-lambda-{uid}": { 30 | "attr": ["timeout=60"], 31 | "policy": ["AWSLambdaBasicExecutionRole"], 32 | } 33 | } 34 | } 35 | } 36 | } 37 | assert infra == expected, infra 38 | assert '"data123"' == run(f"libaws lambda-invoke test-lambda-{uid}") 39 | run("libaws infra-rm infra.yaml --preview") 40 | run("libaws infra-rm infra.yaml") 41 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 42 | assert sorted(infra["infraset"].keys()) == ["none"], infra 43 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 44 | 45 | 46 | if __name__ == "__main__": 47 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 48 | -------------------------------------------------------------------------------- /cmd/dynamodb/item_put.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/alexflint/go-arg" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 10 | ddbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["dynamodb-item-put"] = dynamodbItemPut 16 | lib.Args["dynamodb-item-put"] = dynamodbItemPutArgs{} 17 | } 18 | 19 | type dynamodbItemPutArgs struct { 20 | Table string `arg:"positional,required"` 21 | Attr []string `arg:"positional,required"` 22 | } 23 | 24 | func (dynamodbItemPutArgs) Description() string { 25 | return ` 26 | 27 | put item 28 | 29 | describe attributes like: $name:s|n|b:$value 30 | 31 | >> libaws dynamodb-item-put test-table user:s:jane dob:n:1984 32 | 33 | ` 34 | } 35 | 36 | func dynamodbItemPut() { 37 | var args dynamodbItemPutArgs 38 | arg.MustParse(&args) 39 | ctx := context.Background() 40 | item := map[string]ddbtypes.AttributeValue{} 41 | 42 | for _, key := range args.Attr { 43 | name, kind, val, err := lib.SplitTwice(key, ":") 44 | if err != nil { 45 | lib.Logger.Fatal("error: ", err) 46 | } 47 | switch strings.ToUpper(kind) { 48 | case "S": 49 | item[name] = &ddbtypes.AttributeValueMemberS{ 50 | Value: val, 51 | } 52 | case "B": 53 | item[name] = &ddbtypes.AttributeValueMemberBOOL{ 54 | Value: val == "true", 55 | } 56 | case "N": 57 | item[name] = &ddbtypes.AttributeValueMemberN{ 58 | Value: val, 59 | } 60 | default: 61 | panic(kind) 62 | } 63 | } 64 | 65 | _, err := lib.DynamoDBClient().PutItem(ctx, &dynamodb.PutItemInput{ 66 | TableName: aws.String(args.Table), 67 | Item: item, 68 | }) 69 | 70 | if err != nil { 71 | lib.Logger.Fatal("error: ", err) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /cmd/route53/ls.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | "strings" 8 | 9 | "github.com/alexflint/go-arg" 10 | "github.com/nathants/libaws/lib" 11 | ) 12 | 13 | func init() { 14 | lib.Commands["route53-ls"] = route53Ls 15 | lib.Args["route53-ls"] = route53LsArgs{} 16 | } 17 | 18 | type route53LsArgs struct { 19 | } 20 | 21 | func (route53LsArgs) Description() string { 22 | return "\nlist route53 entries\n" 23 | } 24 | 25 | func route53Ls() { 26 | var args route53LsArgs 27 | arg.MustParse(&args) 28 | ctx := context.Background() 29 | zones, err := lib.Route53ListZones(ctx) 30 | if err != nil { 31 | lib.Logger.Fatal(err) 32 | } 33 | var res []string 34 | for _, zone := range zones { 35 | records, err := lib.Route53ListRecords(ctx, *zone.Id) 36 | if err != nil { 37 | lib.Logger.Fatal(err) 38 | } 39 | for _, record := range records { 40 | if record.AliasTarget != nil { 41 | res = append(res, strings.Join([]string{strings.TrimRight(*zone.Name, "."), strings.TrimRight(*record.Name, "."), "Type=Alias", "Value=" + *record.AliasTarget.DNSName, "HostedZoneId=" + *record.AliasTarget.HostedZoneId}, " ")) 42 | } else { 43 | vals := []string{} 44 | for _, val := range record.ResourceRecords { 45 | if strings.Contains(*val.Value, " ") || strings.Contains(*val.Value, `"`) { 46 | vals = append(vals, "'Value="+*val.Value+"'") 47 | } else { 48 | vals = append(vals, "Value="+*val.Value) 49 | } 50 | } 51 | res = append(res, strings.Join([]string{ 52 | strings.TrimRight(*zone.Name, "."), 53 | strings.TrimRight(*record.Name, "."), 54 | "Type=" + string(record.Type), 55 | "TTL=" + fmt.Sprint(*record.TTL), 56 | strings.Join(vals, " "), 57 | }, " ")) 58 | } 59 | } 60 | } 61 | sort.Strings(res) 62 | for _, r := range res { 63 | fmt.Println(r) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cmd/api/url_domain.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["api-url-domain"] = apiUrlDomain 16 | lib.Args["api-url-domain"] = apiUrlDomainArgs{} 17 | } 18 | 19 | type apiUrlDomainArgs struct { 20 | Name string `arg:"positional,required"` 21 | } 22 | 23 | func (apiUrlDomainArgs) Description() string { 24 | return "\nget api custom domain url\n" 25 | } 26 | 27 | func apiUrlDomain() { 28 | var args apiUrlDomainArgs 29 | arg.MustParse(&args) 30 | ctx := context.Background() 31 | domain, err := lib.ApiListDomains(ctx) 32 | if err != nil { 33 | lib.Logger.Fatal("error: ", err) 34 | } 35 | found := false 36 | for _, domain := range domain { 37 | mappings, err := lib.ApiClient().GetApiMappings(ctx, &apigatewayv2.GetApiMappingsInput{ 38 | DomainName: domain.DomainName, 39 | MaxResults: aws.String(fmt.Sprint(500)), 40 | }) 41 | if err != nil || len(mappings.Items) == 500 { 42 | lib.Logger.Fatal("error: ", err) 43 | } 44 | for _, mapping := range mappings.Items { 45 | if *mapping.Stage == "$default" { 46 | api, err := lib.ApiClient().GetApi(ctx, &apigatewayv2.GetApiInput{ 47 | ApiId: mapping.ApiId, 48 | }) 49 | if err != nil { 50 | lib.Logger.Fatal("error: ", err) 51 | } 52 | if args.Name == *api.Name || args.Name+lib.LambdaWebsocketSuffix == *api.Name { 53 | found = true 54 | if len(domain.DomainNameConfigurations) != 1 { 55 | panic(lib.PformatAlways(domain)) 56 | } 57 | fmt.Println(*api.Name, *domain.DomainName, *domain.DomainNameConfigurations[0].ApiGatewayDomainName) 58 | } 59 | } 60 | } 61 | } 62 | if !found { 63 | os.Exit(1) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cmd/creds/set.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/user" 7 | "path" 8 | "strings" 9 | 10 | "github.com/alexflint/go-arg" 11 | "github.com/nathants/libaws/lib" 12 | ) 13 | 14 | func init() { 15 | lib.Commands["creds-set"] = credsSet 16 | lib.Args["creds-set"] = credsSetArgs{} 17 | } 18 | 19 | type credsSetArgs struct { 20 | Name string `arg:"positional,required"` 21 | } 22 | 23 | func (credsSetArgs) Description() string { 24 | return `switch between aws creds` 25 | } 26 | 27 | func credsSet() { 28 | var args credsSetArgs 29 | arg.MustParse(&args) 30 | usr, err := user.Current() 31 | if err != nil { 32 | lib.Logger.Fatal("error: ", err) 33 | } 34 | home := usr.HomeDir 35 | dir := os.Getenv("LIBAWS_CREDS_DIR") 36 | if dir == "" { 37 | dir = "secure/aws_creds" 38 | } 39 | root := path.Join(home, dir) 40 | if err != nil { 41 | lib.Logger.Fatal("error: ", err) 42 | } 43 | entries, err := os.ReadDir(root) 44 | if err != nil { 45 | lib.Logger.Fatal("error: ", err) 46 | } 47 | for _, entry := range entries { 48 | if !entry.Type().IsRegular() { 49 | continue 50 | } 51 | if !strings.HasSuffix(entry.Name(), ".creds") { 52 | continue 53 | } 54 | name := strings.Split(entry.Name(), ".")[0] 55 | if name == args.Name { 56 | err = os.MkdirAll(path.Join(home, ".aws"), 0700) 57 | if err != nil { 58 | lib.Logger.Fatal("error: ", err) 59 | } 60 | _ = os.Remove(path.Join(home, ".aws", "credentials")) 61 | err := os.Symlink(path.Join(root, name+".creds"), path.Join(home, ".aws", "credentials")) 62 | if err != nil { 63 | lib.Logger.Fatal("error: ", err) 64 | } 65 | _ = os.Remove(path.Join(home, ".aws", "config")) 66 | err = os.Symlink(path.Join(root, name+".config"), path.Join(home, ".aws", "config")) 67 | if err != nil { 68 | lib.Logger.Fatal("error: ", err) 69 | } 70 | os.Exit(0) 71 | } 72 | 73 | } 74 | fmt.Println("no creds for name:", args.Name) 75 | os.Exit(1) 76 | } 77 | -------------------------------------------------------------------------------- /examples/simple/go/websocket/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import uuid 3 | import pytest 4 | import sys 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ['uid'] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | infra["infraset"][f"test-infraset-{uid}"]["lambda"][f"test-lambda-{uid}"]['trigger'][0].pop("attr") 26 | expected = { 27 | "infraset": { 28 | f"test-infraset-{uid}": { 29 | "lambda": { 30 | f"test-lambda-{uid}": { 31 | "attr": ["timeout=60"], 32 | "policy": ["AWSLambdaBasicExecutionRole"], 33 | "trigger": [{"type": "websocket"}], 34 | } 35 | } 36 | } 37 | } 38 | } 39 | assert infra == expected, infra 40 | run(f"libaws infra-url-websocket infra.yaml test-lambda-{uid}") 41 | run("libaws infra-rm infra.yaml --preview") 42 | run("libaws infra-rm infra.yaml") 43 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 44 | assert sorted(infra["infraset"].keys()) == ["none"], infra 45 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 46 | 47 | 48 | if __name__ == "__main__": 49 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 50 | -------------------------------------------------------------------------------- /examples/simple/python/dependencies/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import pytest 3 | import sys 4 | import uuid 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ["uid"] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | expected = { 26 | "infraset": { 27 | f"test-infraset-{uid}": { 28 | "lambda": { 29 | f"test-lambda-{uid}": { 30 | "attr": ["timeout=60"], 31 | "policy": ["AWSLambdaBasicExecutionRole"], 32 | "env": [f"uid={uid}"], 33 | } 34 | } 35 | } 36 | } 37 | } 38 | assert infra == expected, infra 39 | run(f"libaws lambda-invoke test-lambda-{uid}") 40 | assert uid == run(f"libaws logs-tail /aws/lambda/test-lambda-{uid} --from-hours 1 --exit-after {uid} | tail -n1").split()[-1] 41 | run("libaws infra-rm infra.yaml --preview") 42 | run("libaws infra-rm infra.yaml") 43 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 44 | assert sorted(infra["infraset"].keys()) == ["none"], infra 45 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 46 | 47 | 48 | if __name__ == "__main__": 49 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 50 | -------------------------------------------------------------------------------- /examples/simple/python/websocket/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import uuid 3 | import pytest 4 | import sys 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ['uid'] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | infra["infraset"][f"test-infraset-{uid}"]["lambda"][f"test-lambda-{uid}"]['trigger'][0].pop("attr") 26 | expected = { 27 | "infraset": { 28 | f"test-infraset-{uid}": { 29 | "lambda": { 30 | f"test-lambda-{uid}": { 31 | "attr": ["timeout=60"], 32 | "policy": ["AWSLambdaBasicExecutionRole"], 33 | "trigger": [{"type": "websocket"}], 34 | } 35 | } 36 | } 37 | } 38 | } 39 | assert infra == expected, infra 40 | run(f"libaws infra-url-websocket infra.yaml test-lambda-{uid}") 41 | run("libaws infra-rm infra.yaml --preview") 42 | run("libaws infra-rm infra.yaml") 43 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 44 | assert sorted(infra["infraset"].keys()) == ["none"], infra 45 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 46 | 47 | 48 | if __name__ == "__main__": 49 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 50 | -------------------------------------------------------------------------------- /examples/simple/go/dynamodb/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/aws/aws-lambda-go/events" 9 | "github.com/aws/aws-lambda-go/lambda" 10 | "github.com/aws/aws-sdk-go-v2/aws" 11 | "github.com/aws/aws-sdk-go-v2/service/dynamodb" 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | type RecordKey struct { 16 | UserID string `json:"userid" dynamodbav:"userid"` 17 | Version int `json:"version" dynamodbav:"version"` 18 | } 19 | 20 | type RecordData struct { 21 | Data string `json:"data" dynamodbav:"data"` 22 | } 23 | 24 | type Record struct { 25 | RecordKey 26 | RecordData 27 | } 28 | 29 | var uid = os.Getenv("uid") 30 | 31 | func handleRequest(ctx context.Context, event events.DynamoDBEvent) (events.APIGatewayProxyResponse, error) { 32 | for _, record := range event.Records { 33 | item, err := lib.FromDynamoDBEventAVMap(record.Change.Keys) 34 | if err != nil { 35 | lib.Logger.Println("error:", err) 36 | return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, nil 37 | } 38 | out, err := lib.DynamoDBClient().GetItem(ctx, &dynamodb.GetItemInput{ 39 | TableName: aws.String("test-table-" + uid), 40 | Key: item, 41 | }) 42 | if err != nil { 43 | lib.Logger.Println("error:", err) 44 | return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, nil 45 | } 46 | if out.Item == nil { 47 | lib.Logger.Println("error:", err) 48 | return events.APIGatewayProxyResponse{StatusCode: 404}, nil 49 | } 50 | _, err = lib.DynamoDBClient().PutItem(ctx, &dynamodb.PutItemInput{ 51 | TableName: aws.String("test-other-table-" + uid), 52 | Item: out.Item, 53 | }) 54 | if err != nil { 55 | lib.Logger.Println("error:", err) 56 | return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, nil 57 | } 58 | fmt.Printf("put: %#v\n", out.Item) 59 | } 60 | return events.APIGatewayProxyResponse{StatusCode: 200}, nil 61 | } 62 | 63 | func main() { 64 | lambda.Start(handleRequest) 65 | } 66 | -------------------------------------------------------------------------------- /cmd/logs/near.go: -------------------------------------------------------------------------------- 1 | package libaws 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/alexflint/go-arg" 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" 11 | 12 | "github.com/nathants/libaws/lib" 13 | ) 14 | 15 | func init() { 16 | lib.Commands["logs-near"] = logsNear 17 | lib.Args["logs-near"] = logsNearArgs{} 18 | } 19 | 20 | type logsNearArgs struct { 21 | Name string `arg:"positional,required" help:"log group name"` 22 | Timestamp int64 `arg:"positional,required" help:"utc millis timestamp at which to show logs"` 23 | Context int64 `arg:"-c,--context" help:"millis context around timestamp" default:"30000"` 24 | Max int `arg:"-m,--max" default:"64" help:"max results"` 25 | } 26 | 27 | func (logsNearArgs) Description() string { 28 | return "\nshow all logs within CONTEXT millis of TIMESTAMP\n" 29 | } 30 | 31 | func logsNear() { 32 | var args logsNearArgs 33 | arg.MustParse(&args) 34 | ctx := context.Background() 35 | count := 0 36 | var token *string 37 | for { 38 | out, err := lib.LogsClient().FilterLogEvents(ctx, &cloudwatchlogs.FilterLogEventsInput{ 39 | EndTime: aws.Int64(args.Timestamp + args.Context), 40 | StartTime: aws.Int64(args.Timestamp - args.Context), 41 | FilterPattern: aws.String(""), 42 | LogGroupName: aws.String(args.Name), 43 | NextToken: token, 44 | }) 45 | if err != nil { 46 | lib.Logger.Fatal("error: ", err) 47 | } 48 | for _, e := range out.Events { 49 | val := map[string]any{} 50 | err := json.Unmarshal([]byte(*e.Message), &val) 51 | if err != nil { 52 | fmt.Printf("timestamp=%d %s", *e.Timestamp, *e.Message) 53 | } else { 54 | val["timestamp"] = *e.Timestamp 55 | bytes, err := json.Marshal(val) 56 | if err != nil { 57 | lib.Logger.Fatal("error: ", err) 58 | } 59 | fmt.Println(string(bytes)) 60 | } 61 | count++ 62 | if count >= args.Max { 63 | return 64 | } 65 | } 66 | if out.NextToken == nil { 67 | break 68 | } 69 | token = out.NextToken 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /examples/simple/go/schedule/test.py: -------------------------------------------------------------------------------- 1 | # type: ignore 2 | import pytest 3 | import sys 4 | import uuid 5 | import shell 6 | import yaml 7 | import os 8 | 9 | run = lambda *a, **kw: shell.run(*a, stream=True, **kw) 10 | 11 | 12 | def test(): 13 | assert os.environ["LIBAWS_TEST_ACCOUNT"] == run("libaws aws-account") 14 | os.environ['uid'] = uid = str(uuid.uuid4())[-12:] 15 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 16 | assert sorted(infra["infraset"].keys()) == ["none"], infra 17 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 18 | run("libaws infra-ensure infra.yaml --preview") 19 | run("libaws infra-ensure infra.yaml") 20 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 21 | infra.pop("region") 22 | infra.pop("account") 23 | infra["infraset"].pop("none") 24 | infra["infraset"][f"test-infraset-{uid}"].pop("keypair", None) 25 | expected = { 26 | "infraset": { 27 | f"test-infraset-{uid}": { 28 | "lambda": { 29 | f"test-lambda-{uid}": { 30 | "attr": ["timeout=60"], 31 | "policy": ["AWSLambdaBasicExecutionRole"], 32 | "trigger": [ 33 | {"attr": ["rate(1 " "minute)"], 34 | "type": "schedule"} 35 | ], 36 | "env": [f"uid={uid}"], 37 | } 38 | } 39 | } 40 | } 41 | } 42 | assert infra == expected, infra 43 | assert uid == run(f"libaws logs-tail /aws/lambda/test-lambda-{uid} --from-hours 1 --exit-after {uid} | tail -n1").split()[-1] 44 | run("libaws infra-rm infra.yaml --preview") 45 | run("libaws infra-rm infra.yaml") 46 | infra = yaml.safe_load(run("libaws infra-ls --env-values")) 47 | assert sorted(infra["infraset"].keys()) == ["none"], infra 48 | assert sorted(infra["infraset"]["none"].keys()) == ["user"], infra 49 | 50 | 51 | if __name__ == "__main__": 52 | sys.exit(pytest.main([__file__, "-svvx", "--tb", "native"])) 53 | --------------------------------------------------------------------------------