Handling provider and module interdependencies

We are in the process of moving from HCL to cdktf from top to bottom with an extensive and deeply nested HCL module structure.

In the old world we got a number of meta repositories, which contains all configs and also instantiates the providers, sometimes multiple ones with aliases. Those configs and provider configuration are sometimes a bit different, which is one reason why we used this approach.

The config and those providers are then passed to a big submodule A which creates an AWS Account and multiple Kubernetes Clusters. Outputs from this submodule A (like the ClusterID) are also used in the meta repository to instantiate some providers, which are ALSO passed to the Submodule A.

All this is possible in HCL, but not in CDK, as Typescript is of course complaining with circular dependencies. A Token does not help of course. We did this before, as we needed to use the instantiated providers in the meta configuration to e.g. create a VPN or some other stuff on top of that.

...
    const providers = new Providers(
      this,
      "providers",
      someData,
      someData2,
      submoduleA.someOutput,
    );

    const locals = new Locals(this, "locals");

    // Resources
    const submoduleA = new SubmoduleA(
      this,
      "submoduleA",
      providers,
      accountConfig,
      locals,
    );
...

A solution would of course be to instantiate the providers in the submodule A and just pass some config variables. I am not sure though if this problem will come up, but how could we reuse a provider this way? In HCL it is not possible to output a provider from a module. Could I just do this in CDK by returning the instance of a provider from a CDK submodule?

2 Likes

Hi @rstoermer :wave:

I know my reply comes probably way too late, but I’ll still reply mainly as reference for whoever might stumble upon this thread later.

That might work, yeah.

That said, it is also possible to decouple the circular dependency by removing submoduleA.someOutput from the constructor of your Providers class and by setting that property later:

providers.setSomething(submoduleA.someOutput)

That method would then need to change whatever attribute someOutput was used for in the constructor previously, which is usually possible via setters on the constructs that were instantiated.

Hope this helps whoever might read this reply :smile:

– Ansgar

1 Like