googleapis / gapic-generator

Tools for generating API client libraries from API Service Configuration descriptions.
Apache License 2.0
303 stars 129 forks source link

SampleGen: cannot set default for named resource path including `.` #2586

Closed beccasaurus closed 5 years ago

beccasaurus commented 5 years ago

Solved

In the GAPIC configuration for the specific RPC method, add the following for each object.name that you need to map to an entity_name.

field_name_patterns:
  topic.name: topic

For example:

- name: UpdateDatase
  field_name_patterns:
    dataset.name: dataset

Cannot generate a request for rpc with resource including .

e.g. v1/pubsub.proto which has path topic.name (many other APIs also use this pattern)

// Updates an existing topic. Note that certain properties of a
// topic are not modifiable.
rpc UpdateTopic(UpdateTopicRequest) returns (Topic) {
  option (google.api.http) = {
    patch: "/v1/{topic.name=projects/*/topics/*}"    # <=== topic.name
    body: "*"
  };
}

Expected this to work:

# Update Topic
#
# rpc UpdateTopic(UpdateTopicRequest) returns (Topic)
#   patch: "/v1/{topic.name=projects/*/topics/*}"
#
- name: UpdateTopic
  samples:
    standalone:
    - calling_forms: ".*"
      value_sets: [update_topic]
      region_tag: update_topic
  sample_value_sets:
  - id: update_topic
    parameters:
      defaults:
      - topic.name%project="Your Google Cloud Project ID"    # <== topic.name % {project}
      - topic.name%topic="Your Topic Name

Got this:

java.lang.IllegalArgumentException: The field name is not found in the collection map.

If you want to reproduce, try out this pubsub_gapic.yaml

The rpc call for Creating a Topic works (the resource is simply name):

rpc CreateTopic(Topic) returns (Topic) {
  option (google.api.http) = {
    put: "/v1/{name=projects/*/topics/*}"
    body: "*"
  };
}
- name: CreateTopic
  samples:
    standalone:
    - calling_forms: ".*"
      value_sets: [create_topic]
      region_tag: create_topic
  sample_value_sets:
  - id: create_topic
    parameters:
      defaults:
      - name%project="Your Google Cloud Project ID"
      - name%topic="Your Topic Name"

FYI here are the defined collections:

collections:
- name_pattern: projects/{project}
  entity_name: project
  language_overrides:
  - language: csharp
    common_resource_name: Google.Api.Gax.ResourceNames.ProjectName
- name_pattern: projects/{project}/snapshots/{snapshot}
  entity_name: snapshot
  language_overrides:
  - language: java
    entity_name: project_snapshot
- name_pattern: projects/{project}/subscriptions/{subscription}
  entity_name: subscription
  language_overrides:
  - language: java
    entity_name: project_subscription
- name_pattern: projects/{project}/topics/{topic}
  entity_name: topic
  language_overrides:
  - language: java
    entity_name: project_topic

The UpdateTopic rpc uses topic.name and the pattern projects/*/topics/* – which is defined in collections: and uses variable names {project} and {topic}. I couldn't figure out if there's something other than topic.name that I should be using? I think I'm doing it right :)

=> @hzyi-google /cc @vchudnov-g

beccasaurus commented 5 years ago

Request: Priority: P1 Type: Bug (or Type: Feature Request if this repo had the label)

beccasaurus commented 5 years ago

#misc Is there a @googleapis/[team] I can be added to which gets me rights to this repo?

I'm active and I'd like to be able to label my issues etc ~ /cc @andreamlin 🙏

beccasaurus commented 5 years ago

^--- We have a @googleapis/samplegen team which I'm a member of which could be added to this repo (as a good way to encapsulate the perms)

yihanzhen commented 5 years ago

I guess either @vchudnov-g or @lukesneeringer should have the permission.

beccasaurus commented 5 years ago

If you wanted to go that route, @vchudnov-g, this repo can be added here: https://github.com/orgs/googleapis/teams/samplegen/repositories

Also: ping again on the label update request (or update so I can edit, per above).

yihanzhen commented 5 years ago

Found a solution. Can you try adding the following lines here?

- field_name_patterns:
  - topic.name: topic

field_name_patterns tells the generator which fields (including nested fields) are resource names. I tried Java after adding this configuration and the generation succeeded. I got:

  public static void sampleUpdateTopic() {
    // [START update_topic_core]
    try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
      String formattedName =
          TopicAdminClient.formatProjectTopicName(
              "Your Google Cloud Project ID", "Your Topic Name");
      Topic topic = Topic.newBuilder().setName(formattedName).build();
      FieldMask updateMask = FieldMask.newBuilder().build();
      UpdateTopicRequest request =
          UpdateTopicRequest.newBuilder().setTopic(topic).setUpdateMask(updateMask).build();
      ApiFuture<Topic> future = topicAdminClient.updateTopicCallable().futureCall(request);

      // Do something

      Topic response = future.get();
      System.out.println(response);
    } catch (Exception exception) {
      System.err.println("Failed to create the client due to: " + exception);
    }
    // [END update_topic_core]
  }

I haven't tried running this sample or tried generating samples in other languages though, I'll try later.

The generator only needs to know which top level fields are resource names to generate clients, which is probably why the nested resource names are never specified under field_name_patterns.

It's a bit redundant. We need to think about whether we could simplify this configuration once we get there.

michaelbausor commented 5 years ago

Following up on this, @vchudnov-g @hzyi-google @beccasaurus do we have a resolution?

beccasaurus commented 5 years ago

Looks great to me! If I have any issues, I'll re-open. Thanks @hzyi-google!