diff --git a/.gitignore b/.gitignore index 40969f69..a3ea0d1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -bin/ -rpm-package/goat +goat +pkg/ diff --git a/GNUmakefile b/GNUmakefile index 53103019..98e08ea1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,12 +1,15 @@ NAME:=goat -VERSION:=0.9.0 +VERSION:=1.0.0 +OS:=linux +ARCH:=amd64 GOAT_FILES?=$$(find . -name '*.go' | grep -v vendor) +BINPATH=usr/sbin all: build build: deps - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static" -X main.VERSION=$(VERSION)' -o bin/$(NAME) - strip bin/$(NAME) + CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -a -tags netgo -ldflags '-w -extldflags "-static" -X main.VERSION=$(VERSION)' -o $(BINPATH)/$(NAME) + strip $(BINPATH)/$(NAME) test: @go vet ./... @@ -22,18 +25,35 @@ fmt: lint: -gometalinter.v2 --enable-all $(GOAT_FILES) --exclude=_test.go +package_all: pkgclean build deb rpm zip + +zip: + @zip pkg/$(NAME)_$(VERSION)_$(OS)_$(ARCH).zip -j $(BINPATH)/$(NAME) + +deb: + @mkdir -p pkg + fpm -s dir -t deb -n $(NAME) -v $(VERSION) -C . \ + -p pkg/$(NAME)_VERSION_ARCH.deb \ + -d "mdadm" \ + --deb-systemd ./goat@.service \ + $(BINPATH) + +rpm: + @mkdir -p pkg + fpm -s dir -t rpm -n $(NAME) -v $(VERSION) -C . \ + -p pkg/$(NAME)_VERSION_ARCH.rpm \ + -d "mdadm" \ + --rpm-systemd ./goat@.service \ + $(BINPATH) + +pkgclean: + @rm -rf pkg + lintsetup: @go get -u gopkg.in/alecthomas/gometalinter.v2 @gometalinter.v2 --install 2>&1 >/dev/null @go install ./... -clean: - -rm -rf bin - -rpm: build - @cp bin/goat rpm-package/ - GOAT_VERSION=$(VERSION) $(MAKE) -C ./rpm-package/ - dev-env: ## Build a local development environment using Docker @docker run -it --rm \ -v $(shell pwd):/go/src/github.com/sevagh/$(NAME) \ diff --git a/README.md b/README.md index 4d5eea9b..bf1d11d7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![ReportCard](http://goreportcard.com/badge/sevagh/goat)](http://goreportcard.com/report/sevagh/goat) [![GitHub tag](https://img.shields.io/github/tag/sevagh/goat.svg)](https://github.com/sevagh/goat/releases) - # goat :goat: ### Attach EBS volumes and ENIs to running EC2 instances @@ -16,16 +14,45 @@ It's necessary for the instance to have an IAM Role with _at least_ access to th Unfortunately, resource-level permissions are [currently not supported](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/ec2-api-permissions.html#ec2-api-unsupported-resource-permissions) for attaching network interfaces. This means that to use `goat@eni`, your instances must have full permissions for __all__ ENIs. -### RPM-based install +### Install and run + +Goat is a Go binary that should be able to run on any Linux instance. + +In the releases tab you can find a zip of the binary, and a `.deb` and `.rpm` package with systemd support generated by [fpm](https://github.com/jordansissel/fpm). + +To use goat, run it during the launch process of your EC2 instance - you can `systemctl enable goat@TARGET` and `systemctl start goat@TARGET` (where TARGET is one of ebs or eni). + +It's a Linux-specific tool which needs `mdadm` to work for the RAID features. + +#### Usage -Goat is systemd-based and has been developed for CentOS. Install the rpm from the releases page: +In the most basic case, you should run `goat ebs` or `goat eni`. + +Full usage: ``` -$ sudo yum install -y https://github.com/sevagh/goat/releases/download/0.6.0/goat-0.6.0-1.fc27.x86_64.rpm -$ sudo systemctl enable goat@ebs -$ sudo systemctl start goat@ebs +Usage: goat [OPTIONS] ebs|eni + +OPTIONS + -debug + Interactive debug prompts + -logLevel string + Log level (default "info") + -tagPrefix string + Prefix for GOAT related tags (default "GOAT-IN") + -version + Display version and exit ``` +### Environment variables + +You can use the environment variables: + +* `GOAT_LOG_LEVEL` +* `GOAT_TAG_PREFIX` + +Set these the same as `-logLevel` and `-tagPrefix` - the environment variables take precedence. + ### Additional dependencies for ENI Goat by itself is sufficient for the EBS feature, but needs help for setting up an ENI. Refer to [this](./docs/ENI.md#setting-up-the-eni---ec2-net-utils) document. diff --git a/rpm-package/goat@.service b/goat@.service similarity index 77% rename from rpm-package/goat@.service rename to goat@.service index 2bc74f32..62c043ca 100644 --- a/rpm-package/goat@.service +++ b/goat@.service @@ -3,13 +3,13 @@ Description=GOAT: EC2-%i attach utility Documentation=https://github.com/sevagh/goat Requires=network.target remote-fs.target After=network.target remote-fs.target -ConditionPathExists=/usr/bin/goat +ConditionPathExists=/usr/sbin/goat [Service] Type=oneshot User=root Group=root -ExecStart=/usr/bin/goat "%i" --log-level=info +ExecStart=/usr/sbin/goat "%i" SyslogIdentifier=goat [Install] diff --git a/main.go b/main.go index 9d864835..4eb90a26 100644 --- a/main.go +++ b/main.go @@ -16,20 +16,44 @@ func main() { debugPtr := flag.Bool("debug", false, "Interactive debug prompts") tagPrefixPtr := flag.String("tagPrefix", "GOAT-IN", "Prefix for GOAT related tags") + tagPrefixEnv := os.Getenv("GOAT_TAG_PREFIX") + logLevelEnv := os.Getenv("GOAT_LOG_LEVEL") + + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: goat [OPTIONS] ebs|eni\n\nOPTIONS\n") + flag.PrintDefaults() + } + flag.Parse() if *versionPtr { - fmt.Printf("goat %s", VERSION) + fmt.Println("goat ", VERSION) os.Exit(0) } if flag.NArg() != 1 { - log.Fatalf("Usage: goat [OPTIONS] ebs|eni") + flag.Usage() + os.Exit(1) } + command := flag.Args()[0] + logLevel := "" + if logLevelEnv != "" { + logLevel = logLevelEnv // env var takes precedence + } else { + logLevel = *logLevelPtr + } + + tagPrefix := "" + if tagPrefixEnv != "" { + tagPrefix = tagPrefixEnv + } else { + tagPrefix = *tagPrefixPtr + } + log.SetOutput(os.Stderr) - if level, err := log.ParseLevel(*logLevelPtr); err != nil { + if level, err := log.ParseLevel(logLevel); err != nil { log.Fatalf("%v", err) } else { log.SetLevel(level) @@ -39,9 +63,9 @@ func main() { log.Printf("Running goat for %s", command) if command == "ebs" { - GoatEbs(*debugPtr, *tagPrefixPtr) + GoatEbs(*debugPtr, tagPrefix) } else if command == "eni" { - GoatEni(*debugPtr, *tagPrefixPtr) + GoatEni(*debugPtr, tagPrefix) } else { log.Fatalf("Unrecognized command: %s", command) } diff --git a/rpm-package/GNUmakefile b/rpm-package/GNUmakefile deleted file mode 100644 index 25c882cc..00000000 --- a/rpm-package/GNUmakefile +++ /dev/null @@ -1,5 +0,0 @@ -all: rpm - -rpm: - -rpmlint specfile.spec - @rpmbuild -ba specfile.spec --define "_sourcedir $$PWD" --define "_version $$GOAT_VERSION" diff --git a/rpm-package/specfile.spec b/rpm-package/specfile.spec deleted file mode 100644 index df427407..00000000 --- a/rpm-package/specfile.spec +++ /dev/null @@ -1,63 +0,0 @@ -%define pkgname goat - -Name: %{pkgname} -Version: %{_version} -Release: 1%{?dist} -Summary: Attach and mount EBS and ENI - -License: BSD 3-clause -URL: https://github.com/sevagh/goat -Source0: %{pkgname} -Source1: %{pkgname}@.service - -Requires: systemd mdadm - - -%description -Automatically attach AWS resources to a running EC2 instance. - - -#%prep -#%setup -#%build - - -%install -%{__mkdir} -p %{buildroot}/%{_bindir} -%{__mkdir} -p %{buildroot}/%{_unitdir} -%{__install} -m0775 %{SOURCE0} %{buildroot}/%{_bindir}/%{pkgname} -%{__install} -m0777 %{SOURCE1} %{buildroot}/%{_unitdir}/%{pkgname}@.service - - -%files -%{_bindir}/%{pkgname} -%{_unitdir}/%{pkgname}@.service - - -%post -if [ $1 -eq 1 ]; then - /bin/systemctl daemon-reload >/dev/null 2>&1 || : -fi - - -%preun -if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl disable %{pkgname}@*.service >/dev/null 2>&1 || : - /bin/systemctl stop %{pkgname}@*.service >/dev/null 2>&1 || : -fi - - -%postun -/bin/systemctl daemon-reload >/dev/null 2>&1 || : - - -%changelog -* Tue Apr 17 2018 Sevag Hanssian -- Recombine commands -* Tue Mar 06 2018 Sevag Hanssian -- Split subcommands into two binaries -* Thu Aug 10 2017 Sevag Hanssian -- Goat subcommands -* Tue Jul 11 2017 Sevag Hanssian -- First RPM package for goat