Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud Build requires bucket object to have "zip" extension #729

Open
imajus opened this issue Jan 18, 2022 · 4 comments
Open

Cloud Build requires bucket object to have "zip" extension #729

imajus opened this issue Jan 18, 2022 · 4 comments
Assignees
Labels
area/docs Improvements or additions to documentation awaiting-feedback Blocked on input from the author kind/bug Some behavior is incorrect or out of spec

Comments

@imajus
Copy link

imajus commented Jan 18, 2022

File: themes/default/content/registry/packages/gcp/api-docs/appengine/standardappversion/_index.md

I've been facing a problem building a ZIP archive with Cloud Build for deploying gcp.appengine.StandardAppVersion. The closed issue in the Terraform GitHub explains the problem I've experienced and provides the solution.

Current code example in Pulumi bears the issue. In order to fix it, the small adjustment must be applied to the code sample:

const object = new gcp.storage.BucketObject("object", {
    name: 'hello-world.zip', // <= this needs to be added
    bucket: bucket.name,
    source: new pulumi.asset.FileAsset("./test-fixtures/appengine/hello-world.zip"),
});

Here's an excerpt of the the Cloud Build failing build log:

FETCHSOURCE
Fetching storage object: gs://deployment-6fa93b5/bundle-92d69e6#1642482542234736
Copying gs://deployment-6fa93b5/bundle-92d69e6#1642482542234736...
/ [0 files][    0.0 B/100.5 MiB]                                                
/ [0 files][264.0 KiB/100.5 MiB]                                                
-
\
\ [0 files][ 17.5 MiB/100.5 MiB]                                                
|
| [0 files][ 80.2 MiB/100.5 MiB]                                                
/
/ [1 files][100.5 MiB/100.5 MiB]                                                
-
Operation completed over 1 objects/100.5 MiB.                                    
gzip: stdin has more than one entry--rest ignored
tar: Child returned status 2
tar: Error is not recoverable: exiting now
...
@ghost ghost assigned cnunciato Jan 19, 2022
@danielrbradley danielrbradley transferred this issue from pulumi/registry Jan 25, 2022
@danielrbradley danielrbradley added area/docs Improvements or additions to documentation kind/bug Some behavior is incorrect or out of spec labels Jan 25, 2022
@xSAVIKx
Copy link

xSAVIKx commented Jan 26, 2022

An additional problem happens when you use AssetArchive. If you hard-code the name prop, it won't be able to deduct if anything has changed in the archive files. This leads to no deployment updates after the initial deployment.

Ideally, it should be possible to augment the way Pulumi deducts the name from the resource_name.

@realworld666
Copy link

I can backup both of these points from my experience

@besserwisser
Copy link

Jesus, thank you. I spent hours on this :)

@rshade
Copy link
Contributor

rshade commented Dec 24, 2024

It looks like we addressed the zip part in the documentation. However is the second part of the FileAsset still a problem? I wrote a small test app, would yall try this and let me know if it works so that I can update the documentation:

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as fs from "fs";
import * as crypto from "crypto";

const customServiceAccount = new gcp.serviceaccount.Account("custom_service_account", {
    accountId: "my-account",
    displayName: "Custom Service Account",
});
const gaeApi = new gcp.projects.IAMMember("gae_api", {
    project: customServiceAccount.project,
    role: "roles/compute.networkUser",
    member: pulumi.interpolate`serviceAccount:${customServiceAccount.email}`,
});
const storageViewer = new gcp.projects.IAMMember("storage_viewer", {
    project: customServiceAccount.project,
    role: "roles/storage.objectViewer",
    member: pulumi.interpolate`serviceAccount:${customServiceAccount.email}`,
});
const bucket = new gcp.storage.Bucket("appengine-static-content", {
    location: "US",
});

// Read the file content
const filePath = "./test-fixtures/hello-world.zip";
const fileContent = fs.readFileSync(filePath, "utf-8");
// Generate SHA-256 hash of the file content
const hash = crypto.createHash('sha256').update(fileContent).digest('hex');

const object = new gcp.storage.BucketObject("object", {
    name: "hello-world.zip",
    bucket: bucket.name,
    source: new pulumi.asset.FileAsset(filePath),
    metadata: {
        "content-hash": hash
    }
});

const myappDefault = new gcp.appengine.StandardAppVersion("myapp_default", {
    versionId: `v${hash.substring(0, 25)}`,
    service: "default",
    runtime: "nodejs20",
    entrypoint: {
        shell: "node ./app.js",
    },
    deployment: {
        zip: {
            sourceUrl: pulumi.interpolate`https://storage.googleapis.com/${bucket.name}/${object.name}`,
        },
    },
    envVariables: {
        port: "8080",
    },
    automaticScaling: {
        maxConcurrentRequests: 10,
        minIdleInstances: 1,
        maxIdleInstances: 3,
        minPendingLatency: "1s",
        maxPendingLatency: "5s",
        standardSchedulerSettings: {
            targetCpuUtilization: 0.5,
            targetThroughputUtilization: 0.75,
            minInstances: 2,
            maxInstances: 10,
        },
    },
    deleteServiceOnDestroy: true,
    serviceAccount: customServiceAccount.email,
});

const myappV1 = new gcp.appengine.StandardAppVersion("myapp_v1", {
    versionId: `v${hash.substring(0, 25)}`,
    service: "myapp",
    runtime: "nodejs20",
    entrypoint: {
        shell: "node ./app.js",
    },
    deployment: {
        zip: {
            sourceUrl: pulumi.interpolate`https://storage.googleapis.com/${bucket.name}/${object.name}`,
        },
    },
    envVariables: {
        port: "8080",
    },
    automaticScaling: {
        maxConcurrentRequests: 10,
        minIdleInstances: 1,
        maxIdleInstances: 3,
        minPendingLatency: "1s",
        maxPendingLatency: "5s",
        standardSchedulerSettings: {
            targetCpuUtilization: 0.5,
            targetThroughputUtilization: 0.75,
            minInstances: 2,
            maxInstances: 10,
        },
    },
    deleteServiceOnDestroy: true,
    serviceAccount: customServiceAccount.email,
}, { dependsOn: [myappDefault] });

@rshade rshade self-assigned this Dec 24, 2024
@rshade rshade added the awaiting-feedback Blocked on input from the author label Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/docs Improvements or additions to documentation awaiting-feedback Blocked on input from the author kind/bug Some behavior is incorrect or out of spec
Projects
None yet
Development

No branches or pull requests

7 participants