Skip to content
Open
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
128 changes: 81 additions & 47 deletions components/dependencies.mdx
Original file line number Diff line number Diff line change
@@ -1,59 +1,93 @@
---
title: "Dependencies"
description:
"Architect was designed with the future in mind, and the future of any team
building distributed software is a complex web of services."
title: Dependencies
---

Historically this complex web of services has been hard to manage, hard to
reason about, and hard for developers to contribute to.
Historically cloud teams have tried to avoid dependencies and coupling between microservices and APIs
because it creates a lot of infrastructure and CI/CD complexity. However, its all too natural for
developers to try to extend what exists rather than reinvent it, and many teams ended up with complex
webs of microservices nonetheless.

Fortunately, the graphing and collaboration problems this creates have been
solved before. We've seen it with object-oriented programming and inheritance,
and even more recently with package and dependency management. All of our
favorite languages have a way for developers to utilize dependencies through a
resolver to handle the artifact storage, complex graphing, and de-duplication
needed to manage them at-scale. Architect takes this same approach to make it
easier than ever for developers to extend cloud services.
Fortunately, this problem of "dependencies" has been solved before. Every language and operating system
on earth has tools for dependency management to help developers collaborate and extend each others work.
Now Architect is here to provide the same value for APIs and microservices.

## Utilizing dependencies
## Why use dependencies?

```yaml
Citing dependencies as part of your component is not the most natural way for developers to integrate with
software made by other teams, but its also the only way to achieve [on-demand environments](/deployments/automated-previews)
for distributed applications.

Every time a component is deployed with Architect, it will automatically deploy (if needed) and connect to
cited dependencies. Perhaps even more impressive than that is that it will also deploy the dependencies OF your
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cited dependencies. Perhaps even more impressive than that is that it will also deploy the dependencies OF your
cited dependencies. Perhaps even more impressive than that is that it will also deploy the *dependencies your

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this suggestion captures what I was trying to say which is that we deploy the dependencies you didn't know you had as well (e.g. the dependencies OF your own dependencies). Is there a better way to phrase that that you can think of?

component's dependencies and ensure they're integrated as well.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
component's dependencies and ensure they're integrated as well.
dependencies* and ensure they're integrated as well.


Without dependency management integrated into deployments, each and every application would have to maintain a
complex web of CI pipelines or centralized infrastructure-as-code (IaC) templates to create new environments which
can be an educational and logistical nightmare. With Architect, all you ever need to know is your immediate dependencies
and the rest will be automated for you.

## Registering dependencies

Before we can begin using dependencies, we need to register a component that will act as a dependency for others. There
are no restrictions on what type of component can be used as a dependency. All you need is to run the `register` command
to publish your component to Architect's cloud registry.

<Note>
If you're component builds docker images from source, those images will also be published to Architect's registry with
the same access rights.
</Note>

```sh
$ architect register ./backend --tag latest --account my-account
```

Haven't created a component before? Check out the [creating components](/guides/create-a-component) guide to learn more.

## Using dependencies

Now that we have a component in the registry, we can use it as a dependency for another one. Citing another component as
a dependency is easy using the `dependencies` block inside the component spec. The below example shows how to cite a component
named `backend` as a dependency so that it gets automatically deployed with your own component.

```yaml architect.yml
dependencies:
authentication: latest
backend: latest
```

You may also want to integrate with one or more services inside the dependency component. You can easily point to `services`, `outputs`,
and other resources declared inside dependencies using Architect's expression syntax:

```yaml architect.yml
services:
my-api:
interfaces:
http: 8080
app:
build:
context: ./
environment:
AUTH_INTERNAL: ${{ dependencies['authentication'].services.auth.interfaces.main.url }}
AUTH_EXTERNAL: ${{
dependencies['authentication'].services.auth.interfaces.main.ingress.url
}}
BACKEND_ADDR: ${{ dependencies.backend.services.api.interfaces.main.url }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explain where this address comes from and possibly link to components/service-discovery

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you bring in service discovery below. It would still be helpful to explain here that the address comes from the backend app's service declaration in its own architect.yml file.

```

Just like with your favorite package manager, developers can cite the names and
versions of the components that they need to make calls to. Not only will this
allow Architect to provision the dependency automatically, it will also allow
developers to pin to specific versions and ensure that the APIs don't change out
from under them.

## Dependency referencing syntax

We've already shown how Architect enables developers to take advantage of
[service discovery](/components/service-discovery) for connecting to peer
services, and the same approach can be used to connect to the interfaces of
component dependencies. Once you've specified a dependency in your component,
you can reference the interfaces of said dependency using the
`${{ dependencies.*.services.*.interfaces.* }}` expression context.

| field | description |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| url | The fully composed URL of the reference interface. This will take the format, `<protocol>://<username>:<password>@<host>:<port><path>`. |
| protocol | The protocol of the interface being referenced. This will always be the specific value assigned to the interface by the developer. |
| username | The username of the interface being referenced. Not all interfaces have usernames, so this will be an empty string if none is set. |
| password | The password of the interface being referenced. Not all interfaces have passwords, so this will be an empty string if none is set. |
| host | The host value of the interface being referenced. This value is usually dynamic to accomodate the differences between service discovery solutions available to each environment. |
| port | The port value of the interface being referenced. |
| path | The path value of the interface being referenced. Not all interfaces have paths, so this will be an empty string if none is set. |
### Available references

Service addresses aren't the only thing you can inject into your own component from dependencies. Developers can
point to just about any resoure declared by the dependency to enrich their own configuration:

| Key | Description |
| ------------------------------- | -------------------------------------------------- |
| `dependencies.<name>.services` | Allows you to inject values associated with [services](/components/services) inside the dependency |
| `dependencies.<name>.databases` | Allows you to inject values associated with [databases](/components/databases) inside the dependency |
| `dependencies.<name>.outputs` | Allows you to inject output values issued by the dependency |

## Debugging dependencies

By default Architect will pull dependencies down from the cloud registry on every deployment. But if you want to test changes to
two components at once, you can do so by linking the dependency to your host machine with `architect link`. This will cause Architect
to use the local version of the components rather than trying to pull them from the Architect cloud registry. This is helpful when
you are actively developing multiple components that are dependent on one another.

```sh
# Tells architect to use the local source code to fulfill dependencies on the `backend`
$ architect link ./backend/

# Will build and connect to the backend code found locally instead of the docker images pulled from Architect Cloud
$ architect dev ./frontend/
```