in pkg/trait/knative_service.go [172:301]
func (t *knativeServiceTrait) getServiceFor(e *Environment) (*serving.Service, error) {
serviceAnnotations := make(map[string]string)
if e.Integration.Annotations != nil {
for k, v := range e.Integration.Annotations {
serviceAnnotations[k] = v
}
}
// Set Knative rollout
if t.RolloutDuration != "" {
serviceAnnotations[knativeServingRolloutDurationAnnotation] = t.RolloutDuration
}
revisionAnnotations := make(map[string]string)
if e.Integration.Annotations != nil {
for k, v := range filterTransferableAnnotations(e.Integration.Annotations) {
revisionAnnotations[k] = v
}
}
// Set Knative auto-scaling
if t.Class != "" {
revisionAnnotations[knativeServingClassAnnotation] = t.Class
}
if t.Metric != "" {
revisionAnnotations[knativeServingMetricAnnotation] = t.Metric
}
if t.Target != nil {
revisionAnnotations[knativeServingTargetAnnotation] = strconv.Itoa(*t.Target)
}
if t.MinScale != nil && *t.MinScale > 0 {
revisionAnnotations[knativeServingMinScaleAnnotation] = strconv.Itoa(*t.MinScale)
}
if t.MaxScale != nil && *t.MaxScale > 0 {
revisionAnnotations[knativeServingMaxScaleAnnotation] = strconv.Itoa(*t.MaxScale)
}
serviceLabels := map[string]string{
v1.IntegrationLabel: e.Integration.Name,
// Make sure the Eventing webhook will select the source resource,
// in order to inject the sink information.
// This is necessary for Knative environments, that are configured
// with SINK_BINDING_SELECTION_MODE=inclusion.
// See:
// - https://knative.dev/v1.3-docs/eventing/custom-event-source/sinkbinding/create-a-sinkbinding/#optional-choose-sinkbinding-namespace-selection-behavior
// - https://github.com/knative/operator/blob/release-1.2/docs/configuration.md#specsinkbindingselectionmode
"bindings.knative.dev/include": "true",
}
if t.Visibility != "" {
serviceLabels[knativeServingVisibilityLabel] = t.Visibility
}
svc := serving.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: serving.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: e.Integration.Name,
Namespace: e.Integration.Namespace,
Labels: serviceLabels,
Annotations: serviceAnnotations,
},
Spec: serving.ServiceSpec{
ConfigurationSpec: serving.ConfigurationSpec{
Template: serving.RevisionTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
v1.IntegrationLabel: e.Integration.Name,
},
Annotations: revisionAnnotations,
},
Spec: serving.RevisionSpec{
PodSpec: corev1.PodSpec{
ServiceAccountName: e.Integration.Spec.ServiceAccountName,
},
},
},
},
},
}
replicas := e.Integration.Spec.Replicas
isUpdateRequired := false
minScale, ok := svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation]
if ok {
min, err := strconv.Atoi(minScale)
if err != nil {
return nil, err
}
if replicas == nil || min != int(*replicas) {
isUpdateRequired = true
}
} else if replicas != nil {
isUpdateRequired = true
}
maxScale, ok := svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation]
if ok {
max, err := strconv.Atoi(maxScale)
if err != nil {
return nil, err
}
if replicas == nil || max != int(*replicas) {
isUpdateRequired = true
}
} else if replicas != nil {
isUpdateRequired = true
}
if isUpdateRequired {
if replicas == nil {
if t.MinScale != nil && *t.MinScale > 0 {
svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = strconv.Itoa(*t.MinScale)
} else {
delete(svc.Spec.Template.Annotations, knativeServingMinScaleAnnotation)
}
if t.MaxScale != nil && *t.MaxScale > 0 {
svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = strconv.Itoa(*t.MaxScale)
} else {
delete(svc.Spec.Template.Annotations, knativeServingMaxScaleAnnotation)
}
} else {
scale := strconv.Itoa(int(*replicas))
svc.Spec.Template.Annotations[knativeServingMinScaleAnnotation] = scale
svc.Spec.Template.Annotations[knativeServingMaxScaleAnnotation] = scale
}
}
return &svc, nil
}