Skip to content

Commit

Permalink
Add resources for controller main container
Browse files Browse the repository at this point in the history
  • Loading branch information
Julio Chana committed Dec 4, 2018
1 parent 01add9c commit 27ed5dc
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ type Config struct {
WorkerImage string
WorkerPullPolicy string
WorkerServiceAccount string
WorkerRequestsCPU string
WorkerRequestsMemory string
WorkerLimitsCPU string
WorkerLimitsMemory string
}

// Controller listens for new brigade builds and starts the worker pods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -579,3 +579,92 @@ func TestController_WithProjectSpecificWorkerConfig(t *testing.T) {
})
}
}

func TestController_WithWorkerResources(t *testing.T) {
createdPod := false
client := fake.NewSimpleClientset()
client.PrependReactor("create", "pods", func(action core.Action) (bool, runtime.Object, error) {
createdPod = true
t.Log("creating pod")
return false, nil, nil
})

config := &Config{
Namespace: v1.NamespaceDefault,
WorkerImage: "deis/brigade-worker:latest",
WorkerPullPolicy: string(v1.PullIfNotPresent),
WorkerLimitsCPU: "1",
WorkerLimitsMemory: "1Gi",
WorkerRequestsCPU: "500m",
WorkerRequestsMemory: "500Mi",
}
controller := NewController(client, config)

secret := v1.Secret{
ObjectMeta: meta.ObjectMeta{
Name: "moby",
Namespace: v1.NamespaceDefault,
Labels: map[string]string{
"heritage": "brigade",
"component": "build",
"project": "ahab",
"build": "queequeg",
},
},
Data: map[string][]byte{
"script": []byte("hello"),
},
}

sidecarImage := "fake/sidecar:latest"
project := v1.Secret{
ObjectMeta: meta.ObjectMeta{
Name: "ahab",
Namespace: v1.NamespaceDefault,
Labels: map[string]string{
"heritage": "brigade",
"component": "project",
},
},
// This and the missing 'script' will trigger an initContainer
Data: map[string][]byte{
"vcsSidecar": []byte(sidecarImage),
},
}

// Now let's start the controller
stop := make(chan struct{})
defer close(stop)
go controller.Run(1, stop)

client.CoreV1().Secrets(v1.NamespaceDefault).Create(&secret)
client.CoreV1().Secrets(v1.NamespaceDefault).Create(&project)

// Let's wait for the controller to create the pod
wait.Poll(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
return createdPod, nil
})

