initial revision

This commit is contained in:
Jason Swank 2024-12-12 20:22:11 -05:00
commit 3fbd407254
16 changed files with 1190 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin/*

79
Taskfile.yml Normal file
View File

@ -0,0 +1,79 @@
version: '3'
vars:
BINARIES:
sh: ls cmd/
env:
GOOS: linux
GOARCH: amd64
tasks:
default:
cmds:
- task: build-all
build-all:
desc: build all binaries
cmds:
- for: { var: BINARIES }
task: native-compile-{{.ITEM}}
vars:
BINARY: '{{.ITEM}}'
install-all:
desc: install all binaries
cmds:
- for: { var: BINARIES }
task: install
vars:
BINARY: '{{.ITEM}}'
build-*:
desc: build a binary
cmd: |
mkdir -p bin
echo "Building {{.BINARY}} for {{.GOOS}}/{{.GOARCH}}"
GOOS={{.GOOS}} GOARCH={{.GOARCH}} go build -o bin/{{.BINARY}}_{{.GOOS}}_{{.GOARCH}} ./cmd/{{.BINARY}}
vars:
BINARY: '{{index .MATCH 0}}'
native-compile-*:
desc: build a binary
cmd: |
mkdir -p bin
go build -o bin/{{.BINARY}} ./cmd/{{.BINARY}}
vars:
BINARY: '{{index .MATCH 0}}'
cross-compile-*:
desc: cross compile a binary
cmds:
- task: build-{{.BINARY}}
vars:
GOOS: linux
GOARCH: amd64
- task: build-{{.BINARY}}
vars:
GOOS: darwin
GOARCH: arm64
- task: build-{{.BINARY}}
vars:
GOOS: linux
GOARCH: arm64
vars:
BINARY: '{{index .MATCH 0}}'
update:
desc: update dependencies
cmds:
- go get -u ./...
- go mod tidy
install:
desc: install a binary
cmd: |
sudo install -m 0755 bin/{{.BINARY}} $DESTDIR/{{.BINARY}}
env:
DESTDIR: /usr/local/sbin

32
cmd/aws-mgmt/root.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"log/slog"
"os"
cli "github.com/urfave/cli/v2"
"aws-mgmt/internal/cmd"
)
func main() {
log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{}))
// cli.AppHelpTemplate = HelpTemplate
app := &cli.App{
Usage: "AWS management commands",
Commands: []*cli.Command{
cmd.HibernateCommand,
cmd.UpdateACommand,
cmd.SecretsCommand,
},
}
if err := app.Run(os.Args); err != nil {
log.Error(err.Error())
os.Exit(1)
}
}

19
cmd/hibernate/root.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"fmt"
"os"
"aws-mgmt/internal/cmd"
)
func main() {
app := cmd.HibernateApp
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
}

19
cmd/secrets/root.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"fmt"
"os"
"aws-mgmt/internal/cmd"
)
func main() {
app := cmd.SecretsApp
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
}

18
cmd/update-a/root.go Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"fmt"
"os"
"aws-mgmt/internal/cmd"
)
func main() {
app := cmd.UpdateAApp
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
}

115
dist/config.yaml vendored Normal file
View File

@ -0,0 +1,115 @@
project_name: aws-mgmt-go
release:
github:
owner: jswank
name: aws-mgmt-go
name_template: '{{.Tag}}'
builds:
- id: aws-mgmt-go
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
- "386"
goarm:
- "6"
gomips:
- hardfloat
goamd64:
- v1
targets:
- linux_amd64_v1
- linux_arm64
- linux_386
- darwin_amd64_v1
- darwin_arm64
- windows_amd64_v1
- windows_arm64
- windows_386
dir: .
main: .
binary: aws-mgmt-go
builder: go
gobinary: go
command: build
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser
archives:
- id: default
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
format: tar.gz
files:
- src: license*
- src: LICENSE*
- src: readme*
- src: README*
- src: changelog*
- src: CHANGELOG*
snapshot:
name_template: '{{ .Version }}-SNAPSHOT-{{ .ShortCommit }}'
checksum:
name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt'
algorithm: sha256
changelog:
format: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'
dist: dist
env_files:
github_token: ~/.config/goreleaser/github_token
gitlab_token: ~/.config/goreleaser/gitlab_token
gitea_token: ~/.config/goreleaser/gitea_token
source:
name_template: '{{ .ProjectName }}-{{ .Version }}'
format: tar.gz
gomod:
gobinary: go
announce:
twitter:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
mastodon:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
server: ""
reddit:
title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
url_template: '{{ .ReleaseURL }}'
slack:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
username: GoReleaser
discord:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
author: GoReleaser
color: "3888754"
icon_url: https://goreleaser.com/static/avatar.png
teams:
title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
color: '#2D313E'
icon_url: https://goreleaser.com/static/avatar.png
smtp:
subject_template: '{{ .ProjectName }} {{ .Tag }} is out!'
body_template: 'You can view details from: {{ .ReleaseURL }}'
mattermost:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
username: GoReleaser
linkedin:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
telegram:
message_template: '{{ mdv2escape .ProjectName }} {{ mdv2escape .Tag }} is out{{ mdv2escape "!" }} Check it out at {{ mdv2escape .ReleaseURL }}'
parse_mode: MarkdownV2
webhook:
message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}'
content_type: application/json; charset=utf-8
opencollective:
title_template: '{{ .Tag }}'
message_template: '{{ .ProjectName }} {{ .Tag }} is out!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
bluesky:
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
git:
tag_sort: -version:refname
github_urls:
download: https://github.com
gitlab_urls:
download: https://gitlab.com

1
dist/metadata.json vendored Normal file
View File

@ -0,0 +1 @@
{"project_name":"aws-mgmt-go","tag":"v0.0.0","previous_tag":"","version":"0.0.0-SNAPSHOT-a27f612","commit":"a27f6126361f2f72af910005442de0c0701e3df2","date":"2024-11-19T09:03:30.402585616-05:00","runtime":{"goos":"linux","goarch":"amd64"}}

59
go.mod Normal file
View File

@ -0,0 +1,59 @@
module aws-mgmt
go 1.21.1
require (
github.com/aws/aws-sdk-go-v2 v1.32.5
github.com/aws/aws-sdk-go-v2/config v1.28.5
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20
github.com/aws/aws-sdk-go-v2/service/ec2 v1.191.0
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6
github.com/charmbracelet/huh v0.6.0
github.com/pquerna/otp v1.4.0
github.com/urfave/cli/v2 v2.27.5
golang.org/x/term v0.26.0
)
require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect
github.com/aws/smithy-go v1.22.1 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect
github.com/catppuccin/go v0.2.0 // indirect
github.com/charmbracelet/bubbles v0.20.0 // indirect
github.com/charmbracelet/bubbletea v1.2.3 // indirect
github.com/charmbracelet/lipgloss v1.0.0 // indirect
github.com/charmbracelet/x/ansi v0.4.5 // indirect
github.com/charmbracelet/x/exp/strings v0.0.0-20241119170951-e919f77bf23b // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

116
go.sum Normal file
View File

@ -0,0 +1,116 @@
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo=
github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0=
github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o=
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.191.0 h1:F7M5lncJ3dH6VfFohkSTBh0uRmqfB41/XxXfp8NphHI=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.191.0/go.mod h1:mzj8EEjIHSN2oZRXiw1Dd+uB4HZTl7hC8nBzX9IZMWw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E=
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 h1:wmt05tPp/CaRZpPV5B4SaJ5TwkHKom07/BzHoLdkY1o=
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2/go.mod h1:d+K9HESMpGb1EU9/UmmpInbGIUcAkwmcY6ZO/A3zZsw=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 h1:1KDMKvOKNrpD667ORbZ/+4OgvUoaok1gg/MLzrHF9fw=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6/go.mod h1:DmtyfCfONhOyVAJ6ZMTrDSFIeyCBlEO93Qkfhxwbxu0=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg=
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.2.3 h1:d9MdMsANIYZB5pE1KkRqaUV6GfsiWm+/9z4fTuGVm9I=
github.com/charmbracelet/bubbletea v1.2.3/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
github.com/charmbracelet/huh v0.6.0 h1:mZM8VvZGuE0hoDXq6XLxRtgfWyTI3b2jZNKh0xWmax8=
github.com/charmbracelet/huh v0.6.0/go.mod h1:GGNKeWCeNzKpEOh/OJD8WBwTQjV3prFAtQPpLv+AVwU=
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/exp/strings v0.0.0-20241119170951-e919f77bf23b h1:zj6aAhsT/hrh2RRuhkrgdwL328Akf26YjSsAArruCNE=
github.com/charmbracelet/x/exp/strings v0.0.0-20241119170951-e919f77bf23b/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

134
internal/cmd/hibernate.go Normal file
View File

@ -0,0 +1,134 @@
package cmd
import (
"fmt"
"time"
cli "github.com/urfave/cli/v2"
"aws-mgmt/pkg/client"
)
const hibernateDesc = `Hibernate an EC2 instance.
The TIME string is the number of seconds to delay the hibernation, and defaults
to 10. "now" is an alias for 0.
If run on an EC2 instance with an appropriate IAM EC2 role, the instance will
be hibernated. Required IAM permissions include:
- ec2:StopInstances
Alternatively, an instance ID must be specified: that instance will be
hibernated. Required IAM permissions include:
- ec2:StopInstances
`
var HibernateApp = &cli.App{
Name: "hibernate",
Usage: "hibernate an instance",
UsageText: "hibernate [options] [TIME]",
HideHelpCommand: true,
Args: true,
ArgsUsage: "[TIME]",
Action: hibernateFunc,
Description: hibernateDesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
var HibernateCommand = &cli.Command{
Name: "hibernate",
Usage: "hibernate an instance",
UsageText: "hibernate [options] [TIME]",
HideHelpCommand: true,
Args: true,
ArgsUsage: "[TIME]",
Action: hibernateFunc,
Description: hibernateDesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
func hibernateFunc(ctx *cli.Context) error {
// create logger
log, err := createLogger(ctx.String("loglevel"))
if err != nil {
return fmt.Errorf("unable to create a logger, %w", err)
}
// set timer for shutdown
timer, err := setTimer(ctx.Args().Get(0))
if err != nil {
return err
}
log.Debug("timer is set", "timer", timer)
// create aws config
cfg, err := client.CreateAWSConfig()
if err != nil {
return err
}
awsClient := client.NewAWSClient(
client.SetConfig(cfg),
)
// determine instance id
instance_id := ctx.String("instance-id")
if instance_id == "" {
instance_id, err = awsClient.GetInstanceID()
if err != nil {
return err
}
}
log.Debug("instance id is set", "instance_id", instance_id)
log.Info("waiting to hibernate", "timer", timer)
time.Sleep(timer)
// stop instance
state, err := awsClient.StopInstance(instance_id, true)
if err != nil {
return fmt.Errorf("unable to stop instance, %w", err)
}
log.Info("hibernating instance", "instance_id", instance_id, "state", state)
return nil
}
func setTimer(t string) (time.Duration, error) {
var err error
timer := time.Duration(10 * time.Second)
if t != "" {
if t == "now" {
timer = time.Duration(0)
} else {
timer, err = time.ParseDuration(t + "s")
if err != nil {
return timer, fmt.Errorf("unable to set timer, %w", err)
}
}
}
return timer, nil
}

157
internal/cmd/secrets.go Normal file
View File

@ -0,0 +1,157 @@
package cmd
import (
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/huh"
"github.com/pquerna/otp/totp"
cli "github.com/urfave/cli/v2"
"aws-mgmt/pkg/client"
)
const secretsDesc = `View secrets from AWS Secrets Manager.
`
var SecretsApp = &cli.App{
Name: "secrets",
Usage: "view secrets",
UsageText: "secrets [options]",
HideHelpCommand: true,
Args: true,
ArgsUsage: "[secret]",
Action: secretsFunc,
Description: secretsDesc,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "totp",
Usage: "Generate a MFA token based on the secret value",
},
&cli.StringSliceFlag{
Name: "tags",
Usage: "Tags in the format key=value",
},
&cli.BoolFlag{
Name: "sh",
Usage: "Print the equivalent AWS CLI / shell command(s)",
},
},
}
var SecretsCommand = &cli.Command{
Name: "secrets",
Usage: "view secrets",
UsageText: "secrets [options]",
HideHelpCommand: true,
Args: true,
ArgsUsage: "[secret]",
Action: secretsFunc,
Description: secretsDesc,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "totp",
Usage: "Return a MFA token",
},
&cli.StringSliceFlag{
Name: "tags",
Usage: "Tags in the format key=value",
},
},
}
func secretsFunc(c *cli.Context) error {
// create aws config
cfg, err := client.CreateAWSConfig()
if err != nil {
return err
}
awsClient := client.NewAWSClient(
client.SetConfig(cfg),
)
// get hostname & domain
secret := c.Args().Get(0)
tags := parseTags(c.StringSlice("tags"))
if secret == "" {
secrets, err := awsClient.ListSecrets(tags)
if err != nil {
return err
}
if c.Bool("sh") {
str := `aws secretsmanager list-secrets --query 'SecretList[].[Name,Description]' --output text | sort`
fmt.Fprintln(os.Stderr, str)
}
if len(secrets) == 0 {
return fmt.Errorf("no secrets found")
}
secret, err = selectSecretDialog(secrets)
if err != nil {
return err
}
}
// get secret value for secretName
secretValue, err := awsClient.GetSecretValue(secret)
if err != nil {
return err
}
// if the totp flag is set, generate a token
if c.Bool("totp") {
token, err := totp.GenerateCode(secretValue, time.Now())
if err != nil {
return err
}
fmt.Println(token)
} else {
// print the aws cli equivalent command to output this secret to stderr
if c.Bool("sh") {
fmt.Fprintln(os.Stderr, fmt.Sprintf("aws secretsmanager get-secret-value --secret-id %s --query SecretString --output text --no-cli-pager",secret))
}
fmt.Println(secretValue)
}
return nil
}
func parseTags(rawTags []string) map[string]string {
tags := make(map[string]string)
for _, tag := range rawTags {
parts := strings.SplitN(tag, "=", 2)
if len(parts) == 2 {
tags[parts[0]] = parts[1]
}
}
return tags
}
// selectSecretDialog prompts the user to select a secret from a list of SecretListEntry
func selectSecretDialog(secretList []client.SecretListEntry) (string, error) {
// create a select prompt for the user to choose a secret
var secretName string
options := make([]huh.Option[string], len(secretList))
// options := make([]huh.Option, len(secretList))
for i, secret := range secretList {
// create a new option for each secret
options[i] = huh.NewOption[string](strings.TrimSuffix(fmt.Sprintf("%s: %s", secret.Name, secret.Description), ": "), secret.Name)
}
huh.NewSelect[string]().
Title("Select a secret").
Options(options...).
Value(&secretName).
Run()
return secretName, nil
}

139
internal/cmd/update-a.go Normal file
View File

@ -0,0 +1,139 @@
package cmd
import (
"fmt"
"strings"
cli "github.com/urfave/cli/v2"
"aws-mgmt/pkg/client"
)
const updateADesc = `Update a DNS A record for an instance.
The only required argument is the FQDN: other information required to update
the appropriate Route53 record is determined by querying Route53 and IMDS (or
EC2) APIs.
If run on an EC2 instance with an appropriate IAM EC2 role, an A record will be
created for that instance. Required IAM permissions include:
- route53:ListHostedZonesByName
- route53:ChangeResourceRecordSets
Alternatively, an instance ID must be specified: an A record will be created
for that instance. Required IAM permissions include:
- route53:ListHostedZonesByName
- route53:ChangeResourceRecordSets
- ec2:DescribeInstances`
var UpdateAApp = &cli.App{
Name: "update-a",
Usage: "Create / update an A record for an instance with a public IP",
UsageText: "update-a [options] <FQDN>",
HideHelpCommand: true,
Args: true,
ArgsUsage: "<FQDN>",
Action: updateAFunc,
Description: updateADesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
var UpdateACommand = &cli.Command{
Name: "update-a",
Usage: "Create / update an A record for an instance with a public IP",
UsageText: "update-a [options] <FQDN>",
HideHelpCommand: true,
Args: true,
ArgsUsage: "<FQDN>",
Action: updateAFunc,
Description: updateADesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
func updateAFunc(ctx *cli.Context) error {
// create logger
log, err := createLogger(ctx.String("loglevel"))
if err != nil {
return fmt.Errorf("unable to create a logger, %w", err)
}
// create aws config
cfg, err := client.CreateAWSConfig()
if err != nil {
return err
}
awsClient := client.NewAWSClient(
client.SetConfig(cfg),
)
// determine instance id
instance_id := ctx.String("instance-id")
// get hostname & domain
hostname := ctx.Args().Get(0)
domain, err := parseHostname(hostname)
if err != nil {
return err
}
log.Debug("input received", "instance-id", instance_id, "hostname", hostname, "domain", domain)
zoneID, err := awsClient.GetZoneID(domain)
if err != nil {
return err
}
log.Debug("zone id set", "zone-id", zoneID)
var publicIP string
if instance_id != "" {
log.Debug("attempting to retrieve public ip from the EC2 API")
publicIP, err = awsClient.GetEC2PublicIP(instance_id)
} else {
log.Debug("attempting to retrieve public ip from IMDS")
publicIP, err = awsClient.GetMetadata("public-ipv4")
}
if err != nil {
return err
}
log.Debug("public ip retrieved", "public_ip", publicIP)
err = awsClient.UpdateA(hostname, publicIP, zoneID)
if err != nil {
return err
}
log.Info("dns record updated", "hostname", hostname, "zone-id", zoneID, "public-ipv4", publicIP)
return nil
}
func parseHostname(h string) (string, error) {
var domain string
if idx := strings.IndexByte(h, '.'); idx >= 0 {
domain = h[idx+1:]
} else {
return "", fmt.Errorf("hostname (%s) must be a FQDN", h)
}
return domain, nil
}

21
internal/cmd/util.go Normal file
View File

@ -0,0 +1,21 @@
package cmd
import (
"fmt"
"log/slog"
"os"
)
/* create a logger at the specified loglevel */
func createLogger(lvl string) (*slog.Logger, error) {
level := slog.LevelError
err := level.UnmarshalText([]byte(lvl))
if err != nil {
return nil, fmt.Errorf("invalid log level, %w", err)
}
log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
Level: level,
}))
return log, nil
}

