Skip to content

Commit e4b857e

Browse files
[OBS-137] Handle 409 response of create service to again check for service (#232)
* Create a new model to parse error response * Handle the 409 conflict case. Check for error message and call get services again * Try only one time after that bail out with error * Other small fixes: Add to cache after create service flow, small model change
1 parent 6932d4c commit e4b857e

File tree

4 files changed

+68
-26
lines changed

4 files changed

+68
-26
lines changed

apidump/apidump.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func (a *apidump) LookupService() error {
177177
frontClient := rest.NewFrontClient(a.Domain, a.ClientID)
178178

179179
if a.PostmanCollectionID != "" {
180-
backendSvc, err := util.GetServiceIDByPostmanCollectionID(frontClient, a.PostmanCollectionID)
180+
backendSvc, err := util.GetOrCreateServiceIDByPostmanCollectionID(frontClient, a.PostmanCollectionID)
181181
if err != nil {
182182
return err
183183
}

cmd/internal/kube/inject.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ func lookupService(postmanCollectionID, serviceName string) error {
325325
frontClient := rest.NewFrontClient(rest.Domain, telemetry.GetClientID())
326326

327327
if postmanCollectionID != "" {
328-
_, err := util.GetServiceIDByPostmanCollectionID(frontClient, postmanCollectionID)
328+
_, err := util.GetOrCreateServiceIDByPostmanCollectionID(frontClient, postmanCollectionID)
329329
if err != nil {
330330
return err
331331
}

rest/models.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ type Service struct {
2020
type User = api_schema.UserResponse
2121

2222
type CreateServiceResponse struct {
23-
RequestID string `json:"request_id"`
23+
RequestID akid.RequestID `json:"request_id"`
2424
ResourceID akid.ServiceID `json:"resource_id"`
2525
}
26+
27+
type CreateServiceErrorResponse struct {
28+
RequestID akid.RequestID `json:"request_id"`
29+
Message string `json:"message"`
30+
ResourceID string `json:"resource_id"`
31+
}

util/util.go

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package util
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"net/http"
78
"strings"
@@ -93,24 +94,10 @@ func GetServiceIDByName(c rest.FrontClient, name string) (akid.ServiceID, error)
9394
return akid.ServiceID{}, errors.Errorf("cannot determine project ID for %s", name)
9495
}
9596

96-
func GetServiceIDByPostmanCollectionID(c rest.FrontClient, collectionID string) (akid.ServiceID, error) {
97-
// Normalize the collectionID.
98-
collectionID = strings.ToLower(collectionID)
99-
unexpectedErrMsg := "Something went wrong while starting the Agent. " +
100-
"Please contact Postman support (observability-support@postman.com) with the error details"
101-
102-
if id, found := postmanCollectionIDCache.Get(collectionID); found {
103-
printer.Stderr.Debugf("Cached collectionID %q is %q\n", collectionID, akid.String(id.(akid.ServiceID)))
104-
return id.(akid.ServiceID), nil
105-
}
106-
107-
// Fill cache.
108-
ctx, cancel := context.WithTimeout(context.Background(), apiTimeout)
109-
defer cancel()
97+
func GetServiceIDByPostmanCollectionID(c rest.FrontClient, ctx context.Context, collectionID string) (akid.ServiceID, error) {
11098
services, err := c.GetServices(ctx)
11199
if err != nil {
112-
printer.Stderr.Debugf("Failed to get list of services associated with the API Key: %s\n", err)
113-
return akid.ServiceID{}, errors.Wrap(err, unexpectedErrMsg)
100+
return akid.ServiceID{}, err
114101
}
115102

116103
var result akid.ServiceID
@@ -128,24 +115,72 @@ func GetServiceIDByPostmanCollectionID(c rest.FrontClient, collectionID string)
128115

129116
if strings.EqualFold(collectionID, svcCollectionID) {
130117
result = svc.ID
131-
postmanCollectionIDCache.Set(svcCollectionID, svc.ID, cache.DefaultExpiration)
132118
}
133119
}
134120

135-
if (result != akid.ServiceID{}) {
136-
printer.Stderr.Debugf("Postman collectionID %q is %q\n", collectionID, result)
137-
return result, nil
121+
return result, nil
122+
}
123+
124+
func GetOrCreateServiceIDByPostmanCollectionID(c rest.FrontClient, collectionID string) (akid.ServiceID, error) {
125+
// Normalize the collectionID.
126+
collectionID = strings.ToLower(collectionID)
127+
unexpectedErrMsg := "Something went wrong while starting the Agent. " +
128+
"Please contact Postman support (observability-support@postman.com) with the error details"
129+
failedToCreateServiceErrMsg := "Failed to create service for given collectionID: %s\n"
130+
131+
if id, found := postmanCollectionIDCache.Get(collectionID); found {
132+
printer.Stderr.Debugf("Cached collectionID %q is %q\n", collectionID, akid.String(id.(akid.ServiceID)))
133+
return id.(akid.ServiceID), nil
134+
}
135+
136+
// Fetch service and fill cache
137+
ctx, cancel := context.WithTimeout(context.Background(), apiTimeout)
138+
defer cancel()
139+
140+
serviceID, err := GetServiceIDByPostmanCollectionID(c, ctx, collectionID)
141+
if err != nil {
142+
printer.Stderr.Debugf("Failed to get list of services associated with the API Key: %s\n", err)
143+
return akid.ServiceID{}, errors.Wrap(err, unexpectedErrMsg)
144+
}
145+
146+
if (serviceID != akid.ServiceID{}) {
147+
printer.Stderr.Debugf("ServiceID for Postman collectionID %q is %q\n", collectionID, serviceID)
148+
postmanCollectionIDCache.Set(collectionID, serviceID, cache.DefaultExpiration)
149+
return serviceID, nil
138150
}
139151

140152
name := postmanRandomName()
141153
printer.Debugf("Found no service for given collectionID: %s, creating a new service %q\n", collectionID, name)
142154
// Create service for given postman collectionID
143155
resp, err := c.CreateService(ctx, name, collectionID)
144156
if err != nil {
145-
printer.Stderr.Debugf("Failed to create service for given collectionID: %s\n", err)
157+
httpErr, ok := err.(rest.HTTPError)
158+
if !ok {
159+
printer.Stderr.Debugf(failedToCreateServiceErrMsg, err)
160+
return akid.ServiceID{}, errors.Wrap(err, unexpectedErrMsg)
161+
}
162+
163+
var errorResponse rest.CreateServiceErrorResponse
164+
if err := json.Unmarshal(httpErr.Body, &errorResponse); err != nil {
165+
printer.Stderr.Debugf(failedToCreateServiceErrMsg, err)
166+
return akid.ServiceID{}, errors.Wrap(err, unexpectedErrMsg)
167+
}
146168

147-
if httpErr, ok := err.(rest.HTTPError); ok && httpErr.StatusCode == 403 {
148-
error := fmt.Errorf("You cannot send traffic to the collection with ID %s. "+
169+
if httpErr.StatusCode == 409 && errorResponse.Message == "collection_already_mapped" {
170+
serviceID, err := GetServiceIDByPostmanCollectionID(c, ctx, collectionID)
171+
if err != nil {
172+
printer.Stderr.Debugf(failedToCreateServiceErrMsg, err)
173+
return akid.ServiceID{}, errors.Wrap(err, unexpectedErrMsg)
174+
}
175+
176+
if (serviceID != akid.ServiceID{}) {
177+
printer.Stderr.Debugf("ServiceID for Postman collectionID %q is %q\n", collectionID, serviceID)
178+
postmanCollectionIDCache.Set(collectionID, serviceID, cache.DefaultExpiration)
179+
return serviceID, nil
180+
}
181+
182+
} else if httpErr.StatusCode == 403 {
183+
error := fmt.Errorf("you cannot send traffic to the collection with ID %s. "+
149184
"Ensure that your collection ID is correct and that you have edit permissions on the collection. "+
150185
"If you do not have edit permissions, please contact the workspace administrator to add you as a collection editor.", collectionID)
151186
return akid.ServiceID{}, error
@@ -155,6 +190,7 @@ func GetServiceIDByPostmanCollectionID(c rest.FrontClient, collectionID string)
155190
}
156191

157192
printer.Debugf("Got service ID %s\n", resp.ResourceID)
193+
postmanCollectionIDCache.Set(collectionID, resp.ResourceID, cache.DefaultExpiration)
158194

159195
return resp.ResourceID, nil
160196
}

0 commit comments

Comments
 (0)