# kortical.api.environment

This object represents an environment on Kortical.

An environment is a collection of deployed apps + models on Kortical. Environments are chained together within a project, where the contents of one environment are promoted to the next. The default list of environments is Integration --> UAT --> Production.

To make development and reproducibility easy, Kortical gives you the ability to create challenger environments; these are full replicas of a given environment, in which you can alter what model/app versions are deployed. Once you are happy with changes to your challenger environment, you can commit to git; after the continuous integration has run successfully, the changes are automatically propagated to the main environment.

The Environment class includes the following attributes:

  • id - The ID assigned to the project upon creation.
  • name - The name of the project.
  • promotes_to_environment - The next environment (i.e where components will be promoted to).
  • created_by - User that created the environment.
  • created - Time of creation.
  • project - The project which the environment belongs to, represented as a Project object.

In the Kortical CLI, you can view this by running:

>>> kortical environment list

Project [Document Tagging] selected.
+----+------------------+---------------------+
| id |       name       |       created       |
+====+==================+=====================+
| 42 | Document Tagging | 2023/06/06 15:39:02 |
+----+------------------+---------------------+
Environments in project [Document Tagging]:
+-----+-------------+-----------------------------+----------------------------+---------------------+----------------------------------+
| id  |    name     |   promotes_to_environment   |         created_by         |       created       |             project              |
+=====+=============+=============================+============================+=====================+==================================+
| 128 | Integration | id [127], name [UAT]        | owen.saldanha@kortical.com | 2023/06/06 15:39:02 | id [42], name [Document Tagging] |
+-----+-------------+-----------------------------+----------------------------+---------------------+----------------------------------+
| 127 | UAT         | id [126], name [Production] | owen.saldanha@kortical.com | 2023/06/06 15:39:02 | id [42], name [Document Tagging] |
+-----+-------------+-----------------------------+----------------------------+---------------------+----------------------------------+
| 126 | Production  | None                        | owen.saldanha@kortical.com | 2023/06/06 15:39:02 | id [42], name [Document Tagging] |
+-----+-------------+-----------------------------+----------------------------+---------------------+----------------------------------+

Run kortical environment -h for further help.

# Environments

#

# list


This function lists your Kortical environments.

Inputs

  • project - A Project object.
  • include_created_by (= False) - Use this to see which user created the environment.

Returns

  • [Environment, ...] - A list of Environment objects.
from kortical.api.project import Project
from kortical.api.environment import Environment

# List environments
doc_project = Project.get_project('document_tagging')
environments = Environment.list(doc_project)

#

# create_environment


This function creates an environment within a given project, if given a promotes_to environment it will be inserted between that environment and the previous one. If not the new environment will be created at the end of the promoting chain.

Inputs

  • project - A Project object
  • environment_name - The name of the environment you want to create
  • promotes_to_environment_name_or_id (= None) : The name or ID of the environment the new environment will promote to.
  • component_config (= None) - Text, formatted in yml.

Returns

  • Environment - An Environment object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get Project
doc_project = Project.get_project('document_tagging')

# Create environment promoting to Integration
pre_integration = Environment.create_environment(doc_project, 'Pre-Integration', 'Integration')

# Create environment after Production
post_production = Environment.create_environment(doc_project, 'Post-Production')

#

# get_environment


This function gets an environment from Kortical.

Inputs

  • project - A Project object.
  • environment_name_or_id - The name or ID of the environment you want to access.

Returns

  • Environment - An Environment object, None if it does not exist.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get UAT environment for document_tagging
doc_project = Project.get_project('document_tagging')
uat_environment = Environment.get_environment('UAT')

#

# get_selected_environment


This function gets the selected environment from Kortical:

  • If run locally, this is the environment you have selected using the CLI.
  • If run in an app instance, automatically detects the environment in which the app code is deployed.

Inputs

  • project - A Project object.

Returns

  • Environment - An Environment object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get selected environment
doc_project = Project.get_project('document_tagging')
selected_environment = Environment.get_selected_environment()

#

# promote


This function promotes the specified environment. Environments are chained together, for example UAT --> Production. If you have new app/model versions in UAT that are ready to be updated in Production, you can promote so that the Production environment matches the contents of UAT.

No Inputs

Returns

  • None
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Promote to UAT
integration_environment.promote()

#

# delete

This function deletes the given environment. Delete will fail if called on an environment which has a challenger environment or if another environment promotes to it.

No Inputs

Returns

  • response - A dictionary indicating a successful response, along with other useful information if the response is an error.

    • result - success or error

    The following keys are only present in an error case:

    • message - The reason for the error result.
    • challengers: [Environment, ...] - the list of challenger environments promoting to the environment you are trying to delete, can be empty.
    • depending: Environment or None - the environment promoting to the environment you are trying to delete, if any.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get Environment
