pulumi / pulumi-gcp

A Google Cloud Platform (GCP) Pulumi resource package, providing multi-language access to GCP
Apache License 2.0
182 stars 52 forks source link

How to check and enable project services APIs #675

Open chainlink opened 2 years ago

chainlink commented 2 years ago

Desired behavior Create a GCP project, enable APIs, and create kubernetes cluster in one preview/run.

As an example, this module has the option to enable APIs when creating the project https://github.com/terraform-google-modules/terraform-google-project-factory

I'm not sure how to duplicate this functionality in pulumi. I have:

// empty google project already created

const projectCompute = new gcp.projects.Service("compute-api", { 
    disableDependentServices: true,
    project: "my-proj",  //TODO Derive project name from stack
    service: "compute.googleapis.com",
});

const projectKubernetes = new gcp.projects.Service("kubernetes-api", { 
    disableDependentServices: true,
    project: "my-proj", //TODO Derive project name from stack
    service: "container.googleapis.com",
});

export const cluster = new gcp.container.Cluster("gke-cluster", {
    initialNodeCount: 1,
    removeDefaultNodePool: true,
    minMasterVersion: gcp.container.getEngineVersions().then(x=> x.latestMasterVersion),
});

const nodePool = new gcp.container.NodePool(`primary-node-pool`, {
    cluster: cluster.name,
    initialNodeCount: 1,
    location: cluster.location,
    nodeConfig: {
        preemptible: true,
        machineType: "n1-standard-1",
        oauthScopes: [
            "https://www.googleapis.com/auth/compute",
            "https://www.googleapis.com/auth/devstorage.read_only",
            "https://www.googleapis.com/auth/logging.write",
            "https://www.googleapis.com/auth/monitoring"
        ]
    },
    version: gcp.container.getEngineVersions().then(x=> x.latestMasterVersion),
    management: {
        autoRepair: true
    }
}, {
    dependsOn: [cluster]
});

Which results in:

     Type                     Name               Plan       Info
     pulumi:pulumi:Stack      first-project-dev             2 errors
 +   ├─ gcp:projects:Service  compute-api        create     
 +   └─ gcp:projects:Service  kubernetes-api     create     

Diagnostics:
  pulumi:pulumi:Stack (first-project-dev):
    error: Running program '/Users/blah/first/first-project' failed with an unhandled exception:
    Error: invocation of gcp:container/getEngineVersions:getEngineVersions returned an error: invoking gcp:container/getEngineVersions:getEngineVersions: 1 error occurred:
        * Error retrieving available container cluster versions: googleapi: Error 403: Kubernetes Engine API has not been used in project xxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/container.googleapis.com/overview?project=xxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., accessNotConfigured
leezen commented 2 years ago

@chainlink The error above reads like you don't have permission to actually call the Kubernetes Engine API with the user/service account you're running as and not an issue with the program itself. Have you confirmed that the user/account has the right permissions?

Sorry, I re-read your code. Isn't it going to be the case that:

const projectKubernetes = new gcp.projects.Service("kubernetes-api", { 
    disableDependentServices: true,
    project: "my-proj", //TODO Derive project name from stack
    service: "container.googleapis.com",
});

will apply to my-proj whereas your gcp.container.getEngineVersions().then(x=> x.latestMasterVersion) call is taking place w/in the context of potentially a different project? Or are these the same project?

chainlink commented 2 years ago

Hi @leezen thanks for the reply. Yes in this case they're the same project.

leezen commented 2 years ago

Ah, one other thought then is that there's no dependency relationship between having the project.Service resource created before the invoke happens. One thing you could try would be something like the following:

export const cluster = new gcp.container.Cluster("gke-cluster", {
    initialNodeCount: 1,
    removeDefaultNodePool: true,
    minMasterVersion: projectKubernetes.id.apply(id => gcp.container.getEngineVersions().then(x=> x.latestMasterVersion)),
});

This way, you're ensuring that the Service creation has taken place before getEngineVersions

leezen commented 2 years ago

Also relevant is #685 where it seems like the Service resource has known timing issues.