8
votes

I have Google Cloud Service account and projectId and want to get projectNumber programmatically from Java.

enter image description here

How can I get it?

Basically I have Service Account and want to use it for granting role "roles/storage.legacyBucketWriter" for the account "[email protected]" in the Google Cloud Storage Bucket.

6

6 Answers

16
votes

Not sure why they don't expose it directly, but you can do this (assuming your current configuration project corresponds to the desired project number):

PROJECT=$(gcloud config get-value project)
gcloud projects list --filter="$PROJECT" --format="value(PROJECT_NUMBER)"
4
votes

I think GCP did not provide an API to map a project ID to a project number. But they did provide a project list API, after you get the list of the projects. You can map the project number by yourself.

2
votes

There is an API now.

The jar version of the cloudresourcemanager java library supports it directly, as in the example here https://cloud.google.com/resource-manager/reference/rest/v1/projects/get

With maven dependencies, you can do

pom.xml

<!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-cloudresourcemanager -->
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-cloudresourcemanager</artifactId>
    <version>v2-rev20200617-1.30.9</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.7</version>
</dependency>

CloudResourceManagerExample.java (adapted from the example by Google)

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.cloudresourcemanager.CloudResourceManager;
import com.google.api.services.cloudresourcemanager.model.Project;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;

import org.apache.commons.io.IOUtils
import com.google.api.client.http.GenericUrl;
import java.nio.charset.StandardCharsets;

public class CloudResourceManagerExample {
  public static void main(String args[]) throws IOException, GeneralSecurityException {
    // The Project ID (for example, `my-project-123`).
    // Required.
    String projectId = "my-project-id"; // TODO: Update placeholder value.

    CloudResourceManager cloudResourceManagerService = createCloudResourceManagerService();

    String response = IOUtils.toString(cloudResourceManagerService.getRequestFactory().buildGetRequest(new GenericUrl("https://cloudresourcemanager.googleapis.com/v1/projects/" + projectId)).execute().getContent(), StandardCharsets.UTF_8);

    // TODO: Change code below to process the `response` object:
    System.out.println(response);
  }

  public static CloudResourceManager createCloudResourceManagerService()
      throws IOException, GeneralSecurityException {
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

    GoogleCredential credential = GoogleCredential.getApplicationDefault();
    if (credential.createScopedRequired()) {
      credential =
          credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
    }

    return new CloudResourceManager.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Google-CloudResourceManagerSample/0.1")
        .build();
  }
}

response will be something like {"projectNumber": "123456", ...}

1
votes

Although this question is for Java, for those who might find it useful, here is a program to obtain a Google Project number from its ID in Go as well:

package main

import (
    "context"
    "flag"
    "fmt"
    "log"

    "google.golang.org/api/cloudresourcemanager/v1"
)

var projectID string

func main() {
    flag.StringVar(&projectID, "projectID", "", "Google Cloud Project ID")
    flag.Parse()

    cloudresourcemanagerService, err := cloudresourcemanager.NewService(context.Background())
    if err != nil {
        log.Fatalf("NewService: %v", err)
    }

    project, err := cloudresourcemanagerService.Projects.Get(projectID).Do()
    if err != nil {
        log.Fatalf("Get project: %v", err)
    }

    fmt.Printf("Project number for project %s: %d\n", projectID, project.ProjectNumber)
}

You can run it like so:

> go run main.go --projectID="my-project"
Project number for project my-project: 123456789817

(Note that this example uses Google Application Default Credentials (cf. https://godoc.org/google.golang.org/api/cloudresourcemanager/v1#hdr-Creating_a_client)).

0
votes

You can just use gcloud projects describe <<project_id>> (documentation)

$ gcloud projects describe XXX
createTime: ...
lifecycleState: ...
name: ...
parent:
  id: ...
  type: ...
projectId: XXX
projectNumber: 'YYY'
0
votes

My answer doesn't do anything in Java but should work in many environments, i.e. bash or zsh, using tools most have access to during development or within containerized environments.

Assuming you're using some type of build process, you could trivially:

  1. throw the following command into a docker container,
  2. output the result (the project number) in a build step, and
  3. store that in an environment variable for use in additional steps.

Using gcloud, grep , and awk

This assumes you have the string project name set in the PROJECT_NAME environment variable.

This is a super simple solution using the Google Cloud SDK and the commonly available CLI tools grep and awk:

gcloud projects list | grep '${PROJECT_NAME} ' | awk '{print $3}'

Note: I suspect very big accounts with many projects may not want to query the entire list each time an individual project number is required. For those cases @erkolson's answer is likely the best solution.