Skip to content

Commit

Permalink
fetch from public terraform registry
Browse files Browse the repository at this point in the history
* added capability to handle fetch from public terraform registry
* capable now to handle gcp, azure and aws /cc @nutellinoit
* now furyctl has superpowers to dynamically fetch terrraform modules with
labels strategy from customizable yaml configuration /cc @nutellinoit
* new struct provider allows to expose all the providers (roles,
 bases,modules) external references in one place /cc @angelbarrera92
* refactor Registry case
  • Loading branch information
lzecca78 authored Feb 6, 2020
1 parent 4fb9d70 commit 1fba666
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 20 deletions.
41 changes: 40 additions & 1 deletion Furyfile.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

versions:
aws: v1.15.4
monitoring: master
Expand All @@ -10,8 +9,48 @@ roles:
modules:
- name: aws/aws-vpc
- name: aws/aws-kubernetes
- name: terraform-aws-acm
version: v2.5.0
provider:
name: aws
label: official-modules
registry: true
- name: tf_aws_bastion_s3_keys
version: v2.0.0
provider:
name: aws
label: community-modules
registry: true
- name: terraform-google-kubernetes-engine
version: v6.2.0
provider:
name: gcp
label: official-modules
registry: true
- name: terraform-azurerm-aks
version: v2.0
provider:
name: azure
label: official-modules
registry: true

bases:
- name: monitoring
- name: logging
version: master

provider:
roles: {}
bases: {}
modules:
aws:
- url: https://github.com/terraform-aws-modules
label: official-modules
- url: https://github.com/terraform-community-modules
label: community-modules
gcp:
- url: https://github.com/terraform-google-modules
label: official-modules
azure:
- url: https://github.com/Azure
label: official-modules
178 changes: 159 additions & 19 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,57 @@ const (

// Furyconf is reponsible for the structure of the Furyfile
type Furyconf struct {
VendorFolderName string `yaml:"vendorFolderName"`
Versions VersionPattern `yaml:"versions"`
Roles []Package `yaml:"roles"`
Modules []Package `yaml:"modules"`
Bases []Package `yaml:"bases"`
VendorFolderName string `yaml:"vendorFolderName"`
Versions VersionPattern `yaml:"versions"`
Roles []Package `yaml:"roles"`
Modules []Package `yaml:"modules"`
Bases []Package `yaml:"bases"`
Provider ProviderPattern `mapstructure:"provider"`
}

// Map from glob pattern to version associated (e.g. {"aws/*" : "v1.15.4-1"}
// ProviderPattern is the abstraction of the following structure:
//provider:
// modules:
// aws
// - uri: https://github.com/terraform-aws-modules
// label: ufficial-modules
type ProviderPattern map[string]ProviderKind

// ProviderKind is the abstraction of the following structure:
//
// modules:
// aws
// - uri: https://github.com/terraform-aws-modules
// label: ufficial-modules
type ProviderKind map[string][]RegistrySpec

//RegistrySpec contains the couple uri/label to identify each tf new repo declared
type RegistrySpec struct {
BaseURI string `mapstructure:"url"`
Label string `mapstructure:"label"`
}

//VersionPattern Map from glob pattern to version associated (e.g. {"aws/*" : "v1.15.4-1"}
type VersionPattern map[string]string

// Package is the type to contain the definition of a single package
type Package struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
url string
dir string
kind string
Name string `yaml:"name"`
Version string `yaml:"version"`
url string
dir string
kind string
ProviderOpt ProviderOptSpec `mapstructure:"provider"`
Registry bool `mapstructure:"registry"`
}

// Validate is used for validation of configuration and initization of default paramethers
// ProviderSpec is the type that allows to explicit name of cloud provider and referenced label
type ProviderOptSpec struct {
Name string `mapstructure:"name"`
Label string `mapstructure:"label"`
}

