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

Commit

Permalink
added build manager field group
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathankingfc committed Jan 18, 2021
1 parent d8c0406 commit 3017304
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pkg/lib/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/quay/config-tool/pkg/lib/fieldgroups/actionlogarchiving"
"github.com/quay/config-tool/pkg/lib/fieldgroups/apptokenauthentication"
"github.com/quay/config-tool/pkg/lib/fieldgroups/bitbucketbuildtrigger"
"github.com/quay/config-tool/pkg/lib/fieldgroups/buildmanager"
"github.com/quay/config-tool/pkg/lib/fieldgroups/database"
"github.com/quay/config-tool/pkg/lib/fieldgroups/distributedstorage"
"github.com/quay/config-tool/pkg/lib/fieldgroups/elasticsearch"
Expand Down Expand Up @@ -156,6 +157,11 @@ func NewConfig(fullConfig map[string]interface{}) (Config, error) {
return newConfig, err
}
newConfig["OIDC"] = newOIDCFieldGroup
newBuildManagerFieldGroup, err := buildmanager.NewBuildManagerFieldGroup(fullConfig)
if err != nil {
return newConfig, err
}
newConfig["BuildManager"] = newBuildManagerFieldGroup

return newConfig, nil
}
131 changes: 131 additions & 0 deletions pkg/lib/fieldgroups/buildmanager/buildmanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package buildmanager

import (
"fmt"

"github.com/creasty/defaults"
"gopkg.in/yaml.v3"
)

// BuildManagerFieldGroup represents the BuildManager config fields
type BuildManagerFieldGroup struct {
FeatureBuildSupport bool `default:"" validate:"" json:"FEATURE_BUILD_SUPPORT" yaml:"FEATURE_BUILD_SUPPORT"`
BuildManagerConfig *BuildManagerDefinition `default:"" validate:"" json:"BUILD_MANAGER,omitempty" yaml:"BUILD_MANAGER,omitempty"`
}

// BuildManagerDefinition represents a single storage configuration as a tuple (Name, Arguments)
type BuildManagerDefinition struct {
Name string `default:"" validate:"" json:",inline" yaml:",inline"`
Args *BuildManagerArgs `default:"" validate:"" json:",inline" yaml:",inline"`
}

// BuildManagerArgs represents the arguments in the second value of a definition tuple
type BuildManagerArgs struct {
// Args for ephemeral
AllowedWorkerCount int `default:"" validate:"" json:"ALLOWED_WORKER_COUNT,omitempty" yaml:"ALLOWED_WORKER_COUNT,omitempty"`
OrchestratorPrefix string `default:"" validate:"" json:"ORCHESTRATOR_PREFIX,omitempty" yaml:"ORCHESTRATOR_PREFIX,omitempty"`
Orchestrator *OrchestratorArgs `default:"" validate:"" json:"ORCHESTRATOR,omitempty" yaml:"ORCHESTRATOR,omitempty"`
Executors []*ExecutorArgs `default:"" validate:"" json:"EXECUTORS,omitempty" yaml:"EXECUTORS,omitempty"`
}

// OrchestratorArgs represents the arguments in the orchestrator object
type OrchestratorArgs struct {
RedisHost string `default:"" validate:"" json:"REDIS_HOST,omitempty" yaml:"REDIS_HOST,omitempty"`
RedisPassword string `default:"" validate:"" json:"REDIS_PASSWORD,omitempty" yaml:"REDIS_PASSWORD,omitempty"`
RedisSSL bool `default:"" validate:"" json:"REDIS_SSL" yaml:"REDIS_SSL"`
RedisSkipKeyspaceEventSetup bool `default:"" validate:"" json:"REDIS_SKIP_KEYSPACE_EVENT_SETUP" yaml:"REDIS_SKIP_KEYSPACE_EVENT_SETUP"`
}

