viur-cli 2.0.2__tar.gz → 2.1.0.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {viur_cli-2.0.2/src/viur_cli.egg-info → viur_cli-2.1.0.dev1}/PKG-INFO +7 -1
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/README.md +6 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/setup.cfg +0 -1
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/cloud.py +118 -141
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/conf.py +6 -13
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/local.py +7 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/package.py +27 -1
- viur_cli-2.1.0.dev1/src/viur_cli/setup.py +110 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/tool.py +80 -114
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/version.py +1 -1
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1/src/viur_cli.egg-info}/PKG-INFO +7 -1
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli.egg-info/SOURCES.txt +1 -2
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli.egg-info/entry_points.txt +0 -1
- viur_cli-2.0.2/src/viur_cli/scripts/viur_2to3.py +0 -153
- viur_cli-2.0.2/src/viur_cli/setup.py +0 -51
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/LICENSE +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/pyproject.toml +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/setup.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/__init__.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/build.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/cli.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/deprecated.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/__init__.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/cli.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/__init__.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/csvwriter.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/dialog.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/logger.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/module.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/network.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/progressbar.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/readers.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/utils.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/viur.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scriptor/scriptor/writer.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scripts/__init__.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/scripts/get_pyodide.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/update.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli/utils.py +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli.egg-info/dependency_links.txt +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli.egg-info/requires.txt +0 -0
- {viur_cli-2.0.2 → viur_cli-2.1.0.dev1}/src/viur_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: viur_cli
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.1.0.dev1
|
|
4
4
|
Summary: Command-line interface for ViUR application maintenance.
|
|
5
5
|
Home-page: https://github.com/viur-framework/viur-cli
|
|
6
6
|
Author: Andreas H. Kelch
|
|
@@ -194,6 +194,12 @@ It contains the default viur project profile and it can be expanded with several
|
|
|
194
194
|
"kind": "npm",
|
|
195
195
|
"source": ""
|
|
196
196
|
}
|
|
197
|
+
/* OPTIONAL arguments, can be set in default or in a specific profile */
|
|
198
|
+
"appyaml": "app_stub.yaml", // Use a name other than "app.yaml"
|
|
199
|
+
"appyaml_substitition": true, // Set to true to replace only standard variables in app.yaml
|
|
200
|
+
"appyaml_substitition": { // Set to an object to replace these in addition to the standard variables in app.yaml
|
|
201
|
+
"$REGION": "europe-west3"
|
|
202
|
+
}
|
|
197
203
|
},
|
|
198
204
|
"gcloud": {
|
|
199
205
|
"functions": { //Declarations for a cloud function
|
|
@@ -174,6 +174,12 @@ It contains the default viur project profile and it can be expanded with several
|
|
|
174
174
|
"kind": "npm",
|
|
175
175
|
"source": ""
|
|
176
176
|
}
|
|
177
|
+
/* OPTIONAL arguments, can be set in default or in a specific profile */
|
|
178
|
+
"appyaml": "app_stub.yaml", // Use a name other than "app.yaml"
|
|
179
|
+
"appyaml_substitition": true, // Set to true to replace only standard variables in app.yaml
|
|
180
|
+
"appyaml_substitition": { // Set to an object to replace these in addition to the standard variables in app.yaml
|
|
181
|
+
"$REGION": "europe-west3"
|
|
182
|
+
}
|
|
177
183
|
},
|
|
178
184
|
"gcloud": {
|
|
179
185
|
"functions": { //Declarations for a cloud function
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
import subprocess
|
|
3
4
|
import os
|
|
4
5
|
import string
|
|
6
|
+
import time
|
|
5
7
|
import click
|
|
6
8
|
import yaml
|
|
7
9
|
from viur_cli import echo_positive, echo_warning, echo_fatal
|
|
@@ -15,6 +17,53 @@ def cloud():
|
|
|
15
17
|
"""This method defines a command group for working with cloud resources."""
|
|
16
18
|
|
|
17
19
|
|
|
20
|
+
@cloud.command(context_settings={"ignore_unknown_options": True})
|
|
21
|
+
@click.argument("action", type=click.Choice(["bucket2bucket", "bucket2local", "local2bucket"]))
|
|
22
|
+
@click.argument("profile", default="default")
|
|
23
|
+
def copy(action, profile):
|
|
24
|
+
if action == "bucket2bucket":
|
|
25
|
+
if user_check_login():
|
|
26
|
+
storage_copy()
|
|
27
|
+
|
|
28
|
+
if action == "bucket2local":
|
|
29
|
+
if user_check_login():
|
|
30
|
+
datastore_import(profile)
|
|
31
|
+
|
|
32
|
+
if action == "local2bucket":
|
|
33
|
+
if user_check_login():
|
|
34
|
+
datastore_export(profile)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def user_check_login():
|
|
38
|
+
return click.confirm("Are you logged in with your gcloud admin account?", default=False, show_default=True)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def storage_copy():
|
|
42
|
+
# https://console.cloud.google.com/transfer/jobs
|
|
43
|
+
source = click.prompt('Source bucketname')
|
|
44
|
+
target = click.prompt('Target bucketname')
|
|
45
|
+
if not click.confirm(text=f"Copy from {source} to {target}", default=True):
|
|
46
|
+
print("Abort ...")
|
|
47
|
+
return 0
|
|
48
|
+
print(f"gsutil -m cp -r gs://{source}/ gs://{target}/")
|
|
49
|
+
os.system(f"gsutil -m cp -r gs://{source} gs://{target}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def datastore_import(profile):
|
|
53
|
+
conf = config.get_profile(profile)
|
|
54
|
+
target = click.prompt('path to overall_export_metadata')
|
|
55
|
+
os.system(f"gcloud datastore import gs://{target} --project={conf['application_name']}")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def datastore_export(profile):
|
|
59
|
+
conf = config.get_profile(profile)
|
|
60
|
+
target = click.prompt('bucketname')
|
|
61
|
+
timestamp = f'{datetime.now().strftime("%Y%m%d-%H%M%S")}-manual'
|
|
62
|
+
format = "default"
|
|
63
|
+
os.system(
|
|
64
|
+
f"gcloud datastore export gs://{target}/{timestamp}-{format} --format={format} --project={conf['application_name']} ")
|
|
65
|
+
|
|
66
|
+
|
|
18
67
|
@cloud.command(context_settings={"ignore_unknown_options": True})
|
|
19
68
|
@click.argument("action", type=click.Choice(["backup"]))
|
|
20
69
|
def enable(action):
|
|
@@ -196,15 +245,19 @@ def disable_gcp_backup():
|
|
|
196
245
|
|
|
197
246
|
|
|
198
247
|
@cloud.command(context_settings={"ignore_unknown_options": True})
|
|
199
|
-
@click.argument("action", type=click.Choice(["
|
|
248
|
+
@click.argument("action", type=click.Choice(["gcroles"]))
|
|
200
249
|
@click.argument("profile", default="default")
|
|
201
250
|
def setup(action, profile):
|
|
202
251
|
"""
|
|
203
252
|
Set up the specified action for the given profile.
|
|
204
253
|
"""
|
|
205
254
|
if action == "gcloud":
|
|
206
|
-
|
|
207
|
-
|
|
255
|
+
if os.path.exists('deploy'):
|
|
256
|
+
gcloud_setup()
|
|
257
|
+
else:
|
|
258
|
+
echo_error("No 'deploy' directory found in your current working directory."
|
|
259
|
+
"\n Please make sure you are in the correct directory."
|
|
260
|
+
"\n If you want to create a new ViUR Project use 'viur create {name}'")
|
|
208
261
|
if action == "gcroles":
|
|
209
262
|
gcloud_setup_roles(profile)
|
|
210
263
|
|
|
@@ -366,121 +419,6 @@ def transform_dict_to_yaml(transformed_data):
|
|
|
366
419
|
return original_data
|
|
367
420
|
|
|
368
421
|
|
|
369
|
-
def gcloud_setup():
|
|
370
|
-
"""
|
|
371
|
-
Set up the Google Cloud Platform (GCP) environment for a ViUR project.
|
|
372
|
-
|
|
373
|
-
This method performs the following steps:
|
|
374
|
-
1. Prompts the user to enter the GCP project ID.
|
|
375
|
-
2. Checks if the user is authorized with gcloud.
|
|
376
|
-
- If not authorized, prompts the user to authenticate with gcloud and login.
|
|
377
|
-
3. Checks if the GCP App Engine app already exists.
|
|
378
|
-
- If not, prompts the user to create the app and confirm the project is connected to a billing account.
|
|
379
|
-
4. Enables necessary APIs and services for the project.
|
|
380
|
-
5. Configures Google Cloud Storage for the project.
|
|
381
|
-
6. Deploys necessary deployment files (cron.yaml, queue.yaml, index.yaml) to the project.
|
|
382
|
-
7. Checks if the app engine default credentials are set.
|
|
383
|
-
- If not set, prompts the user to authenticate and set the application default user.
|
|
384
|
-
8. Prints a success message with instructions on how to run the project locally.
|
|
385
|
-
|
|
386
|
-
Note: This method does not return anything.
|
|
387
|
-
"""
|
|
388
|
-
project = input("Enter PROJECT_ID: ").strip()
|
|
389
|
-
|
|
390
|
-
if not project:
|
|
391
|
-
echo_fatal("Usage: viur setup gcloud PROJECT_ID")
|
|
392
|
-
return
|
|
393
|
-
|
|
394
|
-
echo_info("Check if user is authorized with gcloud....")
|
|
395
|
-
|
|
396
|
-
try:
|
|
397
|
-
run_command("gcloud auth print-access-token")
|
|
398
|
-
except subprocess.CalledProcessError:
|
|
399
|
-
echo_warning(
|
|
400
|
-
"##############################################################\n"
|
|
401
|
-
"# Please authenticate your Google user with gcloud SDK to #\n"
|
|
402
|
-
"# execute administrative commands. #\n"
|
|
403
|
-
"# In this step, a separate browser window opens to #\n"
|
|
404
|
-
"# authenticate. #\n"
|
|
405
|
-
"# This step is only required once on this computer. #\n"
|
|
406
|
-
"##############################################################\n"
|
|
407
|
-
)
|
|
408
|
-
response = input("Are you ready?[Y/n]")
|
|
409
|
-
if not response.lower() in ("y", ""):
|
|
410
|
-
echo_fatal("User aborted")
|
|
411
|
-
return
|
|
412
|
-
|
|
413
|
-
run_command("gcloud auth login --no-ptomote")
|
|
414
|
-
|
|
415
|
-
# Check if App already exists
|
|
416
|
-
try:
|
|
417
|
-
run_command(f"gcloud app describe --project={project}")
|
|
418
|
-
except subprocess.CalledProcessError:
|
|
419
|
-
echo_warning(
|
|
420
|
-
"##############################################################\n"
|
|
421
|
-
"# Please check and confirm that your project is created and #\n"
|
|
422
|
-
"# connected with a billing account in Google Cloud console. #\n"
|
|
423
|
-
"# Otherwise, some of the following calls may fail. #\n"
|
|
424
|
-
"##############################################################"
|
|
425
|
-
)
|
|
426
|
-
response = input("Continue? [Y/n] ")
|
|
427
|
-
if not response.lower() in ("y", ""):
|
|
428
|
-
echo_error("User aborted.")
|
|
429
|
-
return
|
|
430
|
-
|
|
431
|
-
# Create the Appengine app
|
|
432
|
-
run_command(f"gcloud app create --project={project} --region=europe-west3")
|
|
433
|
-
|
|
434
|
-
# Activate APIs and Services
|
|
435
|
-
services = [
|
|
436
|
-
"datastore.googleapis.com",
|
|
437
|
-
"firestore.googleapis.com",
|
|
438
|
-
"iamcredentials.googleapis.com",
|
|
439
|
-
"cloudbuild.googleapis.com",
|
|
440
|
-
"cloudtasks.googleapis.com",
|
|
441
|
-
"cloudscheduler.googleapis.com",
|
|
442
|
-
"secretmanager.googleapis.com"
|
|
443
|
-
]
|
|
444
|
-
|
|
445
|
-
for service in services:
|
|
446
|
-
run_command(f"gcloud services enable --project={project} {service}")
|
|
447
|
-
|
|
448
|
-
# Configure Google Cloud Storage
|
|
449
|
-
run_command(f"gsutil uniformbucketlevelaccess set on gs://{project}.appspot.com/")
|
|
450
|
-
|
|
451
|
-
for yaml in ["cron.yaml", "queue.yaml", "index.yaml"]:
|
|
452
|
-
run_command(f"cd deploy && gcloud app deploy -q --project={project} {yaml}")
|
|
453
|
-
|
|
454
|
-
echo_info("Check if app engine default credentials are set...")
|
|
455
|
-
try:
|
|
456
|
-
run_command("gcloud auth application-default print-access-token")
|
|
457
|
-
|
|
458
|
-
except subprocess.CalledProcessError:
|
|
459
|
-
echo_warning(
|
|
460
|
-
"##############################################################\n"
|
|
461
|
-
"# Please authenticate your Google user with gcloud SDK now #\n"
|
|
462
|
-
"# to set the application default user. This step is required #\n"
|
|
463
|
-
"# to run ViUR applications locally without further #\n"
|
|
464
|
-
"# credentials that must be supplied from a file. #\n"
|
|
465
|
-
"# This step is only required once on this computer. #\n"
|
|
466
|
-
"##############################################################")
|
|
467
|
-
response = input("Are you ready? [Y/n] ")
|
|
468
|
-
if not response.lower() in ("y", ""):
|
|
469
|
-
echo_fatal("User aborted.")
|
|
470
|
-
return
|
|
471
|
-
|
|
472
|
-
run_command("gcloud auth application-default login")
|
|
473
|
-
|
|
474
|
-
echo_positive(
|
|
475
|
-
"All done!\n"
|
|
476
|
-
"You should now be able to run your project locally with\n"
|
|
477
|
-
" viur run \n"
|
|
478
|
-
"At the first run, it might happen that some functions are\n"
|
|
479
|
-
"causing error 500 because indexes are not immediately\n"
|
|
480
|
-
"served. Therefore, maybe wait a few minutes.\n"
|
|
481
|
-
"Have a nice day.\n")
|
|
482
|
-
|
|
483
|
-
|
|
484
422
|
# Helper function for running Commands in subprocess and getting the Output
|
|
485
423
|
def run_command(command):
|
|
486
424
|
"""
|
|
@@ -501,20 +439,23 @@ def run_command(command):
|
|
|
501
439
|
@click.argument("additional_args", nargs=-1)
|
|
502
440
|
@click.option("--ext", "-e", default=None)
|
|
503
441
|
@click.option("--yes", "-y", is_flag=True, default=False)
|
|
442
|
+
@click.option("--skip_checks", is_flag=True, help="Skip the security checks before the deployment")
|
|
504
443
|
@click.option("--name", "-n", default=None)
|
|
505
|
-
def deploy(action, profile, name, ext, yes, additional_args):
|
|
506
|
-
"""
|
|
444
|
+
def deploy(action, profile, name, ext, yes, skip_checks: bool, additional_args):
|
|
445
|
+
"""Deploy the specified action to a cloud"""
|
|
507
446
|
|
|
508
447
|
conf = config.get_profile(profile)
|
|
509
448
|
|
|
510
449
|
if action == "app":
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
450
|
+
if not skip_checks:
|
|
451
|
+
from . import do_checks
|
|
452
|
+
if not do_checks(dev=False):
|
|
453
|
+
# --yes will not be implemented here because deploying security issues should be an explicit decission
|
|
454
|
+
if not click.confirm(f"The checks were not successful, do you want to continue?"):
|
|
455
|
+
return
|
|
456
|
+
else:
|
|
457
|
+
echo_info("\U00002714 No vulnerabilities found.")
|
|
458
|
+
|
|
518
459
|
version = replace_vars(
|
|
519
460
|
conf["version"],
|
|
520
461
|
{k: v for k, v in conf.items() if k not in ["version"]}
|
|
@@ -529,10 +470,46 @@ def deploy(action, profile, name, ext, yes, additional_args):
|
|
|
529
470
|
# rebuild requirements.txt
|
|
530
471
|
create_req(yes, profile, confirm_value=False)
|
|
531
472
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
473
|
+
app_yaml = Path(conf["distribution_folder"]) / conf.get("appyaml", "app.yaml")
|
|
474
|
+
app_yaml_tmp = app_yaml_hidden = None
|
|
475
|
+
if appyaml_substitition := conf.get("appyaml_substitition"):
|
|
476
|
+
app_yaml_tmp = app_yaml.with_stem(f"app{time.time_ns()}.tmp")
|
|
477
|
+
|
|
478
|
+
susbtitutions = {
|
|
479
|
+
"$PROJECT_ID": conf["application_name"],
|
|
480
|
+
"$PROJECT_VERSION": version,
|
|
481
|
+
"$CLI_PROFILE": profile,
|
|
482
|
+
}
|
|
483
|
+
if isinstance(appyaml_substitition, dict):
|
|
484
|
+
susbtitutions |= appyaml_substitition
|
|
485
|
+
|
|
486
|
+
new_content = app_yaml.read_text()
|
|
487
|
+
for pattern, replacment in susbtitutions.items():
|
|
488
|
+
new_content = new_content.replace(pattern, replacment)
|
|
489
|
+
app_yaml_tmp.write_text(new_content)
|
|
490
|
+
additional_args = [f"--appyaml={app_yaml_tmp.resolve()}", *additional_args]
|
|
491
|
+
|
|
492
|
+
# Sadly the --appyaml does only work if the deploy dir does not contain an app.yaml,
|
|
493
|
+
# thefore we make it "hidden" for the gcloud CLI if there is "app.yaml" is not
|
|
494
|
+
# named differently
|
|
495
|
+
if app_yaml.name == "app.yaml":
|
|
496
|
+
app_yaml_hidden = app_yaml.with_stem(f".{app_yaml.stem}")
|
|
497
|
+
app_yaml.rename(app_yaml_hidden)
|
|
498
|
+
|
|
499
|
+
elif app_yaml.name != "app.yaml":
|
|
500
|
+
# No substitution is used, but an different app.yaml name
|
|
501
|
+
additional_args = [f"--appyaml={app_yaml_tmp.resolve()}", *additional_args]
|
|
502
|
+
|
|
503
|
+
try:
|
|
504
|
+
os.system(
|
|
505
|
+
f'gcloud app deploy --project={conf["application_name"]} --version={version} '
|
|
506
|
+
f'--no-promote {" ".join(additional_args)} {conf["distribution_folder"]} {"-q" if yes else ""}'
|
|
507
|
+
)
|
|
508
|
+
finally:
|
|
509
|
+
if app_yaml_tmp is not None:
|
|
510
|
+
app_yaml_tmp.unlink()
|
|
511
|
+
if app_yaml_hidden is not None:
|
|
512
|
+
app_yaml_hidden.rename(app_yaml)
|
|
536
513
|
|
|
537
514
|
elif action == "cloudfunction":
|
|
538
515
|
os.system(build_deploy_command(name, conf["gcloud"]))
|
|
@@ -594,7 +571,6 @@ def deploy(action, profile, name, ext, yes, additional_args):
|
|
|
594
571
|
f'gcloud app deploy --project={conf["application_name"]} {" ".join(additional_args)} {yaml_file} {"-q" if yes else ""}')
|
|
595
572
|
|
|
596
573
|
|
|
597
|
-
|
|
598
574
|
def build_deploy_command(name, conf):
|
|
599
575
|
"""
|
|
600
576
|
|
|
@@ -627,9 +603,8 @@ def build_deploy_command(name, conf):
|
|
|
627
603
|
echo_fatal(f"The cloudfunction {name} was not found your project.json\n "
|
|
628
604
|
f"You can create a cloudfunction entry by calling 'viur cloud create function'")
|
|
629
605
|
|
|
630
|
-
|
|
631
606
|
command = (
|
|
632
|
-
f"gcloud
|
|
607
|
+
f"gcloud run deploy "
|
|
633
608
|
f"{name} "
|
|
634
609
|
f"--region='{conf['region']}'"
|
|
635
610
|
f"--max-instances={conf['max-instances']}"
|
|
@@ -676,10 +651,10 @@ def create(profile, action, gen, source, name, entrypoint, env_vars_file, memory
|
|
|
676
651
|
function_dict = conf["gcloud"]["functions"].get(function_name, {})
|
|
677
652
|
|
|
678
653
|
function_dict["gen"] = function_dict.get("gen",
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
654
|
+
gen if gen else click.prompt(
|
|
655
|
+
"Please enter your cloud function generation",
|
|
656
|
+
default="2")
|
|
657
|
+
)
|
|
683
658
|
|
|
684
659
|
function_dict["entry-point"] = function_dict.get("entry-point",
|
|
685
660
|
entrypoint if entrypoint else click.prompt(
|
|
@@ -708,12 +683,13 @@ def create(profile, action, gen, source, name, entrypoint, env_vars_file, memory
|
|
|
708
683
|
function_dict["trigger"] = function_dict.get("trigger",
|
|
709
684
|
trigger if trigger else click.prompt(
|
|
710
685
|
"Please enter your cloud function trigger type",
|
|
711
|
-
default="
|
|
686
|
+
default="https")
|
|
687
|
+
|
|
712
688
|
)
|
|
713
689
|
|
|
714
690
|
function_dict["source"] = function_dict.get("source",
|
|
715
691
|
source if source else click.prompt(
|
|
716
|
-
"Enter the directory of your cloud
|
|
692
|
+
"Enter the directory of your cloud function"
|
|
717
693
|
"(deploy/cloudfunction/{FileName})")
|
|
718
694
|
)
|
|
719
695
|
|
|
@@ -722,4 +698,5 @@ def create(profile, action, gen, source, name, entrypoint, env_vars_file, memory
|
|
|
722
698
|
config[profile] = conf
|
|
723
699
|
config.migrate()
|
|
724
700
|
echo_positive("Your cloud function creation was successful, if you want to add more flags, "
|
|
725
|
-
"add them in your project.json
|
|
701
|
+
"add them in your project.json")
|
|
702
|
+
|
|
@@ -17,7 +17,7 @@ class ProjectConfig(dict):
|
|
|
17
17
|
super().__init__()
|
|
18
18
|
self["default"] = {}
|
|
19
19
|
self["format"] = PROJECT_CONFIG_VERSION
|
|
20
|
-
self.
|
|
20
|
+
self.initial_load = False
|
|
21
21
|
|
|
22
22
|
def load(self):
|
|
23
23
|
"""
|
|
@@ -72,21 +72,16 @@ class ProjectConfig(dict):
|
|
|
72
72
|
|
|
73
73
|
def get_profile(self, profile):
|
|
74
74
|
"""Get profile configuration"""
|
|
75
|
+
if not self.initial_load:
|
|
76
|
+
self.load()
|
|
77
|
+
self.initial_load = True
|
|
78
|
+
|
|
75
79
|
if profile == "format":
|
|
76
80
|
echo_fatal("Your profile can not be named 'Format' ")
|
|
77
81
|
if profile not in self:
|
|
78
82
|
echo_fatal(f"{profile!r} is not a valid profile name")
|
|
79
83
|
return self["default"].copy() | self[profile]
|
|
80
84
|
|
|
81
|
-
def delete(self):
|
|
82
|
-
"""Delete profile cofniguration"""
|
|
83
|
-
configname = click.prompt('name')
|
|
84
|
-
try:
|
|
85
|
-
del self[configname]
|
|
86
|
-
self.save()
|
|
87
|
-
except:
|
|
88
|
-
raise click.ClickException(click.style(f"{configname} not found", fg="red"))
|
|
89
|
-
|
|
90
85
|
def find_key(self, dictionary, target_key, target, keep=False):
|
|
91
86
|
if target_key in dictionary:
|
|
92
87
|
if keep:
|
|
@@ -122,7 +117,7 @@ class ProjectConfig(dict):
|
|
|
122
117
|
self.find_key(self, target_key="version", target="default", keep=True)
|
|
123
118
|
# Fail Safe
|
|
124
119
|
if "version" in self:
|
|
125
|
-
del self["version"]
|
|
120
|
+
del self["version"]
|
|
126
121
|
self.remove_key(self, target_key="core")
|
|
127
122
|
|
|
128
123
|
if old_format := self["default"].get("format"):
|
|
@@ -167,8 +162,6 @@ class ProjectConfig(dict):
|
|
|
167
162
|
format_version_updated = False
|
|
168
163
|
|
|
169
164
|
for entry in ("admin", "scriptor", "vi"):
|
|
170
|
-
if not self["default"]["builds"]:
|
|
171
|
-
self["default"]["builds"]
|
|
172
165
|
if entry in self["default"]:
|
|
173
166
|
version_value = self["default"][entry].lstrip("v")
|
|
174
167
|
self["default"]["builds"][entry] = {
|
|
@@ -46,6 +46,13 @@ def run(profile, additional_args):
|
|
|
46
46
|
f"Please install the 'gcloud' tool or Log in with an appropriate account.")
|
|
47
47
|
|
|
48
48
|
conf = config.get_profile(profile)
|
|
49
|
+
additional_args = list(additional_args)
|
|
50
|
+
|
|
51
|
+
if conf.get("port"):
|
|
52
|
+
additional_args.append(f"--port={conf['port']}")
|
|
53
|
+
if conf.get("gunicorn_port"):
|
|
54
|
+
additional_args.append(f"--gunicorn_port={conf['gunicorn_port']}")
|
|
55
|
+
|
|
49
56
|
utils.system(
|
|
50
57
|
f'app_server -A={conf["application_name"]} {conf["distribution_folder"]} {" ".join(additional_args)}')
|
|
51
58
|
|
|
@@ -85,12 +85,13 @@ def get_version_info(software: str, version: str) -> tuple[str, str]:
|
|
|
85
85
|
@cli.command()
|
|
86
86
|
@click.argument('operation', type=click.Choice(['update', 'install']))
|
|
87
87
|
@click.argument('component', type=click.Choice(['vi', 'admin', 'scriptor', 'all']))
|
|
88
|
-
@click.argument('profile', default='default')
|
|
89
88
|
@click.argument("version", default="latest")
|
|
89
|
+
@click.argument('profile', default='default')
|
|
90
90
|
def package(operation, component, profile, version):
|
|
91
91
|
"""
|
|
92
92
|
Performs installements and updates of ViUR Ecosystem packages
|
|
93
93
|
"""
|
|
94
|
+
|
|
94
95
|
conf = config.get_profile(profile)
|
|
95
96
|
operations_links = {
|
|
96
97
|
'vi': vi,
|
|
@@ -141,6 +142,13 @@ def scriptor(version, target, profile):
|
|
|
141
142
|
|
|
142
143
|
real_version, download_url = get_version_info("scriptor", version)
|
|
143
144
|
|
|
145
|
+
old_version=conf.get('builds').get('scriptor').get('version')
|
|
146
|
+
|
|
147
|
+
if old_version == real_version.strip("v"):
|
|
148
|
+
if not click.confirm(f"You have already installed version {old_version} of scriptor.\n"
|
|
149
|
+
f"Do you want to continue and install it again?"):
|
|
150
|
+
return
|
|
151
|
+
|
|
144
152
|
scriptor_path = Path(dist_folder, target)
|
|
145
153
|
tmp_zip_file = Path("scriptor.zip")
|
|
146
154
|
|
|
@@ -168,6 +176,7 @@ def scriptor(version, target, profile):
|
|
|
168
176
|
tmp_zip_file.unlink()
|
|
169
177
|
bar.label = "updated successful"
|
|
170
178
|
|
|
179
|
+
echo_positive(f"Updated scriptor from {old_version} to {real_version}")
|
|
171
180
|
|
|
172
181
|
def admin(version: str, target: str, profile):
|
|
173
182
|
"""Update the admin to a specific version."""
|
|
@@ -176,6 +185,13 @@ def admin(version: str, target: str, profile):
|
|
|
176
185
|
|
|
177
186
|
real_version, download_url = get_version_info("admin", version)
|
|
178
187
|
|
|
188
|
+
old_version=conf.get('builds').get('admin').get('version')
|
|
189
|
+
|
|
190
|
+
if old_version == real_version.strip("v"):
|
|
191
|
+
if not click.confirm(f"You have already installed the version {old_version} of admin.\n"
|
|
192
|
+
f"Do you want to continue and install it again?"):
|
|
193
|
+
return
|
|
194
|
+
|
|
179
195
|
admin_path = Path(dist_folder, target)
|
|
180
196
|
tmp_zip_file = Path("vi-admin.zip")
|
|
181
197
|
|
|
@@ -207,6 +223,8 @@ def admin(version: str, target: str, profile):
|
|
|
207
223
|
tmp_zip_file.unlink()
|
|
208
224
|
bar.label = "updated successful"
|
|
209
225
|
|
|
226
|
+
echo_positive(f"Updated admin from {old_version} to {real_version}")
|
|
227
|
+
|
|
210
228
|
|
|
211
229
|
def vi(version, target, profile):
|
|
212
230
|
"""Updates Vi to the specified version."""
|
|
@@ -215,6 +233,12 @@ def vi(version, target, profile):
|
|
|
215
233
|
dist_folder = conf["distribution_folder"]
|
|
216
234
|
|
|
217
235
|
real_version, download_url = get_version_info("vi", version)
|
|
236
|
+
old_version = conf.get('builds').get('vi').get('version')
|
|
237
|
+
|
|
238
|
+
if old_version == real_version.strip("v"):
|
|
239
|
+
if not click.confirm(f"You have already installed the version {old_version} of vi.\n"
|
|
240
|
+
f"Do you want to continue and install it again?"):
|
|
241
|
+
return
|
|
218
242
|
|
|
219
243
|
vi_path = Path(dist_folder, target)
|
|
220
244
|
tmp_zip_file = Path("vi.zip")
|
|
@@ -246,3 +270,5 @@ def vi(version, target, profile):
|
|
|
246
270
|
elif element == 5:
|
|
247
271
|
tmp_zip_file.unlink()
|
|
248
272
|
bar.label = "updated successful"
|
|
273
|
+
|
|
274
|
+
echo_positive(f"Updated Vi from {old_version} to {real_version}")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import click
|
|
4
|
+
from .cli import cli
|
|
5
|
+
from .utils import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def clean_base(app_id, author=None):
|
|
9
|
+
"""
|
|
10
|
+
Sets up a clean ViUR project base.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
clean_history (bool, optional): Whether to clean the git history. Defaults to True.
|
|
14
|
+
app_id (str, optional): The application-id to use. If not provided, prompts the user.
|
|
15
|
+
author (str, optional): The author's name to use. If not provided, defaults to the current user.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
whoami = getpass.getuser()
|
|
20
|
+
except Exception:
|
|
21
|
+
whoami = "viur"
|
|
22
|
+
|
|
23
|
+
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
24
|
+
os.chdir(app_id)
|
|
25
|
+
|
|
26
|
+
file_list = ["viur-project.md"]
|
|
27
|
+
replacements = {"{{app_id}}": app_id, "{{whoami}}": whoami, "{{timestamp}}": timestamp}
|
|
28
|
+
|
|
29
|
+
for subdir, dirs, files in os.walk("."):
|
|
30
|
+
for file in files:
|
|
31
|
+
filepath = subdir + os.sep + file
|
|
32
|
+
|
|
33
|
+
if any([filepath.endswith(ext) for ext in
|
|
34
|
+
[".py", ".yaml", ".html", ".md", ".sh", ".json", ".js", ".less"]]):
|
|
35
|
+
file_list.append(filepath)
|
|
36
|
+
|
|
37
|
+
for file_obj in file_list:
|
|
38
|
+
lines = []
|
|
39
|
+
with open(file_obj, "r") as infile:
|
|
40
|
+
for line in infile:
|
|
41
|
+
for src, target in replacements.items():
|
|
42
|
+
line = line.replace(src, target)
|
|
43
|
+
lines.append(line)
|
|
44
|
+
with open(file_obj, "w") as outfile:
|
|
45
|
+
for line in lines:
|
|
46
|
+
outfile.write(line)
|
|
47
|
+
|
|
48
|
+
if os.path.exists(".git"):
|
|
49
|
+
echo_info("Cleaning git history")
|
|
50
|
+
subprocess.check_output("git checkout --orphan main_tmp", shell=True)
|
|
51
|
+
echo_info(subprocess.check_output("git branch -D main", shell=True).decode().rstrip("\n"))
|
|
52
|
+
|
|
53
|
+
subprocess.check_output("git branch -m main", shell=True)
|
|
54
|
+
branch_current = subprocess.check_output('git branch --show-current', shell=True).decode().rstrip('\n')
|
|
55
|
+
echo_info(f"Current branch is: {branch_current}")
|
|
56
|
+
echo_info("---")
|
|
57
|
+
|
|
58
|
+
echo_info("Generating project documentation...")
|
|
59
|
+
sys.stdout.flush()
|
|
60
|
+
|
|
61
|
+
os.remove("README.md") # Remove README.md if it exists
|
|
62
|
+
os.rename("viur-project.md", "README.md")
|
|
63
|
+
os.remove(sys.argv[0]) # Remove the script itself
|
|
64
|
+
|
|
65
|
+
echo_positive("Project repository has been set-up now.")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@cli.command()
|
|
69
|
+
@click.argument("name")
|
|
70
|
+
@click.pass_context
|
|
71
|
+
def create(ctx, name):
|
|
72
|
+
"""
|
|
73
|
+
Create a new ViUR project.
|
|
74
|
+
|
|
75
|
+
The 'create' command allows you to create a new ViUR project by cloning the ViUR base project and configuring it.
|
|
76
|
+
You can specify the name of the new project as the 'name' argument.
|
|
77
|
+
|
|
78
|
+
The 'create' command performs the following steps:
|
|
79
|
+
|
|
80
|
+
1. Clones the ViUR base project from the official GitHub repository.
|
|
81
|
+
|
|
82
|
+
2. Configures the new project by running 'clean-base.py'.
|
|
83
|
+
|
|
84
|
+
3. Optionally configures the project as a new gcloud project (if confirmed).
|
|
85
|
+
|
|
86
|
+
Note:
|
|
87
|
+
|
|
88
|
+
- This command initializes the new ViUR project based on the ViUR base project.
|
|
89
|
+
|
|
90
|
+
- Make sure to provide a unique project name to avoid conflicts with existing folders.
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
if os.path.exists(f'./{name}'):
|
|
94
|
+
echo_error(f'"{name}" Folder already exists. Please use a different name or remove this folder ./{name}')
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
# fetch base project
|
|
98
|
+
git_clonne_cmd = ['git', 'clone', f'https://github.com/viur-framework/viur-base.git', name]
|
|
99
|
+
subprocess.run(git_clonne_cmd, check=True)
|
|
100
|
+
|
|
101
|
+
wdir = f"{os.getcwd()}/{name}"
|
|
102
|
+
|
|
103
|
+
# Run clean-base.py
|
|
104
|
+
clean_base_cmd = ['python3', 'clean-base.py', '-A', f'{name}']
|
|
105
|
+
subprocess.run(clean_base_cmd, check=True, cwd=wdir)
|
|
106
|
+
|
|
107
|
+
# Run gcloud config (if confirmed)
|
|
108
|
+
if click.confirm(f'Do you want to configure "{name}" as a new gcloud project?'):
|
|
109
|
+
gcloud_setup_cmd = ['./viur-gcloud-setup.sh', name]
|
|
110
|
+
subprocess.run(gcloud_setup_cmd, check=True, cwd=wdir)
|
|
@@ -1,114 +1,80 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from . import cli
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@cli.group()
|
|
8
|
-
def tool():
|
|
9
|
-
"""
|
|
10
|
-
Run different ViUR-related scripts.
|
|
11
|
-
|
|
12
|
-
The 'tool' group allows you to execute various ViUR-related scripts that help with tasks such as project porting,
|
|
13
|
-
Pyodide installation, and SSL certificate fixes.
|
|
14
|
-
|
|
15
|
-
Available Commands:
|
|
16
|
-
|
|
17
|
-
- '
|
|
18
|
-
|
|
19
|
-
- '
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@
|
|
26
|
-
@click.
|
|
27
|
-
@click.option('--
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
:param
|
|
37
|
-
|
|
38
|
-
:param
|
|
39
|
-
|
|
40
|
-
:param
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Example Usage:
|
|
44
|
-
```
|
|
45
|
-
viur tool
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
:return: None
|
|
49
|
-
"""
|
|
50
|
-
command =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
:return: None
|
|
83
|
-
"""
|
|
84
|
-
command = "get-pyodide"
|
|
85
|
-
if help:
|
|
86
|
-
os.system("get-pyodide -h")
|
|
87
|
-
|
|
88
|
-
if version:
|
|
89
|
-
command += f" -v {version}"
|
|
90
|
-
|
|
91
|
-
if package:
|
|
92
|
-
command += f" -p {package}"
|
|
93
|
-
|
|
94
|
-
if target:
|
|
95
|
-
command += f" -t {target}"
|
|
96
|
-
|
|
97
|
-
os.system(command)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
@tool.command()
|
|
101
|
-
def ssl_fix():
|
|
102
|
-
"""
|
|
103
|
-
SSL certificate fix for macOS.
|
|
104
|
-
|
|
105
|
-
The 'ssl_fix' command is used to perform an SSL certificate fix for macOS.
|
|
106
|
-
|
|
107
|
-
Example Usage:
|
|
108
|
-
```
|
|
109
|
-
viur tool ssl_fix
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
:return: None
|
|
113
|
-
"""
|
|
114
|
-
os.system("chmod +x scripts/macos_certificate_fix.command && ./scripts/macos_certificate_fix.command")
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from . import cli
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@cli.group()
|
|
8
|
+
def tool():
|
|
9
|
+
"""
|
|
10
|
+
Run different ViUR-related scripts.
|
|
11
|
+
|
|
12
|
+
The 'tool' group allows you to execute various ViUR-related scripts that help with tasks such as project porting,
|
|
13
|
+
Pyodide installation, and SSL certificate fixes.
|
|
14
|
+
|
|
15
|
+
Available Commands:
|
|
16
|
+
|
|
17
|
+
- 'pyodide': Run the get_pyodide command.
|
|
18
|
+
|
|
19
|
+
- 'ssl_fix': SSL certificate fix for macOS.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@tool.command()
|
|
24
|
+
@click.option('--version', '-v')
|
|
25
|
+
@click.option('--package', '-p')
|
|
26
|
+
@click.option('--target', '-t')
|
|
27
|
+
@click.option('--help', '-h')
|
|
28
|
+
def pyodide(additional_args, version, package, target, help):
|
|
29
|
+
"""
|
|
30
|
+
The 'pyodide' command allows you to run the 'get_pyodide' command for Pyodide installation.
|
|
31
|
+
|
|
32
|
+
:param additional_args: tuple
|
|
33
|
+
Additional arguments to pass to the 'get_pyodide' command.
|
|
34
|
+
:param version: str, optional
|
|
35
|
+
Specify the version of Pyodide.
|
|
36
|
+
:param package: str, optional
|
|
37
|
+
Specify the package for Pyodide.
|
|
38
|
+
:param target: str, optional
|
|
39
|
+
Specify the target for Pyodide.
|
|
40
|
+
:param help: bool, optional
|
|
41
|
+
Display help for the 'get_pyodide' command.
|
|
42
|
+
|
|
43
|
+
Example Usage:
|
|
44
|
+
```
|
|
45
|
+
viur tool pyodide -v 0.19.1 -p mypackage -t mytarget
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
:return: None
|
|
49
|
+
"""
|
|
50
|
+
command = "get-pyodide"
|
|
51
|
+
if help:
|
|
52
|
+
os.system("get-pyodide -h")
|
|
53
|
+
|
|
54
|
+
if version:
|
|
55
|
+
command += f" -v {version}"
|
|
56
|
+
|
|
57
|
+
if package:
|
|
58
|
+
command += f" -p {package}"
|
|
59
|
+
|
|
60
|
+
if target:
|
|
61
|
+
command += f" -t {target}"
|
|
62
|
+
|
|
63
|
+
os.system(command)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@tool.command()
|
|
67
|
+
def ssl_fix():
|
|
68
|
+
"""
|
|
69
|
+
SSL certificate fix for macOS.
|
|
70
|
+
|
|
71
|
+
The 'ssl_fix' command is used to perform an SSL certificate fix for macOS.
|
|
72
|
+
|
|
73
|
+
Example Usage:
|
|
74
|
+
```
|
|
75
|
+
viur tool ssl_fix
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
:return: None
|
|
79
|
+
"""
|
|
80
|
+
os.system("chmod +x scripts/macos_certificate_fix.command && ./scripts/macos_certificate_fix.command")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: viur_cli
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.1.0.dev1
|
|
4
4
|
Summary: Command-line interface for ViUR application maintenance.
|
|
5
5
|
Home-page: https://github.com/viur-framework/viur-cli
|
|
6
6
|
Author: Andreas H. Kelch
|
|
@@ -194,6 +194,12 @@ It contains the default viur project profile and it can be expanded with several
|
|
|
194
194
|
"kind": "npm",
|
|
195
195
|
"source": ""
|
|
196
196
|
}
|
|
197
|
+
/* OPTIONAL arguments, can be set in default or in a specific profile */
|
|
198
|
+
"appyaml": "app_stub.yaml", // Use a name other than "app.yaml"
|
|
199
|
+
"appyaml_substitition": true, // Set to true to replace only standard variables in app.yaml
|
|
200
|
+
"appyaml_substitition": { // Set to an object to replace these in addition to the standard variables in app.yaml
|
|
201
|
+
"$REGION": "europe-west3"
|
|
202
|
+
}
|
|
197
203
|
},
|
|
198
204
|
"gcloud": {
|
|
199
205
|
"functions": { //Declarations for a cloud function
|
|
@@ -36,5 +36,4 @@ src/viur_cli/scriptor/scriptor/utils.py
|
|
|
36
36
|
src/viur_cli/scriptor/scriptor/viur.py
|
|
37
37
|
src/viur_cli/scriptor/scriptor/writer.py
|
|
38
38
|
src/viur_cli/scripts/__init__.py
|
|
39
|
-
src/viur_cli/scripts/get_pyodide.py
|
|
40
|
-
src/viur_cli/scripts/viur_2to3.py
|
|
39
|
+
src/viur_cli/scripts/get_pyodide.py
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Naive ViUR3 project porting script with a simple search & replace mechanism using lookup table.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import os, argparse, difflib
|
|
7
|
-
|
|
8
|
-
# Naive lookup table. Could be done better later...
|
|
9
|
-
lookup = {
|
|
10
|
-
# old: new
|
|
11
|
-
"BasicApplication": "SkelModule",
|
|
12
|
-
"addItemSuccess": "addSuccess",
|
|
13
|
-
"callDeferred": "CallDeferred",
|
|
14
|
-
"editItemSuccess": "editSuccess",
|
|
15
|
-
"from server import": "from viur.core import",
|
|
16
|
-
"from server.bones import": "from viur.core.bones import",
|
|
17
|
-
"getEmtpyValueFunc": "getEmptyValueFunc",
|
|
18
|
-
"isLocalDevelopmentServer": "conf[\"viur.instance.is_dev_server\"]",
|
|
19
|
-
"onItemAdded": "onAdded",
|
|
20
|
-
"onItemDeleted": "onDeleted",
|
|
21
|
-
"onItemEdited": "onEdited",
|
|
22
|
-
"projectID": "conf[\"viur.instance.project_id\"]",
|
|
23
|
-
"utils.currentLanguage": "current.language",
|
|
24
|
-
"utils.currentRequestData": "current.request_data",
|
|
25
|
-
"utils.currentRequest": "current.request",
|
|
26
|
-
"utils.currentSession": "current.session",
|
|
27
|
-
"utils.getCurrentUser": "current.user.get",
|
|
28
|
-
"utils.isLocalDevelopmentServer": "conf[\"viur.instance.is_dev_server\"]",
|
|
29
|
-
"utils.projectID": "conf[\"viur.instance.project_id\"]",
|
|
30
|
-
"clearUpdateTag=True": "update_relations=False",
|
|
31
|
-
"seoLanguageMap": "seo_language_map", # 800
|
|
32
|
-
"forcePost": "force_post", # 800
|
|
33
|
-
"forceSSL": "force_ssl", # 800
|
|
34
|
-
"internalExposed": "internal_exposed", # 800
|
|
35
|
-
"Session.sameSite": "Session.same_site",
|
|
36
|
-
"Session.useSessionCookie": "Session.use_session_cookie",
|
|
37
|
-
"Session.cookieName": "Session.cookie_name",
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
bones = [
|
|
41
|
-
"base",
|
|
42
|
-
"boolean",
|
|
43
|
-
"captcha",
|
|
44
|
-
"color",
|
|
45
|
-
"credential",
|
|
46
|
-
"date",
|
|
47
|
-
"email",
|
|
48
|
-
"file",
|
|
49
|
-
"key",
|
|
50
|
-
"numeric",
|
|
51
|
-
"password",
|
|
52
|
-
"randomSlice",
|
|
53
|
-
"raw",
|
|
54
|
-
"record",
|
|
55
|
-
"relational",
|
|
56
|
-
"selectCountry",
|
|
57
|
-
"select",
|
|
58
|
-
"sortindex",
|
|
59
|
-
"spatial",
|
|
60
|
-
"string",
|
|
61
|
-
"text",
|
|
62
|
-
"treeLeaf",
|
|
63
|
-
"treeNode",
|
|
64
|
-
"user"
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
lookup.update({
|
|
68
|
-
f"{name}Bone": f"{name[0].upper()}{name[1:]}Bone" for name in bones
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def make_2to3(args, filename):
|
|
73
|
-
"""
|
|
74
|
-
Performs the conversion on a file with the provided options.
|
|
75
|
-
"""
|
|
76
|
-
with open(filename, "r") as f:
|
|
77
|
-
original_content = content = f.read()
|
|
78
|
-
|
|
79
|
-
count = 0
|
|
80
|
-
for k, v in lookup.items():
|
|
81
|
-
if k in content:
|
|
82
|
-
content = content.replace(k, v)
|
|
83
|
-
count += 1
|
|
84
|
-
|
|
85
|
-
if count:
|
|
86
|
-
if not args.dryrun:
|
|
87
|
-
if not args.daredevil:
|
|
88
|
-
os.rename(filename, filename + ".bak")
|
|
89
|
-
|
|
90
|
-
with open(filename, "w") as f:
|
|
91
|
-
f.write(content)
|
|
92
|
-
|
|
93
|
-
print("Modified %r" % filename)
|
|
94
|
-
else:
|
|
95
|
-
print(
|
|
96
|
-
"\n".join(
|
|
97
|
-
difflib.unified_diff(
|
|
98
|
-
original_content.splitlines(),
|
|
99
|
-
content.splitlines(),
|
|
100
|
-
filename,
|
|
101
|
-
filename
|
|
102
|
-
)
|
|
103
|
-
)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def main():
|
|
108
|
-
# Get arguments
|
|
109
|
-
ap = argparse.ArgumentParser(
|
|
110
|
-
description="ViUR3 porting tool"
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
ap.add_argument(
|
|
114
|
-
"path",
|
|
115
|
-
type=str,
|
|
116
|
-
help="Path to file or folder"
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
ap.add_argument(
|
|
120
|
-
"-d", "--dryrun",
|
|
121
|
-
action="store_true",
|
|
122
|
-
help="Dry-run for testing, don't modify files"
|
|
123
|
-
)
|
|
124
|
-
ap.add_argument(
|
|
125
|
-
"-x", "--daredevil",
|
|
126
|
-
action="store_true",
|
|
127
|
-
help="Don't make backups of files, just replace and deal with it"
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
args = ap.parse_args()
|
|
131
|
-
|
|
132
|
-
if os.path.isfile(args.path):
|
|
133
|
-
make_2to3(args, args.path)
|
|
134
|
-
else:
|
|
135
|
-
assert os.path.isdir(args.path), f"The path {args.path!r} is invalid!"
|
|
136
|
-
|
|
137
|
-
# Iterate all files in current folder
|
|
138
|
-
for root, dirs, files in os.walk(args.path):
|
|
139
|
-
# Ignore ViUR library folders
|
|
140
|
-
if any(ignore in root for ignore in ["viur", "flare", "html5"]):
|
|
141
|
-
continue
|
|
142
|
-
|
|
143
|
-
for filename in files:
|
|
144
|
-
# Ignore anything without a .py-extension
|
|
145
|
-
ext = os.path.splitext(filename)[1].lower()[1:]
|
|
146
|
-
if ext not in ["py"]:
|
|
147
|
-
continue
|
|
148
|
-
|
|
149
|
-
make_2to3(args, os.path.join(root, filename))
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if __name__ == "__main__":
|
|
153
|
-
main()
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import os
|
|
3
|
-
from .conf import config
|
|
4
|
-
from .cli import cli
|
|
5
|
-
from .utils import *
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@cli.command()
|
|
9
|
-
@click.argument("name")
|
|
10
|
-
@click.pass_context
|
|
11
|
-
def create(ctx, name):
|
|
12
|
-
"""
|
|
13
|
-
Create a new ViUR project.
|
|
14
|
-
|
|
15
|
-
The 'create' command allows you to create a new ViUR project by cloning the ViUR base project and configuring it.
|
|
16
|
-
You can specify the name of the new project as the 'name' argument.
|
|
17
|
-
|
|
18
|
-
The 'create' command performs the following steps:
|
|
19
|
-
|
|
20
|
-
1. Clones the ViUR base project from the official GitHub repository.
|
|
21
|
-
|
|
22
|
-
2. Configures the new project by running 'clean-base.py'.
|
|
23
|
-
|
|
24
|
-
3. Optionally configures the project as a new gcloud project (if confirmed).
|
|
25
|
-
|
|
26
|
-
Note:
|
|
27
|
-
|
|
28
|
-
- This command initializes the new ViUR project based on the ViUR base project.
|
|
29
|
-
|
|
30
|
-
- Make sure to provide a unique project name to avoid conflicts with existing folders.
|
|
31
|
-
|
|
32
|
-
"""
|
|
33
|
-
if os.path.exists(f'./{name}'):
|
|
34
|
-
echo_error(f'"{name}" Folder exists. Please use a different name or remove this folder ./{name}')
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
# fetch base project
|
|
38
|
-
os.system(
|
|
39
|
-
f'git clone https://github.com/viur-framework/viur-base.git {name}')
|
|
40
|
-
project_json_path = f'./{name}/project.json'
|
|
41
|
-
|
|
42
|
-
# collect project info
|
|
43
|
-
conf = config.get_profile("default")
|
|
44
|
-
appname = conf['application_name']
|
|
45
|
-
|
|
46
|
-
# run clean-base
|
|
47
|
-
os.system(f'cd ./{name} && python3 clean-base.py -A={appname}')
|
|
48
|
-
|
|
49
|
-
# run gcloud config
|
|
50
|
-
if click.confirm(f'Do you want to configure "{appname}" as a new gcloud project?'):
|
|
51
|
-
os.system(f'cd ./{name} && ./viur-gcloud-setup.sh {appname}')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|