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

Commit

Permalink
Adding annotations to all resources (#177)
Browse files Browse the repository at this point in the history
* Adding annotations to all resources

* Added annotations for service objects since they already allowed for that feature

* Updated user guide and utils

* Made service annotations take precedence over general annotations

* Add helper util for merging maps and use it for annotations

* Fix unit test error
  • Loading branch information
JusteenR authored and leochr committed Nov 6, 2019
1 parent 8b40503 commit 752e23b
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 19 deletions.
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

## [0.2.2]

### Added

- Allow users to add new annotations or override default annotations for resources created by the operator via setting annotations on `AppsodyApplication` CRs. ([#177](https://github.com/appsody/appsody-operator/issues/177))

## [0.2.1]

### Added
Expand Down Expand Up @@ -43,7 +49,8 @@ All notable changes to this project will be documented in this file.

The initial release of the Appsody Operator 🎉🥳

[Unreleased]: https://github.com/appsody/appsody-operator/compare/v0.2.1...HEAD
[0.2.1]: https://github.com/appsody/appsody-operator/compare/v0.2.0...v0.2.1
[Unreleased]: https://github.com/appsody/appsody-operator/compare/v0.2.2...HEAD
[0.2.1]: https://github.com/appsody/appsody-operator/compare/0.2.1...v0.2.2
[0.2.1]: https://github.com/appsody/appsody-operator/compare/v0.2.0...0.2.1
[0.2.0]: https://github.com/appsody/appsody-operator/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/appsody/appsody-operator/releases/tag/v0.1.0
18 changes: 18 additions & 0 deletions doc/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,24 @@ spec:

_After the initial deployment of `AppsodyApplication`, any changes to its labels would be applied only when one of the parameters from `spec` is updated._

### Annotations

To add new annotations into all resources created for an `AppsodyApplication`, specify them in your CR as key/value pairs.

```yaml
apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
name: my-appsody-app
annotations:
my-annotation-key: my-annotation-value
spec:
stack: java-microprofile
applicationImage: quay.io/my-repo/my-app:1.0
```

_After the initial deployment of `AppsodyApplication`, any changes to its annotations would be applied only when one of the parameters from `spec` is updated._

### Environment variables

You can set environment variables for your application container. To set environment variables, specify `env` and/or `envFrom` fields in your CR. The environment variables can come directly from key/value pairs, `ConfigMap`s or `Secret`s.
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/appsody/v1beta1/appsodyapplication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,11 @@ func (cr *AppsodyApplication) GetLabels() map[string]string {
return labels
}

// GetAnnotations returns set of annotations to be added to all resources
func (cr *AppsodyApplication) GetAnnotations() map[string]string {
return cr.Annotations
}

// GetType returns status condition type
func (c *StatusCondition) GetType() common.StatusConditionType {
return common.StatusConditionTypeReconciled
Expand Down
1 change: 1 addition & 0 deletions pkg/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,6 @@ type BaseApplication interface {
GetCreateAppDefinition() *bool
GetMonitoring() BaseApplicationMonitoring
GetLabels() map[string]string
GetAnnotations() map[string]string
GetStatus() BaseApplicationStatus
}
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func (r *ReconcileAppsodyApplication) Reconcile(request reconcile.Request) (reco
svc := &corev1.Service{ObjectMeta: defaultMeta}
err = r.CreateOrUpdate(svc, instance, func() error {
appsodyutils.CustomizeService(svc, ba)
svc.Annotations = instance.Spec.Service.Annotations
svc.Annotations = appsodyutils.MergeMaps(svc.Annotations, instance.Spec.Service.Annotations)
if instance.Spec.Monitoring != nil {
svc.Labels["app.appsody.dev/monitor"] = "true"
} else {
Expand Down
52 changes: 36 additions & 16 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,34 @@ import (

// CustomizeDeployment ...
func CustomizeDeployment(deploy *appsv1.Deployment, ba common.BaseApplication) {
obj := ba.(metav1.Object)
deploy.Labels = ba.GetLabels()
deploy.Annotations = MergeMaps(deploy.Annotations, ba.GetAnnotations())

obj := ba.(metav1.Object)
deploy.Spec.Replicas = ba.GetReplicas()

deploy.Spec.Selector = &metav1.LabelSelector{
MatchLabels: map[string]string{
"app.kubernetes.io/name": obj.GetName(),
},
}

if deploy.Annotations == nil {
deploy.Annotations = make(map[string]string)
}
UpdateAppDefinition(deploy.Labels, deploy.Annotations, ba)
}

// CustomizeStatefulSet ...
func CustomizeStatefulSet(statefulSet *appsv1.StatefulSet, ba common.BaseApplication) {
obj := ba.(metav1.Object)
statefulSet.Labels = ba.GetLabels()
statefulSet.Annotations = MergeMaps(statefulSet.Annotations, ba.GetAnnotations())

statefulSet.Spec.Replicas = ba.GetReplicas()
obj := ba.(metav1.Object)
statefulSet.Spec.ServiceName = obj.GetName() + "-headless"
statefulSet.Spec.Selector = &metav1.LabelSelector{
MatchLabels: map[string]string{
"app.kubernetes.io/name": obj.GetName(),
},
}

if statefulSet.Annotations == nil {
statefulSet.Annotations = make(map[string]string)
}
UpdateAppDefinition(statefulSet.Labels, statefulSet.Annotations, ba)
}

Expand Down Expand Up @@ -85,6 +81,7 @@ func UpdateAppDefinition(labels map[string]string, annotations map[string]string
func CustomizeRoute(route *routev1.Route, ba common.BaseApplication) {
obj := ba.(metav1.Object)
route.Labels = ba.GetLabels()
route.Annotations = MergeMaps(route.Annotations, ba.GetAnnotations())
route.Spec.To.Kind = "Service"
route.Spec.To.Name = obj.GetName()
weight := int32(100)
Expand All @@ -102,8 +99,9 @@ func ErrorIsNoMatchesForKind(err error, kind string, version string) bool {

// CustomizeService ...
func CustomizeService(svc *corev1.Service, ba common.BaseApplication) {
svc.Labels = ba.GetLabels()
obj := ba.(metav1.Object)
svc.Labels = ba.GetLabels()
svc.Annotations = MergeMaps(svc.Annotations, ba.GetAnnotations())

if len(svc.Spec.Ports) == 0 {
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{})
Expand All @@ -120,8 +118,10 @@ func CustomizeService(svc *corev1.Service, ba common.BaseApplication) {

// CustomizePodSpec ...
func CustomizePodSpec(pts *corev1.PodTemplateSpec, ba common.BaseApplication) {
pts.Labels = ba.GetLabels()
obj := ba.(metav1.Object)
pts.Labels = ba.GetLabels()
pts.Annotations = MergeMaps(pts.Annotations, ba.GetAnnotations())

if len(pts.Spec.Containers) == 0 {
pts.Spec.Containers = append(pts.Spec.Containers, corev1.Container{})
}
Expand Down Expand Up @@ -185,7 +185,7 @@ func CustomizePersistence(statefulSet *appsv1.StatefulSet, ba common.BaseApplica
},
},
}

pvc.Annotations = MergeMaps(pvc.Annotations, ba.GetAnnotations())
}
statefulSet.Spec.VolumeClaimTemplates = append(statefulSet.Spec.VolumeClaimTemplates, *pvc)
}
Expand All @@ -212,6 +212,8 @@ func CustomizePersistence(statefulSet *appsv1.StatefulSet, ba common.BaseApplica
// CustomizeServiceAccount ...
func CustomizeServiceAccount(sa *corev1.ServiceAccount, ba common.BaseApplication) {
sa.Labels = ba.GetLabels()
sa.Annotations = MergeMaps(sa.Annotations, ba.GetAnnotations())

if ba.GetPullSecret() != nil {
if len(sa.ImagePullSecrets) == 0 {
sa.ImagePullSecrets = append(sa.ImagePullSecrets, corev1.LocalObjectReference{
Expand All @@ -225,7 +227,6 @@ func CustomizeServiceAccount(sa *corev1.ServiceAccount, ba common.BaseApplicatio

// CustomizeAffinity ...
func CustomizeAffinity(a *corev1.Affinity, ba common.BaseApplication) {

a.NodeAffinity = &corev1.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
NodeSelectorTerms: []corev1.NodeSelectorTerm{
Expand Down Expand Up @@ -263,8 +264,9 @@ func CustomizeAffinity(a *corev1.Affinity, ba common.BaseApplication) {

// CustomizeKnativeService ...
func CustomizeKnativeService(ksvc *servingv1alpha1.Service, ba common.BaseApplication) {
ksvc.Labels = ba.GetLabels()
obj := ba.(metav1.Object)
ksvc.Labels = ba.GetLabels()
MergeMaps(ksvc.Annotations, ba.GetAnnotations())

// If `expose` is not set to `true`, make Knative route a private route by adding `serving.knative.dev/visibility: cluster-local`
// to the Knative service. If `serving.knative.dev/visibility: XYZ` is defined in cr.Labels, `expose` always wins.
Expand All @@ -285,6 +287,7 @@ func CustomizeKnativeService(ksvc *servingv1alpha1.Service, ba common.BaseApplic
ksvc.Spec.Template.Spec.Containers[0].Ports = append(ksvc.Spec.Template.Spec.Containers[0].Ports, corev1.ContainerPort{})
}
ksvc.Spec.Template.ObjectMeta.Labels = ba.GetLabels()
ksvc.Spec.Template.ObjectMeta.Annotations = MergeMaps(ksvc.Spec.Template.ObjectMeta.Annotations, ba.GetAnnotations())

ksvc.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort = ba.GetService().GetPort()
ksvc.Spec.Template.Spec.Containers[0].Image = ba.GetApplicationImage()
Expand Down Expand Up @@ -326,8 +329,9 @@ func CustomizeKnativeService(ksvc *servingv1alpha1.Service, ba common.BaseApplic

// CustomizeHPA ...
func CustomizeHPA(hpa *autoscalingv1.HorizontalPodAutoscaler, ba common.BaseApplication) {
hpa.Labels = ba.GetLabels()
obj := ba.(metav1.Object)
hpa.Labels = ba.GetLabels()
hpa.Annotations = MergeMaps(hpa.Annotations, ba.GetAnnotations())

hpa.Spec.MaxReplicas = ba.GetAutoscaling().GetMaxReplicas()
hpa.Spec.MinReplicas = ba.GetAutoscaling().GetMinReplicas()
Expand Down Expand Up @@ -370,8 +374,10 @@ func requiredFieldMessage(fieldPaths ...string) string {

// CustomizeServiceMonitor ...
func CustomizeServiceMonitor(sm *prometheusv1.ServiceMonitor, ba common.BaseApplication) {
sm.Labels = ba.GetLabels()
obj := ba.(metav1.Object)
sm.Labels = ba.GetLabels()
sm.Annotations = MergeMaps(sm.Annotations, ba.GetAnnotations())

sm.Spec.Selector = metav1.LabelSelector{
MatchLabels: map[string]string{
"app.kubernetes.io/name": obj.GetName(),
Expand Down Expand Up @@ -459,3 +465,17 @@ func GetWatchNamespaces() ([]string, error) {

return watchNamespaces, nil
}

// MergeMaps returns a map containing the union of al the key-value pairs from the input maps. The order of the maps passed into the
// func, defines the importance. e.g. if (keyA, value1) is in map1, and (keyA, value2) is in map2, mergeMaps(map1, map2) would contain (keyA, value2).
func MergeMaps(maps ...map[string]string) map[string]string {
dest := make(map[string]string)

for i := range maps {
for key, value := range maps[i] {
dest[key] = value
}
}

return dest
}

0 comments on commit 752e23b

Please sign in to comment.