Skip to content

Commit

Permalink
Redid viur create workflow (#176)
Browse files Browse the repository at this point in the history
* ported clean base tio setup.py

* fixed replacement bug

* removed viur gcloud setup function

* pythonesque directory changes

* now using subprocess

* minor fixes

* minor fixes
  • Loading branch information
Grashalmbeisser authored Nov 8, 2024
1 parent ba5d3ec commit 65fbde3
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 131 deletions.
118 changes: 1 addition & 117 deletions src/viur_cli/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def disable_gcp_backup():


@cloud.command(context_settings={"ignore_unknown_options": True})
@click.argument("action", type=click.Choice(["gcloud", "gcroles"]))
@click.argument("action", type=click.Choice(["gcroles"]))
@click.argument("profile", default="default")
def setup(action, profile):
"""
Expand All @@ -258,7 +258,6 @@ def setup(action, profile):
echo_error("No 'deploy' directory found in your current working directory."
"\n Please make sure you are in the correct directory."
"\n If you want to create a new ViUR Project use 'viur create {name}'")

if action == "gcroles":
gcloud_setup_roles(profile)

Expand Down Expand Up @@ -420,121 +419,6 @@ def transform_dict_to_yaml(transformed_data):
return original_data


def gcloud_setup():
"""
Set up the Google Cloud Platform (GCP) environment for a ViUR project.
This method performs the following steps:
1. Prompts the user to enter the GCP project ID.
2. Checks if the user is authorized with gcloud.
- If not authorized, prompts the user to authenticate with gcloud and login.
3. Checks if the GCP App Engine app already exists.
- If not, prompts the user to create the app and confirm the project is connected to a billing account.
4. Enables necessary APIs and services for the project.
5. Configures Google Cloud Storage for the project.
6. Deploys necessary deployment files (cron.yaml, queue.yaml, index.yaml) to the project.
7. Checks if the app engine default credentials are set.
- If not set, prompts the user to authenticate and set the application default user.
8. Prints a success message with instructions on how to run the project locally.
Note: This method does not return anything.
"""
project = input("Enter PROJECT_ID: ").strip()

if not project:
echo_fatal("Usage: viur setup gcloud PROJECT_ID")
return

echo_info("Check if user is authorized with gcloud....")

try:
run_command("gcloud auth print-access-token")
except subprocess.CalledProcessError:
echo_warning(
"##############################################################\n"
"# Please authenticate your Google user with gcloud SDK to #\n"
"# execute administrative commands. #\n"
"# In this step, a separate browser window opens to #\n"
"# authenticate. #\n"
"# This step is only required once on this computer. #\n"
"##############################################################\n"
)
response = input("Are you ready?[Y/n]")
if not response.lower() in ("y", ""):
echo_fatal("User aborted")
return

run_command("gcloud auth login --no-ptomote")

# Check if App already exists
try:
run_command(f"gcloud app describe --project={project}")
except subprocess.CalledProcessError:
echo_warning(
"##############################################################\n"
"# Please check and confirm that your project is created and #\n"
"# connected with a billing account in Google Cloud console. #\n"
"# Otherwise, some of the following calls may fail. #\n"
"##############################################################"
)
response = input("Continue? [Y/n] ")
if not response.lower() in ("y", ""):
echo_error("User aborted.")
return

# Create the Appengine app
run_command(f"gcloud app create --project={project} --region=europe-west3")

# Activate APIs and Services
services = [
"datastore.googleapis.com",
"firestore.googleapis.com",
"iamcredentials.googleapis.com",
"cloudbuild.googleapis.com",
"cloudtasks.googleapis.com",
"cloudscheduler.googleapis.com",
"secretmanager.googleapis.com"
]

for service in services:
run_command(f"gcloud services enable --project={project} {service}")

# Configure Google Cloud Storage
run_command(f"gsutil uniformbucketlevelaccess set on gs://{project}.appspot.com/")

for yaml in ["cron.yaml", "queue.yaml", "index.yaml"]:
run_command(f"cd deploy && gcloud app deploy -q --project={project} {yaml}")

echo_info("Check if app engine default credentials are set...")
try:
run_command("gcloud auth application-default print-access-token")

except subprocess.CalledProcessError:
echo_warning(
"##############################################################\n"
"# Please authenticate your Google user with gcloud SDK now #\n"
"# to set the application default user. This step is required #\n"
"# to run ViUR applications locally without further #\n"
"# credentials that must be supplied from a file. #\n"
"# This step is only required once on this computer. #\n"
"##############################################################")
response = input("Are you ready? [Y/n] ")
if not response.lower() in ("y", ""):
echo_fatal("User aborted.")
return

run_command("gcloud auth application-default login")

echo_positive(
"All done!\n"
"You should now be able to run your project locally with\n"
" viur run \n"
"At the first run, it might happen that some functions are\n"
"causing error 500 because indexes are not immediately\n"
"served. Therefore, maybe wait a few minutes.\n"
"Have a nice day.\n")


# Helper function for running Commands in subprocess and getting the Output
def run_command(command):
"""
Expand Down
88 changes: 74 additions & 14 deletions src/viur_cli/setup.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,71 @@
import click
import os
from .conf import config
import subprocess
import click
from .cli import cli
from .utils import *


def clean_base(app_id, author=None):
"""
Sets up a clean ViUR project base.
Args:
clean_history (bool, optional): Whether to clean the git history. Defaults to True.
app_id (str, optional): The application-id to use. If not provided, prompts the user.
author (str, optional): The author's name to use. If not provided, defaults to the current user.
"""

try:
whoami = getpass.getuser()
except Exception:
whoami = "viur"

timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
os.chdir(app_id)

file_list = ["viur-project.md"]
replacements = {"{{app_id}}": app_id, "{{whoami}}": whoami, "{{timestamp}}": timestamp}

for subdir, dirs, files in os.walk("."):
for file in files:
filepath = subdir + os.sep + file

if any([filepath.endswith(ext) for ext in
[".py", ".yaml", ".html", ".md", ".sh", ".json", ".js", ".less"]]):
file_list.append(filepath)

for file_obj in file_list:
lines = []
with open(file_obj, "r") as infile:
for line in infile:
for src, target in replacements.items():
line = line.replace(src, target)
lines.append(line)
with open(file_obj, "w") as outfile:
for line in lines:
outfile.write(line)

if os.path.exists(".git"):
echo_info("Cleaning git history")
subprocess.check_output("git checkout --orphan main_tmp", shell=True)
echo_info(subprocess.check_output("git branch -D main", shell=True).decode().rstrip("\n"))

subprocess.check_output("git branch -m main", shell=True)
echo_info(
f"Current branch is: {subprocess.check_output("git branch --show-current", shell=True)
.decode().rstrip("\n")}")
echo_info("---")

echo_info("Generating project documentation...")
sys.stdout.flush()

os.remove("README.md") # Remove README.md if it exists
os.rename("viur-project.md", "README.md")
os.remove(sys.argv[0]) # Remove the script itself

echo_positive("Project repository has been set-up now.")


@cli.command()
@click.argument("name")
@click.pass_context
Expand All @@ -31,21 +92,20 @@ def create(ctx, name):
"""
if os.path.exists(f'./{name}'):
echo_error(f'"{name}" Folder exists. Please use a different name or remove this folder ./{name}')
echo_error(f'"{name}" Folder already exists. Please use a different name or remove this folder ./{name}')
return

# fetch base project
os.system(
f'git clone https://github.com/viur-framework/viur-base.git {name}')
project_json_path = f'./{name}/project.json'
git_clonne_cmd = ['git', 'clone', f'https://github.com/viur-framework/viur-base.git', name]
subprocess.run(git_clonne_cmd, check=True)

# collect project info
conf = config.get_profile("default")
appname = conf['application_name']
wdir = f"{os.getcwd()}/{name}"

# run clean-base
os.system(f'cd ./{name} && python3 clean-base.py -A={appname}')
# Run clean-base.py
clean_base_cmd = ['python3', 'clean-base.py', '-A', f'{name}']
subprocess.run(clean_base_cmd, check=True, cwd=wdir)

# run gcloud config
if click.confirm(f'Do you want to configure "{appname}" as a new gcloud project?'):
os.system(f'cd ./{name} && ./viur-gcloud-setup.sh {appname}')
# Run gcloud config (if confirmed)
if click.confirm(f'Do you want to configure "{name}" as a new gcloud project?'):
gcloud_setup_cmd = ['./viur-gcloud-setup.sh', name]
subprocess.run(gcloud_setup_cmd, check=True, cwd=wdir)

0 comments on commit 65fbde3

Please sign in to comment.