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

Consider composable non-CRD blocks for workflows / dependencies #2256

Open
emonical opened this issue Feb 29, 2024 · 12 comments
Open

Consider composable non-CRD blocks for workflows / dependencies #2256

emonical opened this issue Feb 29, 2024 · 12 comments

Comments

@emonical
Copy link

Currently, all dependencies using the workflow model (seem to) require either declaring them in their own CRD, or expanding on the blocks used inside a single Reconciler.

It would be nice to be able to define a block of dependencies that is reusable in scope. In my particular case, this is so that we can create separate building blocks for commonly reused entities (see datastores, etc) that do not necessarily meet the case for having a standalone CRD.

This is for two reasons:

  1. The entities themselves maybe managed by other operators and we are considering dependency / ready states for the particular operator.
  2. The the individual deployments themselves do not reflect something that is of a desired scope for its own CRD. In several cases, this may be because we are developing an application and the particular implementation under the hood may change, or it is something that doesn't necessarily warrant its own set of description.
  3. The development of commons libraries for shared patterns between operators or, in the case of multi-controller operators, between different pieces.

Additionally, having a mechanism by which dependencies can be mapped at the level of the individual resource, especially in the case of multiple config maps, secrets, volumeclaims, etc, can then be declared at the point of the dependent resource.

class RedisConfigMap<T: HasMetadata>(val app: App) : AbstractNamedCRUDDependentResource<ConfigMap, T>(ConfigMap::class.java)
{
    companion object {
        fun <T: HasMetadata> withDiscriminator(app: App) : AbstractNamedCRUDDependentResource<ConfigMap, T> {
            return RedisConfigMap<T>(app).withDiscriminator()
        }
    }

    override fun desired(primary: T?, context: Context<T>?): ConfigMap {
        return ConfigMapBuilder()
            .withNewMetadata()
            .withNamespace(primary!!.metadata.name)
            .withName(name())
            .endMetadata()
            .addToData("redis-config", "")
            .build()
    }

    override fun name(): String {
        return "${app.appName}-redis-config"
    }

Is an example of a piece of code I am working on (it's Kotlin, so, bear with me -- and thank you glasskube!)

It would be nice if, instead of piling the configuration into annotations on the Resolver, individual resources could also support declaring their dependencies.

@metacosm
Copy link
Collaborator

metacosm commented Mar 1, 2024

Would you mind elaborating on how you think what you're proposing should look like?
On the topic of resources declaring dependencies, you can already do something similar by using the workflow dependsOn feature (a given dependent will only be reconciled when all of the dependents it depends on are reconciled).

@csviri
Copy link
Collaborator

csviri commented Mar 1, 2024

@metacosm
Copy link
Collaborator

metacosm commented Mar 1, 2024

See also discussions around here: https://discord.com/channels/723455000604573736/1032917332235911169/1212475397413928970

Please post it here. Discord is opaque and we should be having these discussions here, not in some other service that people might not have access to.

@csviri
Copy link
Collaborator

csviri commented Mar 1, 2024

So, if I understand properly this would be kinda Group of dependencies, that can be used as a library in another project. Or more precisely a sub-workflow?

It would be nice if, instead of piling the configuration into annotations on the Resolver, individual resources could also support declaring their dependencies.

Not following this part, could you elaborate pls? Do you mean a dependent resource would declare what is needed for to be declared? (That is basically what "depends_on" doing in workflow in resource level)

@csviri
Copy link
Collaborator

csviri commented Mar 1, 2024

See also discussions around here: https://discord.com/channels/723455000604573736/1032917332235911169/1212475397413928970

Please post it here. Discord is opaque and we should be having these discussions here, not in some other service that people might not have access to.

Everybody has access to the Discord, it's open. The issue should do the summary properly after initial discussion IMO.

@metacosm
Copy link
Collaborator

metacosm commented Mar 1, 2024

See also discussions around here: https://discord.com/channels/723455000604573736/1032917332235911169/1212475397413928970

Please post it here. Discord is opaque and we should be having these discussions here, not in some other service that people might not have access to.

Everybody has access to the Discord it's open. The issue should do the summary properly after initial discussion IMO.

Discord is not open. People shouldn't need to create another account to follow a discussion. I have an account and following the link doesn't help me at all (I'm not using Discord's official app) so even in this case, this is making things difficult. Discord should only be there for quick help, not discussions of features that would benefit from wider community input. We need to have a trace linked to the project itself (i.e. here) instead of in some external proprietary tool that might go away (or change their policies with respect to content), though, granted, the same could be said of GitHub itself, as well. 😄
Let's not multiply the channels where information exists and force people to hunt for that information.

@csviri
Copy link
Collaborator

csviri commented Mar 1, 2024

@metacosm could we pls discuss this under a different issue or GitHub discussion or on Discord :) this is not related to this issue.

(but in general I agree that the issue should be independently clear from Discord discussions, will not post links in future)

@emonical
Copy link
Author

emonical commented Mar 1, 2024

@metacosm @csviri: Oh, I'm using the depends on feature in my both my ControllerConfiguration implementation and a custom workflow implementation.

fun <T: HasMetadata> workflowContext() : Workflow<T> {
    val redisConfigMap = RedisConfigMap.withDiscriminator<T>(app = App.EXAMPLE)
    val redisDeployment = RedisDeployment.withDiscriminator<T>(app = App.EXAMPLE)
    val redisService = RedisService.withDiscriminator<T>(app = App.EXAMPLE)

    return WorkflowBuilder<T>()
        .addDependentResource(redisConfigMap)
        .addDependentResource(redisDeployment).dependsOn(redisConfigMap)
        .addDependentResource(redisService)
        .build()
}

This is an example of a redis declaration we're using. It doesn't meet our usecase for a custom resource. There are also cases where I may wish to move either to or from another operators CRD for implementation.

It would be nice if there was a mechanism by which we could wrap that whole block as a dependency without necessarily managing that block as it's own CRD, managed by it's own Controller/Reconciler, since, in it's own right it doesn't really need it's own management semantics.

It's possible I am missing something in implementation, but, it would be nice to be able do something more like this.

@Dependencies(
dependencies = [
...
]
Redis extends DependentWorkflow

@ControllerConfiguration(
dependencies = [
@Dependent(type = Redis::class)
]
class TrivialReconciler() {
override fun reconcile(resource: TrivialResource, context: Context<TrivialResource>?): UpdateControl<TrivialResource> {
... behavior
}

This is some utterly rough pseudocode, but, then, subworkflow could be referenced as a dependency in it's own right, without encapsulating that behavior in the controller configuration for it's parent.

@csviri
Copy link
Collaborator

csviri commented Mar 11, 2024

@emonical I think I understand what you mean, and see the point that the reusability of a group of dependents might bring some value. This is something that can be done with standalone dependencies by just passing the Workflow builder into a shared service, that will add the dependents to the workflow. Maybe if there is more demand for a feature like this, we can think about this to add it also to the managed dependent resources. But I see this feature would bring much complexity, and it is very limited in terms of target audience - especially since as we mentioned this is usually solved by having a separate CRD for a certain functionality.

@emonical
Copy link
Author

emonical commented Mar 12, 2024

That's the path I'm planning on going down. Perhaps consider making the add/set methods on DependentResourceNode public?

@csviri
Copy link
Collaborator

csviri commented Mar 12, 2024

There is a plan to improve the builder, this can be also considered. cc @metacosm

@metacosm
Copy link
Collaborator

@emonical is this still something you are interested in?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants