Skip to content

Commit

Permalink
feat(api): store executed traits in status
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Sep 18, 2024
1 parent 6dbded5 commit 86854bc
Show file tree
Hide file tree
Showing 33 changed files with 4,070 additions and 174 deletions.
8 changes: 8 additions & 0 deletions docs/modules/ROOT/partials/apis/camel-k-crds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3533,6 +3533,13 @@ a list of dependencies needed by the application
the profile needed to run this Integration
|`traits` +
*xref:#_camel_apache_org_v1_Traits[Traits]*
|
the traits executed for the Integration
|`integrationKit` +
*https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core[Kubernetes core/v1.ObjectReference]*
|
Expand Down Expand Up @@ -5817,6 +5824,7 @@ TraitConfiguration parameters configuration
* <<#_camel_apache_org_v1_IntegrationPlatformSpec, IntegrationPlatformSpec>>
* <<#_camel_apache_org_v1_IntegrationProfileSpec, IntegrationProfileSpec>>
* <<#_camel_apache_org_v1_IntegrationSpec, IntegrationSpec>>
* <<#_camel_apache_org_v1_IntegrationStatus, IntegrationStatus>>
Traits represents the collection of trait configurations.
Expand Down
1,693 changes: 1,693 additions & 0 deletions helm/camel-k/crds/camel-k-crds.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pkg/apis/camel/v1/integration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ type IntegrationStatus struct {
Dependencies []string `json:"dependencies,omitempty"`
// the profile needed to run this Integration
Profile TraitProfile `json:"profile,omitempty"`
// the traits executed for the Integration
Traits *Traits `json:"traits,omitempty"`
// the reference of the `IntegrationKit` which is used for this Integration
IntegrationKit *corev1.ObjectReference `json:"integrationKit,omitempty"`
// The IntegrationPlatform watching this Integration
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/camel/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,693 changes: 1,693 additions & 0 deletions pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions pkg/trait/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ func TestBuilderTraitNotAppliedBecauseOfNilPhase(t *testing.T) {
e.IntegrationKit.Status.Phase = v1.IntegrationKitPhaseInitialization

t.Run(string(e.Platform.Status.Cluster), func(t *testing.T) {
conditions, err := NewBuilderTestCatalog().apply(e)
conditions, traits, err := NewBuilderTestCatalog().apply(e)

require.NoError(t, err)
assert.NotEmpty(t, conditions)
assert.Empty(t, traits)
assert.NotEmpty(t, e.ExecutedTraits)
assert.Nil(t, e.GetTrait("builder"))
assert.Empty(t, e.Pipeline)
Expand All @@ -80,9 +81,10 @@ func TestBuilderTraitNotAppliedBecauseOfNilPhase(t *testing.T) {

func TestS2IBuilderTrait(t *testing.T) {
env := createBuilderTestEnv(v1.IntegrationPlatformClusterOpenShift, v1.IntegrationPlatformBuildPublishStrategyS2I, v1.BuildStrategyRoutine)
conditions, err := NewBuilderTestCatalog().apply(env)
conditions, traits, err := NewBuilderTestCatalog().apply(env)

require.NoError(t, err)
assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
assert.NotNil(t, env.GetTrait("builder"))
Expand All @@ -97,9 +99,10 @@ func TestS2IBuilderTrait(t *testing.T) {

func TestJibBuilderTrait(t *testing.T) {
env := createBuilderTestEnv(v1.IntegrationPlatformClusterOpenShift, v1.IntegrationPlatformBuildPublishStrategyJib, v1.BuildStrategyRoutine)
conditions, err := NewBuilderTestCatalog().apply(env)
conditions, traits, err := NewBuilderTestCatalog().apply(env)

require.NoError(t, err)
assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
assert.NotNil(t, env.GetTrait("builder"))
Expand Down
10 changes: 7 additions & 3 deletions pkg/trait/camel.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const (
type camelTrait struct {
BasePlatformTrait
traitv1.CamelTrait `property:",squash"`
// private configuration used only internally
runtimeVersion string
}

func newCamelTrait() Trait {
Expand Down Expand Up @@ -73,8 +75,10 @@ func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
if runtimeVersion, err := determineRuntimeVersion(e); err != nil {
return false, nil, err
} else {
t.RuntimeVersion = runtimeVersion
t.runtimeVersion = runtimeVersion
}
} else {
t.runtimeVersion = t.RuntimeVersion
}

var cond *TraitCondition
Expand All @@ -89,7 +93,7 @@ func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
traitConfigurationReason,
fmt.Sprintf(
"Operated with CamelCatalog version %s which may be different from the runtime used in the container",
t.RuntimeVersion,
t.runtimeVersion,
),
)
}
Expand All @@ -102,7 +106,7 @@ func (t *camelTrait) Apply(e *Environment) error {
// expects a CamelCatalog to be loaded regardless it's a managed or
// non managed build Integration
if e.CamelCatalog == nil {
if err := t.loadOrCreateCatalog(e, t.RuntimeVersion); err != nil {
if err := t.loadOrCreateCatalog(e, t.runtimeVersion); err != nil {
return err
}
}
Expand Down
147 changes: 115 additions & 32 deletions pkg/trait/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,6 @@ type containerTrait struct {
func newContainerTrait() Trait {
return &containerTrait{
BasePlatformTrait: NewBasePlatformTrait(containerTraitID, containerTraitOrder),
ContainerTrait: traitv1.ContainerTrait{
Port: defaultContainerPort,
ServicePort: defaultServicePort,
ServicePortName: defaultContainerPortName,
Name: defaultContainerName,
RunAsNonRoot: ptr.To(defaultContainerRunAsNonRoot),
SeccompProfileType: defaultContainerSeccompProfileType,
AllowPrivilegeEscalation: ptr.To(defaultContainerAllowPrivilegeEscalation),
CapabilitiesDrop: []corev1.Capability{defaultContainerCapabilitiesDrop},
RequestCPU: defaultContainerResourceCPU,
RequestMemory: defaultContainerResourceMemory,
LimitCPU: defaultContainerLimitCPU,
LimitMemory: defaultContainerLimitMemory,
},
}
}

Expand All @@ -94,8 +80,9 @@ func (t *containerTrait) Configure(e *Environment) (bool, *TraitCondition, error

if ptr.Deref(t.Auto, true) {
if t.Expose == nil {
e := e.Resources.GetServiceForIntegration(e.Integration) != nil
t.Expose = &e
if e.Resources.GetServiceForIntegration(e.Integration) != nil {
t.Expose = ptr.To(true)
}
}
}

Expand Down Expand Up @@ -138,7 +125,7 @@ func (t *containerTrait) configureContainer(e *Environment) error {
e.ApplicationProperties = make(map[string]string)
}
container := corev1.Container{
Name: t.Name,
Name: t.getContainerName(),
Image: e.Integration.Status.Image,
Env: make([]corev1.EnvVar, 0),
}
Expand Down Expand Up @@ -230,16 +217,16 @@ func (t *containerTrait) configureService(e *Environment, container *corev1.Cont
}
containerPort := corev1.ContainerPort{
Name: name,
ContainerPort: int32(t.Port),
ContainerPort: int32(t.getPort()),
Protocol: corev1.ProtocolTCP,
}
if !isKnative {
// The service is managed by Knative, so, we only take care of this when it's managed by us
service := e.Resources.GetServiceForIntegration(e.Integration)
if service != nil {
servicePort := corev1.ServicePort{
Name: t.ServicePortName,
Port: int32(t.ServicePort),
Name: t.getServicePortName(),
Port: int32(t.getServicePort()),
Protocol: corev1.ProtocolTCP,
TargetPort: intstr.FromString(name),
}
Expand Down Expand Up @@ -271,21 +258,21 @@ func (t *containerTrait) configureResources(container *corev1.Container) {
limitsList = make(corev1.ResourceList)
}

requestsList, err = kubernetes.ConfigureResource(t.RequestCPU, requestsList, corev1.ResourceCPU)
requestsList, err = kubernetes.ConfigureResource(t.getRequestCPU(), requestsList, corev1.ResourceCPU)
if err != nil {
t.L.Error(err, "unable to parse quantity", "request-cpu", t.RequestCPU)
t.L.Error(err, "unable to parse quantity", "request-cpu", t.getRequestCPU())
}
requestsList, err = kubernetes.ConfigureResource(t.RequestMemory, requestsList, corev1.ResourceMemory)
requestsList, err = kubernetes.ConfigureResource(t.getRequestMemory(), requestsList, corev1.ResourceMemory)
if err != nil {
t.L.Error(err, "unable to parse quantity", "request-memory", t.RequestMemory)
t.L.Error(err, "unable to parse quantity", "request-memory", t.getRequestMemory())
}
limitsList, err = kubernetes.ConfigureResource(t.LimitCPU, limitsList, corev1.ResourceCPU)
limitsList, err = kubernetes.ConfigureResource(t.getLimitCPU(), limitsList, corev1.ResourceCPU)
if err != nil {
t.L.Error(err, "unable to parse quantity", "limit-cpu", t.LimitCPU)
t.L.Error(err, "unable to parse quantity", "limit-cpu", t.getLimitCPU())
}
limitsList, err = kubernetes.ConfigureResource(t.LimitMemory, limitsList, corev1.ResourceMemory)
limitsList, err = kubernetes.ConfigureResource(t.getLimitMemory(), limitsList, corev1.ResourceMemory)
if err != nil {
t.L.Error(err, "unable to parse quantity", "limit-memory", t.LimitMemory)
t.L.Error(err, "unable to parse quantity", "limit-memory", t.getLimitMemory())
}

container.Resources.Requests = requestsList
Expand All @@ -300,12 +287,12 @@ func (t *containerTrait) configureCapabilities(e *Environment) {

func (t *containerTrait) setSecurityContext(e *Environment, container *corev1.Container) error {
sc := corev1.SecurityContext{
RunAsNonRoot: t.RunAsNonRoot,
RunAsNonRoot: t.getRunAsNonRoot(),
SeccompProfile: &corev1.SeccompProfile{
Type: t.SeccompProfileType,
Type: t.getSeccompProfileType(),
},
AllowPrivilegeEscalation: t.AllowPrivilegeEscalation,
Capabilities: &corev1.Capabilities{Drop: t.CapabilitiesDrop, Add: t.CapabilitiesAdd},
AllowPrivilegeEscalation: t.getAllowPrivilegeEscalation(),
Capabilities: &corev1.Capabilities{Drop: t.getCapabilitiesDrop(), Add: t.CapabilitiesAdd},
}

runAsUser, err := t.getUser(e)
Expand Down Expand Up @@ -342,3 +329,99 @@ func (t *containerTrait) getUser(e *Environment) (*int64, error) {

return runAsUser, nil
}

func (t *containerTrait) getPort() int {
if t.Port == 0 {
return defaultContainerPort
}

return t.Port
}

func (t *containerTrait) getServicePort() int {
if t.ServicePort == 0 {
return defaultServicePort
}

return t.ServicePort
}

func (t *containerTrait) getServicePortName() string {
if t.ServicePortName == "" {
return defaultContainerPortName
}

return t.ServicePortName
}

func (t *containerTrait) getContainerName() string {
if t.Name == "" {
return defaultContainerName
}

return t.Name
}

func (t *containerTrait) getRunAsNonRoot() *bool {
if t.RunAsNonRoot == nil {
return ptr.To(defaultContainerRunAsNonRoot)
}

return t.RunAsNonRoot
}

func (t *containerTrait) getSeccompProfileType() corev1.SeccompProfileType {
if t.SeccompProfileType == "" {
return defaultContainerSeccompProfileType
}

return t.SeccompProfileType
}

func (t *containerTrait) getAllowPrivilegeEscalation() *bool {
if t.AllowPrivilegeEscalation == nil {
return ptr.To(defaultContainerAllowPrivilegeEscalation)
}

return t.AllowPrivilegeEscalation
}

func (t *containerTrait) getCapabilitiesDrop() []corev1.Capability {
if t.CapabilitiesDrop == nil {
return []corev1.Capability{defaultContainerCapabilitiesDrop}
}

return t.CapabilitiesDrop
}

func (t *containerTrait) getRequestCPU() string {
if t.RequestCPU == "" {
return defaultContainerResourceCPU
}

return t.RequestCPU
}

func (t *containerTrait) getRequestMemory() string {
if t.RequestMemory == "" {
return defaultContainerResourceMemory
}

return t.RequestMemory
}

func (t *containerTrait) getLimitCPU() string {
if t.LimitCPU == "" {
return defaultContainerLimitCPU
}

return t.LimitCPU
}

func (t *containerTrait) getLimitMemory() string {
if t.LimitMemory == "" {
return defaultContainerLimitMemory
}

return t.LimitMemory
}
12 changes: 8 additions & 4 deletions pkg/trait/container_probes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ func TestProbesDependencies(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseInitialization

conditions, err := env.Catalog.apply(&env)
conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Contains(t, env.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus:camel-quarkus-microprofile-health")
}
Expand All @@ -105,8 +106,9 @@ func TestProbesOnDeployment(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseDeploying

conditions, err := env.Catalog.apply(&env)
conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)

container := env.GetIntegrationContainer()
Expand Down Expand Up @@ -143,8 +145,9 @@ func TestProbesOnDeploymentWithCustomScheme(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseDeploying

conditions, err := env.Catalog.apply(&env)
conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)

container := env.GetIntegrationContainer()
Expand Down Expand Up @@ -200,8 +203,9 @@ func TestProbesOnKnativeService(t *testing.T) {
"controller strategy: knative-service",
)

conditions, err := env.Catalog.apply(&env)
conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
assert.NotEmpty(t, traits)
assert.Contains(t, conditions, ctrlStrategyCondition)
assert.Contains(t, conditions, serviceOverrideCondition)

Expand Down
Loading

0 comments on commit 86854bc

Please sign in to comment.