Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
(GH-263) Add initial implementation
Browse files Browse the repository at this point in the history
This initial implementation of the project:

1. Configures golangci and goreleaser
2. Initializes prm as a cobra app which:
   a. Includes telemetry from pdkgo, enabling
      binaries with/without telemetry enabled
   b. Implements the version command
  • Loading branch information
michaeltlombardi committed Oct 27, 2021
1 parent f46b285 commit ac35405
Show file tree
Hide file tree
Showing 7 changed files with 1,166 additions and 0 deletions.
53 changes: 53 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Inspired by https://github.com/golangci/golangci-lint/blob/54bfbb9a52299b6ecbdde9365282aa40a5561bf1/.golangci.yml#L1
linters-settings:
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dogsled
- dupl
- errcheck
- exportloopref
- exhaustive
- funlen
- gochecknoinits
- goconst
- gocritic
- gocyclo
- gofmt
- goimports
- golint
- gomnd
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- lll
- misspell
- nakedret
- noctx
- nolintlint
- rowserrcheck
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace

goconst:
min-len: 2
min-occurrences: 2
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
100 changes: 100 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
project_name: prm

release:
name_template: "PRM {{.Version}}"
prerelease: auto

before:
hooks:
- go mod tidy
- go fmt ./...

builds:
- binary: prm
id: prm
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm
- arm64
asmflags:
- all=-trimpath={{.Env.WORKINGDIR}}
gcflags:
- all=-trimpath={{.Env.WORKINGDIR}}
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.CommitDate}} -X main.honeycomb_api_key={{.Env.HONEYCOMB_API_KEY}} -X main.honeycomb_dataset={{.Env.HONEYCOMB_DATASET}}
mod_timestamp: '{{ .CommitTimestamp }}'
tags:
- telemetry
- binary: prm
id: notel_prm
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm
- arm64
asmflags:
- all=-trimpath={{.Env.WORKINGDIR}}
gcflags:
- all=-trimpath={{.Env.WORKINGDIR}}
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.CommitDate}} -X main.honeycomb_api_key={{.Env.HONEYCOMB_API_KEY}} -X main.honeycomb_dataset={{.Env.HONEYCOMB_DATASET}}
mod_timestamp: '{{ .CommitTimestamp }}'

archives:
- name_template: "prm_{{ tolower .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
id: prm
builds:
- prm
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
wrap_in_directory: false
format_overrides:
- goos: windows
format: zip
files:
- templates/**/*
- name_template: "notel_prm_{{ tolower .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
id: notel_prm
builds:
- notel_prm
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
wrap_in_directory: false
format_overrides:
- goos: windows
format: zip
files:
- templates/**/*


checksum:
name_template: 'checksums.txt'

snapshot:
name_template: "{{ .Tag }}-{{.ShortCommit}}"

changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
128 changes: 128 additions & 0 deletions cmd/root/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package root

import (
"os"
"path/filepath"
"strings"

homedir "github.com/mitchellh/go-homedir"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var (
cfgFile string
LogLevel string
LocalTemplateCache string

debug bool
// format string
)

func InitLogger() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix

lvl, err := zerolog.ParseLevel(LogLevel)
if err != nil {
panic("Could not initialize zerolog")
}

zerolog.SetGlobalLevel(lvl)

if lvl == zerolog.InfoLevel {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
} else {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout}).With().Caller().Logger()
}

log.Trace().Msg("Initialized zerolog")
}

func CreateRootCommand() *cobra.Command {
tmp := &cobra.Command{
Use: "prm",
Short: "prm - Puppet Runtime Manager",
Long: `Puppet Runtime Manager (PRM) - Execute commands and validate against Puppet content`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
},
SilenceUsage: true,
SilenceErrors: true,
}
tmp.Flags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.prm.yaml)")

tmp.PersistentFlags().StringVar(&LogLevel, "log-level", zerolog.InfoLevel.String(), "Log level (debug, info, warn, error, fatal, panic)")
err := tmp.RegisterFlagCompletionFunc("log-level", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
var levels = []string{"debug", "info", "warn", "error", "fatal", "panic"}
return find(levels, toComplete), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
})
cobra.CheckErr(err)

