diff --git a/spcs-three-tier/README.md b/spcs-three-tier/README.md index 0bc00d2..7e5ea72 100644 --- a/spcs-three-tier/README.md +++ b/spcs-three-tier/README.md @@ -123,6 +123,24 @@ See the [documentation](https://other-docs.snowflake.com/en/native-apps/provider 8. Click "Publish". + +#### Upgrade +In the provider account + +alter application package spcs_app_pkg add version v1 using @spcs_app_pkg.napp.app_stage; +alter application package spcs_app_pkg set default release directive version=v1 patch=0; + +add patch +alter application package spcs_app_pkg add patch for version v1 using @spcs_app_pkg.napp.app_stage; +alter application package spcs_app_pkg set default release directive version=v1 patch=1; + +add version v2 +alter application package spcs_app_pkg add version v2 using @spcs_app_pkg.napp.app_stage; +alter application package spcs_app_pkg set default release directive version=v2 patch=1; + +Check the status: +If you have multiple + ### Debugging There are some Stored Procedures to allow the Consumer to see the status and logs for the containers and services. These procedures are granted to the `app_admin` diff --git a/spcs-three-tier/app/manifest.yml b/spcs-three-tier/app/manifest.yml index 4f0f146..13b2be3 100644 --- a/spcs-three-tier/app/manifest.yml +++ b/spcs-three-tier/app/manifest.yml @@ -1,10 +1,10 @@ manifest_version: 1 version: - name: V1 + name: versioned_schema label: "First Version" configuration: - grant_callback: v1.create_services + grant_callback: versioned_schema.create_services artifacts: setup_script: setup.sql @@ -20,7 +20,7 @@ artifacts: - /spcs_app/napp/img_repo/eap_router lifecycle_callbacks: - version_initializer: v1.init + version_initializer: versioned_schema.init privileges: - BIND SERVICE ENDPOINT: @@ -39,13 +39,13 @@ references: - SELECT object_type: VIEW multi_valued: false - register_callback: v1.register_single_callback + register_callback: versioned_schema.register_single_callback - WIKIPEDIA_EAI: label: "Wikipedia Access Integration" description: "EAI for Egress from NA+SPCS" privileges: [USAGE] object_type: EXTERNAL_ACCESS_INTEGRATION - register_callback: v1.register_single_callback - configuration_callback: v1.get_configuration + register_callback: versioned_schema.register_single_callback + configuration_callback: versioned_schema.get_configuration required_at_setup: true \ No newline at end of file diff --git a/spcs-three-tier/app/setup.sql b/spcs-three-tier/app/setup.sql index 433b80e..9baf05b 100644 --- a/spcs-three-tier/app/setup.sql +++ b/spcs-three-tier/app/setup.sql @@ -3,11 +3,11 @@ CREATE APPLICATION ROLE IF NOT EXISTS app_user; CREATE SCHEMA IF NOT EXISTS app_public; GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_admin; GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_user; -CREATE OR ALTER VERSIONED SCHEMA v1; -GRANT USAGE ON SCHEMA v1 TO APPLICATION ROLE app_admin; +CREATE OR ALTER VERSIONED SCHEMA versioned_schema; +GRANT USAGE ON SCHEMA versioned_schema TO APPLICATION ROLE app_admin; -CREATE OR REPLACE PROCEDURE v1.register_single_callback(ref_name STRING, operation STRING, ref_or_alias STRING) +CREATE OR REPLACE PROCEDURE versioned_schema.register_single_callback(ref_name STRING, operation STRING, ref_or_alias STRING) RETURNS STRING LANGUAGE SQL AS $$ @@ -25,9 +25,9 @@ CREATE OR REPLACE PROCEDURE v1.register_single_callback(ref_name STRING, operati RETURN 'Operation ' || operation || ' succeeds.'; END; $$; -GRANT USAGE ON PROCEDURE v1.register_single_callback(STRING, STRING, STRING) TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.register_single_callback(STRING, STRING, STRING) TO APPLICATION ROLE app_admin; -CREATE OR REPLACE PROCEDURE v1.get_configuration(ref_name STRING) +CREATE OR REPLACE PROCEDURE versioned_schema.get_configuration(ref_name STRING) RETURNS STRING LANGUAGE SQL AS @@ -47,26 +47,33 @@ BEGIN END; $$; -GRANT USAGE ON PROCEDURE v1.get_configuration(STRING) TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.get_configuration(STRING) TO APPLICATION ROLE app_admin; -- The version initializer callback is executed after a successful installation, upgrade, or downgrade of an application object. --- In case the application fails to upgrade, the version initializer of the previous (successful) version will be executed so you +-- In case the application fails to upgrade, the version initializer of the previous (successful) version will be executed so you -- can clean up application state that may have been modified during the failed upgrade. -CREATE OR REPLACE PROCEDURE v1.init() -RETURNS STRING + +-- this is the first the version(version v1 patch 0) of the app package. We consider the case that when the +-- app is upgraded to next version and try to alter the services and it fails. In that case +-- it will fail back to version v1 patch 0 and call this procedure versioned_schema.init() to +-- restore the services and app can fully function. +CREATE OR REPLACE PROCEDURE versioned_schema.init() +RETURNS STRING LANGUAGE SQL -EXECUTE AS OWNER +EXECUTE AS OWNER AS $$ -BEGIN - ALTER SERVICE IF EXISTS app_public.frontend FROM SPECIFICATION_FILE='frontend.yaml'; - ALTER SERVICE IF EXISTS app_public.backend FROM SPECIFICATION_FILE='backend.yaml'; +BEGIN + --create services if not exist + call versioned_schema.create_services(); + --wait for 300 seconds, but it will stop if two services have READY status, + -- or any of the services has the FAILED status. + select system$wait_for_services(300, 'app_public.backend', 'app_public.frontend'); + RETURN 'init complete'; END $$; -GRANT USAGE ON PROCEDURE v1.init() TO APPLICATION ROLE app_admin; - -CREATE OR REPLACE PROCEDURE v1.start_backend(pool_name VARCHAR) +CREATE OR REPLACE PROCEDURE versioned_schema.start_backend(pool_name VARCHAR) RETURNS string LANGUAGE sql AS $$ @@ -78,9 +85,9 @@ BEGIN GRANT USAGE ON SERVICE app_public.backend TO APPLICATION ROLE app_user; END $$; -GRANT USAGE ON PROCEDURE v1.start_backend(VARCHAR) TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.start_backend(VARCHAR) TO APPLICATION ROLE app_admin; -CREATE OR REPLACE PROCEDURE v1.start_frontend(pool_name VARCHAR) +CREATE OR REPLACE PROCEDURE versioned_schema.start_frontend(pool_name VARCHAR) RETURNS string LANGUAGE sql AS $$ @@ -95,10 +102,10 @@ BEGIN RETURN 'Service started. Check status, and when ready, get URL'; END $$; -GRANT USAGE ON PROCEDURE v1.start_frontend(VARCHAR) TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.start_frontend(VARCHAR) TO APPLICATION ROLE app_admin; -CREATE OR REPLACE PROCEDURE v1.create_services(privileges array) +CREATE OR REPLACE PROCEDURE versioned_schema.create_services() RETURNS STRING LANGUAGE SQL AS @@ -114,11 +121,15 @@ CREATE OR REPLACE PROCEDURE v1.create_services(privileges array) MAX_NODES = 1 INSTANCE_FAMILY = CPU_X64_XS; - CALL v1.start_backend('backend_compute_pool'); - CALL v1.start_frontend('frontend_compute_pool'); + CALL versioned_schema.start_backend('backend_compute_pool'); + CALL versioned_schema.start_frontend('frontend_compute_pool'); + + # needed for installation from listing/cross account + GRANT SERVICE ROLE app_public.frontend!ALL_ENDPOINTS_USAGE TO APPLICATION ROLE app_admin; + + GRANT USAGE ON PROCEDURE versioned_schema.create_services( ) TO APPLICATION ROLE app_admin; END; $$; -GRANT USAGE ON PROCEDURE v1.create_services(array) TO APPLICATION ROLE app_admin; CREATE OR REPLACE PROCEDURE app_public.stop_app() @@ -133,7 +144,7 @@ END $$; GRANT USAGE ON PROCEDURE app_public.stop_app() TO APPLICATION ROLE app_admin; -CREATE OR REPLACE PROCEDURE v1.app_url() +CREATE OR REPLACE PROCEDURE versioned_schema.app_url() RETURNS string LANGUAGE sql AS @@ -146,8 +157,8 @@ BEGIN RETURN ingress_url; END $$; -GRANT USAGE ON PROCEDURE v1.app_url() TO APPLICATION ROLE app_admin; -GRANT USAGE ON PROCEDURE v1.app_url() TO APPLICATION ROLE app_user; +GRANT USAGE ON PROCEDURE versioned_schema.app_url() TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.app_url() TO APPLICATION ROLE app_user; -- Support functions EXECUTE IMMEDIATE FROM 'support.sql'; \ No newline at end of file diff --git a/spcs-three-tier/app_for_upgrade/manifest.yml b/spcs-three-tier/app_for_upgrade/manifest.yml new file mode 100644 index 0000000..7ef61b2 --- /dev/null +++ b/spcs-three-tier/app_for_upgrade/manifest.yml @@ -0,0 +1,48 @@ +manifest_version: 2 +version: + name: versioned_schema + label: "Second Version" + +artifacts: + setup_script: setup.sql + + default_web_endpoint: + service: app_public.frontend + endpoint: app + + container_services: + images: + - /spcs_app/napp/img_repo/eap_frontend + - /spcs_app/napp/img_repo/eap_backend + - /spcs_app/napp/img_repo/eap_router + +lifecycle_callbacks: + version_initializer: versioned_schema.init + +privileges: + - BIND SERVICE ENDPOINT: + description: "Ability to create ingress URLs." + required_at_setup: true + - CREATE COMPUTE POOL: + required_at_setup: true + description: "Enable appplication to create its own compute pool(s)" + + +references: + - ORDERS_TABLE: + label: "Orders table" + description: "Orders table in TPC-H samples" + privileges: + - SELECT + object_type: VIEW + multi_valued: false + register_callback: versioned_schema.register_single_callback + + - WIKIPEDIA_EAI: + label: "Wikipedia Access Integration" + description: "EAI for Egress from NA+SPCS" + privileges: [USAGE] + object_type: EXTERNAL_ACCESS_INTEGRATION + register_callback: versioned_schema.register_single_callback + configuration_callback: versioned_schema.get_configuration + required_at_setup: true \ No newline at end of file diff --git a/spcs-three-tier/app_for_upgrade/setup.sql b/spcs-three-tier/app_for_upgrade/setup.sql new file mode 100644 index 0000000..401ac76 --- /dev/null +++ b/spcs-three-tier/app_for_upgrade/setup.sql @@ -0,0 +1,151 @@ +CREATE APPLICATION ROLE IF NOT EXISTS app_admin; +CREATE APPLICATION ROLE IF NOT EXISTS app_user; +CREATE SCHEMA IF NOT EXISTS app_public; +GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_admin; +GRANT USAGE ON SCHEMA app_public TO APPLICATION ROLE app_user; +CREATE OR ALTER VERSIONED SCHEMA versioned_schema; +GRANT USAGE ON SCHEMA versioned_schema TO APPLICATION ROLE app_admin; + + +CREATE OR REPLACE PROCEDURE versioned_schema.register_single_callback(ref_name STRING, operation STRING, ref_or_alias STRING) + RETURNS STRING + LANGUAGE SQL + AS $$ + BEGIN + CASE (operation) + WHEN 'ADD' THEN + SELECT system$set_reference(:ref_name, :ref_or_alias); + WHEN 'REMOVE' THEN + SELECT system$remove_reference(:ref_name); + WHEN 'CLEAR' THEN + SELECT system$remove_reference(:ref_name); + ELSE + RETURN 'Unknown operation: ' || operation; + END CASE; + RETURN 'Operation ' || operation || ' succeeds.'; + END; + $$; +GRANT USAGE ON PROCEDURE versioned_schema.register_single_callback(STRING, STRING, STRING) TO APPLICATION ROLE app_admin; + +CREATE OR REPLACE PROCEDURE versioned_schema.get_configuration(ref_name STRING) +RETURNS STRING +LANGUAGE SQL +AS +$$ +BEGIN + CASE (UPPER(ref_name)) + WHEN 'WIKIPEDIA_EAI' THEN + RETURN OBJECT_CONSTRUCT( + 'type', 'CONFIGURATION', + 'payload', OBJECT_CONSTRUCT( + 'host_ports', ARRAY_CONSTRUCT('upload.wikimedia.org'), + 'allowed_secrets', 'NONE') + )::STRING; + ELSE + RETURN ''; + END CASE; +END; +$$; + +GRANT USAGE ON PROCEDURE versioned_schema.get_configuration(STRING) TO APPLICATION ROLE app_admin; + +-- The version initializer callback is executed after a successful run of the setup script. +-- In case the versioned_schema.init() failed, the version initializer of the previous version will be executed +CREATE OR REPLACE PROCEDURE versioned_schema.init() +RETURNS STRING +LANGUAGE SQL +EXECUTE AS OWNER +AS +$$ +BEGIN + ALTER SERVICE IF EXISTS app_public.frontend FROM SPECIFICATION_FILE='frontend.yaml'; + ALTER SERVICE IF EXISTS app_public.backend FROM SPECIFICATION_FILE='backend.yaml'; + select system$wait_for_services(300, 'app_public.backend', 'app_public.frontend'); + RETURN 'init complete'; +END $$; + +CREATE OR REPLACE PROCEDURE versioned_schema.start_backend(pool_name VARCHAR) + RETURNS string + LANGUAGE sql + AS $$ +BEGIN + CREATE SERVICE IF NOT EXISTS app_public.backend + IN COMPUTE POOL Identifier(:pool_name) + FROM SPECIFICATION_FILE='backend.yaml' + QUERY_WAREHOUSE = 'WH_NAC'; + GRANT USAGE ON SERVICE app_public.backend TO APPLICATION ROLE app_user; +END +$$; +GRANT USAGE ON PROCEDURE versioned_schema.start_backend(VARCHAR) TO APPLICATION ROLE app_admin; + +CREATE OR REPLACE PROCEDURE versioned_schema.start_frontend(pool_name VARCHAR) + RETURNS string + LANGUAGE sql + AS $$ +BEGIN + CREATE SERVICE IF NOT EXISTS app_public.frontend + IN COMPUTE POOL Identifier(:pool_name) + FROM SPECIFICATION_FILE='frontend.yaml' + EXTERNAL_ACCESS_INTEGRATIONS=( reference('WIKIPEDIA_EAI') ); + + GRANT USAGE ON SERVICE app_public.frontend TO APPLICATION ROLE app_user; + + RETURN 'Service started. Check status, and when ready, get URL'; +END +$$; +GRANT USAGE ON PROCEDURE versioned_schema.start_frontend(VARCHAR) TO APPLICATION ROLE app_admin; + + +CREATE OR REPLACE PROCEDURE versioned_schema.create_services(privileges array) + RETURNS STRING + LANGUAGE SQL + AS + $$ + BEGIN + CREATE COMPUTE POOL IF NOT EXISTS frontend_compute_pool + MIN_NODES = 1 + MAX_NODES = 1 + INSTANCE_FAMILY = CPU_X64_XS; + + CREATE COMPUTE POOL IF NOT EXISTS backend_compute_pool + MIN_NODES = 1 + MAX_NODES = 1 + INSTANCE_FAMILY = CPU_X64_XS; + + CALL versioned_schema.start_backend('backend_compute_pool'); + CALL versioned_schema.start_frontend('frontend_compute_pool'); + END; +$$; +GRANT USAGE ON PROCEDURE versioned_schema.create_services(array) TO APPLICATION ROLE app_admin; + + +CREATE OR REPLACE PROCEDURE app_public.stop_app() + RETURNS string + LANGUAGE sql + AS +$$ +BEGIN + DROP SERVICE IF EXISTS app_public.backend; + DROP SERVICE IF EXISTS app_public.frontend; +END +$$; +GRANT USAGE ON PROCEDURE app_public.stop_app() TO APPLICATION ROLE app_admin; + +CREATE OR REPLACE PROCEDURE versioned_schema.app_url() + RETURNS string + LANGUAGE sql + AS +$$ +DECLARE + ingress_url VARCHAR; +BEGIN + SHOW ENDPOINTS IN SERVICE app_public.frontend; + SELECT "ingress_url" INTO :ingress_url FROM TABLE (RESULT_SCAN (LAST_QUERY_ID())) LIMIT 1; + RETURN ingress_url; +END +$$; +GRANT USAGE ON PROCEDURE versioned_schema.app_url() TO APPLICATION ROLE app_admin; +GRANT USAGE ON PROCEDURE versioned_schema.app_url() TO APPLICATION ROLE app_user; + +-- Support functions +EXECUTE IMMEDIATE FROM 'support.sql'; \ No newline at end of file diff --git a/spcs-three-tier/prepare/consumer_setup.sql b/spcs-three-tier/prepare/consumer_setup.sql index 2acbe91..22573c1 100644 --- a/spcs-three-tier/prepare/consumer_setup.sql +++ b/spcs-three-tier/prepare/consumer_setup.sql @@ -1,4 +1,10 @@ USE ROLE ACCOUNTADMIN; +CREATE ROLE IF NOT EXISTS nac; +GRANT CREATE APPLICATION ON ACCOUNT TO ROLE nac; +GRANT CREATE INTEGRATION ON ACCOUNT TO ROLE nac; +-- needed for app installation from a listing +GRANT IMPORT SHARE ON ACCOUNT TO nac; + -- (Mock) Consumer role GRANT ROLE nac TO ROLE ACCOUNTADMIN; CREATE WAREHOUSE IF NOT EXISTS wh_nac WITH WAREHOUSE_SIZE='XSMALL'; diff --git a/spcs-three-tier/prepare/provider_setup.sql b/spcs-three-tier/prepare/provider_setup.sql index fec5a88..7fdb5ab 100644 --- a/spcs-three-tier/prepare/provider_setup.sql +++ b/spcs-three-tier/prepare/provider_setup.sql @@ -16,12 +16,6 @@ USE ROLE naspcs_role; CREATE DATABASE IF NOT EXISTS spcs_app; CREATE SCHEMA IF NOT EXISTS spcs_app.napp; --- For Provider-side Testing -USE ROLE ACCOUNTADMIN; -CREATE ROLE IF NOT EXISTS nac; -GRANT CREATE APPLICATION ON ACCOUNT TO ROLE nac; -GRANT CREATE INTEGRATION ON ACCOUNT TO ROLE nac; - -- Create the Image Repository USE ROLE naspcs_role; CREATE IMAGE REPOSITORY IF NOT EXISTS spcs_app.napp.img_repo; diff --git a/spcs-three-tier/prepare/spcs_setup.sql b/spcs-three-tier/prepare/spcs_setup.sql deleted file mode 100644 index cd712e7..0000000 --- a/spcs-three-tier/prepare/spcs_setup.sql +++ /dev/null @@ -1,5 +0,0 @@ -USE ROLE ACCOUNTADMIN; -CREATE SECURITY INTEGRATION IF NOT EXISTS snowservices_ingress_oauth - TYPE=oauth - OAUTH_CLIENT=snowservices_ingress - ENABLED=true; \ No newline at end of file diff --git a/spcs-three-tier/register_callback.sql b/spcs-three-tier/register_callback.sql index 09a94c2..dd180a5 100755 --- a/spcs-three-tier/register_callback.sql +++ b/spcs-three-tier/register_callback.sql @@ -1,4 +1,4 @@ USE ROLE nac; USE WAREHOUSE wh_nac; GRANT USAGE ON WAREHOUSE wh_nac TO APPLICATION spcs_app_instance; -CALL spcs_app_instance.v1.register_single_callback('ORDERS_TABLE' , 'ADD', SYSTEM$REFERENCE('VIEW', 'NAC_TEST.DATA.ORDERS', 'PERSISTENT', 'SELECT')); +CALL spcs_app_instance.versioned_schema.register_single_callback('ORDERS_TABLE' , 'ADD', SYSTEM$REFERENCE('VIEW', 'NAC_TEST.DATA.ORDERS', 'PERSISTENT', 'SELECT')); diff --git a/spcs-three-tier/setup.sh b/spcs-three-tier/setup.sh index fb80d0a..3d6d84f 100755 --- a/spcs-three-tier/setup.sh +++ b/spcs-three-tier/setup.sh @@ -1,5 +1,4 @@ set -e -snow sql -f "prepare/spcs_setup.sql" snow sql -f "prepare/provider_setup.sql" snow sql -f "prepare/consumer_setup.sql"