def deploy(project, location, stage, skip_function, only_function, config, force): """ You can set the project and location using environment variable GOOGLE_PROJECT and GOOGLE_LOCATION Note: Allowed GOOGLE_LOCATION values for API GATEWAY are: asia-east1, europe-west1, us-eastl1 and us-central1. Note: Make sure api-gateway, cloudfunctions, and storage are enabled in your project """ try: _project = project or get_default_project() if not _project: click.echo( "Project not found. Set --project flag or add to gcloud by using gcloud config set project PROJECT" ) os.environ["GOOGLE_PROJECT"] = _project os.environ["GOOGLE_LOCATION"] = location if stage: os.environ["STAGE"] = stage if config: config = json.loads(config) app = get_goblet_app(GConfig().main_file or "main.py") Deployer({"name": app.function_name}).deploy( app, skip_function=skip_function, only_function=only_function, config=config, force=force, ) except FileNotFoundError as not_found: click.echo( f"Missing {not_found.filename}. Make sure you are in the correct directory and this file exists" )
def test_deploy_cloudrun(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") mock = Mock() monkeypatch.setattr(subprocess, "check_output", mock) app = Goblet(function_name="goblet", backend="cloudrun") setattr(app, "entrypoint", "app") app.handlers["http"] = HTTP(dummy_function) Deployer({"name": app.function_name}).deploy( app, only_function=True, force=True, config={"cloudrun": {"no-allow-unauthenticated": "", "max-instances": "2"}}, ) assert set( [ "gcloud", "run", "deploy", "--no-allow-unauthenticated", "--max-instances", "2", ] ).issubset(set(mock.call_args[0][0]))
def test_deploy_pubsub_cross_project(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "pubsub-deploy-cross-project") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") service_account = "*****@*****.**" app = Goblet(function_name="goblet-topic-cross-project") setattr(app, "entrypoint", "app") app.topic("test", project="goblet-cross-project")(dummy_function) Deployer({ "name": app.function_name }).deploy(app, force=True, config={"pubsub": { "serviceAccountEmail": service_account }}) put_subscription = get_response( "pubsub-deploy-cross-project", "put-v1-projects-goblet-subscriptions-goblet-topic-cross-project-test_1.json", ) responses = get_responses("pubsub-deploy-cross-project") assert "goblet-cross-project" in put_subscription["body"]["topic"] assert len(responses) == 5
def test_cloudfunction_delta(self, monkeypatch, requests_mock): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-east1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-cloudfunction-delta") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") requests_mock.register_uri( "HEAD", "https://storage.googleapis.com/mock", headers={"x-goog-hash": "crc32c=+kjoHA==, md5=QcWxCkEOHzBSBgerQcjMEg=="}, ) assert not Deployer(config={"name": "goblet_test_app"})._cloudfunction_delta( VersionedClients().cloudfunctions, f"{DATA_DIR_MAIN}/test_zip.txt.zip" ) assert Deployer(config={"name": "goblet_test_app"})._cloudfunction_delta( VersionedClients().cloudfunctions, f"{DATA_DIR_MAIN}/fail_test_zip.txt.zip" )
def package(stage): """generates the goblet zipped package in .goblet folder""" try: if stage: os.environ["STAGE"] = stage app = get_goblet_app(GConfig().main_file or "main.py") Deployer({"name": app.function_name}).package() except FileNotFoundError as not_found: click.echo( f"Missing {not_found.filename}. Make sure you are in the correct directory and this file exists" )
def test_destroy_http_function_all(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-function-destroy-all") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_example") Deployer(config={"name": "goblet_example"}).destroy(app, all=True) responses = get_responses("deployer-function-destroy-all") assert len(responses) == 4
def test_destroy_cloudrun(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-cloudrun-destroy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet", backend="cloudrun") Deployer({"name": app.function_name}).destroy(app) responses = get_responses("deployer-cloudrun-destroy") assert len(responses) == 1 assert responses[0]["body"]["status"] == "Success" assert responses[0]["body"]["details"]["name"] == "goblet"
def test_deploy_http_function(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-function-deploy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_example") setattr(app, "entrypoint", "app") app.handlers["http"] = HTTP(dummy_function) Deployer().deploy(app, only_function=True, force=True) responses = get_responses("deployer-function-deploy") assert len(responses) == 3
def test_destroy_http_function(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-function-destroy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_example") Deployer(config={"name": "goblet_test_app"}).destroy(app) responses = get_responses("deployer-function-destroy") assert len(responses) == 1 assert responses[0]["body"]["metadata"]["type"] == "DELETE_FUNCTION" assert ( responses[0]["body"]["metadata"]["target"] == "projects/goblet/locations/us-central1/functions/goblet_test_app" )
def test_set_iam_bindings(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "deployer-function-bindings") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_bindings") setattr(app, "entrypoint", "app") app.handlers["http"] = HTTP(dummy_function) bindings = [{"role": "roles/cloudfunctions.invoker", "members": ["allUsers"]}] Deployer(config={"name": "goblet_test_app"}).deploy( app, only_function=True, config={"bindings": bindings}, force=True ) responses = get_responses("deployer-function-bindings") assert len(responses) == 4 assert responses[2]["body"]["bindings"] == bindings
def test_deploy_storage(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "storage-deploy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_storage") setattr(app, "entrypoint", "app") app.storage("test", "finalize")(dummy_function) Deployer().deploy(app, force=True) responses = get_responses("storage-deploy") assert len(responses) == 3 assert responses[2]["body"]["metadata"]["target"].endswith( "goblet_storage-storage-test-finalize") assert (responses[2]["body"]["metadata"]["request"]["eventTrigger"] ["resource"] == "projects/goblet/buckets/test") assert (responses[2]["body"]["metadata"]["request"]["eventTrigger"] ["eventType"] == "google.storage.object.finalize")
def test_deploy_routes(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "routes-deploy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_routes") setattr(app, "entrypoint", "app") app.route("/")(dummy_function) Deployer().deploy(app, force=True) post_api = get_response( "routes-deploy", "post-v1-projects-goblet-locations-global-apis_1.json") post_config = get_response( "routes-deploy", "post-v1-projects-goblet-locations-global-apis-goblet-routes-configs_1.json", ) post_gw = get_response( "routes-deploy", "post-v1-projects-goblet-locations-us-central1-gateways_1.json", ) get_gw = get_response( "routes-deploy", "get-v1-projects-goblet-locations-us-central1-gateways-goblet-routes_1.json", ) assert post_api["body"]["metadata"]["verb"] == "create" assert post_api["body"]["metadata"]["target"].endswith("goblet-routes") assert post_config["body"]["metadata"]["verb"] == "create" assert post_config["body"]["metadata"]["target"].endswith( "goblet-routes") assert post_gw["body"]["metadata"]["verb"] == "create" assert post_gw["body"]["metadata"]["target"].endswith("goblet-routes") assert get_gw["body"]["state"] == "ACTIVE" assert get_gw["body"]["displayName"] == "goblet-routes"
def destroy(project, location, stage, all): """ Deletes all resources in gcp that are defined the current deployment The --all flag removes cloudfunction artifacts in cloud storage as well """ try: _project = project or get_default_project() if not _project: click.echo( "Project not found. Set --project flag or add to gcloud by using gcloud config set project PROJECT" ) os.environ["GOOGLE_PROJECT"] = _project os.environ["GOOGLE_LOCATION"] = location if stage: os.environ["STAGE"] = stage app = get_goblet_app(GConfig().main_file or "main.py") Deployer({"name": app.function_name}).destroy(app, all) except FileNotFoundError as not_found: click.echo( f"Missing {not_found.filename}. Make sure you are in the correct directory and this file exists" )
def test_deploy_pubsub(self, monkeypatch): monkeypatch.setenv("GOOGLE_PROJECT", "goblet") monkeypatch.setenv("GOOGLE_LOCATION", "us-central1") monkeypatch.setenv("GOBLET_TEST_NAME", "pubsub-deploy") monkeypatch.setenv("GOBLET_HTTP_TEST", "REPLAY") app = Goblet(function_name="goblet_topic") setattr(app, "entrypoint", "app") app.topic("test-topic")(dummy_function) Deployer().deploy(app, force=True) responses = get_responses("pubsub-deploy") assert len(responses) == 3 assert responses[2]["body"]["metadata"]["target"].endswith( "goblet_topic-topic-test-topic") assert (responses[2]["body"]["metadata"]["request"]["eventTrigger"] ["resource"] == "projects/goblet/topics/test-topic") assert ( responses[2]["body"]["metadata"]["request"]["eventTrigger"] ["eventType"] == "providers/cloud.pubsub/eventTypes/topic.publish")
def sync(project, location, stage, dryrun): """ Syncs resources that are deployed with current app configuration. This command will delete resources based on naming convention that are no longer in the app configuration. Use --dryrun flag to see what resources are flagged as being deleted. """ try: _project = project or get_default_project() if not _project: click.echo( "Project not found. Set --project flag or add to gcloud by using gcloud config set project PROJECT" ) os.environ["GOOGLE_PROJECT"] = _project os.environ["GOOGLE_LOCATION"] = location if stage: os.environ["STAGE"] = stage app = get_goblet_app(GConfig().main_file or "main.py") Deployer({"name": app.function_name}).sync(app, dryrun) except FileNotFoundError as not_found: click.echo( f"Missing {not_found.filename}. Make sure you are in the correct directory and this file exists" )