265
pkg/client/aws.go Normal file
View File

@ -0,0 +1,265 @@
package client
import (
"context"
"errors"
"fmt"
"io"
"sort"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/route53"
r53 "github.com/aws/aws-sdk-go-v2/service/route53/types"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
sm "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types"
)
type AWSClient struct {
cfg aws.Config
}
type SecretListEntry struct {
Name string
Description string
}
type optionFunc func(*AWSClient)
func NewAWSClient(optionFuncs ...optionFunc) *AWSClient {
awsClient := AWSClient{}
for _, option := range optionFuncs {
option(&awsClient)
}
return &awsClient
}
func SetConfig(cfg aws.Config) optionFunc {
return func(c *AWSClient) {
c.cfg = cfg
}
}
/* Create config for AWS clients. If region is unset, attempt to set it via IMDS. */
func CreateAWSConfig() (aws.Config, error) {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
return cfg, fmt.Errorf("unable to load default AWS config, %w", err)
}
// try to set the region using IMDS if it's not already set
if cfg.Region == "" {
resp, err := imds.NewFromConfig(cfg).GetRegion(context.TODO(), &imds.GetRegionInput{})
if err != nil {
return cfg, fmt.Errorf("unable to get AWS region from IMDS, %w", err)
}
cfg, _ = config.LoadDefaultConfig(context.TODO(), config.WithRegion(resp.Region))
}
return cfg, nil
}
/* Get the running instance id */
func (c AWSClient) GetInstanceID() (string, error) {
id, err := imds.NewFromConfig(c.cfg).GetInstanceIdentityDocument(context.TODO(), &imds.GetInstanceIdentityDocumentInput{})
if err != nil {
return "", err
}
return id.InstanceID, nil
}
// getZoneID returns the zone id given domain
func (c AWSClient) GetZoneID(domain string) (string, error) {
r53Client := route53.NewFromConfig(c.cfg)
output, err := r53Client.ListHostedZonesByName(context.TODO(), &route53.ListHostedZonesByNameInput{
DNSName: aws.String(domain),
})
if err != nil {
return "", err
}
if len(output.HostedZones) == 0 {
return "", errors.New("no matching zone")
}
return *output.HostedZones[0].Id, nil
}
// GetMetadata returns the specified path from instance metadata
func (c AWSClient) GetMetadata(path string) (string, error) {
imdsClient := imds.NewFromConfig(c.cfg)
metadata, err := imdsClient.GetMetadata(context.TODO(), &imds.GetMetadataInput{
Path: path,
})
if err != nil {
return "", err
}
buf := new(strings.Builder)
_, err = io.Copy(buf, metadata.Content)
if err != nil {
return "", err
}
return buf.String(), nil
}
func (c AWSClient) StopInstance(instance_id string, hibernate bool) (string, error) {
si_out, err := ec2.NewFromConfig(c.cfg).StopInstances(context.TODO(), &ec2.StopInstancesInput{
InstanceIds: []string{instance_id},
Hibernate: aws.Bool(hibernate),
})
if err != nil {
return "", err
}
return string(si_out.StoppingInstances[0].CurrentState.Name), nil
}
func (c AWSClient) GetEC2Tag(instance_id string, tag_name string) (string, error) {
result, err := ec2.NewFromConfig(c.cfg).DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{
InstanceIds: []string{instance_id},
})
if err != nil {
return "", err
}
for _, reservation := range result.Reservations {
for _, instance := range reservation.Instances {
for _, tag := range instance.Tags {
// Check if the tag key matches the one you're interested in
if *tag.Key == tag_name {
return *tag.Value, nil
}
}
}
}
return "", nil
}
func (c AWSClient) GetEC2PublicIP(instance_id string) (string, error) {
var publicIP string
result, err := ec2.NewFromConfig(c.cfg).DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{
InstanceIds: []string{instance_id},
})
if err != nil {
return "", err
}
for _, reservation := range result.Reservations {
for _, instance := range reservation.Instances {
if instance.PublicIpAddress != nil {
publicIP = *instance.PublicIpAddress
}
}
}
if publicIP == "" {
err = errors.New("no public ip address is associated with the instance")
}
return publicIP, err
}
func (c AWSClient) UpdateA(hostname, ipaddress, zoneID string) error {
change := r53.Change{
Action: "UPSERT",
ResourceRecordSet: &r53.ResourceRecordSet{
Name: aws.String(hostname),
Type: "A",
TTL: aws.Int64(60),
ResourceRecords: []r53.ResourceRecord{
r53.ResourceRecord{Value: aws.String(ipaddress)},
},
},
}
_, err := route53.NewFromConfig(c.cfg).ChangeResourceRecordSets(context.TODO(), &route53.ChangeResourceRecordSetsInput{
HostedZoneId: aws.String(zoneID),
ChangeBatch: &r53.ChangeBatch{
Changes: []r53.Change{change},
},
})
return err
}
// ListSecrets lists all secrets with tags matching the tags map, returning a sorted list
// of secrets names and descriptions from the response.
func (c AWSClient) ListSecrets(tags map[string]string) ([]SecretListEntry, error) {
client := secretsmanager.NewFromConfig(c.cfg)
// construct filters from tags map
var filters []sm.Filter
// filters := make([]sm.Filter, 0, len(tags)*2)
for key, value := range tags {
filters = append(filters, sm.Filter{
Key: sm.FilterNameStringTypeTagKey,
Values: []string{key},
})
if value != "" {
filters = append(filters, sm.Filter{
Key: sm.FilterNameStringTypeTagValue,
Values: []string{value},
})
}
}
var secretList []SecretListEntry
// Set the initial pagination token to an empty string
var nextToken *string
// Loop until there are no more pages
for {
// Call ListSecrets with the pagination token
input := &secretsmanager.ListSecretsInput{
Filters: filters,
NextToken: nextToken,
}
resp, err := client.ListSecrets(context.TODO(), input)
if err != nil {
return secretList, fmt.Errorf("unable to list secrets, %w", err)
}
// Process the secrets in the current page
for _, secret := range resp.SecretList {
entry := SecretListEntry{
Name: *secret.Name,
}
if secret.Description != nil {
entry.Description = *secret.Description
}
secretList = append(secretList, entry)
}
// Check if there are more pages
if resp.NextToken == nil {
break
}
// Set the pagination token for the next iteration
nextToken = resp.NextToken
}
// sort secretList alphabetically by name
sort.Slice(secretList, func(i, j int) bool {
return secretList[i].Name < secretList[j].Name
})
return secretList, nil
}
// GetSecretValue retrieves the secret value for the given secret name.
func (c AWSClient) GetSecretValue(secretName string) (string, error) {
client := secretsmanager.NewFromConfig(c.cfg)
input := &secretsmanager.GetSecretValueInput{
SecretId: &secretName,
}
resp, err := client.GetSecretValue(context.TODO(), input)
if err != nil {
return "", fmt.Errorf("unable to get secret value, %w", err)
}
return *resp.SecretString, nil
}

15
pkg/logout/now.go Normal file
View File

@ -0,0 +1,15 @@
package logout
import (
"os"
"syscall"
"golang.org/x/term"
)
func Now() {
if term.IsTerminal(int(os.Stdout.Fd())) {
ppid := os.Getppid()
_ = syscall.Kill(ppid, 1)
}
}