Fix #1234: add a master trait (as addon)
diff --git a/addons/master/master.go b/addons/master/master.go
index ed40e1a..33b4ff8 100644
--- a/addons/master/master.go
+++ b/addons/master/master.go
@@ -18,30 +18,180 @@
package master
import (
+ "fmt"
+ "strings"
+
+ "github.com/apache/camel-k/deploy"
+ v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+ "github.com/apache/camel-k/pkg/metadata"
"github.com/apache/camel-k/pkg/trait"
+ "github.com/apache/camel-k/pkg/util"
+ "github.com/apache/camel-k/pkg/util/kubernetes"
+ "github.com/apache/camel-k/pkg/util/uri"
+ "k8s.io/apimachinery/pkg/runtime"
)
// The Master trait allows to configure the integration to automatically leverage Kubernetes resources for doing
// leader election and starting *master* routes only on certain instances.
//
-// It's activated automatically when using the master endpoint in a route, e.g. `from("master:telegram:bots")...`.
+// It's activated automatically when using the master endpoint in a route, e.g. `from("master:lockname:telegram:bots")...`.
+//
+// NOTE: this trait adds special permissions to the integration service account in order to read/write configmaps and read pods.
+// It's recommended to use a different service account than "default" when running the integration.
//
// +camel-k:trait=master
type masterTrait struct {
trait.BaseTrait `property:",squash"`
+ // Enables automatic configuration of the trait.
+ Auto *bool `property:"auto"`
+ // When this flag is active, the operator analyzes the source code to add dependencies required by delegate endpoints.
+ // E.g. when using `master:lockname:timer`, then `camel:timer` is automatically added to the set of dependencies.
+ // It's enabled by default.
+ IncludeDelegateDependencies *bool `property:"include-delegate-dependencies"`
+ // Name of the configmap that will be used to store the lock. Defaults to "<integration-name>-lock".
+ Configmap string `property:"configmap"`
+ // Label that will be used to identify all pods contending the lock. Defaults to "camel.apache.org/integration".
+ LabelKey string `property:"label-key"`
+ // Label value that will be used to identify all pods contending the lock. Defaults to the integration name.
+ LabelValue string `property:"label-value"`
+ delegateDependencies []string
}
+// NewMasterTrait --
func NewMasterTrait() trait.Trait {
return &masterTrait{
- BaseTrait: trait.NewBaseTrait("master", 2500),
+ BaseTrait: trait.NewBaseTrait("master", 850),
}
}
+const (
+ masterComponent = "master"
+)
+
func (t *masterTrait) Configure(e *trait.Environment) (bool, error) {
- return false, nil
+ if t.Enabled != nil && !*t.Enabled {
+ return false, nil
+ }
+
+ if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+ return false, nil
+ }
+
+ if t.Auto == nil || *t.Auto {
+ // Check if the master component has been used
+ sources, err := kubernetes.ResolveIntegrationSources(t.Ctx, t.Client, e.Integration, e.Resources)
+ if err != nil {
+ return false, err
+ }
+
+ meta := metadata.ExtractAll(e.CamelCatalog, sources)
+
+ if t.Enabled == nil {
+ for _, endpoint := range meta.FromURIs {
+ if uri.GetComponent(endpoint) == masterComponent {
+ enabled := true
+ t.Enabled = &enabled
+ }
+ }
+ }
+
+ if t.Enabled == nil || !*t.Enabled {
+ return false, nil
+ }
+
+ if t.IncludeDelegateDependencies == nil || *t.IncludeDelegateDependencies {
+ t.delegateDependencies = findAdditionalDependencies(e, meta)
+ }
+
+ if t.Configmap == "" {
+ t.Configmap = fmt.Sprintf("%s-lock", e.Integration.Name)
+ }
+
+ if t.LabelKey == "" {
+ t.LabelKey = "camel.apache.org/integration"
+ }
+
+ if t.LabelValue == "" {
+ t.LabelValue = e.Integration.Name
+ }
+ }
+
+ return t.Enabled != nil && *t.Enabled, nil
}
func (t *masterTrait) Apply(e *trait.Environment) error {
+ if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+ util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel.k/camel-k-runtime-master")
+
+ // Master sub endpoints need to be added to the list of dependencies
+ for _, dep := range t.delegateDependencies {
+ util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, dep)
+ }
+
+ } else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+ serviceAccount := e.Integration.Spec.ServiceAccountName
+ if serviceAccount == "" {
+ serviceAccount = "default"
+ }
+
+ var templateData = struct {
+ Namespace string
+ Name string
+ ServiceAccount string
+ }{
+ Namespace: e.Integration.Namespace,
+ Name: fmt.Sprintf("%s-master", e.Integration.Name),
+ ServiceAccount: serviceAccount,
+ }
+
+ role, err := loadResource(e, "master-role.tmpl", templateData)
+ if err != nil {
+ return err
+ }
+ roleBinding, err := loadResource(e, "master-role-binding.tmpl", templateData)
+ if err != nil {
+ return err
+ }
+
+ e.Resources.Add(role)
+ e.Resources.Add(roleBinding)
+
+ e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
+ v1.ConfigurationSpec{Type: "property", Value: "customizer.master.enabled=true"},
+ v1.ConfigurationSpec{Type: "property", Value: fmt.Sprintf("customizer.master.configMapName=%s", t.Configmap)},
+ v1.ConfigurationSpec{Type: "property", Value: fmt.Sprintf("customizer.master.labelKey=%s", t.LabelKey)},
+ v1.ConfigurationSpec{Type: "property", Value: fmt.Sprintf("customizer.master.labelValue=%s", t.LabelValue)},
+ )
+ }
+
return nil
}
+
+func findAdditionalDependencies(e *trait.Environment, meta metadata.IntegrationMetadata) (dependencies []string) {
+ for _, endpoint := range meta.FromURIs {
+ if uri.GetComponent(endpoint) == masterComponent {
+ parts := strings.Split(endpoint, ":")
+ if len(parts) > 2 {
+ // syntax "master:lockname:endpoint:..."
+ childComponent := parts[2]
+ if artifact := e.CamelCatalog.GetArtifactByScheme(childComponent); artifact != nil {
+ dependencies = append(dependencies, artifact.GetDependencyID())
+ }
+ }
+ }
+ }
+ return dependencies
+}
+
+func loadResource(e *trait.Environment, name string, params interface{}) (runtime.Object, error) {
+ data, err := deploy.TemplateResource(fmt.Sprintf("/addons/master/%s", name), params)
+ if err != nil {
+ return nil, err
+ }
+ obj, err := kubernetes.LoadResourceFromYaml(e.Client.GetScheme(), data)
+ if err != nil {
+ return nil, err
+ }
+ return obj, nil
+}
diff --git a/build/maven/pom-runtime.xml b/build/maven/pom-runtime.xml
index e93d27b..6f9ef89 100644
--- a/build/maven/pom-runtime.xml
+++ b/build/maven/pom-runtime.xml
@@ -89,6 +89,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-runtime-master</artifactId>
+ <version>${runtime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
<artifactId>camel-k-runtime-cron</artifactId>
<version>${runtime.version}</version>
</dependency>
diff --git a/deploy/addons/master/master-role-binding.tmpl b/deploy/addons/master/master-role-binding.tmpl
new file mode 100644
index 0000000..b6d0bea
--- /dev/null
+++ b/deploy/addons/master/master-role-binding.tmpl
@@ -0,0 +1,16 @@
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: {{ .Name }}
+ namespace: {{ .Namespace }}
+ labels:
+ app: "camel-k"
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Namespace }}
+ name: {{ .ServiceAccount }}
+roleRef:
+ kind: Role
+ namespace: {{ .Namespace }}
+ name: {{ .Name }}
+ apiGroup: rbac.authorization.k8s.io
diff --git a/deploy/addons/master/master-role.tmpl b/deploy/addons/master/master-role.tmpl
new file mode 100644
index 0000000..efe939e
--- /dev/null
+++ b/deploy/addons/master/master-role.tmpl
@@ -0,0 +1,27 @@
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: {{ .Name }}
+ namespace: {{ .Namespace }}
+ labels:
+ app: "camel-k"
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - create
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - get
+ - list
+ - watch
diff --git a/deploy/resources.go b/deploy/resources.go
index 5e10a0c..8719462 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -38,6 +38,28 @@
name: "/",
modTime: time.Time{},
},
+ "/addons": &vfsgen۰DirInfo{
+ name: "addons",
+ modTime: time.Time{},
+ },
+ "/addons/master": &vfsgen۰DirInfo{
+ name: "master",
+ modTime: time.Time{},
+ },
+ "/addons/master/master-role-binding.tmpl": &vfsgen۰CompressedFileInfo{
+ name: "master-role-binding.tmpl",
+ modTime: time.Time{},
+ uncompressedSize: 362,
+
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x90\xbd\x4e\xc5\x30\x0c\x85\xf7\x3c\x85\x75\xf7\x1b\xd4\x0d\x65\x83\x85\x8d\xa1\x48\xec\x4e\x6a\xc0\x34\x89\xa3\xfc\x74\xa0\xea\xbb\xa3\xb6\x48\x14\x09\xf5\x8e\xc9\xa7\x63\x7f\x3e\x23\xc7\xc1\x40\x2f\x9e\x1e\x39\x0e\x1c\xdf\x15\x26\x7e\xa5\x5c\x58\xa2\x81\x6c\xd1\x69\x6c\xf5\x43\x32\x7f\x61\x65\x89\x7a\xbc\x2f\x9a\xe5\x6e\xea\x2c\x55\xec\x54\xa0\x8a\x03\x56\x34\x0a\x20\x62\x20\x03\xf3\x0c\xfa\x19\x03\xc1\xb2\xfc\xfc\x95\x84\xee\x00\xb6\xe7\x4e\x3d\x5a\xf2\x65\xcd\x02\x60\x4a\x06\x2e\x0e\x03\xf9\xeb\x78\x51\xa5\xd9\x4f\x72\x75\x83\x57\xd8\x35\x5f\x28\x4f\xec\xe8\xc1\x39\x69\xb1\x6e\xa9\xf3\xf9\x47\xa7\xbf\xe1\x95\x67\xf1\xd4\xd3\xdb\xba\xe1\xb7\x86\x9b\xce\xff\x5d\x89\x89\x9f\xb2\xb4\x74\xd2\x98\xfa\x0e\x00\x00\xff\xff\xa6\x3e\x0f\x20\x6a\x01\x00\x00"),
+ },
+ "/addons/master/master-role.tmpl": &vfsgen۰CompressedFileInfo{
+ name: "master-role.tmpl",
+ modTime: time.Time{},
+ uncompressedSize: 347,
+
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x8d\xb1\x6e\xc3\x30\x0c\x44\x77\x7d\x05\xe1\xdd\x2e\xb2\x15\xfa\x81\x6e\x1d\x3a\x74\x3f\xcb\x6c\x22\x58\x16\x09\x4a\x4a\x81\x06\xf9\xf7\xa2\x72\x02\x14\xed\x92\x89\xc7\x77\x47\xde\x1a\xf3\xe2\xe9\x4d\x12\x3b\x68\x7c\x67\x2b\x51\xb2\x27\x9b\x11\x26\xb4\x7a\x12\x8b\x5f\xa8\x51\xf2\xb4\x3e\x97\x29\xca\xd3\xf9\x30\x73\xc5\xc1\x6d\x5c\xb1\xa0\xc2\x3b\xa2\x8c\x8d\x3d\x5d\x2e\x34\xbd\x62\x63\xba\x5e\x6f\xac\x28\xc2\x2f\xa3\xaf\xbb\x9b\x30\x73\x2a\x3f\xb7\x44\x50\xf5\x34\x04\x6c\x9c\xc6\x75\x70\xd6\x12\x17\xef\x46\x82\xc6\x17\x93\xa6\x3d\x36\xd2\x30\x38\x22\xe3\x22\xcd\x02\xdf\x58\x90\xfc\x11\x8f\x1b\xb4\x38\xa2\x33\xdb\x7c\xe7\xc6\xa8\xdc\xe5\x91\x6b\x9f\x29\x96\x5d\x28\x6a\x38\x75\xd5\x74\xb9\xa7\x3e\x3b\x7c\xa8\x53\x65\xf9\xd3\xf6\xaf\x62\xff\xf6\x1d\x00\x00\xff\xff\x40\x05\x71\xea\x5b\x01\x00\x00"),
+ },
"/builder-role-binding.yaml": &vfsgen۰CompressedFileInfo{
name: "builder-role-binding.yaml",
modTime: time.Time{},
@@ -310,6 +332,7 @@
},
}
fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
+ fs["/addons"].(os.FileInfo),
fs["/builder-role-binding.yaml"].(os.FileInfo),
fs["/builder-role-kubernetes.yaml"].(os.FileInfo),
fs["/builder-role-openshift.yaml"].(os.FileInfo),
@@ -344,6 +367,13 @@
fs["/templates"].(os.FileInfo),
fs["/user-cluster-role.yaml"].(os.FileInfo),
}
+ fs["/addons"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
+ fs["/addons/master"].(os.FileInfo),
+ }
+ fs["/addons/master"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
+ fs["/addons/master/master-role-binding.tmpl"].(os.FileInfo),
+ fs["/addons/master/master-role.tmpl"].(os.FileInfo),
+ }
fs["/templates"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/templates/groovy.tmpl"].(os.FileInfo),
fs["/templates/java.tmpl"].(os.FileInfo),
diff --git a/deploy/resources_support.go b/deploy/resources_support.go
index 23a514b..9164f88 100644
--- a/deploy/resources_support.go
+++ b/deploy/resources_support.go
@@ -18,8 +18,10 @@
package deploy
import (
+ "bytes"
"io/ioutil"
"strings"
+ "text/template"
"github.com/apache/camel-k/pkg/util/log"
)
@@ -51,6 +53,24 @@
return data
}
+// TemplateResource loads a file resource as go template and processes it using the given parameters
+func TemplateResource(name string, params interface{}) (string, error) {
+ rawData := ResourceAsString(name)
+ if rawData == "" {
+ return "", nil
+ }
+ tmpl, err := template.New(name).Parse(rawData)
+ if err != nil {
+ return "", err
+ }
+
+ var buf bytes.Buffer
+ if err := tmpl.Execute(&buf, params); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
// Resources lists all file names in the given path (starts with '/')
func Resources(dirName string) []string {
dir, err := assets.Open(dirName)
diff --git a/examples/Master.java b/examples/Master.java
new file mode 100755
index 0000000..c9bccb8
--- /dev/null
+++ b/examples/Master.java
@@ -0,0 +1,20 @@
+// camel-k: language=java
+
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * This example shows how to start a route on a single instance of the integration.
+ * Increase the number of replicas to see it in action (the route will be started on a single pod only).
+ */
+public class Master extends RouteBuilder {
+ @Override
+ public void configure() throws Exception {
+
+ // Write your routes here, for example:
+ from("master:lock:timer:master?period=1s")
+ .setBody()
+ .simple("This message is printed by a single pod, even if you increase the number of replicas!")
+ .to("log:info");
+
+ }
+}
diff --git a/pkg/apis/camel/v1/camelcatalog_types_support.go b/pkg/apis/camel/v1/camelcatalog_types_support.go
index 7ee6ee8..edda60f 100644
--- a/pkg/apis/camel/v1/camelcatalog_types_support.go
+++ b/pkg/apis/camel/v1/camelcatalog_types_support.go
@@ -17,7 +17,11 @@
package v1
-import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+import (
+ "strings"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
// NewCamelCatalog --
func NewCamelCatalog(namespace string, name string) CamelCatalog {
@@ -57,3 +61,15 @@
},
}
}
+
+// GetDependencyID returns a Camel K recognizable maven dependency for the artifact
+func (a CamelArtifact) GetDependencyID() string {
+ artifactID := a.ArtifactID
+ if a.GroupID == "org.apache.camel" && strings.HasPrefix(artifactID, "camel-") {
+ return "camel:" + artifactID[6:]
+ }
+ if a.GroupID == "org.apache.camel.quarkus" && strings.HasPrefix(artifactID, "camel-quarkus-") {
+ return "camel-quarkus:" + artifactID[14:]
+ }
+ return "mvn:" + a.GroupID + ":" + artifactID + ":" + a.Version
+}
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index 1024e88..b2b44d6 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -172,7 +172,7 @@
}
// CronJob strategy requires common schedule
- strategy, err := e.DetermineControllerStrategy(t.ctx, t.client)
+ strategy, err := e.DetermineControllerStrategy(t.Ctx, t.Client)
if err != nil {
return false, err
}
@@ -326,7 +326,7 @@
func (t *cronTrait) getSourcesFromURIs(e *Environment) ([]string, error) {
var sources []v1.SourceSpec
var err error
- if sources, err = kubernetes.ResolveIntegrationSources(t.ctx, t.client, e.Integration, e.Resources); err != nil {
+ if sources, err = kubernetes.ResolveIntegrationSources(t.Ctx, t.Client, e.Integration, e.Resources); err != nil {
return nil, err
}
meta := metadata.ExtractAll(e.CamelCatalog, sources)
diff --git a/pkg/trait/deployment.go b/pkg/trait/deployment.go
index c8e04a2..4abf44c 100644
--- a/pkg/trait/deployment.go
+++ b/pkg/trait/deployment.go
@@ -62,7 +62,7 @@
//
// Don't deploy when a different strategy is needed (e.g. Knative, Cron)
//
- strategy, err := e.DetermineControllerStrategy(t.ctx, t.client)
+ strategy, err := e.DetermineControllerStrategy(t.Ctx, t.Client)
if err != nil {
e.Integration.Status.SetErrorCondition(
v1.IntegrationConditionDeploymentAvailable,
diff --git a/pkg/trait/deployment_test.go b/pkg/trait/deployment_test.go
index 6205987..7d9c666 100644
--- a/pkg/trait/deployment_test.go
+++ b/pkg/trait/deployment_test.go
@@ -140,7 +140,7 @@
trait := newDeploymentTrait().(*deploymentTrait)
enabled := true
trait.Enabled = &enabled
- trait.client, _ = test.NewFakeClient(&appsv1.Deployment{
+ trait.Client, _ = test.NewFakeClient(&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "integration-name",
Namespace: "namespace",
diff --git a/pkg/trait/gc.go b/pkg/trait/gc.go
index c9013c1..2c42cc9 100644
--- a/pkg/trait/gc.go
+++ b/pkg/trait/gc.go
@@ -186,7 +186,7 @@
client.InNamespace(e.Integration.Namespace),
util.MatchingSelector{Selector: selector},
}
- if err := t.client.List(context.TODO(), &resources, options...); err != nil {
+ if err := t.Client.List(context.TODO(), &resources, options...); err != nil {
if !k8serrors.IsNotFound(err) && !k8serrors.IsForbidden(err) {
t.L.ForIntegration(e.Integration).Errorf(err, "cannot list child resources: %v", gvk)
}
@@ -195,7 +195,7 @@
for _, resource := range resources.Items {
r := resource
- err := t.client.Delete(context.TODO(), &r, client.PropagationPolicy(metav1.DeletePropagationBackground))
+ err := t.Client.Delete(context.TODO(), &r, client.PropagationPolicy(metav1.DeletePropagationBackground))
if err != nil {
// The resource may have already been deleted
if !k8serrors.IsNotFound(err) {
@@ -257,7 +257,7 @@
if diskCachedDiscoveryClient != nil {
return diskCachedDiscoveryClient, nil
}
- config := t.client.GetConfig()
+ config := t.Client.GetConfig()
httpCacheDir := filepath.Join(mustHomeDir(), ".kube", "http-cache")
diskCacheDir := filepath.Join(mustHomeDir(), ".kube", "cache", "discovery", toHostDir(config.Host))
var err error
@@ -268,14 +268,14 @@
if memoryCachedDiscoveryClient != nil {
return memoryCachedDiscoveryClient, nil
}
- memoryCachedDiscoveryClient = memory.NewMemCacheClient(t.client.Discovery())
+ memoryCachedDiscoveryClient = memory.NewMemCacheClient(t.Client.Discovery())
return memoryCachedDiscoveryClient, nil
case disabledDiscoveryCache, "":
- return t.client.Discovery(), nil
+ return t.Client.Discovery(), nil
default:
t.L.ForIntegration(e.Integration).Infof("unsupported discovery cache type: %s", *t.DiscoveryCache)
- return t.client.Discovery(), nil
+ return t.Client.Discovery(), nil
}
}
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index c75f854..4596623 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -78,7 +78,7 @@
Name: name,
}
- if err := t.client.Get(t.ctx, key, &k); err != nil {
+ if err := t.Client.Get(t.Ctx, key, &k); err != nil {
return errors.Wrapf(err, "unable to find integration kit %s, %s", name, err)
}
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index 1db7f39..15f012b 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -204,8 +204,8 @@
trait := newJvmTrait().(*jvmTrait)
enabled := true
trait.Enabled = &enabled
- trait.ctx = context.TODO()
- trait.client = client
+ trait.Ctx = context.TODO()
+ trait.Client = client
environment := &Environment{
Catalog: NewCatalog(context.TODO(), nil),
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index 7032c49..cd55fac 100644
--- a/pkg/trait/knative.go
+++ b/pkg/trait/knative.go
@@ -388,13 +388,13 @@
continue
}
possibleRefs := knativeutil.FillMissingReferenceData(serviceType, ref)
- actualRef, err := knativeutil.GetAddressableReference(t.ctx, t.client, possibleRefs, e.Integration.Namespace, ref.Name)
+ actualRef, err := knativeutil.GetAddressableReference(t.Ctx, t.Client, possibleRefs, e.Integration.Namespace, ref.Name)
if err != nil && k8serrors.IsNotFound(err) {
return errors.Errorf("cannot find %s %s", serviceType, ref.Name)
} else if err != nil {
return errors.Wrapf(err, "error looking up %s %s", serviceType, ref.Name)
}
- targetURL, err := knativeutil.GetSinkURL(t.ctx, t.client, actualRef, e.Integration.Namespace)
+ targetURL, err := knativeutil.GetSinkURL(t.Ctx, t.Client, actualRef, e.Integration.Namespace)
if err != nil {
return errors.Wrapf(err, "cannot determine address of %s %s", string(serviceType), ref.Name)
}
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index 63dc548..5f10270 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -121,7 +121,7 @@
return false, nil
}
- strategy, err := e.DetermineControllerStrategy(t.ctx, t.client)
+ strategy, err := e.DetermineControllerStrategy(t.Ctx, t.Client)
if err != nil {
e.Integration.Status.SetErrorCondition(
v1.IntegrationConditionKnativeServiceAvailable,
@@ -145,7 +145,7 @@
if t.Auto == nil || *t.Auto {
// Check the right value for minScale, as not all services are allowed to scale down to 0
if t.MinScale == nil {
- sources, err := kubernetes.ResolveIntegrationSources(t.ctx, t.client, e.Integration, e.Resources)
+ sources, err := kubernetes.ResolveIntegrationSources(t.Ctx, t.Client, e.Integration, e.Resources)
if err != nil {
e.Integration.Status.SetErrorCondition(
v1.IntegrationConditionKnativeServiceAvailable,
@@ -250,7 +250,7 @@
var sources []v1.SourceSpec
var err error
- if sources, err = kubernetes.ResolveIntegrationSources(t.ctx, t.client, e.Integration, e.Resources); err != nil {
+ if sources, err = kubernetes.ResolveIntegrationSources(t.Ctx, t.Client, e.Integration, e.Resources); err != nil {
return nil, err
}
diff --git a/pkg/trait/platform.go b/pkg/trait/platform.go
index fe11fdc..9db375f 100644
--- a/pkg/trait/platform.go
+++ b/pkg/trait/platform.go
@@ -57,7 +57,7 @@
if t.Auto == nil || !*t.Auto {
if e.Platform == nil && t.CreateDefault == nil {
// Calculate if the platform should be automatically created when missing.
- if ocp, err := openshift.IsOpenShift(t.client); err != nil {
+ if ocp, err := openshift.IsOpenShift(t.Client); err != nil {
return false, err
} else if ocp {
t.CreateDefault = &ocp
@@ -92,7 +92,7 @@
}
func (t *platformTrait) getOrCreatePlatform(e *Environment) (*v1.IntegrationPlatform, error) {
- pl, err := platform.GetOrLookupAny(t.ctx, t.client, e.Integration.Namespace, e.Integration.Status.Platform)
+ pl, err := platform.GetOrLookupAny(t.Ctx, t.Client, e.Integration.Namespace, e.Integration.Status.Platform)
if err != nil && k8serrors.IsNotFound(err) {
if t.CreateDefault != nil && *t.CreateDefault {
platformName := e.Integration.Status.Platform
diff --git a/pkg/trait/platform_test.go b/pkg/trait/platform_test.go
index 43b306d..8932ad2 100644
--- a/pkg/trait/platform_test.go
+++ b/pkg/trait/platform_test.go
@@ -61,7 +61,7 @@
trait.CreateDefault = &createPlatform
var err error
- trait.client, err = test.NewFakeClient()
+ trait.Client, err = test.NewFakeClient()
assert.Nil(t, err)
enabled, err := trait.Configure(&e)
@@ -96,7 +96,7 @@
trait.CreateDefault = &createPlatform
var err error
- trait.client, err = test.NewFakeClient()
+ trait.Client, err = test.NewFakeClient()
assert.Nil(t, err)
enabled, err := trait.Configure(&e)
@@ -155,7 +155,7 @@
var err error
existingPlatform := v1.NewIntegrationPlatform("ns1", "existing")
existingPlatform.Status.Phase = input.platformPhase
- trait.client, err = test.NewFakeClient(&existingPlatform)
+ trait.Client, err = test.NewFakeClient(&existingPlatform)
assert.Nil(t, err)
enabled, err := trait.Configure(&e)
diff --git a/pkg/trait/pull_secret.go b/pkg/trait/pull_secret.go
index c7e0326..57fe0da 100644
--- a/pkg/trait/pull_secret.go
+++ b/pkg/trait/pull_secret.go
@@ -64,7 +64,7 @@
if secret != "" {
key := client.ObjectKey{Namespace: e.Platform.Namespace, Name: secret}
obj := corev1.Secret{}
- if err := t.client.Get(t.ctx, key, &obj); err != nil {
+ if err := t.Client.Get(t.Ctx, key, &obj); err != nil {
return false, err
}
if obj.Type == corev1.SecretTypeDockerConfigJson {
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index 73daac2..6257e9e 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -75,7 +75,7 @@
}
if t.Auto == nil || *t.Auto {
- sources, err := kubernetes.ResolveIntegrationSources(t.ctx, t.client, e.Integration, e.Resources)
+ sources, err := kubernetes.ResolveIntegrationSources(t.Ctx, t.Client, e.Integration, e.Resources)
if err != nil {
e.Integration.Status.SetCondition(
v1.IntegrationConditionServiceAvailable,
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index 9d863f2..3d87d1b 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -108,36 +108,36 @@
// NewBaseTrait --
func NewBaseTrait(id string, order int) BaseTrait {
return BaseTrait{
- id: ID(id),
- order: order,
- L: log.Log.WithName("traits").WithValues("trait", id),
+ TraitID: ID(id),
+ ExecutionOrder: order,
+ L: log.Log.WithName("traits").WithValues("trait", id),
}
}
// BaseTrait is the root trait with noop implementations for hooks
type BaseTrait struct {
- id ID
+ TraitID ID
// Can be used to enable or disable a trait. All traits share this common property.
- Enabled *bool `property:"enabled"`
- client client.Client
- ctx context.Context
- order int
- L log.Logger
+ Enabled *bool `property:"enabled"`
+ Client client.Client
+ Ctx context.Context
+ ExecutionOrder int
+ L log.Logger
}
// ID returns the identifier of the trait
func (trait *BaseTrait) ID() ID {
- return trait.id
+ return trait.TraitID
}
// InjectClient implements client.ClientInject and allows to inject a client into the trait
func (trait *BaseTrait) InjectClient(c client.Client) {
- trait.client = c
+ trait.Client = c
}
// InjectContext allows to inject a context into the trait
func (trait *BaseTrait) InjectContext(ctx context.Context) {
- trait.ctx = ctx
+ trait.Ctx = ctx
}
// InfluencesKit determines if the trait has any influence on Integration Kits
@@ -163,7 +163,7 @@
// Order contains the order value provided during initialization
func (trait *BaseTrait) Order() int {
- return trait.order
+ return trait.ExecutionOrder
}
/* ControllerStrategySelector */
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
index 0f1a219..788e512 100644
--- a/pkg/util/source/inspector.go
+++ b/pkg/util/source/inspector.go
@@ -190,14 +190,7 @@
}
uriStart := uriSplit[0]
if component := i.catalog.GetArtifactByScheme(uriStart); component != nil {
- artifactID := component.ArtifactID
- if component.GroupID == "org.apache.camel" && strings.HasPrefix(artifactID, "camel-") {
- return "camel:" + artifactID[6:]
- }
- if component.GroupID == "org.apache.camel.quarkus" && strings.HasPrefix(artifactID, "camel-quarkus-") {
- return "camel-quarkus:" + artifactID[14:]
- }
- return "mvn:" + component.GroupID + ":" + artifactID + ":" + component.Version
+ return component.GetDependencyID()
}
return ""
}