# Future-Proofing the Source Hydrator API
## Multi-Source Support
### Proposal 1: `sourceHydrator.drySources`
**NOTE: This is my current recommendation.**
Pros:
* Parallel to source/sources UX
* Parallel to source/sources implementation
Cons:
* Two fields, gotta validate that one and only one is present (similar to regular multi-source)
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
sourceHydrator:
drySource:
repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: helm-guestbook
drySources:
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: helm-guestbook
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: external-secrets
```
### Proposal 2: `sourceHydrator.drySource.additionalSources`
Pros:
* No need for drySource/drySources mutual exclusivity validation
Cons:
* Awkward apparent primary/secondary relationship between top-level drySource and nested additionalSources
* Awkward lack of parallelism between `additionalSources` and source modifiers like `helm` and `kustomize`
* Awkward apparent relationship between top level modifiers (like `drySource.helm`) and nested modifiers (`drySource.additionalSources[0].helm`); unclear whether the former config applies to the latter sources
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
sourceHydrator:
drySource:
repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: helm-guestbook
additionalSources:
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: external-secrets
```
### Proposal 3: `source.hydrator`/`sources[].hydrator` with Nested Dry Source
Pros:
* No new field or validation/fallback requirements de-conflicting with `source` and `sources`
* Somewhat easier adoption, because you can add to and update an existing field instead of using a completely new one
Cons:
* The fact that the top-level config is the "hydrated config" is not explicit in the API field names; only the "dry" config is explicitly named as such
* User has to move the top level `targetRevision` and `path` into the `drySource`
* `targetRevision` field for hydrated source is misleading because it actually must be a branch
* Existence of `chart`, `helm`, and `kustomize` fields under `sources[0]` is misleading, because none of those is actually valid when using the hydrator
* The presence of the `directory` field breaks rendered-manifests guarantees: you can filter after hydration, which means the hydrated state isn't necessarily the synced state.
* The presence of the `directory` field is weird, because there isn't really a valid use case
* The lack of parallelism in the source fields' behavior is awkward: `helm`, `kustomize`, and `directory` are hydration modifiers, but `hydrator` introduces completely out-of-band behavior
* It's unclear how the hydrator should behave when two sources' configs match vs. differ
* If the hydration destination branch is the same, do we concatenate the output of all sources into one file?
* If the hydration destination branches differ, is that an error? Or do we just asynchronously hydrate to the different destinations?
* If differently-destined are allowed, there's a risk of races when syncing: if we've hydrated and pushed source 1, we might sync that before we finish hydrating and pushing source 2. To prevent this race, we'd need a locking mechanism shared by the synchronization and hydration code.
* In general, this mixes hydration and synchronization concerns. We currently use the `ApplicationSource` field to determine whether the configured source has changed since the last sync. If we embed hydration config, the synchronization code will need special comparison logic to avoid considering hydration fields when comparing the last sync to the current config.
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
sources:
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: environments/e2e
path: guestbook
hydrator:
drySource:
targetRevision: HEAD
path: helm-guestbook
hydrateTo:
targetBranch: environments/e2e-next
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: environments/e2e
path: guestbook
hydrator:
drySource:
targetRevision: HEAD
path: external-secrets
hydrateTo:
targetBranch: environments/e2e-next
```
### Proposal 4: `source.hydrator`/`sources[].hydrator` with Nested Hydrated Source
Pros:
* No new field or validation/fallback requirements de-conflicting with `source` and `sources`
* Somewhat easier adoption, because you can add to an existing field instead of using a completely new one
* It's even easier than Proposal 3, because you don't have to change the top-level (dry) source config
Cons:
* The fact that the top-level config is the "dry config" is not explicit in the API field names; only the "sync" (hydrated) config is explicitly named as such
* `targetRevision` field for hydrated source is misleading because it actually must be a branch
* Existence of `chart`, `helm`, `kustomize`, and `directory` fields under `sources[0]` is misleading, those fields will not be supported by the hydrator in the initial implementation
* The lack of parallelism in the source fields' behavior is awkward: `helm`, `kustomize`, and `directory` are hydration modifiers, but `hydrator` introduces completely out-of-band behavior
* It's unclear how the hydrator should behave when two sources' configs match vs. differ
* If the hydration destination branch is the same, do we concatenate the output of all sources into one file?
* If the hydration destination branches differ, is that an error? Or do we just asynchronously hydrate to the different destinations?
* If differently-destined are allowed, there's a risk of races when syncing: if we've hydrated and pushed source 1, we might sync that before we finish hydrating and pushing source 2. To prevent this race, we'd need a locking mechanism shared by the synchronization and hydration code.
* In general, this mixes hydration and synchronization concerns. We currently use the `ApplicationSource` field to determine whether the configured source has changed since the last sync. If we embed hydration config, the synchronization code will need special comparison logic to avoid considering hydration fields when comparing the last sync to the current config.
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
sources:
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: helm-guestbook
hydrator:
syncSource:
targetRevision: environments/e2e
path: guestbook
hydrateTo:
targetBranch: environments/e2e-next
- repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: external-secrets
hydrator:
drySource:
targetRevision: environments/e2e
path: guestbook
hydrateTo:
targetBranch: environments/e2e-next
```