Skip to content

Commit

Permalink
refactor(pubsublite): internal utils for reservations (#4363)
Browse files Browse the repository at this point in the history
Adds ReservationPath and modifies LocationPath to support zones or regions.
  • Loading branch information
tmdiep committed Jul 1, 2021
1 parent ef01940 commit 2b3bb85
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 9 deletions.
2 changes: 1 addition & 1 deletion pubsublite/integration_test.go
Expand Up @@ -130,7 +130,7 @@ func TestIntegration_ResourceAdminOperations(t *testing.T) {
region, _ := wire.ZoneToRegion(zone)
resourceID := resourceIDs.New()

locationPath := wire.LocationPath{Project: proj, Zone: zone}.String()
locationPath := wire.LocationPath{Project: proj, Location: zone}.String()
topicPath := wire.TopicPath{Project: proj, Zone: zone, TopicID: resourceID}.String()
subscriptionPath := wire.SubscriptionPath{Project: proj, Zone: zone, SubscriptionID: resourceID}.String()
t.Logf("Topic path: %s", topicPath)
Expand Down
48 changes: 41 additions & 7 deletions pubsublite/internal/wire/resources.go
Expand Up @@ -49,18 +49,18 @@ func ZoneToRegion(zone string) (string, error) {
return zone[0:strings.LastIndex(zone, "-")], nil
}

// LocationPath stores a path consisting of a project and zone.
// LocationPath stores a path consisting of a project and zone/region.
type LocationPath struct {
// A Google Cloud project. The project ID (e.g. "my-project") or the project
// number (e.g. "987654321") can be provided.
Project string

// A Google Cloud zone, for example "us-central1-a".
Zone string
// A Google Cloud zone or region, for example "us-central1-a", "us-central1".
Location string
}

func (l LocationPath) String() string {
return fmt.Sprintf("projects/%s/locations/%s", l.Project, l.Zone)
return fmt.Sprintf("projects/%s/locations/%s", l.Project, l.Location)
}

var locPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)$`)
Expand All @@ -72,7 +72,7 @@ func ParseLocationPath(input string) (LocationPath, error) {
return LocationPath{}, fmt.Errorf("pubsublite: invalid location path %q. valid format is %q",
input, "projects/PROJECT_ID/locations/ZONE")
}
return LocationPath{Project: parts[1], Zone: parts[2]}, nil
return LocationPath{Project: parts[1], Location: parts[2]}, nil
}

// TopicPath stores the full path of a Pub/Sub Lite topic.
Expand All @@ -94,7 +94,7 @@ func (t TopicPath) String() string {

// Location returns the topic's location path.
func (t TopicPath) Location() LocationPath {
return LocationPath{Project: t.Project, Zone: t.Zone}
return LocationPath{Project: t.Project, Location: t.Zone}
}

var topicPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)/topics/([^/]+)$`)
Expand Down Expand Up @@ -129,7 +129,7 @@ func (s SubscriptionPath) String() string {

// Location returns the subscription's location path.
func (s SubscriptionPath) Location() LocationPath {
return LocationPath{Project: s.Project, Zone: s.Zone}
return LocationPath{Project: s.Project, Location: s.Zone}
}

var subsPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)/subscriptions/([^/]+)$`)
Expand All @@ -144,6 +144,40 @@ func ParseSubscriptionPath(input string) (SubscriptionPath, error) {
return SubscriptionPath{Project: parts[1], Zone: parts[2], SubscriptionID: parts[3]}, nil
}

// ReservationPath stores the full path of a Pub/Sub Lite reservation.
type ReservationPath struct {
// A Google Cloud project. The project ID (e.g. "my-project") or the project
// number (e.g. "987654321") can be provided.
Project string

// A Google Cloud region. An example region is "us-central1".
Region string

// The ID of the Pub/Sub Lite reservation, for example "my-reservation-name".
ReservationID string
}

func (r ReservationPath) String() string {
return fmt.Sprintf("projects/%s/locations/%s/reservations/%s", r.Project, r.Region, r.ReservationID)
}

// Location returns the reservation's location path.
func (r ReservationPath) Location() LocationPath {
return LocationPath{Project: r.Project, Location: r.Region}
}

var reservationPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)/reservations/([^/]+)$`)

// ParseReservationPath parses the full path of a Pub/Sub Lite reservation.
func ParseReservationPath(input string) (ReservationPath, error) {
parts := reservationPathRE.FindStringSubmatch(input)
if len(parts) < 4 {
return ReservationPath{}, fmt.Errorf("pubsublite: invalid reservation path %q. valid format is %q",
input, "projects/PROJECT_ID/locations/REGION/reservations/RESERVATION_ID")
}
return ReservationPath{Project: parts[1], Region: parts[2], ReservationID: parts[3]}, nil
}

type topicPartition struct {
Path string
Partition int
Expand Down
59 changes: 58 additions & 1 deletion pubsublite/internal/wire/resources_test.go
Expand Up @@ -120,7 +120,7 @@ func TestParseLocationPath(t *testing.T) {
{
desc: "valid: location path",
input: "projects/987654321/locations/europe-west1-d",
wantPath: LocationPath{Project: "987654321", Zone: "europe-west1-d"},
wantPath: LocationPath{Project: "987654321", Location: "europe-west1-d"},
},
{
desc: "invalid: zone",
Expand Down Expand Up @@ -270,3 +270,60 @@ func TestParseSubscriptionPath(t *testing.T) {
})
}
}

func TestParseReservationPath(t *testing.T) {
for _, tc := range []struct {
desc string
input string
wantPath ReservationPath
wantErr bool
}{
{
desc: "valid: reservation path",
input: "projects/987654321/locations/europe-west1/reservations/my-reservation",
wantPath: ReservationPath{Project: "987654321", Region: "europe-west1", ReservationID: "my-reservation"},
},
{
desc: "invalid: region only",
input: "europe-west1",
wantErr: true,
},
{
desc: "invalid: topic path",
input: "projects/987654321/locations/europe-west1-d/topics/my-topic",
wantErr: true,
},
{
desc: "invalid: missing project",
input: "projects//locations/europe-west1/reservations/my-reservation",
wantErr: true,
},
{
desc: "invalid: missing region",
input: "projects/987654321/locations//reservations/my-reservation",
wantErr: true,
},
{
desc: "invalid: missing reservation id",
input: "projects/987654321/locations/europe-west1/reservations/",
wantErr: true,
},
{
desc: "invalid: has prefix",
input: "prefix/projects/987654321/locations/europe-west1/reservations/my-reservation",
wantErr: true,
},
{
desc: "invalid: has suffix",
input: "projects/my-project/locations/us-west1/reservations/my-reservation/subresource/desc",
wantErr: true,
},
} {
t.Run(tc.desc, func(t *testing.T) {
gotPath, gotErr := ParseReservationPath(tc.input)
if gotPath != tc.wantPath || (gotErr != nil) != tc.wantErr {
t.Errorf("ParseReservationPath(%q) = (%v, %v), want (%v, err=%v)", tc.input, gotPath, gotErr, tc.wantPath, tc.wantErr)
}
})
}
}

0 comments on commit 2b3bb85

Please sign in to comment.