From e7c1ebb43eb90865c1e40cdfd887ff65afb18227 Mon Sep 17 00:00:00 2001 From: Chris Nivera Date: Fri, 19 Jul 2024 16:27:19 -0700 Subject: [PATCH 1/5] popup if env vars not populated --- admin_apps/app.py | 40 ++++++++++++++++--- .../snowflake_utils/env_vars.py | 25 +++++++++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/admin_apps/app.py b/admin_apps/app.py index fc0dadd6..03cb6749 100644 --- a/admin_apps/app.py +++ b/admin_apps/app.py @@ -1,13 +1,41 @@ -import os - import streamlit as st from admin_apps.shared_utils import GeneratorAppScreen +from semantic_model_generator.snowflake_utils.env_vars import ( + assert_required_env_vars, + SNOWFLAKE_ACCOUNT_LOCATOR, + SNOWFLAKE_HOST, + SNOWFLAKE_USER, +) # set_page_config must be run as the first Streamlit command on the page, before any other streamlit imports. st.set_page_config(layout="wide", page_icon="💬", page_title="Semantic Model Generator") +@st.experimental_dialog(title="Setup") +def env_setup_popup(missing_env_vars: list[str]) -> None: + """ + Renders a dialog box to prompt the user to set the required environment variables. + Args: + missing_env_vars: A list of missing environment variables. + """ + formatted_missing_env_vars = "\n".join(f"- **{s}**" for s in missing_env_vars) + st.markdown( + f"""Oops! It looks like the following required environment variables are missing: \n{formatted_missing_env_vars}\n\n +Please follow the [setup instructions](https://github.com/Snowflake-Labs/semantic-model-generator?tab=readme-ov-file#setup) to properly configure your environment. Restart this app after you've set the required environment variables.""" + ) + st.stop() + + +def verify_environment_setup() -> None: + """ + Ensures that the correct environment variables are set before proceeding. + """ + missing_env_vars = assert_required_env_vars() + if missing_env_vars: + env_setup_popup(missing_env_vars) + + if __name__ == "__main__": from admin_apps.journeys import builder, iteration @@ -43,10 +71,12 @@ def onboarding_dialog() -> None: ): iteration.show() + verify_environment_setup() + # Populating common state between builder and iteration apps. - st.session_state["account_name"] = os.environ.get("SNOWFLAKE_ACCOUNT_LOCATOR") - st.session_state["host_name"] = os.environ.get("SNOWFLAKE_HOST") - st.session_state["user_name"] = os.environ.get("SNOWFLAKE_USER") + st.session_state["account_name"] = SNOWFLAKE_ACCOUNT_LOCATOR + st.session_state["host_name"] = SNOWFLAKE_HOST + st.session_state["user_name"] = SNOWFLAKE_USER # When the app first loads, show the onboarding screen. if "page" not in st.session_state: diff --git a/semantic_model_generator/snowflake_utils/env_vars.py b/semantic_model_generator/snowflake_utils/env_vars.py index ea54b24f..67fd156b 100644 --- a/semantic_model_generator/snowflake_utils/env_vars.py +++ b/semantic_model_generator/snowflake_utils/env_vars.py @@ -5,5 +5,28 @@ SNOWFLAKE_WAREHOUSE = os.getenv("SNOWFLAKE_WAREHOUSE") SNOWFLAKE_USER = os.getenv("SNOWFLAKE_USER") SNOWFLAKE_PASSWORD = os.getenv("SNOWFLAKE_PASSWORD") -SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST") +SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST") # optional per README docs SNOWFLAKE_AUTHENTICATOR = os.getenv("SNOWFLAKE_AUTHENTICATOR") +SNOWFLAKE_ACCOUNT_LOCATOR = os.getenv("SNOWFLAKE_ACCOUNT_LOCATOR") + + +def assert_required_env_vars() -> list[str]: + """ + Ensures that the required environment variables are set before proceeding. + Returns: list of missing required environment variables + + """ + + missing_env_vars = [] + if not SNOWFLAKE_ROLE: + missing_env_vars.append("SNOWFLAKE_ROLE") + if not SNOWFLAKE_WAREHOUSE: + missing_env_vars.append("SNOWFLAKE_WAREHOUSE") + if not SNOWFLAKE_USER: + missing_env_vars.append("SNOWFLAKE_USER") + if not SNOWFLAKE_ACCOUNT_LOCATOR: + missing_env_vars.append("SNOWFLAKE_ACCOUNT_LOCATOR") + if not SNOWFLAKE_PASSWORD and not SNOWFLAKE_AUTHENTICATOR: + missing_env_vars.append("SNOWFLAKE_PASSWORD/SNOWFLAKE_AUTHENTICATOR") + + return missing_env_vars From de1e9d0a258cd6544fe1ef645724a75561f6d663 Mon Sep 17 00:00:00 2001 From: Chris Nivera Date: Fri, 19 Jul 2024 16:31:32 -0700 Subject: [PATCH 2/5] remove credentials from streamlit --- admin_apps/journeys/iteration.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/admin_apps/journeys/iteration.py b/admin_apps/journeys/iteration.py index b32bd7af..0b1bedc3 100644 --- a/admin_apps/journeys/iteration.py +++ b/admin_apps/journeys/iteration.py @@ -33,6 +33,11 @@ yaml_to_semantic_model, ) from semantic_model_generator.protos import semantic_model_pb2 +from semantic_model_generator.snowflake_utils.env_vars import ( + SNOWFLAKE_ACCOUNT_LOCATOR, + SNOWFLAKE_HOST, + SNOWFLAKE_USER, +) from semantic_model_generator.snowflake_utils.snowflake_connector import ( SnowflakeConnector, ) @@ -487,13 +492,8 @@ def set_up_requirements() -> None: # Otherwise, we should collect the prebuilt YAML location from the user so that we can download it. with st.form("download_yaml_requirements"): st.markdown( - "Before we get started, let's make sure we have everything set up. If you'd like to populate these values by default, please follow the [environment variable setup instructions](https://github.com/Snowflake-Labs/semantic-model-generator/blob/main/README.md#setup)." - ) - account_name = st.text_input( - "Account", value=os.environ.get("SNOWFLAKE_ACCOUNT_LOCATOR") + "Fill in the Snowflake stage details to download your existing YAML file." ) - host_name = st.text_input("Host", value=os.environ.get("SNOWFLAKE_HOST")) - user_name = st.text_input("User", value=os.environ.get("SNOWFLAKE_USER")) stage_database = st.text_input("Stage database", value="") stage_schema = st.text_input("Stage schema", value="") stage_name = st.text_input("Stage name", value="") @@ -504,9 +504,9 @@ def set_up_requirements() -> None: stage_schema=stage_schema, stage_name=stage_name, ) - st.session_state["account_name"] = account_name - st.session_state["host_name"] = host_name - st.session_state["user_name"] = user_name + st.session_state["account_name"] = SNOWFLAKE_ACCOUNT_LOCATOR + st.session_state["host_name"] = SNOWFLAKE_HOST + st.session_state["user_name"] = SNOWFLAKE_USER st.session_state["file_name"] = file_name st.session_state["page"] = GeneratorAppScreen.ITERATION st.rerun() From c92adfeca13c51d38b9304c67719a8d60295b70e Mon Sep 17 00:00:00 2001 From: Chris Nivera Date: Fri, 19 Jul 2024 16:33:37 -0700 Subject: [PATCH 3/5] lint --- admin_apps/app.py | 2 +- admin_apps/journeys/iteration.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/admin_apps/app.py b/admin_apps/app.py index 03cb6749..eb2b69e1 100644 --- a/admin_apps/app.py +++ b/admin_apps/app.py @@ -2,10 +2,10 @@ from admin_apps.shared_utils import GeneratorAppScreen from semantic_model_generator.snowflake_utils.env_vars import ( - assert_required_env_vars, SNOWFLAKE_ACCOUNT_LOCATOR, SNOWFLAKE_HOST, SNOWFLAKE_USER, + assert_required_env_vars, ) # set_page_config must be run as the first Streamlit command on the page, before any other streamlit imports. diff --git a/admin_apps/journeys/iteration.py b/admin_apps/journeys/iteration.py index 0b1bedc3..bf6865fd 100644 --- a/admin_apps/journeys/iteration.py +++ b/admin_apps/journeys/iteration.py @@ -1,5 +1,4 @@ import json -import os import time from typing import Any, Dict, List, Optional From ebcb98afd7846eeb04638330d5dd742131f7b1f5 Mon Sep 17 00:00:00 2001 From: Chris Nivera Date: Fri, 19 Jul 2024 16:34:26 -0700 Subject: [PATCH 4/5] todo --- admin_apps/journeys/iteration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/admin_apps/journeys/iteration.py b/admin_apps/journeys/iteration.py index bf6865fd..3406be14 100644 --- a/admin_apps/journeys/iteration.py +++ b/admin_apps/journeys/iteration.py @@ -493,6 +493,7 @@ def set_up_requirements() -> None: st.markdown( "Fill in the Snowflake stage details to download your existing YAML file." ) + # TODO: Make these dropdown selectors by fetching all dbs/schemas similar to table approach? stage_database = st.text_input("Stage database", value="") stage_schema = st.text_input("Stage schema", value="") stage_name = st.text_input("Stage name", value="") From e78af6b3c798034c8290bf5fd562d0643578edce Mon Sep 17 00:00:00 2001 From: Chris Nivera Date: Fri, 26 Jul 2024 14:08:21 -0700 Subject: [PATCH 5/5] fix authenticator --- semantic_model_generator/snowflake_utils/env_vars.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/semantic_model_generator/snowflake_utils/env_vars.py b/semantic_model_generator/snowflake_utils/env_vars.py index 67fd156b..630b23f9 100644 --- a/semantic_model_generator/snowflake_utils/env_vars.py +++ b/semantic_model_generator/snowflake_utils/env_vars.py @@ -29,4 +29,12 @@ def assert_required_env_vars() -> list[str]: if not SNOWFLAKE_PASSWORD and not SNOWFLAKE_AUTHENTICATOR: missing_env_vars.append("SNOWFLAKE_PASSWORD/SNOWFLAKE_AUTHENTICATOR") + # Assert that SNOWFLAKE_PASSWORD is required unless the user is using the externalbrowser authenticator + if ( + SNOWFLAKE_AUTHENTICATOR + and SNOWFLAKE_AUTHENTICATOR.lower() != "externalbrowser" + and not SNOWFLAKE_PASSWORD + ): + missing_env_vars.append("SNOWFLAKE_PASSWORD") + return missing_env_vars