doc_project = Project.get_project('document_tagging')
environment = Environment.get_environment(doc_project, 'EnvironmentToDelete')

response = environment.delete()
>>> print(response)
{'result': 'success'}
# Or
{'result': 'error', 'message': 'Cannot delete environment due to existing environments or challenger environments with a dependency on this environment.', 'challengers': [], 'depending': 'id [9], name [Integration]'}

# Challenger Environments

A challenger environment is a copy of an existing environment; at time of creation, it has an identical state (e.g environment config, components, replicas). Typical workflows that might require challengers include:

  • A bug is found in web_app in the Production environment. A challenger is created from Production to replicate the issue. The code is deployed/tested in the challenger until the issue is resolved. The challenger is promoted to apply the fix to Production.
  • Two developers are working on apps + models in Integration; they can use separate challenger environments so one person's changes does not affect the other.

#

# list_challengers


This function returns a list of challenger environments for the environment.

Inputs

  • environment - An Environment object.

Returns

  • [Environment, ...] - A list of Environment objects, representing challengers.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get list of challengers
challenger_environments = integration_environment.list_challengers()

#

# create_challenger


This function creates a new challenger environment in Kortical.

Inputs

  • environment - An Environment object.
  • challenger_name - Name of the new challenger environment you want to create.
  • component_config (= None) - A specification for the environment, which describes what components (+ versions) should be deployed.

Returns

  • Environment - An Environment object, representing the challenger.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get integration environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Create challenger (by default calls it <environment_name>_<your name>, e.g Integration-Owen)
owen_integration_environment = integration_environment.create_challenger()

#

# is_challenger


This function tells you whether the environment is a disposable challenger (used for development) or a main environment (e.g Integration).

Returns

  • is_challenger - True or False.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment('Integration')

# Find out if it is a challenger
>>> print(integration_environment.is_challenger())
False

# Component Instances

TIP

See kortical.api.model_instance and kortical.api.app_instance for more information.

#

# list_component_instances


This function lists all component instances deployed to the specified environment.

Inputs

  • component_type (= None) - filter by component type (e.g app, model).

Returns

  • [ComponentInstance, ...] - a list of ComponentInstance objects.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get apps in the Integration environment
app_instances = integration_environment.list_component_instances(component_type='app')

#

# create_component_instance


This function creates a new component instance in the specified environment.

Inputs

  • component_name_or_version_id - Version ID used to specify the component + version you want to add. If a component name is passed in, uses the default version ID (you can view this in kortical app list and kortical model list).

Returns

  • ComponentInstance - a ComponentInstance object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Deploy version_id 58 to the Integration environment
new_model_instance = integration_environment.create_component_instance(component_name_or_version_id=58)

#

# get_component_instance


This function gets a component instance in the specified environment.

Inputs

  • component_name_or_instance_id - Version ID used to specify the component + version you want to add. If a component name is passed in, uses the default version ID (you can view this in kortical app list and kortical model list).
  • component_type (= None) - specify the component type if apps/models share the same name.

Returns

  • ComponentInstance - a ComponentInstance object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get instance
model_instance = integration_environment.get_component_instance(component_name_or_version_id='nlp_classifier')

#

# wait_for_all_components_ready


This function waits for all components to enter a Running state for the specified environment; this is ideal for cases where you are deploying an app/model, and need everything to be fully operational before executing further steps (e.g running tests).

No Inputs

Returns

  • None
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Promote to UAT
integration_environment.wait_for_all_components_ready()

# Component Config

Component config reflects the current state of an environment.

During development, it is highly likely you have altered your challenger environment by deploying new component versions to it; these changes are reflected in the component config. When you commit a change, you will have the option to save the component config as part of the commit. This provides a record in git of not only the code for the app but also of all of the other apps and models in the environment to replicate the full system functionality at deployment time. It also allows us to identify potential merge conflicts and to select the appropriate version, when merging to master.

#

# get_component_config


This function returns the component config for the environment.

No Inputs

Returns

  • text - Text, formatted in yml.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get environment config
config = integration_environment.get_environment_config()

>>> print(config)
components:
- component:
    component_version_id: 79
    name: document_tagging
    type: model
- component:
    component_version_id: 31
    name: nlp_document_classifier
    type: app

In this example, we have two components deployed to the Integration environment: one app and one model. To learn more about deploying apps/models, follow the ML Ops - Deployment guide.

#

# set_component_config


This function sets the environment config for the environment.

Inputs

  • component_config - Text, formatted in yml.

Returns

  • None
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Set component config (most likely from a file in your app folder)
with open('config/component_config.yml', 'r') as f:
    component_config = f.read()
config = integration_environment.set_component_config(component_config)

# Cronjobs

TIP

