Skip to content

Commit

Permalink
feat: add support for labels in func.yaml
Browse files Browse the repository at this point in the history
This change adds support for setting labels on deployed functions. It does
not include any command line ability to do so. It was unclear how to best
test this, as YAML marshaling will blow up if that bit is incorrect.

I suppose the ideal test would be to actually add a label in an integration
test and check to see if it's there on deployment.

Signed-off-by: Lance Ball <lball@redhat.com>
  • Loading branch information
lance committed Jun 30, 2021
1 parent 08df25b commit 0c11af2
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 21 deletions.
1 change: 1 addition & 0 deletions cmd/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ builderMap:
default: quay.io/boson/faas-go-builder
envs: []
annotations: {}
labels: {}
`
tmpDir, err := ioutil.TempDir("", "bar")
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type config struct {
Envs Envs `yaml:"envs"`
Annotations map[string]string `yaml:"annotations"`
Options Options `yaml:"options"`
Labels map[string]string `yaml:"labels"`
// Add new values to the toConfig/fromConfig functions.
}

Expand Down Expand Up @@ -221,6 +222,7 @@ func fromConfig(c config) (f Function) {
Envs: c.Envs,
Annotations: c.Annotations,
Options: c.Options,
Labels: c.Labels,
}
}

Expand All @@ -238,6 +240,7 @@ func toConfig(f Function) config {
Envs: f.Envs,
Annotations: f.Annotations,
Options: f.Options,
Labels: f.Labels,
}
}

Expand Down
4 changes: 4 additions & 0 deletions function.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ type Function struct {

// Options to be set on deployed function (scaling, etc.)
Options Options

// Map of user-supplied labels
// Example: { "tier": "backend" }
Labels map[string]string
}

// NewFunction loads a Function from a path on disk. use .Initialized() to determine if
Expand Down
53 changes: 33 additions & 20 deletions knative/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (result fn.Deploym
referencedSecrets := sets.NewString()
referencedConfigMaps := sets.NewString()

service, err := generateNewService(f.Name, f.ImageWithDigest(), f.Runtime, f.Envs, f.Volumes, f.Annotations, f.Options)
// service, err := generateNewService(f.Name, f.ImageWithDigest(), f.Runtime, f.Envs, f.Volumes, f.Annotations, f.Options)
service, err := generateNewService(f)
if err != nil {
err = fmt.Errorf("knative deployer failed to generate the Knative Service: %v", err)
return fn.DeploymentResult{}, err
Expand Down Expand Up @@ -120,7 +121,7 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (result fn.Deploym
return fn.DeploymentResult{}, err
}

_, err = client.UpdateServiceWithRetry(ctx, f.Name, updateService(f.ImageWithDigest(), newEnv, newEnvFrom, newVolumes, newVolumeMounts, f.Annotations, f.Options), 3)
_, err = client.UpdateServiceWithRetry(ctx, f.Name, updateService(f, newEnv, newEnvFrom, newVolumes, newVolumeMounts), 3)
if err != nil {
err = fmt.Errorf("knative deployer failed to update the Knative Service: %v", err)
return fn.DeploymentResult{}, err
Expand Down Expand Up @@ -149,42 +150,50 @@ func probeFor(url string) *corev1.Probe {
}
}

func generateNewService(name, image, runtime string, envs fn.Envs, volumes fn.Volumes, annotations map[string]string, options fn.Options) (*servingv1.Service, error) {
// func generateNewService(name, image, runtime string, envs fn.Envs, volumes fn.Volumes, annotations map[string]string, options fn.Options) (*servingv1.Service, error) {
func generateNewService(f fn.Function) (*servingv1.Service, error) {
containers := []corev1.Container{
{
Image: image,
Image: f.ImageWithDigest(),
},
}

if runtime != "quarkus" {
if f.Runtime != "quarkus" {
containers[0].LivenessProbe = probeFor("/health/liveness")
containers[0].ReadinessProbe = probeFor("/health/readiness")
}

referencedSecrets := sets.NewString()
referencedConfigMaps := sets.NewString()

newEnv, newEnvFrom, err := processEnvs(envs, &referencedSecrets, &referencedConfigMaps)
newEnv, newEnvFrom, err := processEnvs(f.Envs, &referencedSecrets, &referencedConfigMaps)
if err != nil {
return nil, err
}
containers[0].Env = newEnv
containers[0].EnvFrom = newEnvFrom

newVolumes, newVolumeMounts, err := processVolumes(volumes, &referencedSecrets, &referencedConfigMaps)
newVolumes, newVolumeMounts, err := processVolumes(f.Volumes, &referencedSecrets, &referencedConfigMaps)
if err != nil {
return nil, err
}
containers[0].VolumeMounts = newVolumeMounts
labels := map[string]string{
"boson.dev/function": "true",
"boson.dev/runtime": f.Runtime,
}

if f.Labels != nil {
for k, v := range f.Labels {
labels[k] = v
}
}

service := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
"boson.dev/function": "true",
"boson.dev/runtime": runtime,
},
Annotations: annotations,
Name: f.Name,
Labels: labels,
Annotations: f.Annotations,
},
Spec: v1.ServiceSpec{
ConfigurationSpec: v1.ConfigurationSpec{
Expand All @@ -200,33 +209,37 @@ func generateNewService(name, image, runtime string, envs fn.Envs, volumes fn.Vo
},
}

err = setServiceOptions(&service.Spec.Template, options)
err = setServiceOptions(&service.Spec.Template, f.Options)
if err != nil {
return service, err
}

return service, nil
}

func updateService(image string, newEnv []corev1.EnvVar, newEnvFrom []corev1.EnvFromSource, newVolumes []corev1.Volume, newVolumeMounts []corev1.VolumeMount,
annotations map[string]string, options fn.Options) func(service *servingv1.Service) (*servingv1.Service, error) {
// func updateService(image string, newEnv []corev1.EnvVar, newEnvFrom []corev1.EnvFromSource, newVolumes []corev1.Volume, newVolumeMounts []corev1.VolumeMount,
func updateService(f fn.Function, newEnv []corev1.EnvVar, newEnvFrom []corev1.EnvFromSource, newVolumes []corev1.Volume, newVolumeMounts []corev1.VolumeMount) func(service *servingv1.Service) (*servingv1.Service, error) {
return func(service *servingv1.Service) (*servingv1.Service, error) {
// Removing the name so the k8s server can fill it in with generated name,
// this prevents conflicts in Revision name when updating the KService from multiple places.
service.Spec.Template.Name = ""

// Don't bother being as clever as we are with env variables
// Just set the annotations to be whatever we find in func.yaml
for k, v := range annotations {
// Just set the annotations and labels to be whatever we find in func.yaml
for k, v := range f.Annotations {
service.ObjectMeta.Annotations[k] = v
}

err := setServiceOptions(&service.Spec.Template, options)
err := setServiceOptions(&service.Spec.Template, f.Options)
if err != nil {
return service, err
}

err = flags.UpdateImage(&service.Spec.Template.Spec.PodSpec, image)
for k, v := range f.Labels {
service.ObjectMeta.Labels[k] = v
}

err = flags.UpdateImage(&service.Spec.Template.Spec.PodSpec, f.ImageWithDigest())
if err != nil {
return service, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkged.go

Large diffs are not rendered by default.

0 comments on commit 0c11af2

Please sign in to comment.