Add services to an app¶
The topic describes how to configure and use services in a Snowflake Native App with Snowpark Container Services. For information on using a job service in an app, see Add job services to an app.
Privileges required to create a service in the consumer account¶
In order for an app to create a service in the consumer account, the consumer must first grant the following privileges:
CREATE COMPUTE POOL
This privileges is required for all services. One or more compute pools are required to create a service in the consumer account.
BIND SERVICE ENDPOINT
This privilege is required for any service that exposes endpoints. If a service needs to make connections to URLs outside of Snowflake, this privilege is required for the app to create the required external access integration.
Considerations when creating services within an app¶
The following considerations apply when creating a service within a Snowflake Native App with Snowpark Container Services:
References to warehouses. See Best practices when using services within an app for information on using in a Snowflake Native App with Snowpark Container Services.
Quoted names for a service within an app are not supported.
Services cannot not be created in a versioned schema.
Services may not be created outside of the application using a container image created within the app.
Best practices when using services within an app¶
The following are best practices and considerations when using services within a Snowflake Native App with Snowpark Container Services:
Create a Streamlit app or stored procedures that allows consumers to interact with a service.
In some situations, a consumer may need to create, start, stop, restart, and manage the services provided by the app.
Use a single stored procedure to verify that the consumer has granted all the required privileges.
A service may require that the consumer grants multiple privileges to the app. For example, a service may require the CREATE COMPUTE POOL, CREATE WAREHOUSE, BIND SERVICE ENDPOINT and other privileges. An app may also require reference to existing objects in the consumer account.
In this context, Snowflake recommends using a single stored procedure to verify that all prerequisites have been met. After all prerequisites are verified, this stored procedure would then create the service.
If a service requires a warehouse to execute queries, the app should create the warehouse directly in the consumer account. This requires that the consumer grant the CREATE WAREHOUSE global privilege to the app. See Request global privileges from consumers for more information.
When creating a service using a specification template, store the arguments provided by the consumer inside your application instance. This allows them to be passed as arguments when upgrading a service.
Create a service in an app¶
To create a service in an app, use the CREATE SERVICE command in the setup script. Providers should always consider calling this command from within a stored procedure instead of running it directly.
Within an app with containers, services can be created using specification file or by using a specification template.
Create a service from a specification file¶
To create a service a service from a specification file, use the CREATE SERVICE command and include a reference to the service specification file:
CREATE SERVICE IF NOT EXISTS app_service
IN COMPUTE POOL app_compute_pool
FROM SPECIFICATION_FILE = '/containers/service1_spec.yaml';
This example shows how to create the service using the FROM SPECIFICATION_FILE clause which uses a relative path to the file. The FROM SPECIFICATION_FILE clause points to the service specification file that is specific to a version of the app. This path is relative to the app root directory.
However, you can also use a specification file on a stage. See CREATE SERVICE for more information.
Create a service with a specification template¶
To create a service using a specification template, use the FROM SPECIFICATION_TEMPLATE_FILE clause of the CREATE SERVICE command as shown in the following example:
CREATE SERVICE IF NOT EXISTS app_service
IN COMPUTE POOL app_compute_pool
FROM SPECIFICATION_TEMPLATE_FILE = '/containers/service1_spec.yaml';
See specification template for more information.
Add the CREATE SERVICE command to a stored procedure¶
A Snowflake Native Apps with Snowpark Container Services supports multiple ways of creating a service within a stored procedure.
A provider can use any combination of these methods to create services in the consumer account.
Create a service by using the grant_callback
property¶
grant_callback
is a property in the manifest file that allows providers to
specify a callback function. The callback function is a stored procedure that can
create compute pools, services and perform other setup tasks required by the application.
Note
Using the grant_callback
property to specify the callback function is only
supported by Snowflake Native Apps with Snowpark Container Services.
The advantage of specifying a callback function with grant_callback
is that
the stored procedure is not called until the consumer grants the required privileges
to the app. This ensures that the app has the privileges required to create services
and other objects in the consumer account.
To use grant_callback
add it to the configuration
section of the
manifest.yml
file:
configuration:
log_level: INFO
trace_level: ALWAYS
grant_callback: core.grant_callback
Then, in the setup script, define a call back function as shown in the following example:
CREATE SCHEMA core;
CREATE APPLICATION ROLE app_public;
CREATE OR REPLACE PROCEDURE core.grant_callback(privileges array)
RETURNS STRING
AS $$
BEGIN
IF (ARRAY_CONTAINS('CREATE COMPUTE POOL'::VARIANT, privileges)) THEN
CREATE COMPUTE POOL IF NOT EXISTS app_compute_pool
MIN_NODES = 1
MAX_NODES = 3
INSTANCE_FAMILY = GPU_NV_M;
END IF;
IF (ARRAY_CONTAINS('BIND SERVICE ENDPOINT'::VARIANT, privileges)) THEN
CREATE SERVICE IF NOT EXISTS core.app_service
IN COMPUTE POOL my_compute_pool
FROM SPECIFICATION_FILE = '/containers/service1_spec.yaml';
END IF;
RETURN 'DONE';
END;
$$;
GRANT USAGE ON PROCEDURE core.grant_callback(array) TO APPLICATION ROLE app_public;
This example creates a grant_callback
procedure that does the following:
Tests whether the consumer has granted the CREATE COMPUTE POOL privilege to the app. If the consumer has granted this privilege, the
grant_callback
procedure creates the compute pool.Tests whether the consumer has granted the BIND SERVICE ENDPOINT privilege to the app. If the consumer has granted this privilege, the
grant_callback
procedure creates the service.
This example shows a pattern for creating services and a compute pool in an app with containers. In this example, the app first tests whether the consumer has granted the required privileges and then creates the service or compute pool.
Create a service based on a reference definition¶
An app can create services using a reference definition by using the
register_callback
property in the manifest.yml
file. This property specifies a
stored procedure used to bind an object in the consumer account to the reference definition.
For more information on using references in an app, see Request references and object-level privileges from consumers
An app can use the register_callback
of the reference to create a service after all the
required references are bound. If a service is created before all the references to an external access
integrations or secret is allowed, the service creation fails.
Create a service using a stored procedure¶
An app can create a service directly within a stored procedure. As with other stored procedures, providers can define them in the application setup script. This stored procedure would use the CREATE SERVICE command to create the service, then grant the necessary privileges on the stored procedure to an application role.
The consumer would call this stored procedure to create the service in their account after they have given the app the required privileges and references.
Determine the status of a service¶
To determine the status of a service, an app can call the SYSTEM$GET_SERVICE_STATUS — Deprecated system function from the setup script.
This system function returns a JSON object for each container in each service instance.