예제 #1
0
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"
        )
예제 #2
0
    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]))
예제 #3
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
예제 #4
0
    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"
        )
예제 #5
0
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"
        )
예제 #6
0
    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
예제 #7
0
    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"
예제 #8
0
    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
예제 #9
0
    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"
        )
예제 #10
0
    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
예제 #11
0
    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")
예제 #12
0
    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"
예제 #13
0
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"
        )
예제 #14
0
    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")
예제 #15
0
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"
        )