-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* starting * cp * cp * I think we can use this! * with docker * example and action
- Loading branch information
Jack Lindamood
committed
Aug 22, 2022
1 parent
a093a68
commit 529fcbe
Showing
22 changed files
with
1,769 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/.env | ||
/.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
name: Build and test code | ||
|
||
on: | ||
push: | ||
tags: | ||
- v* | ||
branches: | ||
- master | ||
- main | ||
pull_request: | ||
|
||
|
||
jobs: | ||
build: | ||
name: Test | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Install Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.19.x | ||
- name: Check out code | ||
uses: actions/checkout@v2 | ||
- name: golangci-lint | ||
uses: golangci/golangci-lint-action@v2 | ||
with: | ||
version: latest | ||
- name: Build | ||
run: go build -mod=readonly ./cmd/atlantis-drift-detection/main.go | ||
- name: Verify | ||
run: go mod verify | ||
- name: Test | ||
run: go test -v ./... | ||
- name: Docker build | ||
run: docker build -t atlantis-drift-detection . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
FROM golang:1.19.0 as build | ||
|
||
WORKDIR /app | ||
|
||
COPY go.mod . | ||
COPY go.sum . | ||
RUN go mod download | ||
COPY . . | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags '-w' -o /atlantis-drift-detection ./cmd/atlantis-drift-detection/main.go | ||
|
||
FROM ubuntu:22.10 | ||
|
||
RUN apt-get update \ | ||
&& apt-get install -y wget unzip git \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
|
||
ARG TERRAFORM_VERSION=1.2.3 | ||
# Download terraform for linux | ||
RUN wget --quiet https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \ | ||
&& unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip \ | ||
&& mv terraform /usr/bin \ | ||
&& rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip | ||
|
||
COPY --from=build /atlantis-drift-detection /atlantis-drift-detection | ||
|
||
ENTRYPOINT ["/atlantis-drift-detection"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: 'Atlantis terraform drift detection' | ||
description: 'Some automation to detect drift inside atlantis via the remote /plan endpoint' | ||
branding: | ||
icon: 'activity' | ||
color: 'blue' | ||
inputs: | ||
atlantisHost: | ||
description: 'Atlantis hostname with protocol. Example: "https://atlantis.company.com' | ||
required: true | ||
atlantisToken: | ||
description: 'Atlantis API token' | ||
required: true | ||
repo: | ||
description: 'Repository to check' | ||
required: true | ||
slackWebhookURL: | ||
description: 'Slack webhook URL to send notifications to' | ||
required: false | ||
runs: | ||
using: 'docker' | ||
image: 'Dockerfile' | ||
env: | ||
ATLANTIS_HOST: '{{ inputs.atlantisHost }}' | ||
ATLANTIS_TOKEN: '{{ inputs.atlantisToken }}' | ||
REPO: '{{ inputs.repo }}' | ||
SLACK_WEBHOOK_URL: '{{ inputs.slackWebhookURL }}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/cresta/atlantis-drift-detection/internal/atlantis" | ||
"github.com/cresta/atlantis-drift-detection/internal/drifter" | ||
"github.com/cresta/atlantis-drift-detection/internal/notification" | ||
"github.com/cresta/atlantis-drift-detection/internal/terraform" | ||
"github.com/cresta/gogit" | ||
"github.com/cresta/gogithub" | ||
"github.com/joho/godotenv" | ||
"net/http" | ||
"os" | ||
|
||
// Empty import allows pinning to version atlantis uses | ||
_ "github.com/nlopes/slack" | ||
"go.uber.org/zap" | ||
) | ||
import "github.com/joeshaw/envdecode" | ||
|
||
type config struct { | ||
Repo string `env:"REPO,required"` | ||
AtlantisHostname string `env:"ATLANTIS_HOST,required"` | ||
AtlantisToken string `env:"ATLANTIS_TOKEN,required"` | ||
DirectoryWhitelist []string `env:"DIRECTORY_WHITELIST,required"` | ||
SlackWebhookURL string `env:"SLACK_WEBHOOK_URL"` | ||
} | ||
|
||
func loadEnvIfExists() error { | ||
_, err := os.Stat(".env") | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return nil | ||
} | ||
return fmt.Errorf("error checking for .env file: %v", err) | ||
} | ||
return godotenv.Load() | ||
} | ||
|
||
type zapGogitLogger struct { | ||
logger *zap.Logger | ||
} | ||
|
||
func (z *zapGogitLogger) build(strings map[string]string, ints map[string]int64) *zap.Logger { | ||
l := z.logger | ||
for k, v := range strings { | ||
l = l.With(zap.String(k, v)) | ||
} | ||
for k, v := range ints { | ||
l = l.With(zap.Int64(k, v)) | ||
} | ||
return l | ||
} | ||
|
||
func (z *zapGogitLogger) Debug(_ context.Context, msg string, strings map[string]string, ints map[string]int64) { | ||
z.build(strings, ints).Debug(msg) | ||
} | ||
|
||
func (z *zapGogitLogger) Info(_ context.Context, msg string, strings map[string]string, ints map[string]int64) { | ||
z.build(strings, ints).Info(msg) | ||
} | ||
|
||
var _ gogit.Logger = (*zapGogitLogger)(nil) | ||
|
||
func main() { | ||
ctx := context.Background() | ||
zapCfg := zap.NewProductionConfig() | ||
zapCfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel) | ||
logger, err := zapCfg.Build(zap.AddCaller()) | ||
if err != nil { | ||
panic(err) | ||
} | ||
if err := loadEnvIfExists(); err != nil { | ||
logger.Panic("Failed to load .env", zap.Error(err)) | ||
} | ||
var cfg config | ||
if err := envdecode.Decode(&cfg); err != nil { | ||
logger.Panic("failed to decode config", zap.Error(err)) | ||
} | ||
cloner := &gogit.Cloner{ | ||
Logger: &zapGogitLogger{logger}, | ||
} | ||
notif := ¬ification.Multi{ | ||
Notifications: []notification.Notification{ | ||
¬ification.Zap{Logger: logger.With(zap.String("notification", "true"))}, | ||
}, | ||
} | ||
if cfg.SlackWebhookURL != "" { | ||
notif.Notifications = append(notif.Notifications, ¬ification.SlackWebhook{ | ||
WebhookURL: cfg.SlackWebhookURL, | ||
HTTPClient: http.DefaultClient, | ||
}) | ||
} | ||
ghClient, err := gogithub.NewGQLClient(ctx, logger, nil) | ||
if err != nil { | ||
logger.Panic("failed to create github client", zap.Error(err)) | ||
} | ||
tf := terraform.Client{ | ||
Logger: logger.With(zap.String("terraform", "true")), | ||
} | ||
d := drifter.Drifter{ | ||
DirectoryWhitelist: cfg.DirectoryWhitelist, | ||
Logger: logger.With(zap.String("drifter", "true")), | ||
Repo: cfg.Repo, | ||
AtlantisClient: &atlantis.Client{ | ||
AtlantisHostname: cfg.AtlantisHostname, | ||
Token: cfg.AtlantisToken, | ||
HTTPClient: http.DefaultClient, | ||
}, | ||
Cloner: cloner, | ||
GithubClient: ghClient, | ||
Terraform: &tf, | ||
Notification: notif, | ||
} | ||
if err := d.Drift(ctx); err != nil { | ||
logger.Panic("failed to drift", zap.Error(err)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Just the protocol and hostname of atlantis | ||
ATLANTIS_HOST=https://atlantis.company.com | ||
# Your atlantis token | ||
ATLANTIS_TOKEN=PRIVATE_TOKEN | ||
# A plan that is ok | ||
PLAN_SUMMARY_OK='{"Repo": "company/terraform", "Ref": "master", "Type": "Github", "Dir": "environments/aws/env1", "Workspace": "account1"}' | ||
# A plan that you expect to have changes | ||
PLAN_SUMMARY_CHANGES='{"Repo": "company/terraform", "Ref": "master", "Type": "Github", "Dir": "environments/aws/env1", "Workspace": "account1"}' | ||
# A plan you expect to already be locked | ||
PLAN_SUMMARY_LOCK='{"Repo": "company/terraform", "Ref": "master", "Type": "Github", "Dir": "environments/aws/env1", "Workspace": "account1"}' | ||
# Local directory to terraform | ||
TERRAFORM_DIR=/home/USER/GolandProjects/terraform | ||
# A sub directory in TERRAFORM_DIR that has terraform files | ||
TERRAFORM_SUBDIR=environments/aws/env1 | ||
# Optional: A directory to whitelist (will only run for this directory) | ||
DIRECTORY_WHITELIST=environments/aws/lambda/helloworld | ||
# Optional: A slack webhook URL to get notifications | ||
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/X/Y/Z | ||
# Your terraform repository | ||
REPO=company/terraform | ||
# Optional: (but sometimes useful) | ||
AWS_PROFILE=extra-prfiles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
module github.com/cresta/atlantis-drift-detection | ||
|
||
go 1.19 | ||
|
||
require ( | ||
github.com/cresta/gogit v0.0.2 | ||
github.com/cresta/gogithub v0.1.1 | ||
github.com/cresta/pipe v0.0.1 | ||
github.com/joeshaw/envdecode v0.0.0-20200121155833-099f1fc765bd | ||
github.com/joho/godotenv v1.4.0 | ||
github.com/nlopes/slack v0.4.0 | ||
github.com/runatlantis/atlantis v0.19.8 | ||
github.com/stretchr/testify v1.8.0 | ||
go.uber.org/zap v1.22.0 | ||
) | ||
|
||
require ( | ||
github.com/Laisky/graphql v1.0.5 // indirect | ||
github.com/Masterminds/goutils v1.1.1 // indirect | ||
github.com/Masterminds/semver/v3 v3.1.1 // indirect | ||
github.com/Masterminds/sprig/v3 v3.2.2 // indirect | ||
github.com/agext/levenshtein v1.2.3 // indirect | ||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect | ||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect | ||
github.com/benbjohnson/clock v1.3.0 // indirect | ||
github.com/beorn7/perks v1.0.1 // indirect | ||
github.com/bradleyfalzon/ghinstallation v1.1.1 // indirect | ||
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 // indirect | ||
github.com/cactus/go-statsd-client/statsd v0.0.0-20200623234511-94959e3146b2 // indirect | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | ||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect | ||
github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect | ||
github.com/go-playground/locales v0.14.0 // indirect | ||
github.com/go-playground/universal-translator v0.18.0 // indirect | ||
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect | ||
github.com/golang/protobuf v1.5.2 // indirect | ||
github.com/google/go-cmp v0.5.8 // indirect | ||
github.com/google/go-github/v29 v29.0.3 // indirect | ||
github.com/google/go-github/v31 v31.0.0 // indirect | ||
github.com/google/go-github/v45 v45.2.0 // indirect | ||
github.com/google/go-querystring v1.1.0 // indirect | ||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect | ||
github.com/google/uuid v1.3.0 // indirect | ||
github.com/gorilla/mux v1.8.0 // indirect | ||
github.com/gorilla/websocket v1.5.0 // indirect | ||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect | ||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect | ||
github.com/hashicorp/go-version v1.6.0 // indirect | ||
github.com/hashicorp/hcl v1.0.0 // indirect | ||
github.com/hashicorp/hcl/v2 v2.13.0 // indirect | ||
github.com/hashicorp/terraform-config-inspect v0.0.0-20211115214459-90acf1ca460f // indirect | ||
github.com/huandu/xstrings v1.3.2 // indirect | ||
github.com/imdario/mergo v0.3.13 // indirect | ||
github.com/leodido/go-urn v1.2.1 // indirect | ||
github.com/m3db/prometheus_client_golang v1.12.8 // indirect | ||
github.com/m3db/prometheus_client_model v0.2.1 // indirect | ||
github.com/m3db/prometheus_common v0.34.7 // indirect | ||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect | ||
github.com/mcdafydd/go-azuredevops v0.12.1 // indirect | ||
github.com/mitchellh/copystructure v1.2.0 // indirect | ||
github.com/mitchellh/go-homedir v1.1.0 // indirect | ||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect | ||
github.com/mitchellh/reflectwalk v1.0.2 // indirect | ||
github.com/moby/moby v20.10.17+incompatible // indirect | ||
github.com/pkg/errors v0.9.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/prometheus/procfs v0.8.0 // indirect | ||
github.com/remeh/sizedwaitgroup v1.0.0 // indirect | ||
github.com/rogpeppe/go-internal v1.8.1 // indirect | ||
github.com/shopspring/decimal v1.3.1 // indirect | ||
github.com/shurcooL/githubv4 v0.0.0-20220520033151-0b4e3294ff00 // indirect | ||
github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 // indirect | ||
github.com/sirupsen/logrus v1.9.0 // indirect | ||
github.com/spf13/cast v1.5.0 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
github.com/twmb/murmur3 v1.1.6 // indirect | ||
github.com/uber-go/tally v3.5.0+incompatible // indirect | ||
github.com/xanzy/go-gitlab v0.72.0 // indirect | ||
github.com/zclconf/go-cty v1.10.0 // indirect | ||
go.etcd.io/bbolt v1.3.6 // indirect | ||
go.uber.org/atomic v1.10.0 // indirect | ||
go.uber.org/multierr v1.8.0 // indirect | ||
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect | ||
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect | ||
golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 // indirect | ||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect | ||
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect | ||
golang.org/x/text v0.3.7 // indirect | ||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect | ||
google.golang.org/appengine v1.6.7 // indirect | ||
google.golang.org/protobuf v1.28.1 // indirect | ||
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect | ||
gopkg.in/yaml.v2 v2.4.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
Oops, something went wrong.