// ExecutorArgs represents the arguments in an executor object
type ExecutorArgs struct {
Executor string `default:"" validate:"" json:"EXECUTOR,omitempty" yaml:"EXECUTOR,omitempty"`
BuilderNamespace string `default:"" validate:"" json:"BUILDER_NAMESPACE,omitempty" yaml:"BUILDER_NAMESPACE,omitempty"`
K8sAPIServer string `default:"" validate:"" json:"K8S_API_SERVER,omitempty" yaml:"K8S_API_SERVER,omitempty"`
VolumeSize string `default:"" validate:"" json:"VOLUME_SIZE,omitempty" yaml:"VOLUME_SIZE,omitempty"`
KubernetesDistribution string `default:"" validate:"" json:"KUBERNETES_DISTRIBUTION,omitempty" yaml:"KUBERNETES_DISTRIBUTION,omitempty"`
ContainerMemoryLimits string `default:"" validate:"" json:"CONTAINER_MEMORY_LIMITS,omitempty" yaml:"CONTAINER_MEMORY_LIMITS,omitempty"`
ContainerCPULimits string `default:"" validate:"" json:"CONTAINER_CPU_LIMITS,omitempty" yaml:"CONTAINER_CPU_LIMITS,omitempty"`
ContainerMemoryRequest string `default:"" validate:"" json:"CONTAINER_MEMORY_REQUEST,omitempty" yaml:"CONTAINER_MEMORY_REQUEST,omitempty"`
ContainerCPURequest string `default:"" validate:"" json:"CONTAINER_CPU_REQUEST,omitempty" yaml:"CONTAINER_CPU_REQUEST,omitempty"`
NodeSelectorLabelKey string `default:"" validate:"" json:"NODE_SELECTOR_LABEL_KEY,omitempty" yaml:"NODE_SELECTOR_LABEL_KEY,omitempty"`
NodeSelectorLabelValue string `default:"" validate:"" json:"NODE_SELECTOR_LABEL_VALUE,omitempty" yaml:"NODE_SELECTOR_LABEL_VALUE,omitempty"`
ContainerRuntime string `default:"" validate:"" json:"CONTAINER_RUNTIME,omitempty" yaml:"CONTAINER_RUNTIME,omitempty"`
ServiceAccountName string `default:"" validate:"" json:"SERVICE_ACCOUNT_NAME,omitempty" yaml:"SERVICE_ACCOUNT_NAME,omitempty"`
ServiceAccountToken string `default:"" validate:"" json:"SERVICE_ACCOUNT_TOKEN,omitempty" yaml:"SERVICE_ACCOUNT_TOKEN,omitempty"`
QuayUsername string `default:"" validate:"" json:"QUAY_USERNAME,omitempty" yaml:"QUAY_USERNAME,omitempty"`
QuayPassword string `default:"" validate:"" json:"QUAY_PASSWORD,omitempty" yaml:"QUAY_PASSWORD,omitempty"`
WorkerImage string `default:"" validate:"" json:"WORKER_IMAGE,omitempty" yaml:"WORKER_IMAGE,omitempty"`
WorkerTag string `default:"" validate:"" json:"WORKER_TAG,omitempty" yaml:"WORKER_TAG,omitempty"`
BuilderVMContainerImage string `default:"" validate:"" json:"BUILDER_VM_CONTAINER_IMAGE,omitempty" yaml:"BUILDER_VM_CONTAINER_IMAGE,omitempty"`
SetupTime int `default:"" validate:"" json:"SETUP_TIME,omitempty" yaml:"SETUP_TIME,omitempty"`
MinimumRetryThreshold int `default:"" validate:"" json:"MINIMUM_RETRY_THRESHOLD" yaml:"MINIMUM_RETRY_THRESHOLD"`
SSHAuthorizedKeys []interface{} `default:"" validate:"" json:"SSH_AUTHORIZED_KEYS,omitempty" yaml:"SSH_AUTHORIZED_KEYS,omitempty"`
// ec2 fields
EC2Region string `default:"" validate:"" json:"EC2_REGION,omitempty" yaml:"EC2_REGION,omitempty"`
CoreOSAMI string `default:"" validate:"" json:"COREOS_AMI,omitempty" yaml:"COREOS_AMI,omitempty"`
AwsAccessKey string `default:"" validate:"" json:"AWS_ACCESS_KEY,omitempty" yaml:"AWS_ACCESS_KEY,omitempty"`
AwsSecretKey string `default:"" validate:"" json:"AWS_SECRET_KEY,omitempty" yaml:"AWS_SECRET_KEY,omitempty"`
EC2InstanceType string `default:"" validate:"" json:"EC2_INSTANCE_TYPE,omitempty" yaml:"EC2_INSTANCE_TYPE,omitempty"`
EC2VPCSubnetID string `default:"" validate:"" json:"EC2_VPC_SUBNET_ID,omitempty" yaml:"EC2_VPC_SUBNET_ID,omitempty"`
EC2SecurityGroupIDs []interface{} `default:"" validate:"" json:"EC2_SECURITY_GROUP_IDS,omitempty" yaml:"EC2_SECURITY_GROUP_IDS,omitempty"`
EC2KeyName string `default:"" validate:"" json:"EC2_KEY_NAME,omitempty" yaml:"EC2_KEY_NAME,omitempty"`
BlockDeviceSize int `default:"" validate:"" json:"BLOCK_DEVICE_SIZE,omitempty" yaml:"BLOCK_DEVICE_SIZE,omitempty"`
}

