-
Notifications
You must be signed in to change notification settings - Fork 218
Error when using multiple dependent resources of the same class #1653
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
Comments
any news on this? |
Hi @derlin , this seems to be suspicious, you are both initializing and using the event source of dbSecret, that is at least not intended.
What you should do is create an informer and use that in all the dependent resource of same type. So maybe just remoce Maybe rename |
I created an issue: #1691 Will take a look on this soon, remember something that it was an issue in the past to properly support multiple informers in same types in all cases; But I don't see now why it would be a problem. Is there a particular reason why you cant use just one informer for both the Secret? @derlin |
@csviri What do you mean ? Both sources are for secrets, but with completely different configuration. The first one, credentials secret, looks for a specific label and a namespace+name matching the namespace+name in the CR spec How else would you configure this if not using separate informers ? Also remember that this configuration worked fine prior to the major update, so I don't think it was a problem before. |
There could be just one Informer for all secretes a proper label selector.
there is a lot going in the background, but will take a look and try to make it as generic as possible, ideally covering this case |
What you can do is to set a resourceDiscriminator that will select the target resource atm, see the releated implementation when things go bad for you: Just, to give a little insight, discriminators were designed for these purposes. But mainly for multiple resources with same type, should work also here. (Hopefully will have time to take a look in tomorrow into it deeper.) |
@csviri happy new year ! I had a look at the PR, thank you for the example on how to use discriminators. I tried using them and it works: see this commit. However, I wasn't able to get rid of the two separate informers for I also failed to use read-only dependent resources. It says in the docs:
When subclassing The docs also mentions AbstractSimpleDependentResource, but this is a dead link / it doesn't exist. |
Hi @derlin , happy new year!
Usually if you just watch one resource from one namespace and an other from another namespace is fine also. Alternatively you can have a cluster scoped InformerEventSource, or with a selected namespaces - that is also supported. Ideally resources are filtered by label. There is not much can be done more then these. Will update also the docs but:
Note that you usually don't extend the Note that the highest level abstraction we are using in the workflows is DependentResource You can even implement a custom hierarchy for this interface. But right this needs to be better documented, will create an issue, and update the docs also regarding to this. |
Thank you for the explanations and the (soon-to-be) updated docs! One more question (sorry for the spam ^^'). In my case, the config and credentials secrets are both resources that are used by many dbs (akka primary resources). That is, multiple db/primary may refer to the same secondary resource(s). I am currently creating an context.getPrimaryCache().addIndexer(indexName, db -> List.of(indexKey(db)));
var informerConfiguration = InformerConfiguration.from(cls)
.withPrimaryToSecondaryMapper((Db db) -> Set.of(new ResourceID(
db.getSpec().getConfigRef().getName(),
db.getSpec().getConfigRef().getNamespace())))
.withSecondaryToPrimaryMapper(
secondary -> context
.getPrimaryCache()
.byIndex(indexName, indexKey(secondary))
.stream()
.map(ResourceID::fromResource)
.collect(Collectors.toSet()))
.build(); I tried to move this into a dependent resource in multiple ways, but here is one of the latest iterations:: @Slf4j
public class DependentConfig extends KubernetesDependentResource<Config, Db>
implements SecondaryToPrimaryMapper<Config>, PrimaryToSecondaryMapper<Db> {
public static final String INFORMER_NAME = "dependent_config";
private IndexerResourceCache<Db> cache; // ⬅ don't know how to access it otherwise
public DependentConfig(KubernetesClient kubernetesClient) {
super(Config.class);
setKubernetesClient(kubernetesClient);
}
@Override
protected InformerEventSource<Config, Db> createEventSource(EventSourceContext<Db> context) {
this.cache = context.getPrimaryCache(); // ⬅ get a reference for later
cache.addIndexer(INFORMER_NAME,
db -> List.of(db.getSpec().getConfigRef().getNamespace() + "#" + db.getSpec().getConfigRef().getName()));
return super.createEventSource(context);
}
@Override
public Set<ResourceID> toSecondaryResourceIDs(Db db) {
return Set.of(new ResourceID(
db.getSpec().getConfigRef().getName(),
db.getSpec().getConfigRef().getNamespace()));
}
@Override
public Set<ResourceID> toPrimaryResourceIDs(Config config) {
return cache
.byIndex(INFORMER_NAME, config.getMetadata().getNamespace() + "#" + config.getMetadata().getName())
.stream().map(ResourceID::fromResource) .collect(Collectors.toSet());
}
} Using a dependent resource for the config like above, if I start the operator and there is already an existing config + db, all is fine (the reconcile method is able to find the config). If I create a db after the operator has started, then it cannot find the secondary resource / the config anymore. If I restart, it is fine again. I guess this means the informer cache is correctly initialized, but not updated. But why ? I don't see exactly the difference between the dependent implementation and the one where I create the informer event source manually. Did I miss something ? |
@derlin yes, this is not supported for reason explained here: Basically the only reason you might want to have a dependent resources for such is to have some reconcile precondition conditions - thus have it more nicely expressed. So if you have such a use case, we can support this, but again, its just to have a condition on a read only resource usually. Will comment this on that issue, and reopen it for further discussion. |
Ok thanks. The "manual" way seems to still work on 4.X, so as long as it doesn't break, I am fine with this way of doing. We can close this issue. Thanks again for your time! |
Bug Report
What did you do?
I am using the JOSDK through quarkus-operator-sdk. I have a specific use case that I explained in #1437. The code is available at https://github.com/derlin/josdk-operator-dependent-crs/blob/main/src/main/java/ch/derlin/configreconciler/DbReconciler.java .
Now, I am trying to migrate to quarkus-operator-sdk 5.X, which updates JOSDK from 3.X to 4.X. The difficulty comes from the fact that I have two different event sources for the same class
Secret
.My event sources are prepared like this. The
createInformer
method creates its own event source, while thedbSecret
is an instance ofCRUDKubernetesDependentResource<Secret, Db>
:In my reconciliation, I have the following:
This was working fine with the old version but with 4.X I get the following exception when calling
dbSecret.reconcile(resource, context)
:I added the line
dbSecret.useEventSourceWithName()
(see first code snippet) to try to avoid this error, to no avail.SIDE NOTE: I also have no idea how to do the
getSecondaryResource
with the new implementation, any hint ?What did you expect to see?
I would expect the code to keep working, meaning I am able to reconcile my
dbSecret
(and also fetch my secondary resources) as before.What did you see instead? Under which circumstances?
I see the exception (see above):
Environment
I am using K3D for testing (vanilla kubernetes).
$ Mention java-operator-sdk version from pom.xml file
$ java -version
java -version openjdk version "11.0.16.1" 2022-08-12 OpenJDK Runtime Environment Homebrew (build 11.0.16.1+0) OpenJDK 64-Bit Server VM Homebrew (build 11.0.16.1+0, mixed mode)
$ kubectl version
kubectl version --short Flag --short has been deprecated, and will be removed in the future. The --short output will become the default. Client Version: v1.25.4 Kustomize Version: v4.5.7 Server Version: v1.24.4+k3s1
Possible Solution
I think the problem comes from https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/SingleDependentResourceReconciler.java#L18 where the
.getSecondaryResource()
doesn't use any discriminator / doesn't look for the event source name.Additional context
I already shared my use case in this issue #1437. A minimal reproducible example is available at https://github.com/derlin/josdk-operator-dependent-crs/tree/quarkus-operator-5.X :
main
⮕ working version with 3.Xquarkus-operator-5.X
⮕ failing version with 4.XThe text was updated successfully, but these errors were encountered: