Skip to content

Commit

Permalink
implement UPDATE /target
Browse files Browse the repository at this point in the history
  • Loading branch information
whywaita committed Jul 21, 2021
1 parent e0bd31f commit c92d4bd
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pkg/web/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func NewMux(ds datastore.Datastore) *goji.Mux {
apacheLogging(r)
handleTargetRead(w, r, ds)
})
mux.HandleFunc(pat.Put("/target/:id"), func(w http.ResponseWriter, r *http.Request) {
mux.HandleFunc(pat.Post("/target/:id"), func(w http.ResponseWriter, r *http.Request) {
apacheLogging(r)
handleTargetUpdate(w, r, ds)
})
Expand Down
73 changes: 72 additions & 1 deletion pkg/web/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"strings"
"time"

"github.com/google/go-cmp/cmp"

"github.com/whywaita/myshoes/pkg/datastore"
"github.com/whywaita/myshoes/pkg/gh"
"github.com/whywaita/myshoes/pkg/logger"
Expand Down Expand Up @@ -193,7 +195,51 @@ func sanitizeTarget(t *datastore.Target) UserTarget {
}

func handleTargetUpdate(w http.ResponseWriter, r *http.Request, ds datastore.Datastore) {
outputErrorMsg(w, http.StatusMethodNotAllowed, "not implement")
ctx := r.Context()
targetID, err := parseReqTargetID(r)
if err != nil {
logger.Logf(false, "failed to decode request body: %+v", err)
outputErrorMsg(w, http.StatusBadRequest, "incorrect target id")
return
}

inputTarget := TargetCreateParam{}
if err := json.NewDecoder(r.Body).Decode(&inputTarget); err != nil {
logger.Logf(false, "failed to decode request body: %+v", err)
outputErrorMsg(w, http.StatusBadRequest, "json decode error")
return
}
newTarget := inputTarget.ToDS("", time.Time{})

oldTarget, err := ds.GetTarget(ctx, targetID)
if err != nil {
logger.Logf(false, "failed to get target: %+v", err)
outputErrorMsg(w, http.StatusBadRequest, "incorrect target id (not found)")
return
}
if err := validateUpdateTarget(oldTarget, &newTarget); err != nil {
logger.Logf(false, "input error in validateUpdateTarget: %+v", err)
outputErrorMsg(w, http.StatusBadRequest, "request parameter has value of not updatable")
return
}

if err := ds.UpdateResourceType(ctx, targetID, inputTarget.ResourceType); err != nil {
logger.Logf(false, "failed to ds.UpdateResourceType: %+v", err)
outputErrorMsg(w, http.StatusInternalServerError, "datastore update error")
return
}

updatedTarget, err := ds.GetTarget(ctx, targetID)
if err != nil {
logger.Logf(false, "failed to get recently target in datastore: %+v", err)
outputErrorMsg(w, http.StatusInternalServerError, "datastore get error")
return
}
ut := sanitizeTarget(updatedTarget)

w.Header().Set("Content-Type", "application/json;charset=utf-8")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ut)
return
}

Expand Down Expand Up @@ -252,3 +298,28 @@ func outputErrorMsg(w http.ResponseWriter, status int, msg string) {
Error string `json:"error"`
}{Error: msg})
}

// validateUpdateTarget check input target that can valid input in update.
func validateUpdateTarget(old, new *datastore.Target) error {
for _, t := range []*datastore.Target{old, new} {
t.UUID = uuid.UUID{}

// can update variables
t.ResourceType = datastore.ResourceTypeUnknown

// time
t.TokenExpiredAt = time.Time{}
t.CreatedAt = time.Time{}
t.UpdatedAt = time.Time{}

// generated
t.Status = ""
t.GitHubToken = ""
}

if diff := cmp.Diff(old, new); diff != "" {
return fmt.Errorf("mismatch (-want +got):\n%s", diff)
}

return nil
}
65 changes: 65 additions & 0 deletions pkg/web/target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,71 @@ func Test_handleTargetRead(t *testing.T) {
}
}

func Test_handleTargetUpdate(t *testing.T) {
testURL := testutils.GetTestURL()
_, teardown := testutils.GetTestDatastore()
defer teardown()

setStubFunctions()

target := `{"scope": "repo", "resource_type": "micro", "runner_user": "ubuntu"}`

resp, err := http.Post(testURL+"/target", "application/json", bytes.NewBufferString(target))
if err != nil {
t.Fatalf("failed to POST request: %+v", err)
}
content, statusCode := parseResponse(resp)
if statusCode != http.StatusCreated {
t.Fatalf("must be response statuscode is 201, but got %d: %+v", resp.StatusCode, string(content))
}
var respTarget web.UserTarget
if err := json.Unmarshal(content, &respTarget); err != nil {
t.Fatalf("failed to unmarshal response JSON: %+v", err)
}
targetUUID := respTarget.UUID

tests := []struct {
input string
want *web.UserTarget
err bool
}{
{
input: `{"scope": "repo", "resource_type": "nano", "runner_user": "ubuntu"}`,
want: &web.UserTarget{
UUID: targetUUID,
Scope: "repo",
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano.String(),
RunnerUser: "ubuntu",
Status: datastore.TargetStatusActive,
},
},
}

for _, test := range tests {
resp, err := http.Post(fmt.Sprintf("%s/target/%s", testURL, targetUUID.String()), "application/json", bytes.NewBufferString(test.input))
if !test.err && err != nil {
t.Fatalf("failed to POST request: %+v", err)
}
content, code := parseResponse(resp)
if code != http.StatusOK {
t.Fatalf("must be response statuscode is 201, but got %d: %+v", code, string(content))
}

var got web.UserTarget
if err := json.Unmarshal(content, &got); err != nil {
t.Fatalf("failed to unmarshal resoponse content: %+v", err)
}

got.CreatedAt = time.Time{}
got.UpdatedAt = time.Time{}

if diff := cmp.Diff(test.want, &got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
}
}

func Test_handleTargetDelete(t *testing.T) {
testURL := testutils.GetTestURL()
testDatastore, teardown := testutils.GetTestDatastore()
Expand Down

0 comments on commit c92d4bd

Please sign in to comment.