// NewBuildManagerFieldGroup creates a new BitbucketBuildTriggerFieldGroup
func NewBuildManagerFieldGroup(fullConfig map[string]interface{}) (*BuildManagerFieldGroup, error) {
newBuildManagerFieldGroup := &BuildManagerFieldGroup{}

bytes, err := yaml.Marshal(fullConfig)
if err != nil {
return nil, err
}

err = yaml.Unmarshal(bytes, newBuildManagerFieldGroup)
if err != nil {
return nil, err
}

defaults.Set(newBuildManagerFieldGroup)

return newBuildManagerFieldGroup, nil
}

func (bm *BuildManagerDefinition) UnmarshalYAML(value *yaml.Node) error {

// Ensure correct shape
if len(value.Content) != 2 || value.Content[0].Tag != "!!str" || value.Content[1].Tag != "!!map" {
return fmt.Errorf("Incorrect format for value BUILD_MANAGER")
}

bm.Name = value.Content[0].Value
err := value.Content[1].Decode(&bm.Args)
if err != nil {
return err
}

return nil

}

func (bm *BuildManagerDefinition) MarshalYAML() (interface{}, error) {

name := &yaml.Node{
Kind: yaml.ScalarNode,
Value: bm.Name,
}

args := &yaml.Node{}
err := args.Encode(bm.Args)
if err != nil {
return nil, err
}

node := &yaml.Node{
Kind: yaml.SequenceNode,
Content: []*yaml.Node{name, args},
}

return node, nil

}
6 changes: 6 additions & 0 deletions pkg/lib/fieldgroups/buildmanager/buildmanager_fields.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package buildmanager

// Fields returns a list of strings representing the fields in this field group
func (fg *BuildManagerFieldGroup) Fields() []string {
return []string{"FEATURE_BUILD_SUPPORT", "BUILD_MANAGER"}
}
128 changes: 128 additions & 0 deletions pkg/lib/fieldgroups/buildmanager/buildmanager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package buildmanager

import (
"reflect"
"testing"

"github.com/jojomi/go-spew/spew"
"gopkg.in/yaml.v3"
)