pod, err := client.CoreV1().Pods(v1.NamespaceDefault).Get(secret.Name, meta.GetOptions{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

c := pod.Spec.Containers[0]
if c.Name != "brigade-runner" {
t.Error("Container.Name is not correct")
}

if cpu := c.Resources.Limits.Cpu(); cpu.String() != config.WorkerLimitsCPU {
t.Errorf("Worker resources limit cpu is not the expected one. Got: %s, Expected: %s", cpu.String(), config.WorkerLimitsCPU)
}
if mem := c.Resources.Limits.Memory(); mem.String() != config.WorkerLimitsMemory {
t.Errorf("Worker resources limit memory is not the expected one. Got: %s, Expected: %s", mem.String(), config.WorkerLimitsMemory)
}
if cpu := c.Resources.Requests.Cpu(); cpu.String() != config.WorkerRequestsCPU {
t.Errorf("Worker resources limit cpu is not the expected one. Got: %s, Expected: %s", cpu.String(), config.WorkerRequestsCPU)
}
if mem := c.Resources.Requests.Memory(); mem.String() != config.WorkerRequestsMemory {
t.Errorf("Worker resources limit memory is not the expected one. Got: %s, Expected: %s", mem.String(), config.WorkerRequestsMemory)
}
}
26 changes: 25 additions & 1 deletion brigade-controller/cmd/brigade-controller/controller/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apiresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/Azure/brigade/pkg/storage/kube"
Expand Down Expand Up @@ -77,6 +78,8 @@ func (c *Controller) updateBuildStatus(build *v1.Secret) error {
func NewWorkerPod(build, project *v1.Secret, config *Config) v1.Pod {
env := workerEnv(project, build, config)

resources := workerResources(config)

cmd := []string{"yarn", "-s", "start"}
if cmdBytes, ok := project.Data["workerCommand"]; ok && len(cmdBytes) > 0 {
cmd = strings.Split(string(cmdBytes), " ")
Expand Down Expand Up @@ -114,7 +117,8 @@ func NewWorkerPod(build, project *v1.Secret, config *Config) v1.Pod {
projectVolume,
sidecarVolume,
},
Env: env,
Env: env,
Resources: resources,
}},
Volumes: []v1.Volume{{
Name: buildVolume.Name,
Expand Down Expand Up @@ -233,6 +237,26 @@ func workerEnv(project, build *v1.Secret, config *Config) []v1.EnvVar {
}
}

// workerResources generates the resources for the worker, given in the cofiguration
// If the value is not given, or it's wrong, an empty quantity will be set
func workerResources(config *Config) v1.ResourceRequirements {
limitCPU, _ := apiresource.ParseQuantity(config.WorkerLimitsCPU)
limitMemory, _ := apiresource.ParseQuantity(config.WorkerLimitsMemory)
requestCPU, _ := apiresource.ParseQuantity(config.WorkerRequestsCPU)
requestMemory, _ := apiresource.ParseQuantity(config.WorkerRequestsMemory)

return v1.ResourceRequirements{
Limits: v1.ResourceList{
v1.ResourceCPU: limitCPU,
v1.ResourceMemory: limitMemory,
},
Requests: v1.ResourceList{
v1.ResourceCPU: requestCPU,
v1.ResourceMemory: requestMemory,
},
}
}

// secretRef generate a SecretKeyRef env var entry if `key` is present in `secret`.
// If the key does not exist a name/value pair is returned with an empty value
func secretRef(key string, secret *v1.Secret) *v1.EnvVarSource {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)

func TestNewWorkerPod_Defaults(t *testing.T) {
Expand All @@ -30,4 +31,22 @@ func TestNewWorkerPod_Defaults(t *testing.T) {
t.Errorf("Unexpected command: %s", cmd)
}

emptyQuantity := resource.Quantity{}

if quantity := container.Resources.Limits.Cpu(); *quantity != emptyQuantity {
t.Errorf("Unexpected cpu limits quantity: %s", quantity.String())
}

if quantity := container.Resources.Limits.Memory(); *quantity != emptyQuantity {
t.Errorf("Unexpected memory limits quantity: %s", quantity.String())
}

if quantity := container.Resources.Requests.Cpu(); *quantity != emptyQuantity {
t.Errorf("Unexpected cpu requests quantity: %s", quantity.String())
}

if quantity := container.Resources.Requests.Memory(); *quantity != emptyQuantity {
t.Errorf("Unexpected memory requests quantity: %s", quantity.String())
}

}
4 changes: 4 additions & 0 deletions brigade-controller/cmd/brigade-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func main() {
flag.StringVar(&ctrConfig.WorkerImage, "worker-image", defaultWorkerImage(), "kubernetes worker image")
flag.StringVar(&ctrConfig.WorkerPullPolicy, "worker-pull-policy", defaultWorkerPullPolicy(), "kubernetes worker image pull policy")
flag.StringVar(&ctrConfig.WorkerServiceAccount, "worker-service-account", defaultWorkerServiceAccount(), "kubernetes worker service account name")
flag.StringVar(&ctrConfig.WorkerRequestsCPU, "worker-requests-cpu", "", "kubernetes worker cpu requests")
flag.StringVar(&ctrConfig.WorkerRequestsMemory, "worker-requests-memory", "", "kubernetes worker memory requests")
flag.StringVar(&ctrConfig.WorkerLimitsCPU, "worker-limits-cpu", "", "kubernetes worker cpu limits")
flag.StringVar(&ctrConfig.WorkerLimitsMemory, "worker-limits-memory", "", "kubernetes worker memory limits")
flag.Parse()

// creates the connection
Expand Down

0 comments on commit 27ed5dc

Please sign in to comment.