cli/launchpad/generic.go (66 lines of code) (raw):
package launchpad
import (
"errors"
"fmt"
"log"
"regexp"
"strings"
)
const (
// defaultIndentSize defines default indent size when calling String and dump.
defaultIndentSize = 2
apiCFTv1alpha1 = "cft.dev/v1alpha1"
)
// supportedVersion defines API version and support resource for each version.
var supportedVersion = map[string]map[crdKind]func() resourceHandler{
apiCFTv1alpha1: v1alpha1SupportedKind,
}
// v1alpha1SupportedKind defines v1alpha1's supported resources.
var v1alpha1SupportedKind = map[crdKind]func() resourceHandler{
Folder: func() resourceHandler { return &folderYAML{} },
Organization: func() resourceHandler { return &orgYAML{} },
}
var (
errValidationFailed = errors.New("validation failed")
errMissingRequiredField = errors.New("missing required field")
errInvalidParent = errors.New("invalid parent reference")
errInvalidInput = errors.New("invalid input")
tfNameRegex = regexp.MustCompile(`^[a-zA-Z][a-zA-Z\d\-\_]*$`)
)
// resourceHandler represents a resource that can be processed by launchpad.
type resourceHandler interface {
// resId defines the internal referencable id.
resId() string
// validate ensures the parsed YAML has validate fields.
validate() error
// kind returns the validated crdKind of the resource.
kind() crdKind
// addToOrg adds the resource into the assembled organization.
addToOrg(ao *assembledOrg) error
// resolveReferences takes action on resources referencing the current resource.
resolveReferences(refs []resourceHandler) error
}
// crdKind is the CustomResourceDefinition (CRD) which is indicated by YAML Kind value.
type crdKind int
const (
CloudFoundation crdKind = iota
Folder
Organization
)
func (k crdKind) String() string {
return []string{"CloudFoundation", "Folder", "Organization"}[k]
}
// newCRDKind parses string formatted crdKind and convert to internal format.
//
// Unsupported format given will return -1, caller is expected to handle unknown type.
func newCRDKind(crdKindStr string) crdKind {
switch strings.ToLower(crdKindStr) {
case "cloudfoundation":
return CloudFoundation
case "folder":
return Folder
case "organization":
return Organization
default:
log.Printf("warning: unsupported CustomResourceDefinition %q", crdKindStr)
return -1
}
}
// headerYAML defines the common fields all CRD is required to have.
type headerYAML struct {
APIVersion string `yaml:"apiVersion"`
KindStr string `yaml:"kind"`
}
func (h *headerYAML) kind() crdKind { return newCRDKind(h.KindStr) }
// referenceYAML represents an explicit reference to another resource.
//
// It is common to have reference relationship among difference resources. For example,
// parent-children relationship such as project belong to a folder, network belong to a
// project. referenceYAML is the relationship identifier between these resources.
type referenceYAML struct {
TargetTypeStr string `yaml:"type"`
TargetId string `yaml:"id"`
}
func (r *referenceYAML) TargetType() crdKind { return newCRDKind(r.TargetTypeStr) }
func (r *referenceYAML) resId() string { return fmt.Sprintf("%s.%s", r.TargetType(), r.TargetId) }