Skip to content

Commit

Permalink
Add targets base structure
Browse files Browse the repository at this point in the history
  • Loading branch information
julienduchesne committed Apr 8, 2019
1 parent b0309b0 commit 1b1dc51
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 9 deletions.
4 changes: 4 additions & 0 deletions cli/credentialslist.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"fmt"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand All @@ -14,6 +15,9 @@ var listCredentialsCmd = &cobra.Command{
Use: "list-credentials",
Short: "Resolves and lists all configured credentials",
Run: func(cmd *cobra.Command, args []string) {
if !configuration.Sources.ValidateConfiguration() {
log.Fatal("The sources section of the config file is invalid")
}
allCredentials, err := configuration.Sources.Credentials()
if err != nil {
panic(err)
Expand Down
8 changes: 7 additions & 1 deletion cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"io/ioutil"
"os"

"github.com/mitchellh/mapstructure"

"gopkg.in/yaml.v2"

"github.com/coveo/credentials-sync/sync"
Expand All @@ -27,14 +29,18 @@ var rootCmd = &cobra.Command{
Support Jenkins only for now.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
configuration = &sync.Configuration{}
configurationDict := map[string]interface{}{}
var (
err error
fileContent []byte
)
if fileContent, err = ioutil.ReadFile(configurationFile); err != nil {
return err
}
return yaml.Unmarshal(fileContent, configuration)
if err = yaml.Unmarshal(fileContent, configurationDict); err != nil {
return err
}
return mapstructure.Decode(configurationDict, configuration)
},
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
Expand Down
8 changes: 7 additions & 1 deletion cli/targetslist.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@ package cli
import (
"fmt"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var listTargetsCmd = &cobra.Command{
Use: "list-targets",
Short: "Resolves and lists all configured targets",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
if !configuration.Targets.ValidateConfiguration() {
log.Fatal("The targets section of the config file is invalid")
}
for _, target := range configuration.Targets.AllTargets() {
fmt.Println(target.ToString())
}
},
}
5 changes: 4 additions & 1 deletion cli/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ var validateCmd = &cobra.Command{
Short: "Parses and validates the given configuration",
Run: func(cmd *cobra.Command, args []string) {
if !configuration.Sources.ValidateConfiguration() {
log.Fatal("The config file is invalid")
log.Fatal("The sources section of the config file is invalid")
}
if !configuration.Targets.ValidateConfiguration() {
log.Fatal("The targets section of the config file is invalid")
}
log.Info("The config file is valid!")
},
Expand Down
3 changes: 3 additions & 0 deletions credentials/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ type Base struct {
ID string
Description string
CredType string

// For multi-value fields. Such as SSM
Value string
}

// BaseToString prints out the credentials fields common to all types of credentials
Expand Down
9 changes: 9 additions & 0 deletions credentials/credentials_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import (
"fmt"
)

// SecretTextCredentials represents credentials composed of a single string value
type SecretTextCredentials struct {
Base `mapstructure:",squash"`
Secret string
}

// NewSecretText instantiates a SecretTextCredentials struct
func NewSecretText() *SecretTextCredentials {
cred := &SecretTextCredentials{}
cred.CredType = "Secret text"
return cred
}

// ToString prints out the content of a SecretTextCredentials struct.
// If showSensitive is true, the secret text will be shown
func (cred *SecretTextCredentials) ToString(showSensitive bool) string {
secretText := "*******"
if showSensitive {
Expand All @@ -26,6 +30,11 @@ func (cred *SecretTextCredentials) ToString(showSensitive bool) string {
return fmt.Sprintf("%s - %s", cred.BaseToString(), secretText)
}

// Validate verifies that the credentials is valid.
// A SecretTextCredentials is always considered valid, as empty values are accepted.
func (cred *SecretTextCredentials) Validate() bool {
if cred.Secret == "" && cred.Value != "" {
cred.Secret = cred.Value
}
return true
}
12 changes: 12 additions & 0 deletions credentials/credentials_userpass.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package credentials

import (
"fmt"
"strings"

log "github.com/sirupsen/logrus"
)

// UsernamePasswordCredentials represents credentials composed of a username and a password
Expand Down Expand Up @@ -38,5 +41,14 @@ func (cred *UsernamePasswordCredentials) ToString(showSensitive bool) string {
// Validate verifies that the credentials is valid.
// A UsernamePasswordCredentials is always considered valid, as empty values are accepted.
func (cred *UsernamePasswordCredentials) Validate() bool {
if cred.Username == "" && cred.Password == "" && cred.Value != "" {
splitValue := strings.Split(cred.Value, ":")
if len(splitValue) != 2 {
log.Errorf("The credentials with ID %s has an invalid username:password value: %s", cred.ID, cred.Value)
return false
}
cred.Username = splitValue[0]
cred.Password = splitValue[1]
}
return true
}
2 changes: 1 addition & 1 deletion credentials/source_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

type LocalSource struct {
File string `yaml:"file"`
File string
}

func (source *LocalSource) Credentials() ([]Credentials, error) {
Expand Down
6 changes: 3 additions & 3 deletions credentials/sources.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ type Source interface {
}

type SourcesConfiguration struct {
AWSS3Sources []*AWSS3Source `yaml:"aws_s3"`
AWSSSMSources []*AWSSSMSource `yaml:"aws_ssm"`
LocalSources []*LocalSource `yaml:"local"`
AWSS3Sources []*AWSS3Source `mapstructure:"aws_s3"`
AWSSSMSources []*AWSSSMSource `mapstructure:"aws_ssm"`
LocalSources []*LocalSource `mapstructure:"local"`
}

func (sc *SourcesConfiguration) AllSources() []Source {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.12

require (
github.com/aws/aws-sdk-go v1.19.11
github.com/bndr/gojenkins v0.2.0
github.com/mitchellh/mapstructure v1.1.2
github.com/sirupsen/logrus v1.4.1
github.com/spf13/cobra v0.0.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/aws/aws-sdk-go v1.19.11 h1:tqaTGER6Byw3QvsjGW0p018U2UOqaJPeJuzoaF7jjoQ=
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/bndr/gojenkins v0.2.0 h1:fplg5+NQoDCPlJSXSqCIspf7uiLiDzMpw9rimLt5sHs=
github.com/bndr/gojenkins v0.2.0/go.mod h1:J2FxlujWW87NJJrdysyctcDllRVYUONGGlHX16134P4=
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/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
Expand Down
4 changes: 2 additions & 2 deletions sync/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import (
)

type Configuration struct {
Sources *credentials.SourcesConfiguration `yaml:"sources"`
Targets *targets.Configuration `yaml:"targets"`
Sources *credentials.SourcesConfiguration
Targets *targets.Configuration
}
70 changes: 70 additions & 0 deletions targets/jenkins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package targets

import (
"errors"
"fmt"
"net/url"

log "github.com/sirupsen/logrus"

"github.com/bndr/gojenkins"
"github.com/coveo/credentials-sync/credentials"
)

type JenkinsTarget struct {
Base `mapstructure:",squash"`

LoginCredentials *credentials.Credentials
URL string
SecureConnection bool

client *gojenkins.Jenkins
existingCredentials []credentials.Credentials
}

func (jenkins *JenkinsTarget) Initialize() error {
auth := (*jenkins.LoginCredentials).(*credentials.UsernamePasswordCredentials)
jenkins.client = gojenkins.CreateJenkins(jenkins.URL, auth.Username, auth.Password)
jenkins.client.Requester.SslVerify = jenkins.SecureConnection
jenkins.client.Init()
var err error
defer func() {
if r := recover(); r != nil {
log.Error("Recovered the following error while initializing Jenkins: ", r)
switch x := r.(type) {
case string:
err = errors.New(x)
case error:
err = x
default:
err = errors.New("unknown panic")
}
}
}()
return err
}

func (jenkins *JenkinsTarget) ToString() string {
return fmt.Sprintf("%s (Jenkins) - %s", jenkins.BaseToString(), jenkins.URL)
}

func (jenkins *JenkinsTarget) UpdateListOfCredentials(listOfCredentials []*credentials.Credentials) error {
for _, credentials := range listOfCredentials {
if err := jenkins.UpdateCredentials(credentials); err != nil {
return err
}
}
return nil
}

func (jenkins *JenkinsTarget) UpdateCredentials(credentials *credentials.Credentials) error {
return nil
}

func (jenkins *JenkinsTarget) ValidateConfiguration() bool {
if _, err := url.ParseRequestURI(jenkins.URL); err != nil {
log.Errorf("The Jenkins target `%s` has an invalid URL: %s", jenkins.Name, jenkins.URL)
return false
}
return true
}
58 changes: 58 additions & 0 deletions targets/targets.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,62 @@
package targets

import (
"fmt"
"strings"

"github.com/coveo/credentials-sync/credentials"
log "github.com/sirupsen/logrus"
)

type Target interface {
BaseValidateConfiguration() bool
Initialize() error
ToString() string
UpdateListOfCredentials([]*credentials.Credentials) error
UpdateCredentials(*credentials.Credentials) error
ValidateConfiguration() bool
}

type Base struct {
Name string
Tags map[string]string
}

// BaseToString prints out the target fields common to all types of targets
func (targetBase *Base) BaseToString() string {
tagString := ""
for tagKey, tagValue := range targetBase.Tags {
tagString = fmt.Sprintf("%s %s=%s", tagString, tagKey, tagValue)
}
return fmt.Sprintf("%s [Tags: %s]", targetBase.Name, strings.TrimSpace(tagString))
}

func (targetBase *Base) BaseValidateConfiguration() bool {
if targetBase.Name == "" {
log.Errorf("Every target need to define a name")
return false
}
return true
}

type Configuration struct {
JenkinsTargets []*JenkinsTarget `mapstructure:"jenkins"`
}

func (config *Configuration) AllTargets() []Target {
targets := []Target{}
for _, target := range config.JenkinsTargets {
targets = append(targets, target)
}
return targets
}

func (config *Configuration) ValidateConfiguration() bool {
configIsOK := true
for _, target := range config.AllTargets() {
if !target.ValidateConfiguration() || !target.BaseValidateConfiguration() {
configIsOK = false
}
}
return configIsOK
}

0 comments on commit 1b1dc51

Please sign in to comment.