func TestValidateBuildManager(t *testing.T) {

before := []byte(`
FEATURE_BUILD_SUPPORT: true
BUILD_MANAGER:
- ephemeral
- ALLOWED_WORKER_COUNT: 1
ORCHESTRATOR_PREFIX: buildman/production/
ORCHESTRATOR:
REDIS_HOST: quay-redis-host
REDIS_PASSWORD: quay-redis-password
REDIS_SSL: true
REDIS_SKIP_KEYSPACE_EVENT_SETUP: false
EXECUTORS:
- EXECUTOR: kubernetes
BUILDER_NAMESPACE: builder
K8S_API_SERVER: api.openshift.somehost.org:6443
VOLUME_SIZE: 8G
KUBERNETES_DISTRIBUTION: openshift
CONTAINER_MEMORY_LIMITS: 5120Mi
CONTAINER_CPU_LIMITS: 1000m
CONTAINER_MEMORY_REQUEST: 3968Mi
CONTAINER_CPU_REQUEST: 500m
NODE_SELECTOR_LABEL_KEY: beta.kubernetes.io/instance-type
NODE_SELECTOR_LABEL_VALUE: n1-standard-4
CONTAINER_RUNTIME: podman
SERVICE_ACCOUNT_NAME: name
SERVICE_ACCOUNT_TOKEN: name
QUAY_USERNAME: brew-username
QUAY_PASSWORD: brew-password
WORKER_IMAGE: <registry>/quay-quay-builder
WORKER_TAG: some_tag
BUILDER_VM_CONTAINER_IMAGE: '<registry>/quay-quay-builder-qemu-rhcos:v3.4.0'
SETUP_TIME: 180
MINIMUM_RETRY_THRESHOLD: 0
SSH_AUTHORIZED_KEYS:
- ssh-rsa 12345 someuser@email.com
- ssh-rsa 67890 someuser2@email.com
`)

var confMap BuildManagerFieldGroup
err := yaml.Unmarshal(before, &confMap)
if err != nil {
t.Errorf(err.Error())
return
}

after, err := yaml.Marshal(confMap)
if err != nil {
t.Errorf(err.Error())
return
}

var confMap2 BuildManagerFieldGroup
err = yaml.Unmarshal(after, &confMap2)
if err != nil {
t.Errorf("fail" + err.Error())
return
}

if !reflect.DeepEqual(confMap, confMap2) {
t.Errorf("unequal")
spew.Dump(confMap)
spew.Dump(confMap2)
return
}

spew.Dump(confMap2)
t.Error()

// // Define test data
// var tests = []struct {
// name string
// config map[string]interface{}
// want string
// }{{name: "my_test",
// config: confMap,
// want: "invalid"},
// }

// // Iterate through tests
// for _, tt := range tests {

// // Run specific test
// t.Run(tt.name, func(t *testing.T) {

// // Get validation result
// fg, err := NewBuildManagerFieldGroup(tt.config)
// if err != nil && tt.want != "typeError" {
// t.Errorf("Expected %s. Received %s", tt.want, err.Error())
// }

// opts := shared.Options{
// Mode: "testing",
// }

// validationErrors := fg.Validate(opts)

// // Get result type
// received := ""
// if len(validationErrors) == 0 {
// received = "valid"
// } else {
// received = "invalid"
// }

// // Compare with expected
// if tt.want != received {
// t.Errorf("Expected %s. Received %s", tt.want, received)
// for _, err := range validationErrors {
// t.Errorf(err.Message)
// }
// }

// })
// }

}
19 changes: 19 additions & 0 deletions pkg/lib/fieldgroups/buildmanager/buildmanager_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package buildmanager

import (

//mysql driver
_ "github.com/lib/pq" // postgres driver
"github.com/quay/config-tool/pkg/lib/shared"
)

// Validate checks the configuration settings for this field group
func (fg *BuildManagerFieldGroup) Validate(opts shared.Options) []shared.ValidationError {

// Make empty errors
errors := []shared.ValidationError{}

// Return errors
return errors

}

0 comments on commit 3017304

Please sign in to comment.