# 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 aProject
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 objectenvironment_name
- The name of the environment you want to createpromotes_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
orerror
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
orNone
- 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
orFalse
.
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.gapp
,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 inkortical app list
andkortical 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 inkortical app list
andkortical 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 injson
oryaml
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 arereplicas
,worker_group
andlow_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)