Building a Stack¶
The Stack is the definition of your infrastructure that Opslib will manage.
It’s made up of components, with the root component being
an instance of Stack
.
from opslib import Stack
stack = Stack(__name__)
Opslib tries to import a module named stack
(which is why our file is
called stack.py
). In the module, it looks for an object named stack
.
The __name__
argument helps Opslib figure out where the code is defined, so
it can create its .opslib
directory, next to stack.py
, to store its
state.
Attaching components¶
To build up the stack, we attach components to it, by setting them as attributes:
from pathlib import Path
from opslib import LocalHost
stack.host = LocalHost()
stack.hello = stack.host.file(
path=Path("/tmp/hello.txt"),
content="Hello World!\n"
)
At this point, the host
and hello
components are attached to the stack,
and will be deployed when we run opslib - deploy
.
$ opslib - deploy
$ cat /tmp/hello.txt
Hello World!
Defining components¶
Attaching everything to the root stack object doesn’t scale much, so we’ll want to organize components into higher level structures:
from opslib import Component, Prop
class Bucket(Component):
class Props:
host = Prop(LocalHost)
color = Prop(str)
def build(self):
self.file = self.props.host.file(
path=Path(f"/tmp/{self.props.color}.txt"),
content=f"A splash of {self.props.color}\n"),
)
stack.red = Bucket(host=stack.host, color="red")
stack.green = Bucket(host=stack.host, color="green")
stack.blue = Bucket(host=stack.host, color="blue")
The Bucket
component receives two Props: host
and color
.
The component’s build()
method creates
sub-components and attaches them. It’s called when the Bucket
component is
attached to something (in our case, the stack
).
Note
build()
is not called when the
component is created, but rather later, when it’s attached. This means that
a detached component doesn’t have any of its child components created and
attached yet.