See kortical.api.cronjobs for more information.

#

# list_cronjobs


This function lists all cronjobs deployed to the specified environment.

No Inputs

Returns

  • [Cronjob, ...] - a list of Cronjob objects.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get apps in the Integration environment
cronjobs = integration_environment.list_cronjobs()

#

# get_cronjob


This function gets a cronjob in the specified environment.

Inputs

  • cronjob_name_or_id - Name or ID used to refer to the cronjob.

Returns

  • Cronjob - a Cronjob object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get instance
cronjob = integration_environment.get_cronjob(cronjob_name_or_id=3)

#

# create_cronjob


This function creates a new cronjob in the specified environment.

Inputs

  • cronjob_name - The name you want to assign to this cronjob.
  • time_parameters - a dictionary that specifies the cronjob's schedule; see valid keys below.
  • url - The URL you want the cronjob to call.
  • url_headers (= None) - A dictionary of headers the cronjob should use when calling the URL.

Acceptable time parameter keys are:

  • cron_time_string - a raw string representing the cronjob schedule.
  • A combination of the keys minute, hour, day_of_month, month, day_of_week.

Returns

  • Cronjob - a Cronjob object.
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Create
new_cronjob = integration_environment.create_cronjob(
    cronjob_name='clean_job',
    time_parameters='0 23 * * 7', # Runs every Sunday at 11pm
    url='www.test.com'
)

# Environment Config

Environment Config allows you to configure various settings on an environment basis, that do not get promoted. This is ideal for cases such as where to store artefacts, what channels should error reporting be sent to.

#

# get_environment_config


This function returns the environment config for the environment.

Inputs

  • format (= None) - Load the config, typically in json or yaml format. Ignore this argument to get the raw text.

Returns

  • text - Environment config in text format (or dictionary if a format is specified).
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get environment config
config = integration_environment.get_environment_config(format='yaml')

>>> print(config)
{}

In this example, we have not set any config for this environment.

#

# set_environment_config


This function sets the environment config for the environment.

Inputs

  • environment_config - Text. This allows you to set config in any format you like (e.g yml, json).

Returns

  • text - Text (i.e the config you just set for the environment).
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Set environment config from a yml file
with open('config/integration_config.yml', 'r') as f:
    environment_config = f.read()
config = integration_environment.set_environment_config('Here is some config')

>>> print(config)
''

# Kortical Config (Environment Level)

Kortical Config allows you to configure various settings (i.e worker group, replicas) at a project/environment/component level, including:

  • Replicas - this is the number of pods each component will have when deployed to this environment. Applies to both apps and models.
  • Worker Group - this is the worker group on which this environment will be hosted.
  • Low-latency mode - for models only. This will reduce prediction request times, but at the expense of less logging.

For example, if we assign 3 replicas to an environment, then all the components inside that environment will run on 3 replicas.

#

# get_kortical_config


This function returns the Kortical config for the environment.

No Inputs

Returns

  • (config, inherited_config) - Two dictionaries. The first dictionary contains any environment level settings you have made, the second one shows you what has been inherited from a higher level (i.e company/project level Kortical Config).
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')

# Get Kortical Config
kortical_config, inherited_config = integration_environment.get_kortical_config()

>>> print(kortical_config, inherited_config)
{} {'replicas': 2, 'worker_group': 'default', 'low_latency_mode': False}

In this example, we have not set any config for this environment (i.e everything inherits).

#

# set_kortical_config


This function sets the Kortical config for the environment.

Inputs

  • kortical_config - A dictionary of settings you want to configure for the environment. Valid keys are replicas, worker_group and low_latency_mode.

Returns

  • (config, inherited_config) - Two dictionaries. The first dictionary contains any environment level settings you have made, the second one shows you what has been inherited from a higher setting (i.e company/project level Kortical Config).
from kortical.api.project import Project
from kortical.api.environment import Environment

# Get environment
doc_project = Project.get_project('document_tagging')
integration_environment = Environment.get_environment(doc_project, 'Integration')
kortical_config, inherited_config = integration_environment.get_kortical_config()


# Set Kortical Config
kortical_config, inherited_config = integration_environment.set_kortical_config({'replicas': 3})

>>> print(kortical_config, inherited_config)
{'replicas': 3} {'replicas': 2, 'worker_group': 'default', 'low_latency_mode': False}

To undo, simply set the key to a None value:

kortical_config, inherited_config = integration_environment.set_kortical_config({'replicas': None})

>>> print(kortical_config, inherited_config)
{} {'replicas': 2, 'worker_group': 'default', 'low_latency_mode': False}

WARNING

Note that the inherited config dictionary does not include what you have set at the environment level! If you want a simplified view, you could run the following:

full_environment_kortical_config = inherited_config.update(kortical_config)