From f59bb70577b7af1347ef6b2cbcbe18d4d1f9f3b0 Mon Sep 17 00:00:00 2001 From: Hugo Bollon Date: Thu, 28 Dec 2023 16:24:22 +0100 Subject: [PATCH] feat: support noLocks and noVersioning with all state providers --- state/gcp.go | 31 ++++++++++++++++++++++++------- state/gitlab.go | 26 ++++++++++++++++++++++---- state/tfe.go | 31 ++++++++++++++++++++++++------- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/state/gcp.go b/state/gcp.go index f4404edf..6cd472ff 100644 --- a/state/gcp.go +++ b/state/gcp.go @@ -19,12 +19,14 @@ import ( // GCP is a state provider type, leveraging GCS type GCP struct { - svc *storage.Client - buckets []string + svc *storage.Client + buckets []string + noLocks bool + noVersioning bool } // NewGCP creates an GCP object -func NewGCP(gcp config.GCPConfig) (*GCP, error) { +func NewGCP(gcp config.GCPConfig, noLocks, noVersioning bool) (*GCP, error) { ctx := context.Background() var client *storage.Client @@ -52,8 +54,10 @@ func NewGCP(gcp config.GCPConfig) (*GCP, error) { } gcpInstance = &GCP{ - svc: client, - buckets: gcp.GCSBuckets, + svc: client, + buckets: gcp.GCSBuckets, + noLocks: noLocks, + noVersioning: noVersioning, } log.WithFields(log.Fields{ @@ -67,7 +71,7 @@ func NewGCP(gcp config.GCPConfig) (*GCP, error) { func NewGCPCollection(c *config.Config) ([]*GCP, error) { var gcpInstances []*GCP for _, gcp := range c.GCP { - gcpInstance, err := NewGCP(gcp) + gcpInstance, err := NewGCP(gcp, c.Provider.NoLocks, c.Provider.NoVersioning) if err != nil || gcpInstance == nil { return nil, err } @@ -79,6 +83,11 @@ func NewGCPCollection(c *config.Config) ([]*GCP, error) { // GetLocks returns a map of locks by State path func (a *GCP) GetLocks() (locks map[string]LockInfo, err error) { + if a.noLocks { + locks = make(map[string]LockInfo) + return + } + ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, time.Second*60) defer cancel() @@ -167,7 +176,7 @@ func (a *GCP) GetState(st, versionID string) (sf *statefile.File, err error) { fileName := st[bucketSplit+1:] obj := a.svc.Bucket(bucketName).Object(fileName) - if versionID != "" { + if versionID != "" && !a.noVersioning { version, err := strconv.ParseInt(versionID, 10, 64) if err != nil { return nil, err @@ -205,6 +214,14 @@ func (a *GCP) GetState(st, versionID string) (sf *statefile.File, err error) { // GetVersions returns a slice of Version objects func (a *GCP) GetVersions(state string) (versions []Version, err error) { + if a.noVersioning { + versions = append(versions, Version{ + ID: state, + LastModified: time.Now(), + }) + return + } + versions = []Version{} ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, time.Second*60) diff --git a/state/gitlab.go b/state/gitlab.go index 507f3f69..7282c4df 100644 --- a/state/gitlab.go +++ b/state/gitlab.go @@ -6,6 +6,7 @@ import ( "net/url" "regexp" "strconv" + "time" "github.com/camptocamp/terraboard/config" "github.com/camptocamp/terraboard/internal/terraform/states/statefile" @@ -14,18 +15,22 @@ import ( // Gitlab is a state provider type, leveraging GitLab type Gitlab struct { - Client gitlab.Client + Client gitlab.Client + noLocks bool + noVersioning bool } // NewGitlab creates a new Gitlab object -func NewGitlab(gl config.GitlabConfig) *Gitlab { +func NewGitlab(gl config.GitlabConfig, noLocks, noVersioning bool) *Gitlab { var instance *Gitlab if gl.Token == "" { return nil } instance = &Gitlab{ - Client: gitlab.NewClient(gl.Address, gl.Token), + Client: gitlab.NewClient(gl.Address, gl.Token), + noLocks: noLocks, + noVersioning: noVersioning, } return instance } @@ -34,7 +39,7 @@ func NewGitlab(gl config.GitlabConfig) *Gitlab { func NewGitlabCollection(c *config.Config) []*Gitlab { var gitlabInstances []*Gitlab for _, gitlab := range c.Gitlab { - if glInstance := NewGitlab(gitlab); glInstance != nil { + if glInstance := NewGitlab(gitlab, c.Provider.NoLocks, c.Provider.NoVersioning); glInstance != nil { gitlabInstances = append(gitlabInstances, glInstance) } } @@ -44,6 +49,11 @@ func NewGitlabCollection(c *config.Config) []*Gitlab { // GetLocks returns a map of locks by State path func (g *Gitlab) GetLocks() (locks map[string]LockInfo, err error) { + if g.noLocks { + locks = make(map[string]LockInfo) + return + } + locks = make(map[string]LockInfo) var projects gitlab.Projects projects, err = g.Client.GetProjectsWithTerraformStates() @@ -89,6 +99,14 @@ func (g *Gitlab) GetStates() (states []string, err error) { // GetVersions returns a slice of Version objects func (g *Gitlab) GetVersions(state string) (versions []Version, err error) { + if g.noVersioning { + versions = append(versions, Version{ + ID: state, + LastModified: time.Now(), + }) + return + } + var projects gitlab.Projects projects, err = g.Client.GetProjectsWithTerraformStates() if err != nil { diff --git a/state/tfe.go b/state/tfe.go index 67caffb8..c22dc9a0 100644 --- a/state/tfe.go +++ b/state/tfe.go @@ -14,12 +14,14 @@ import ( // TFE is a state provider type, leveraging Terraform Enterprise type TFE struct { *tfe.Client - org string - ctx *context.Context + org string + ctx *context.Context + noLocks bool + noVersioning bool } // NewTFE creates a new TFE object -func NewTFE(tfeObj config.TFEConfig) (*TFE, error) { +func NewTFE(tfeObj config.TFEConfig, noLocks, noVersioning bool) (*TFE, error) { var tfeInstance *TFE if tfeObj.Token == "" { return nil, nil @@ -37,9 +39,11 @@ func NewTFE(tfeObj config.TFEConfig) (*TFE, error) { ctx := context.Background() tfeInstance = &TFE{ - Client: client, - org: tfeObj.Organization, - ctx: &ctx, + Client: client, + org: tfeObj.Organization, + ctx: &ctx, + noLocks: noLocks, + noVersioning: noVersioning, } return tfeInstance, nil @@ -49,7 +53,7 @@ func NewTFE(tfeObj config.TFEConfig) (*TFE, error) { func NewTFECollection(c *config.Config) ([]*TFE, error) { var tfeInstances []*TFE for _, tfe := range c.TFE { - tfeInstance, err := NewTFE(tfe) + tfeInstance, err := NewTFE(tfe, c.Provider.NoLocks, c.Provider.NoVersioning) if err != nil || tfeInstance == nil { return nil, err } @@ -61,6 +65,11 @@ func NewTFECollection(c *config.Config) ([]*TFE, error) { // GetLocks returns a map of locks by State path func (t *TFE) GetLocks() (locks map[string]LockInfo, err error) { + if t.noLocks { + locks = make(map[string]LockInfo) + return + } + locks = make(map[string]LockInfo) options := tfe.WorkspaceListOptions{ @@ -132,6 +141,14 @@ func (t *TFE) GetStates() (states []string, err error) { // GetVersions returns a slice of Version objects func (t *TFE) GetVersions(state string) (versions []Version, err error) { + if t.noVersioning { + versions = append(versions, Version{ + ID: state, + LastModified: time.Now(), + }) + return + } + options := tfe.StateVersionListOptions{ ListOptions: tfe.ListOptions{ PageNumber: 1,