diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65e8a01 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +**/*.tfvars +**/*.tfstate* +.idea +*.retry +.terraform +*.iml +dist/* +/csm +coverage.out diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..239cd55 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,51 @@ +run: + deadline: 5m + +linters: + # please, do not use `enable-all`: it's deprecated and will be removed soon. + # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dogsled + - dupl + - errcheck + # - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - golint + - gosec + - gosimple + - govet + - ineffassign + - interfacer + - lll + - misspell + - nakedret + - scopelint + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unparam + - unused + - varcheck + - whitespace + + +linters-settings: + dupl: + threshold: 400 + lll: + line-length: 170 + gocyclo: + min-complexity: 30 + golint: + min-confidence: 0.85 diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..ea6a9d9 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,27 @@ +before: + hooks: + - go mod download +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin +archives: + - replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a7830b7 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git.signintra.com/schenker/csm + +go 1.15 + +require github.com/fatih/color v1.9.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6d654d0 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go new file mode 100644 index 0000000..7e0ae9f --- /dev/null +++ b/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "net" + + "github.com/fatih/color" +) + +func main() { + s, err := net.ResolveUDPAddr("udp4", ":31000") + if err != nil { + panic(err) + } + + connection, err := net.ListenUDP("udp4", s) + if err != nil { + panic(err) + } + defer connection.Close() + + for { + res, err := Read(connection) + if err != nil { + _ = fmt.Errorf("%v: %w", "unknown response", err) + continue + } + if res.Type == "ApiCallAttempt" { // omit Verdicts + msg := fmt.Sprintf("%v %-50.50v %v\n", res.HTTPStatusCode, fmt.Sprintf("%s:%s", res.Service, res.API), res.Fqdn) + if res.HTTPStatusCode >= 400 { + color.Red(msg) + } else { + color.Green(msg) + } + } + } +} + +type Response struct { + // Attempt + Version int `json:"Version"` + ClientID string `json:"ClientId"` + Type string `json:"Type"` + Service string `json:"Service"` + API string `json:"Api"` + Timestamp int64 `json:"Timestamp"` + AttemptLatency int `json:"AttemptLatency"` + Fqdn string `json:"Fqdn"` + UserAgent string `json:"UserAgent"` + AccessKey string `json:"AccessKey"` + Region string `json:"Region"` + SessionToken string `json:"SessionToken"` + HTTPStatusCode int `json:"HttpStatusCode"` + XAmznRequestID string `json:"XAmznRequestId"` + + // Verdict + AttemptCount int `json:"AttemptCount"` + FinalHTTPStatusCode int `json:"FinalHttpStatusCode"` + Latency int `json:"Latency"` + MaxRetriesExceeded int `json:"MaxRetriesExceeded"` +} + +func Read(conn *net.UDPConn) (*Response, error) { + b := make([]byte, 1024) + oob := make([]byte, 40) + + //nolint:dogsled + _, _, _, _, err := conn.ReadMsgUDP(b, oob) + if err != nil { + return nil, err + } + + // Remove NULL characters + b = bytes.Trim(b, "\x00") + ret := &Response{} + + if err := json.Unmarshal(b, ret); err != nil { + return nil, err + } + + return ret, err +}