Skip to content
This repository has been archived by the owner on Nov 15, 2022. It is now read-only.

Commit

Permalink
Process containers list same way
Browse files Browse the repository at this point in the history
Abstracted out the processing on containers. So now this abstracted
functions can also be called on list of containers in init-container
not just container in pod.
  • Loading branch information
surajssd committed Jul 31, 2017
1 parent ab990b5 commit dfb4dfb
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 73 deletions.
1 change: 1 addition & 0 deletions pkg/spec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type ConfigMapMod struct {

type PodSpecMod struct {
Containers []Container `json:"containers,omitempty"`
InitContainers []Container `json:"initContainers,omitempty"`
api_v1.PodSpec `json:",inline"`
}

Expand Down
78 changes: 5 additions & 73 deletions pkg/transform/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,75 +265,6 @@ func populateVolumes(app *spec.App) error {
return nil
}

func populateContainerHealth(app *spec.App) error {
for cn, c := range app.Containers {
// check if health and liveness given together
if c.Health != nil && (c.ReadinessProbe != nil || c.LivenessProbe != nil) {
return fmt.Errorf("cannot define field health and livnessProbe"+
" or readinessProbe together in app.containers[%d]", cn)
}
if c.Health != nil {
c.LivenessProbe = c.Health
c.ReadinessProbe = c.Health
}
app.PodSpec.Containers = append(app.PodSpec.Containers, c.Container)
}
return nil
}

func populateEnvFrom(app *spec.App) error {
// iterate on the containers so that we can extract envFrom
// that we have custom defined
for ci, c := range app.Containers {
for ei, e := range c.EnvFrom {
cmName := e.ConfigMapRef.Name

// we also need to check if the configMap specified if it exists
var cmFound bool
// to populate the envs we also need to know the data
// from configmaps defined in the app
for _, cm := range app.ConfigMaps {
// we will only populate the configMap that is specified
// not every configMap out there
if cm.Name != cmName {
continue
}
var envs []api_v1.EnvVar
// start populating
for k := range cm.Data {
// here we are directly referring to the containers
// from app.PodSpec.Containers because that is where data
// is parsed into so populating that is more valid thing to do
envs = append(envs, api_v1.EnvVar{
Name: k,
ValueFrom: &api_v1.EnvVarSource{
ConfigMapKeyRef: &api_v1.ConfigMapKeySelector{
LocalObjectReference: api_v1.LocalObjectReference{
Name: cmName,
},
Key: k,
},
},
})
}
// we collect all the envs from configMap before
// envs provided inside the container
envs = append(envs, app.PodSpec.Containers[ci].Env...)
app.PodSpec.Containers[ci].Env = envs

cmFound = true
// once the population is done we exit out of the loop
// we don't need to check other configMaps
break
}
if !cmFound {
return fmt.Errorf("undefined configMap in app.containers[%d].envFrom[%d].configMapRef.name", ci, ei)
}
}
}
return nil
}

func CreateK8sObjects(app *spec.App) ([]runtime.Object, error) {
var objects []runtime.Object

Expand All @@ -351,16 +282,17 @@ func CreateK8sObjects(app *spec.App) ([]runtime.Object, error) {
return nil, errors.Wrap(err, "Unable to create Kubernetes Ingresses")
}

// withdraw the health and populate actual pod spec
if err := populateContainerHealth(app); err != nil {
app.PodSpec.Containers, err = populateContainers(app.Containers, app.ConfigMaps)
if err != nil {
return nil, errors.Wrapf(err, "app %q", app.Name)
}
log.Debugf("object after population: %#v\n", app)

// withdraw the envFrom and populate actual containers
if err := populateEnvFrom(app); err != nil {
app.PodSpec.InitContainers, err = populateContainers(app.InitContainers, app.ConfigMaps)
if err != nil {
return nil, errors.Wrapf(err, "app %q", app.Name)
}
log.Debugf("object after population: %#v\n", app)

// create pvc for each root level persistent volume
var pvcs []runtime.Object
Expand Down
101 changes: 101 additions & 0 deletions pkg/transform/kubernetes/populators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package kubernetes

import (
"encoding/json"
"fmt"

"github.com/kedgeproject/kedge/pkg/spec"

log "github.com/Sirupsen/logrus"
"github.com/pkg/errors"
api_v1 "k8s.io/client-go/pkg/api/v1"
)

func populateProbes(c spec.Container) (spec.Container, error) {
// check if health and liveness given together
if c.Health != nil && (c.ReadinessProbe != nil || c.LivenessProbe != nil) {
return c, fmt.Errorf("cannot define field 'health' and " +
"'livnessProbe' or 'readinessProbe' together")
}
if c.Health != nil {
c.LivenessProbe = c.Health
c.ReadinessProbe = c.Health
}
return c, nil
}

func searchConfigMap(cms []spec.ConfigMapMod, name string) (spec.ConfigMapMod, error) {
for _, cm := range cms {
if cm.Name == name {
return cm, nil
}
}
return spec.ConfigMapMod{}, fmt.Errorf("configMap %q not found", name)
}

func convertEnvFromToEnvs(envFrom []spec.EnvFromSource, cms []spec.ConfigMapMod) ([]api_v1.EnvVar, error) {
var envs []api_v1.EnvVar

// we will iterate on all envFroms
for ei, e := range envFrom {
cmName := e.ConfigMapRef.Name

// see if the configMap name which is given actually exists
cm, err := searchConfigMap(cms, cmName)
if err != nil {
return nil, errors.Wrapf(err, "envFrom[%d].configMapRef.name", ei)
}
// once that configMap is found extract all data from it and create a env out of it
for k := range cm.Data {
envs = append(envs, api_v1.EnvVar{
Name: k,
ValueFrom: &api_v1.EnvVarSource{
ConfigMapKeyRef: &api_v1.ConfigMapKeySelector{
LocalObjectReference: api_v1.LocalObjectReference{
Name: cmName,
},
Key: k,
},
},
})
}
}
return envs, nil
}

func populateEnvFrom(c spec.Container, cms []spec.ConfigMapMod) (spec.Container, error) {
// now do the env from
envs, err := convertEnvFromToEnvs(c.EnvFrom, cms)
if err != nil {
return c, err
}
// we collect all the envs from configMap before
// envs provided inside the container
envs = append(envs, c.Env...)
c.Env = envs
return c, nil
}

func populateContainers(containers []spec.Container, cms []spec.ConfigMapMod) ([]api_v1.Container, error) {
var cnts []api_v1.Container

for cn, c := range containers {
// process health field
c, err := populateProbes(c)
if err != nil {
return cnts, errors.Wrapf(err, "error converting 'health' to 'probes', app.containers[%d]", cn)
}

// process envFrom field
c, err = populateEnvFrom(c, cms)
if err != nil {
return cnts, fmt.Errorf("error converting 'envFrom' to 'envs', app.containers[%d].%s", cn, err.Error())
}

cnts = append(cnts, c.Container)
}

b, _ := json.MarshalIndent(cnts, "", " ")
log.Debugf("containers after populating health: %s", string(b))
return cnts, nil
}

0 comments on commit dfb4dfb

Please sign in to comment.