Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(catalog): capabilities properties #1185

Merged
merged 1 commit into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,27 @@ default SortedSet<Artifact> getDependencies() {
return Collections.emptySortedSet();
}

@Value.Auxiliary
@Value.Default
@Value.NaturalOrder
default SortedSet<Property> getRuntimeProperties() {
return Collections.emptySortedSet();
}

@Value.Auxiliary
@Value.Default
@Value.NaturalOrder
default SortedSet<Property> getBuildTimeProperties() {
return Collections.emptySortedSet();
}

@Value.Auxiliary
@Value.Default
@Value.NaturalOrder
default SortedSet<Property> getMetadata() {
return Collections.emptySortedSet();
}

static CamelCapability forArtifact(String groupId, String artifactId) {
return new Builder().addDependency(groupId, artifactId).build();
}
Expand All @@ -52,5 +73,17 @@ public Builder addDependency(String groupId, String artifactId, Optional<String>
return super.addDependencies(Artifact.from(groupId, artifactId, classifier.get()));
}
}

public Builder addRuntimeProperty(String key, String value) {
return super.addRuntimeProperty(Property.from(key, value));
}

public Builder addBuildTimeProperty(String key, String value) {
return super.addBuildTimeProperty(Property.from(key, value));
}

public Builder addMetadata(String key, String value) {
return super.addMetadata(Property.from(key, value));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.k.catalog.model;

import java.util.Comparator;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonPropertyOrder({"key", "value"})
public interface Property extends Comparable<Property> {
String getKey();
String getValue();

@Override
default int compareTo(Property o) {
return Comparator
.comparing(Property::getKey)
.compare(this, o);
}

static Property from(String key, String value) {
return new Property() {
@Override
public String getKey() {
return key;
}

@Override
public String getValue() {
return value;
}
};
}

}
41 changes: 41 additions & 0 deletions support/camel-k-maven-plugin/src/it/generate-catalog/verify.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,47 @@ new File(basedir, "catalog.yaml").withReader {
assert catalog.spec.runtime.capabilities['telemetry'].dependencies[0].artifactId == 'camel-quarkus-opentelemetry'
assert catalog.spec.runtime.capabilities['master'].dependencies[0].groupId == 'org.apache.camel.k'
assert catalog.spec.runtime.capabilities['master'].dependencies[0].artifactId == 'camel-k-master'
// Logging properties
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[0].key == 'color'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[0].value == 'quarkus.console.color'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[1].key == 'format'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[1].value == 'quarkus.log.console.format'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[2].key == 'json'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[2].value == 'quarkus.log.console.json'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[3].key == 'jsonPrettyPrint'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[3].value == 'quarkus.log.console.json.pretty-print'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[4].key == 'level'
assert catalog.spec.runtime.capabilities['logging'].runtimeProperties[4].value == 'quarkus.log.level'
// Master properties
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[0].key == 'labelKeyFormat'
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[0].value == 'quarkus.camel.cluster.kubernetes.labels.\"%s\"'
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[1].key == 'resourceName'
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[1].value == 'quarkus.camel.cluster.kubernetes.resource-name'
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[2].key == 'resourceType'
assert catalog.spec.runtime.capabilities['master'].runtimeProperties[2].value == 'quarkus.camel.cluster.kubernetes.resource-type'
assert catalog.spec.runtime.capabilities['master'].buildTimeProperties[0].key == 'enabled'
assert catalog.spec.runtime.capabilities['master'].buildTimeProperties[0].value == 'quarkus.camel.cluster.kubernetes.enabled'
// Telemetry properties
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[0].key == 'endpoint'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[0].value == 'quarkus.opentelemetry.tracer.exporter.otlp.endpoint'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[1].key == 'sampler'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[1].value == 'quarkus.opentelemetry.tracer.sampler'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[2].key == 'samplerParentBased'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[2].value == 'quarkus.opentelemetry.tracer.sampler.parent-based'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[3].key == 'samplerRatio'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[3].value == 'quarkus.opentelemetry.tracer.sampler.ratio'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[4].key == 'serviceName'
assert catalog.spec.runtime.capabilities['telemetry'].runtimeProperties[4].value == 'quarkus.opentelemetry.tracer.resource-attributes'
// Service Binding properties
assert catalog.spec.runtime.capabilities['service-binding'].runtimeProperties[0].key == 'enabled'
assert catalog.spec.runtime.capabilities['service-binding'].runtimeProperties[0].value == 'quarkus.kubernetes-service-binding.enabled'
// Health properties
assert catalog.spec.runtime.capabilities['health'].metadata[0].key == 'defaultLivenessProbePath'
assert catalog.spec.runtime.capabilities['health'].metadata[0].value == '/q/health/live'
assert catalog.spec.runtime.capabilities['health'].metadata[1].key == 'defaultReadinessProbePath'
assert catalog.spec.runtime.capabilities['health'].metadata[1].value == '/q/health/ready'
assert catalog.spec.runtime.capabilities['health'].metadata[2].key == 'defaultStartupProbePath'
assert catalog.spec.runtime.capabilities['health'].metadata[2].value == '/q/health/started'

assert catalog.spec.loaders['groovy'].groupId == 'org.apache.camel.quarkus'
assert catalog.spec.loaders['groovy'].artifactId == 'camel-quarkus-groovy-dsl'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.camel.k.catalog.model.CatalogLanguageDefinition;
import org.apache.camel.k.catalog.model.CatalogOtherDefinition;
import org.apache.camel.k.catalog.model.CatalogSupport;
import org.apache.camel.k.catalog.model.Property;
import org.apache.camel.k.catalog.model.k8s.ObjectMeta;
import org.apache.camel.k.catalog.model.k8s.crd.CamelCatalog;
import org.apache.camel.k.catalog.model.k8s.crd.CamelCatalogSpec;
Expand Down Expand Up @@ -464,7 +465,11 @@ private void addCapabilities(RuntimeSpec.Builder runtimeSpec, CamelCatalogSpec.B

artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-microprofile-health"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "health", artifacts, false);
List<Property> properties = new ArrayList<>();
properties.add(Property.from("defaultLivenessProbePath", "/q/health/live"));
properties.add(Property.from("defaultReadinessProbePath", "/q/health/ready"));
properties.add(Property.from("defaultStartupProbePath", "/q/health/started"));
squakez marked this conversation as resolved.
Show resolved Hide resolved
addCapability(runtimeSpec, catalogSpec, "health", artifacts, new ArrayList<>(), new ArrayList<>(), properties, false);

artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-platform-http"));
Expand All @@ -483,18 +488,32 @@ private void addCapabilities(RuntimeSpec.Builder runtimeSpec, CamelCatalogSpec.B
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-opentracing"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "tracing", artifacts, false);

// Telemetry capability
artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-opentelemetry"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "telemetry", artifacts, false);

artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.k", "camel-k-master"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "master", artifacts, true);
properties.clear();
properties.add(Property.from("endpoint", "quarkus.opentelemetry.tracer.exporter.otlp.endpoint"));
properties.add(Property.from("serviceName", "quarkus.opentelemetry.tracer.resource-attributes"));
properties.add(Property.from("sampler", "quarkus.opentelemetry.tracer.sampler"));
properties.add(Property.from("samplerRatio", "quarkus.opentelemetry.tracer.sampler.ratio"));
properties.add(Property.from("samplerParentBased", "quarkus.opentelemetry.tracer.sampler.parent-based"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice to validate if i.e. the same keys also apply to spring-boot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. I think this would be the next step when we onboard the new runtime. We'd need to understand how to harmonize the parameters expected by the operator according to the different runtimes requirements. The goal of this PR is to move towards that goal without breaking compatibility of what's expected now. Eventually it will be a matter of changing these parameters in the future catalog releases, driven by the changes in the operator as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there are many more questions that must be answered, i.e. :

  • how to handle cases where a key is not applicable, but another one is needed
  • how to handle breaking changes, so properties that have disappeared or become required ('d like to avoid having to do version checks)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I acknowledge them but this PR doesn't aim to solve this aspect. This is something we need to address regardless this PR. Do you think that challenge can be tackled separately?

addCapability(runtimeSpec, catalogSpec, "telemetry", artifacts, properties, new ArrayList<>(), new ArrayList<>(), false);

artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.k", "camel-k-resume-kafka"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "resume-kafka", artifacts, true);

// Master capability
artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.k", "camel-k-master"));
properties.clear();
properties.add(Property.from("resourceName", "quarkus.camel.cluster.kubernetes.resource-name"));
properties.add(Property.from("resourceType", "quarkus.camel.cluster.kubernetes.resource-type"));
properties.add(Property.from("labelKeyFormat", "quarkus.camel.cluster.kubernetes.labels.\"%s\""));
List<Property> buildTimeProps = new ArrayList<>();
buildTimeProps.add(Property.from("enabled", "quarkus.camel.cluster.kubernetes.enabled"));
addCapability(runtimeSpec, catalogSpec, "master", artifacts, properties, buildTimeProps, new ArrayList<>(), true);

artifacts.clear();
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-hashicorp-vault"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "hashicorp-vault", artifacts, false);
Expand Down Expand Up @@ -526,6 +545,20 @@ private void addCapabilities(RuntimeSpec.Builder runtimeSpec, CamelCatalogSpec.B
artifacts.add(Artifact.from("org.apache.camel.quarkus", "camel-quarkus-jaxb"));
artifacts.add(Artifact.from("org.jolokia", "jolokia-agent-jvm", "javaagent"));
addCapabilityAndDependecies(runtimeSpec, catalogSpec, "jolokia", artifacts, true);

artifacts.clear();
properties.clear();
properties.add(Property.from("level", "quarkus.log.level"));
properties.add(Property.from("color", "quarkus.console.color"));
properties.add(Property.from("format", "quarkus.log.console.format"));
properties.add(Property.from("json", "quarkus.log.console.json"));
properties.add(Property.from("jsonPrettyPrint", "quarkus.log.console.json.pretty-print"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a json logging option in spring-boot https://docs.spring.io/spring-boot/docs/3.0.0/reference/htmlsingle/#features.logging, it seems that to enable json logging one has to use a backend specific logging configuration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Same comment as with the above telemetry capability.

addCapability(runtimeSpec, catalogSpec, "logging", artifacts, properties, new ArrayList<>(), new ArrayList<>(), false);

artifacts.clear();
properties.clear();
properties.add(Property.from("enabled", "quarkus.kubernetes-service-binding.enabled"));
addCapability(runtimeSpec, catalogSpec, "service-binding", artifacts, properties, new ArrayList<>(), new ArrayList<>(), false);
}

private void addCapabilityAndDependecies(RuntimeSpec.Builder runtimeSpec, CamelCatalogSpec.Builder catalogSpec, String name,
Expand All @@ -545,6 +578,33 @@ private void addCapabilityAndDependecies(RuntimeSpec.Builder runtimeSpec, CamelC
CamelCapability dependency = capBuilder.build();
runtimeSpec.putCapability(name, dependency);
}
}

private void addCapability(RuntimeSpec.Builder runtimeSpec, CamelCatalogSpec.Builder catalogSpec, String name,
List<Artifact> artifacts, List<Property> runtimeProperties, List<Property> buildTimeProperties, List<Property> metadataProperties, boolean addDependency) {
if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains(name)) {
CamelCapability.Builder capBuilder = new CamelCapability.Builder();
runtimeProperties.forEach(property -> {
capBuilder.addRuntimeProperty(property.getKey(), property.getValue());
});
buildTimeProperties.forEach(property -> {
capBuilder.addBuildTimeProperty(property.getKey(), property.getValue());
});
metadataProperties.forEach(property -> {
capBuilder.addMetadata(property.getKey(), property.getValue());
});
artifacts.forEach(artifact -> {
capBuilder.addDependency(artifact.getGroupId(), artifact.getArtifactId(), artifact.getClassifier());
if (addDependency) {
catalogSpec.putArtifact(new CamelArtifact.Builder()
.groupId(artifact.getGroupId())
.artifactId(artifact.getArtifactId())
.classifier(artifact.getClassifier())
.build());
}
});
CamelCapability cap = capBuilder.build();
runtimeSpec.putCapability(name, cap);
}
}
}
Loading