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

Composition Condition support for XRs and XRCs #14

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ go 1.22.4
require (
github.com/alecthomas/kong v0.9.0
github.com/apple/pkl-go v0.8.0
github.com/crossplane/crossplane-runtime v1.15.1
github.com/crossplane/function-sdk-go v0.2.0
github.com/crossplane/crossplane-runtime v1.16.0
github.com/crossplane/function-sdk-go v0.3.0-rc.0.0.20240628013706-bc16c875629d
github.com/google/go-cmp v0.6.0
google.golang.org/protobuf v1.34.2
k8s.io/apimachinery v0.30.2
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crossplane/crossplane-runtime v1.15.1 h1:g1h75tNYOQT152IUNxs8ZgSsRFQKrZN9z69KefMujXs=
github.com/crossplane/crossplane-runtime v1.15.1/go.mod h1:kRcJjJQmBFrR2n/KhwL8wYS7xNfq3D8eK4JliEScOHI=
github.com/crossplane/crossplane-runtime v1.16.0 h1:lz+l0wEB3qowdTmN7t0PZkfuNSvfOoEhQrEYFbYqMow=
github.com/crossplane/crossplane-runtime v1.16.0/go.mod h1:Pz2tdGVMF6KDGzHZOkvKro0nKc8EzK0sb/nSA7pH4Dc=
github.com/crossplane/function-sdk-go v0.2.0 h1:4r+dXeGgwOC2XehJlHsHlkdkUsGW8PzkiyPPd2cshQs=
github.com/crossplane/function-sdk-go v0.2.0/go.mod h1:AvaWMHeKvzzE0vODLBrU5njOzW6sm61Ou4js9OdBUXM=
github.com/crossplane/function-sdk-go v0.3.0-rc.0.0.20240628013706-bc16c875629d h1:foFcAZ7sBZp6wFEQUL8sAwEejRewztl6GBQ5P50i/sk=
github.com/crossplane/function-sdk-go v0.3.0-rc.0.0.20240628013706-bc16c875629d/go.mod h1:20eEseResKdP2p+uj+Wn2KyJOvC25R3YInj876n4ncg=
github.com/crossplane/upjet v1.1.0-rc.0.0.20231227120826-4cb45f9104ac h1:T1MTxsPAE/Cs0/EAGjeC29H9O/rO81yol2/5qGsf888=
github.com/crossplane/upjet v1.1.0-rc.0.0.20231227120826-4cb45f9104ac/go.mod h1:t9etxIdYaxgyvFPBToikm5zBHi8RIpX8N4mTH77lQFM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -213,6 +217,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
Expand Down
25 changes: 25 additions & 0 deletions pkl/crossplane.contrib.example/compositions/steps/full.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,28 @@ context {
meta = if (request.meta != null) new {
ttl = 60.s
} else null

local observedObj: Object? = request.observed.resources.getOrNull("cm-one")?.resource as Object?
local observedObjSyncedCondition: Object.Condition? = observedObj?.status?.conditions?.ifNonNull(
(conds: Listing<Condition>) -> conds.toList().findOrNull(
(cond: Object.Condition) -> cond.type == "Synced"
)
)

conditions {
if (observedObjSyncedCondition != null && observedObjSyncedCondition.message.contains("connect failed: cannot get provider config"))
new {
target = TARGET_COMPOSITE_AND_CLAIM
status = STATUS_CONDITION_FALSE
message = "The ProviderConfig 'default' is missing"
reason = "ProviderConfig"
type = "Healthy"
}
else
new {
target = TARGET_COMPOSITE_AND_CLAIM
status = STATUS_CONDITION_TRUE
reason = "TestsPassed"
type = "Healthy"
}
}
72 changes: 72 additions & 0 deletions pkl/crossplane.contrib/CompositionResponse.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,41 @@ context: Mapping<String, Any>?
/// Requirements that must be satisfied for this Function to run successfully.
requirements: Requirements?

/// Status Conditions to be applied to the Composite Resource and sometimes the Claim.
conditions: Listing<Condition?>

class ResponseMeta {

/// Time-to-live of this response. Deterministic Functions with no side-effects
/// (e.g. simple templating Functions) may specify a TTL. Crossplane may choose
/// to cache responses until the TTL expires.
ttl: Duration
}

/// A Result of running a Function.
class Result {
/// Severity of this result.
severity: Severity

/// Human-readable details about the result.
message: String

hidden const SEVERITY_UNSPECIFIED: Severity = 0
hidden const SEVERITY_FATAL: Severity = 1
hidden const SEVERITY_WARNING: Severity = 2
hidden const SEVERITY_NORMAL: Severity = 3
}
typealias Severity = Int(isBetween(0,3))

class State {
/// The state of the composite resource (XR).
composite: Resource

/// The state of any composed resources.
resources: Mapping<String, Resource>
}

/// Requirements that must be satisfied for a Function to run successfully.
class Requirements {
extraResources: Mapping<String, ResourceSelector?>
}
Expand All @@ -71,6 +106,43 @@ class MatchLabels {
labels: Mapping<String, String>
}

/// A Status Condition to be applied to the Composite Resource and sometimes the
/// Claim. For detailed information on proper usage of Conditions, please see
/// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
class Condition {
/// Type of condition in CamelCase or in foo.example.com/CamelCase.
type: String
/// Status of the condition.
status: Status = STATUS_CONDITION_UNSPECIFIED
/// Reason contains a programmatic identifier indicating the reason for the
/// condition's last transition. Producers of specific condition types may
/// define expected values and meanings for this field, and whether the values
/// are considered a guaranteed API. The value should be a CamelCase string.
/// This field may not be empty.
reason: String
/// Message is a human readable message indicating details about the
/// transition. This may be an empty string.
message: String?
/// The resources this condition targets.
target: Target?

hidden const STATUS_CONDITION_UNSPECIFIED: Status = 0
hidden const STATUS_CONDITION_UNKNOWN: Status = 1
hidden const STATUS_CONDITION_TRUE: Status = 2
hidden const STATUS_CONDITION_FALSE: Status = 3

/// If the target is unspecified, the result targets the composite resource.
hidden const TARGET_UNSPECIFIED: Target = 0
/// Target the composite resource. Results that target the composite resource
/// should include detailed, advanced information.
hidden const TARGET_COMPOSITE: Target = 1
/// Target the composite and the claim. Results that target the composite and
/// the claim should include only end-user friendly information.
hidden const TARGET_COMPOSITE_AND_CLAIM: Target = 2
}
typealias Status = Int(isBetween(0, 3))
typealias Target = Int(isBetween(0, 2))

output {
renderer = new YamlRenderer {
converters {
Expand Down
Loading