Skip to content

Properties

Formas can be parameterized by properties. Properties not only allow to add more flexibility for forma application, but also to abstract infrastructure for developers, for example in Platform Engineering settings. Let's look at an example of how to achieve that:

Declaration of a parameterized service

properties {
  team = new formae.Prop {
    flag = "team"
  }
  size = new formae.Prop {
    flag = "size"
    default = "xs"
  }
}

local _vpc = new vpc_resources.VpcResources {
  team = properties.team.value
}

local _database = new database_resources.DatabaseResources {
  team = properties.team.value
  size = properties.size.value
  vpc = _vpc.vpc
  subnet1 = _vpc.subnet1
  subnet2 = _vpc.subnet2
}

The above code declares a service and parameterizes it with two properties:

  • team: some team name
  • size: database size, expressed as t-shirt size

All the low-level details are hidden behind the service, so that consumers of that service - for example, developer teams, don't need to ever see the underlying details, while the platform team can easily change them according to changing non-functional requirements.

Making sure properties are type and value safe

Properties can be easily constrained, ensuring total type- and value-safety. For example:

typealias Team = "team-a" | "team-b"

function RegionFromTeam(team: Team): aws.Region = (
  if (team == "team-a")
    "us-east-1"
  else if (team == "team-b")
    "us-west-1"
  else
    throw("Unknown team: \(team)")
)

typealias DbRawSize = "db.t3.micro" | "db.t3.small"

typealias DbSize = String((str) -> (
  str.matches(Regex(#"(?i)^(XS|S)"#))
))

function DbRawSizeFromSize(size: DbSize): DbRawSize = (
  if (size.toLowerCase() == "xs")
    "db.t3.micro"
  else if (size.toLowerCase() == "s")
    "db.t3.small"
  else
    throw("Unknown size: \(size)")
)

In the above code, team and database size are constrained to just a few values. If the consumer of the service is not providing correct values of their correct type, the forma will not be applicable.

Setting properties when applying a forma

The consumer - be it a developer or even a CI/CD job - only needs to provide properties of a forma when running the apply command. No need to understand the forma itself.

To see available properties for a forma, use the --help flag:

formae apply --help examples/complete/services/database.pkl
...

Properties:
      --size        property: size [default: "xs"]
      --team        property: team [required]

Try it yourself

formae is shipped with a few examples. Refer to the services example to see properties in action.