// Validate is used for validation of configuration and initization of default parameters
func (f *Furyconf) Validate() error {
if f.VendorFolderName == "" {
f.VendorFolderName = defaultVendorFolderName
Expand All @@ -72,7 +103,6 @@ func (f *Furyconf) Parse() ([]Package, error) {
v.kind = "katalog"
pkgs = append(pkgs, v)
}

repoPrefix := sshRepoPrefix
dotGitParticle := ""
if https {
Expand All @@ -82,7 +112,14 @@ func (f *Furyconf) Parse() ([]Package, error) {

// Now we generate the dowload url and local dir
for i := 0; i < len(pkgs); i++ {
url := new(URLSpec)
directory := new(DirSpec)
version := pkgs[i].Version
registry := pkgs[i].Registry
cloudPlatform := pkgs[i].ProviderOpt
urlPrefix := repoPrefix
pkgKind := pkgs[i].kind

if version == "" {
for k, v := range f.Versions {
if strings.HasPrefix(pkgs[i].Name, k) {
Expand All @@ -92,13 +129,116 @@ func (f *Furyconf) Parse() ([]Package, error) {
}
}
}

kindSpec := newKind(pkgKind, f.Provider)
block := strings.Split(pkgs[i].Name, "/")
if len(block) == 2 {
pkgs[i].url = fmt.Sprintf("%s-%s%s//%s/%s?ref=%s", repoPrefix, block[0], dotGitParticle, pkgs[i].kind, block[1], version)
} else if len(block) == 1 {
pkgs[i].url = fmt.Sprintf("%s-%s%s//%s?ref=%s", repoPrefix, block[0], dotGitParticle, pkgs[i].kind, version)
}
pkgs[i].dir = fmt.Sprintf("%s/%s/%s", f.VendorFolderName, pkgs[i].kind, pkgs[i].Name)
url = newURL(urlPrefix, block, dotGitParticle, pkgKind, version, registry, cloudPlatform, kindSpec)
pkgs[i].url = url.strategy()
directory = newDir(f.VendorFolderName, pkgKind, pkgs[i].Name, registry, cloudPlatform)
pkgs[i].dir = directory.strategy()
}

return pkgs, nil
}

func newKind(kind string, provider ProviderPattern) ProviderKind {
providerChoosen := provider[kind]
return providerChoosen
}

func (k *ProviderKind) getLabeledURI(providerName, label string) (string, error) {
for name, providerSpecList := range *k {
if name == providerName {
for _, providerMap := range providerSpecList {
if providerMap.Label == label {
return fmt.Sprintf("git::%s", providerMap.BaseURI), nil
}
}
}
}
return "", fmt.Errorf("no label %s found", label)
}

func (k *ProviderKind) pickCloudProviderURL(cloudProvider ProviderOptSpec) string {
name := cloudProvider.Name
label := cloudProvider.Label
url, err := k.getLabeledURI(name, label)
if err != nil {
log.Fatal(err)
}
return url
}

// DirSpec is the abstraction of the fields needed for generating a destination directory
type DirSpec struct {
VendorFolder string
Kind string
Name string
Registry bool
Provider ProviderOptSpec
}

func newDir(folder, kind, name string, registry bool, provider ProviderOptSpec) *DirSpec {
return &DirSpec{
VendorFolder: folder,
Kind: kind,
Name: name,
Registry: registry,
Provider: provider,
}
}

func (d *DirSpec) strategy() string {
if d.Registry {
return fmt.Sprintf("%s/%s/%s/%s/%s", d.VendorFolder, d.Kind, d.Provider.Label, d.Provider.Name, d.Name)
}
return fmt.Sprintf("%s/%s/%s", d.VendorFolder, d.Kind, d.Name)
}

//URLSpec is the rappresentation of the fields needed to elaborate a url
type URLSpec struct {
Prefix string
Blocks []string
DotGitParticle string
Kind string
Version string
Registry bool
CloudProvider ProviderOptSpec
KindSpec ProviderKind
}

// newUrl initialize the URLSpec struct
func newURL(prefix string, blocks []string, dotGitParticle, kind, version string, registry bool, cloud ProviderOptSpec, kindSpec ProviderKind) *URLSpec {
return &URLSpec{
Registry: registry,
Prefix: prefix,
Blocks: blocks,
DotGitParticle: dotGitParticle,
Kind: kind,
Version: version,
CloudProvider: cloud,
KindSpec: kindSpec,
}
}

func (n *URLSpec) strategy() string {
var url string
if n.Registry {
urlPrefix := n.KindSpec.pickCloudProviderURL(n.CloudProvider)
dotGitParticle := ".git"
url = fmt.Sprintf("%s/%s%s?ref=%s", urlPrefix, n.Blocks[0], dotGitParticle, n.Version)
} else {
url = n.getURLfromCompanyRepos()
}
return url
}

func (n *URLSpec) getURLfromCompanyRepos() string {
var url string
if len(n.Blocks) == 2 {
url = fmt.Sprintf("%s-%s%s//%s/%s?ref=%s", n.Prefix, n.Blocks[0], n.DotGitParticle, n.Kind, n.Blocks[1], n.Version)
} else if len(n.Blocks) == 1 {
url = fmt.Sprintf("%s-%s%s//%s?ref=%s", n.Prefix, n.Blocks[0], n.DotGitParticle, n.Kind, n.Version)
}
return url
}

0 comments on commit 1fba666

Please sign in to comment.