Skip to content

SaaS Configuration

One of the biggest complexities with operating SaaS at scale is to meet the needs of different customers with varying requirements.

Often, you need a way for your tenants to customize their deployments. The customization could be:

  • How your application is configured
  • What capabilities are enabled
  • What cloud provider, region, account is chosen
  • What infrastructure is used
  • How the infrastructure is configured based on the cost and security requirements

To enable, we have made sure that you can define and build the experience thats best for your application.

To achieve the above, we have defined the concept of parameterization where you can parameterize anything and assign a type to it.

There are 3 types of parameters:

  • Static parameters
  • Dynamic parameters
  • System parameters

We will go over each one of them in detail below.

Static parameters

There are certain parameters that you don't want your customers to worry about and prefer to control them internally. However, you stil want to version it so that when you change them, you can control which tenant gets the updated values or know who has the updated version.

Dynamic parameters

There are certain parameters that you want your customers to configure.

You can define such variables and configure them to be dynamic based on the customer input. To achieve this, you can set the value of the corresponding parameters to any API parameter.

Now, you may also want to configure infrastructure dynamically based on the customer input. Here are some example infrastructure settings that you can dynamically configure:

  • replicaCountAPIParam: to configure number of replicas
  • instanceTypes: to configure instance type
  • instanceStorageIOPSAPIParam: to configure storage IOPS
  • instanceStorageThroughputAPIParam: to configure storage throughput
  • instanceStorageTypeAPIParam: to configure storage type
  • instanceStorageSizeGiAPIParam: to configure storage size in GBs

Note

If you need to dynamically customize some specific infra settings, please reach out to us support@omnistrate.com

Here is an example API param for PostgreSQL writer resource. As you can see different API parameter are defined and used to configure database configuration (ex - postgresqlUsername) and underlying infrastructure (ex - writerInstanceType):

x-omnistrate-api-params:
  - key: writerInstanceType
    description: Writer Instance Type
    name: Writer Instance Type
    type: String
    modifiable: true
    required: true
    export: true
  - key: postgresqlPassword
    description: Default DB Password
    name: Password
    type: String
    modifiable: false
    required: true
    export: false
  - key: postgresqlDatabase
    description: Default DB Name
    name: Default Database
    type: String
    modifiable: false
    required: true
    export: true
  - key: postgresqlUsername
    description: Username
    name: Default DB Username
    type: String
    modifiable: false
    required: true
    export: true
  - key: postgresqlRootPassword
    description: Root Password
    name: Root DB Password
    type: String
    modifiable: false
    required: false
    export: false
    defaultValue: rootpassword12345
environment:
  - POSTGRESQL_PASSWORD=$var.postgresqlPassword
  - POSTGRESQL_DATABASE=$var.postgresqlDatabase
  - POSTGRESQL_USERNAME=$var.postgresqlUsername
  - POSTGRESQL_POSTGRES_PASSWORD=$var.postgresqlRootPassword
  - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
  - POSTGRESQL_LOG_HOSTNAME=true
  - POSTGRESQL_REPLICATION_MODE=master
  - POSTGRESQL_REPLICATION_USER=repl_user
  - POSTGRESQL_REPLICATION_PASSWORD=repl_password
  - POSTGRESQL_DATA_DIR=/var/lib/postgresql/data/dbdata
  - SECURITY_CONTEXT_USER_ID=1001
  - SECURITY_CONTEXT_FS_GROUP=1001
  - SECURITY_CONTEXT_GROUP_ID=0
x-omnistrate-compute:
  instanceTypes:
    - cloudProvider: aws
      apiParam: writerInstanceType
    - cloudProvider: gcp
      apiParam: writerInstanceType
System parameters

Finally, there are some system parameters that we have defined in the system that you can use. The values of them are determined at runtime based on other configuration.

  • Server ID: unique ID of each node in a resource instance. As an example, if you creating Kafka SaaS, then you may define Kafka Cluster as one resource and ZK as another resource. For every instance of Kafka resource, you can use Server ID as a broker ID for each of the brokers (or nodes)
  • Node name: unique name of each node in a resource instance
  • Node names: set of all the node names in a given resource instance
  • Global endpoint: global endpoint of a resource instance that will be load-balanced across all its nodes
  • Local endpoints: list of local endpoints in a resource instance corresponding to each of the nodes
  • Bucket name: bucket name if cluster storage is configured

In addition, if you define the environment variables SECURITY_CONTEXT_GROUP_ID, SECURITY_CONTEXT_USER_ID and SECURITY_CONTEXT_FS_GROUP, we will automatically use them to configure user ID, group ID and fsGroup ID.

Info

A detailed list of system parameters be found on Build Guides / System Parameters

Dependencies and SaaS configuration

Now, you may have several resources (or service component) and they maybe dependent on each other. Let's say if you have resource A (with API param X) that depends on resource B (with API param Y), then you can refer to resource B API and System parameters to configure resource A. More specifically, following variables will be available to configure service/infrastructure parameters of resource A:

  • Service component A: API parameter X aka $var.X
  • Service component A: Server ID aka $(NODE_INDEX)
  • Service component A: Node name aka $sys.compute.node.name
  • Service component A: Node names aka $sys.compute.nodes[*].name
  • Service component A: Global endpoint aka $sys.network.externalClusterEndpoint
  • Service component A: Local endpoints aka $sys.network.nodes[*].internalEndpoint
  • Service component B: API parameter Y aka $B.var.Y
  • Service component B: Node name aka $B.sys.compute.node.name
  • Service component B: Node names aka $B.sys.compute.nodes[*].name
  • Service component B: Global endpoint aka $B.sys.network.externalClusterEndpoint
  • Service component B: Local endpoints aka $B.sys.network.nodes[*].internalEndpoint

As an example, let's say you are building Kafka SaaS, and Kafka resource depends on Zookeeper (ZK) resource. You will need to configure Kafka component with ZK endpoint.

Note

Note that in the above example resource B can't refer to parent resource A. Only parent resources can refer to child resources