tmp.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "enable debug output")
// tmp.PersistentFlags().StringVarP(&format, "format", "f", "junit", "formating (default is junit)")

return tmp
}

func InitConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := homedir.Dir()
viper.SetConfigName(".prm")
viper.SetConfigType("yaml")
viper.AddConfigPath(home)
viper.AddConfigPath(filepath.Join(home, ".config"))
}

viper.AutomaticEnv()

if err := viper.ReadInConfig(); err == nil {
log.Trace().Msgf("Using config file: %s", viper.ConfigFileUsed())
}
}

// Returns the cobra command called, e.g. new or install
// and also the fully formatted command as passed with arguments/flags.
// Idea borrowed from carolynvs/porter:
// https://github.com/carolynvs/porter/blob/ccca10a63627e328616c1006600153da8411a438/cmd/porter/main.go
func GetCalledCommand(cmd *cobra.Command) (string, string) {
if len(os.Args) < 2 {
return "", ""
}

calledCommandStr := os.Args[1]

// Also figure out the full called command from the CLI
// Is there anything sensitive you could leak here? 🤔
calledCommandArgs := strings.Join(os.Args[1:], " ")

return calledCommandStr, calledCommandArgs
}

// Both contains and find are copied from the pdkgo repo because they lived in an internal pkg:
// github.com/puppetlabs/pdkgo/internal/pkg/utils
// To use these directly, the utils pkg would need to be public
// contains checks if a string is present in a slice
func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}

return false
}

// finds a string present in a slice
func find(source []string, match string) []string {
var matches []string
if contains(source, match) {
matches = append(matches, match)
}
return matches
}
57 changes: 57 additions & 0 deletions cmd/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package version

import (
"fmt"
"os"
"regexp"
"strings"
"time"

"github.com/puppetlabs/pdkgo/pkg/telemetry"
"github.com/spf13/cobra"
)

func CreateVersionCommand(version, buildDate string, commit string) *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
_, span := telemetry.NewSpan(cmd.Context(), "version")
defer telemetry.EndSpan(span)
telemetry.AddStringSpanAttribute(span, "name", "version")

fmt.Fprint(os.Stdout, Format(version, buildDate, commit))
},
}

return cmd
}

func Format(version, buildDate string, commit string) string {
version = strings.TrimSpace(strings.TrimPrefix(version, "v"))

var dateStr string
if buildDate != "" {
t, _ := time.Parse(time.RFC3339, buildDate)
dateStr = t.Format("2006/01/02")
}

if commit != "" && len(commit) > 7 {
length := len(commit) - 7
commit = strings.TrimSpace(commit[:len(commit)-length])
}

return fmt.Sprintf("prm %s %s %s\n\n%s",
version, commit, dateStr, changelogURL(version))
}

func changelogURL(version string) string {
path := "https://github.com/puppetlabs/prm"
r := regexp.MustCompile(`^v?\d+\.\d+\.\d+(-[\w.]+)?$`)
if !r.MatchString(version) {
return fmt.Sprintf("%s/releases/latest", path)
}

url := fmt.Sprintf("%s/releases/tag/%s", path, strings.TrimPrefix(version, "v"))
return url
}
43 changes: 43 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module github.com/puppetlabs/prm

go 1.17

require (
github.com/mitchellh/go-homedir v1.1.0
github.com/puppetlabs/pdkgo v0.0.0-20211026093604-d365a907d61a
github.com/rs/zerolog v1.25.0
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.9.0
)

require (
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
github.com/denisbrodbeck/machineid v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
go.opentelemetry.io/otel v1.0.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect
go.opentelemetry.io/otel/sdk v1.0.1 // indirect
go.opentelemetry.io/otel/trace v1.0.1 // indirect
go.opentelemetry.io/proto/otlp v0.9.0 // indirect
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 // indirect
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect
google.golang.org/grpc v1.41.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
Loading

0 comments on commit ac35405

Please sign in to comment.