From 1812ce7324a6b4991eeb4e7b394f7aa17da347a0 Mon Sep 17 00:00:00 2001 From: Chuck D'Antonio Date: Mon, 10 Feb 2025 16:38:58 -0500 Subject: [PATCH 1/4] Makes some progress toward replacing ID endpoint --- setup/cmd/kots-field-labs/main.go | 2 +- setup/cmd/kots-field-labs/param.go | 8 +-- setup/pkg/fieldlabs/environment_create.go | 9 +++ setup/pkg/fieldlabs/members.go | 71 +++++++++++++++-------- setup/pkg/fieldlabs/policy.go | 26 +++++---- 5 files changed, 77 insertions(+), 39 deletions(-) diff --git a/setup/cmd/kots-field-labs/main.go b/setup/cmd/kots-field-labs/main.go index d30beb8ac..6157d6a1c 100644 --- a/setup/cmd/kots-field-labs/main.go +++ b/setup/cmd/kots-field-labs/main.go @@ -40,7 +40,7 @@ func HandleRequest(event fieldlabs.LambdaEvent) error { APIOrigin: "https://api.replicated.com/vendor", GraphQLOrigin: "https://g.replicated.com/graphql", KURLSHOrigin: "https://kurl.sh", - IDOrigin: "https://api.replicated.com/vendor", + IDOrigin: "https://api.replicated.com", } action, ok := actions[event.Action] diff --git a/setup/cmd/kots-field-labs/param.go b/setup/cmd/kots-field-labs/param.go index 63ddb1098..6e68a6012 100644 --- a/setup/cmd/kots-field-labs/param.go +++ b/setup/cmd/kots-field-labs/param.go @@ -60,7 +60,7 @@ func GetParams() (*fieldlabs.Params, error) { params.KURLSHOrigin = "https://kurl.sh" } if params.IDOrigin == "" { - params.IDOrigin = "https://api.replicated.com/vendor" + params.IDOrigin = "https://api.replicated.com" } actionString := os.Getenv("REPLICATED_ACTION") @@ -119,7 +119,7 @@ func getLoginResponse(params *fieldlabs.Params) (*string, error) { return nil, errors.Wrap(err, "marshal login params") } - loginReq, err := http.NewRequest("POST", fmt.Sprintf("%s/v1/login", params.IDOrigin), bytes.NewBuffer(loginBody)) + loginReq, err := http.NewRequest("POST", fmt.Sprintf("%s/vendor/v1/login", params.IDOrigin), bytes.NewBuffer(loginBody)) if err != nil { return nil, errors.Wrap(err, "build login request") } @@ -131,9 +131,9 @@ func getLoginResponse(params *fieldlabs.Params) (*string, error) { } defer loginResp.Body.Close() - if loginResp.StatusCode != 201 { + if loginResp.StatusCode != 201 && loginResp.StatusCode != 200 { body, _ := ioutil.ReadAll(loginResp.Body) - return nil, fmt.Errorf("GET /policies %d: %s", loginResp.StatusCode, body) + return nil, fmt.Errorf("Parsing login response `/vendor/v1/login` %d: %s", loginResp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(loginResp.Body) if err != nil { diff --git a/setup/pkg/fieldlabs/environment_create.go b/setup/pkg/fieldlabs/environment_create.go index 0b6066050..3c540bcba 100644 --- a/setup/pkg/fieldlabs/environment_create.go +++ b/setup/pkg/fieldlabs/environment_create.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "strings" "time" + "encoding/json" "github.com/pkg/errors" "github.com/replicatedhq/replicated/pkg/kotsclient" @@ -103,6 +104,9 @@ func (e *EnvironmentManager) Ensure(track *TrackSpec) error { if err != nil { return errors.Wrap(err, "add member") } + memberJson, _ := json.Marshal(members) + policyJson, _ := json.Marshal(policies) + e.Log.ActionWithSpinner("Added member: %s %s", memberJson, policyJson) err = e.createVendorTrack(*app, *track) if err != nil { @@ -120,13 +124,16 @@ func (e *EnvironmentManager) createVendorTrack(app types.App, trackSpec TrackSpe e.Log.ActionWithSpinner("Provision track %s", appTrackSlug) // get the stable channel to assign for customer + e.Log.ActionWithSpinner("Get stable channel") channel, err := e.getChannel(track) if err != nil { return errors.Wrapf(err, "get Stable channel") } track.Status.Channel = channel + e.Log.ActionWithSpinner("Got channel: %s", channel) // Create customer + e.Log.ActionWithSpinner("Create customer") if trackSpec.Customer != "" { customer, err := e.getOrCreateCustomer(track) if err != nil { @@ -162,6 +169,7 @@ func (e *EnvironmentManager) createVendorTrack(app types.App, trackSpec TrackSpe track.Status.Release = release + e.Log.ActionWithSpinner("Promote release") err = e.Client.PromoteRelease(app.ID, release.Sequence, "0.1.0", trackSpec.Slug, false, channel.ID) if err != nil { return errors.Wrapf(err, "promote release %d to channel %q", release.Sequence, channel.Slug) @@ -198,6 +206,7 @@ func (e *EnvironmentManager) createVendorTrack(app types.App, trackSpec TrackSpe } } } + e.Log.ActionWithSpinner("Provisioned") return nil } diff --git a/setup/pkg/fieldlabs/members.go b/setup/pkg/fieldlabs/members.go index bb02bd528..8527cfcd8 100644 --- a/setup/pkg/fieldlabs/members.go +++ b/setup/pkg/fieldlabs/members.go @@ -60,8 +60,14 @@ func (e *EnvironmentManager) getMembersMap() (map[string]MemberList, error) { return nil, errors.Wrap(err, "get members") } + membersJson, _ := json.Marshal(members) + fmt.Sprintf("members: %s", membersJson) + membersMap := make(map[string]MemberList) for i := 0; i < len(members); i += 1 { + memberJson, _ := json.Marshal(members) + fmt.Sprintf("member: %s", memberJson) + fmt.Sprintf("member: %s", members[i].Email) membersMap[members[i].Email] = members[i] } return membersMap, nil @@ -69,7 +75,7 @@ func (e *EnvironmentManager) getMembersMap() (map[string]MemberList, error) { // Delete team members created with multi-player mode func (e *EnvironmentManager) DeleteMember(id string) error { - url := fmt.Sprintf("%s/v1/team/member?user_id=%s", e.Params.IDOrigin, id) + url := fmt.Sprintf("%s/v1/team/member/%s", e.Params.IDOrigin, id) req, err := http.NewRequest( "DELETE", url, @@ -77,7 +83,7 @@ func (e *EnvironmentManager) DeleteMember(id string) error { ) if err != nil { - return err + return errors.Wrap(err, fmt.Sprintf("DELETE %s/v1/team/member?user_id=%s", e.Params.IDOrigin, id)) } req.Header.Set("Authorization", e.Params.SessionToken) req.Header.Set("Accept", "application/json") @@ -92,38 +98,48 @@ func (e *EnvironmentManager) DeleteMember(id string) error { panic(err.Error()) } if resp.StatusCode != 204 { - return fmt.Errorf("GET /v1/team/member %d: %s", resp.StatusCode, body) + return fmt.Errorf("DELETE /v1/team/member/%s %d: %s", id, resp.StatusCode, body) } return nil } func (e *EnvironmentManager) addMember(members map[string]MemberList, policies map[string]string) error { inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" + + e.Log.Verbose() + e.Log.Debug("Inviting %s", inviteEmail) err := e.inviteMember(inviteEmail, members, policies) if err != nil { return err } // Signup + e.Log.Debug("Signing up %s", inviteEmail) sr, err := e.signupMember(inviteEmail) if err != nil { return err } + inviteId := sr.Token // Verify + signupResponseJson, _ := json.Marshal(sr) + e.Log.Debug("Verfiying %s", signupResponseJson) vr, err := e.verifyMember(sr) if err != nil { return err } // Capture Invite Id - invite, err := e.captureInvite(vr) + verifyResponseJson, _ := json.Marshal(vr) + e.Log.Debug("Capturing %s with %s", inviteId, verifyResponseJson) + invite, err := e.captureInvite(inviteId, vr) if err != nil { return err } // Accept Invite - err = e.acceptInvite(invite, e.Params.ParticipantId, vr) + e.Log.Debug("Accepting invite %s for participant %s", inviteId, e.Params.ParticipantId) + err = e.acceptInvite(invite.Invite.Id, e.Params.ParticipantId, vr) if err != nil { return err } @@ -140,17 +156,18 @@ type AcceptBody struct { FromTeamSelection bool `json:"from_team_selection"` } -func (e *EnvironmentManager) acceptInvite(invite *InvitedTeams, participantId string, vr *VerifyResponse) error { +func (e *EnvironmentManager) acceptInvite(inviteId string, participantId string, vr *VerifyResponse) error { h := sha256.Sum256([]byte(participantId)) sum := fmt.Sprintf("%x", h) - ab := AcceptBody{InviteId: (*invite).Teams[0].InviteId, FirstName: "Repl", LastName: "Replicated", Password: string(sum[0:20]), ReplaceAccount: false, FromTeamSelection: true} + + ab := AcceptBody{InviteId: inviteId, FirstName: "Repl", LastName: "Replicated", Password: string(sum[0:20]), ReplaceAccount: false, FromTeamSelection: true} acceptBodyBytes, err := json.Marshal(ab) if err != nil { return errors.Wrap(err, "marshal accept body") } req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/v1/signup/accept-invite", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/signup/accept-invite", e.Params.IDOrigin), bytes.NewReader(acceptBodyBytes), ) if err != nil { @@ -172,18 +189,24 @@ func (e *EnvironmentManager) acceptInvite(invite *InvitedTeams, participantId st return nil } -type InvitedTeams struct { - Teams []struct { - Id string `json:"id"` - Name string `json:"name"` - InviteId string `json:"invite_id"` - } `json:"invited_teams"` +type Invite struct { + Invite struct { + Id string `json:"id"` + Email string `json:"email"` + HasConflict string `json:"has_conflict"` + } `json:"invite"` + Team struct { + Id string `json:"id"` + Name string `json:"name"` + InviteId string `json:"invite_id"` + } `json:"team"` } -func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*InvitedTeams, error) { +func (e *EnvironmentManager) captureInvite(inviteId string, vr *VerifyResponse) (*Invite, error) { + e.Log.Verbose() req, err := http.NewRequest( "GET", - fmt.Sprintf("%s/v1/signup/teams", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/signup/teams", e.Params.IDOrigin, inviteId), nil, ) if err != nil { @@ -194,19 +217,20 @@ func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*InvitedTeams, e resp, err := http.DefaultClient.Do(req) if err != nil { - return nil, errors.Wrap(err, "send signup teams request") + return nil, errors.Wrap(err, "getting the invite") } defer resp.Body.Close() if resp.StatusCode != 200 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("POST /v1/signup/teams %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("GET /v1/invite/%s %d: %s", inviteId, resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) + e.Log.Debug(fmt.Sprintf("GET /v1/invite/%s %d: %s", inviteId, resp.StatusCode, bodyBytes)) if err != nil { return nil, errors.Wrap(err, "read body") } - var body InvitedTeams + var body Invite if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { return nil, errors.Wrap(err, "decode body") } @@ -227,7 +251,7 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, } req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/v1/signup/verify", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/signup/verify", e.Params.IDOrigin), bytes.NewReader(verifyBodyBytes), ) if err != nil { @@ -244,7 +268,7 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("POST /v1/signup/verify %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("POST /vendor/v1/signup/verify %d: %s", resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -254,6 +278,7 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { return nil, errors.Wrap(err, "decode body") } + e.Log.Debug(fmt.Sprintf("POST /vendor/v1/signup/verify %d: %s", resp.StatusCode, body)) return &body, nil } @@ -271,7 +296,7 @@ func (e *EnvironmentManager) signupMember(inviteEmail string) (*SignupResponse, } req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/v1/signup", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/signup", e.Params.IDOrigin), bytes.NewReader(signupBodyBytes), ) if err != nil { @@ -317,7 +342,7 @@ func (e *EnvironmentManager) inviteMember(inviteEmail string, members map[string } req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/v1/team/invite", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/team/invite", e.Params.IDOrigin), bytes.NewReader(inviteBodyBytes), ) if err != nil { diff --git a/setup/pkg/fieldlabs/policy.go b/setup/pkg/fieldlabs/policy.go index 3fd6df3c6..fa79e2c4f 100644 --- a/setup/pkg/fieldlabs/policy.go +++ b/setup/pkg/fieldlabs/policy.go @@ -37,6 +37,10 @@ type PolicyResourcesV1 struct { Denied []string `json:"denied"` } +type PolicyListResponse struct { + Policies []PolicyListItem `json:"policies"` +} + type PolicyListItem struct { Id string `json:"id"` Name string `json:"name"` @@ -49,7 +53,7 @@ type PolicyUpdate struct { func (e *EnvironmentManager) getPolicies() (map[string]string, error) { req, err := http.NewRequest( "GET", - fmt.Sprintf("%s/v1/policies", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/policies", e.Params.IDOrigin), nil, ) if err != nil { @@ -67,17 +71,17 @@ func (e *EnvironmentManager) getPolicies() (map[string]string, error) { panic(err.Error()) } if resp.StatusCode != 200 { - return nil, fmt.Errorf("GET /v1/policies %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("GET /vendor/v1/policies %d: %s", resp.StatusCode, body) } - var policies []PolicyListItem + var policies PolicyListResponse err = json.Unmarshal([]byte(body), &policies) if err != nil { - return nil, errors.Wrap(err, "list policies unmarshal") + return nil, errors.Wrap(err, fmt.Sprintf("list policies unmarshal %s", body)) } policiesMap := make(map[string]string) - for i := 0; i < len(policies); i += 1 { - policiesMap[policies[i].Name] = policies[i].Id + for i := 0; i < len(policies.Policies); i += 1 { + policiesMap[policies.Policies[i].Name] = policies.Policies[i].Id } return policiesMap, nil } @@ -113,7 +117,7 @@ func (e *EnvironmentManager) createRBAC(app types.App, policies map[string]strin } req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/v1/policy", e.Params.IDOrigin), + fmt.Sprintf("%s/vendor/v1/policy", e.Params.IDOrigin), bytes.NewReader(rbacBodyBytes), ) if err != nil { @@ -128,9 +132,9 @@ func (e *EnvironmentManager) createRBAC(app types.App, policies map[string]strin return errors.Wrap(err, "send rbac request") } defer resp.Body.Close() - if resp.StatusCode != 201 { + if resp.StatusCode != 201 && resp.StatusCode != 200 { body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("POST /v1/policy %d: %s", resp.StatusCode, body) + return fmt.Errorf("POST /vendor/v1/policy %d: %s", resp.StatusCode, body) } return nil @@ -138,7 +142,7 @@ func (e *EnvironmentManager) createRBAC(app types.App, policies map[string]strin // Delete policies create through multi-player mode func (e *EnvironmentManager) DeletePolicyId(id string) error { - url := fmt.Sprintf("%s/v1/policy/%s", e.Params.IDOrigin, id) + url := fmt.Sprintf("%s/vendor/v1/policy/%s", e.Params.IDOrigin, id) req, err := http.NewRequest( "DELETE", url, @@ -161,7 +165,7 @@ func (e *EnvironmentManager) DeletePolicyId(id string) error { panic(err.Error()) } if resp.StatusCode != 204 { - return fmt.Errorf("GET /v1/policy %d: %s", resp.StatusCode, body) + return fmt.Errorf("GET /vendor/v1/policy %d: %s", resp.StatusCode, body) } return nil } From fcc39510dc00b79ed3842f57b907514d7c0eb04a Mon Sep 17 00:00:00 2001 From: Chuck D'Antonio Date: Mon, 10 Feb 2025 16:53:55 -0500 Subject: [PATCH 2/4] Goes back to original flow for adding a member --- setup/pkg/fieldlabs/members.go | 36 ++++++++++------------------------ 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/setup/pkg/fieldlabs/members.go b/setup/pkg/fieldlabs/members.go index 8527cfcd8..6a02ad985 100644 --- a/setup/pkg/fieldlabs/members.go +++ b/setup/pkg/fieldlabs/members.go @@ -104,47 +104,36 @@ func (e *EnvironmentManager) DeleteMember(id string) error { } func (e *EnvironmentManager) addMember(members map[string]MemberList, policies map[string]string) error { - inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" - - e.Log.Verbose() - e.Log.Debug("Inviting %s", inviteEmail) + inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" err := e.inviteMember(inviteEmail, members, policies) if err != nil { return err } // Signup - e.Log.Debug("Signing up %s", inviteEmail) sr, err := e.signupMember(inviteEmail) if err != nil { return err } - inviteId := sr.Token // Verify - signupResponseJson, _ := json.Marshal(sr) - e.Log.Debug("Verfiying %s", signupResponseJson) vr, err := e.verifyMember(sr) if err != nil { return err } // Capture Invite Id - verifyResponseJson, _ := json.Marshal(vr) - e.Log.Debug("Capturing %s with %s", inviteId, verifyResponseJson) - invite, err := e.captureInvite(inviteId, vr) + invite, err := e.captureInvite(vr) if err != nil { return err } // Accept Invite - e.Log.Debug("Accepting invite %s for participant %s", inviteId, e.Params.ParticipantId) - err = e.acceptInvite(invite.Invite.Id, e.Params.ParticipantId, vr) + err = e.acceptInvite(invite, e.Params.ParticipantId, vr) if err != nil { return err } return nil - } type AcceptBody struct { @@ -189,20 +178,15 @@ func (e *EnvironmentManager) acceptInvite(inviteId string, participantId string, return nil } -type Invite struct { - Invite struct { - Id string `json:"id"` - Email string `json:"email"` - HasConflict string `json:"has_conflict"` - } `json:"invite"` - Team struct { - Id string `json:"id"` - Name string `json:"name"` - InviteId string `json:"invite_id"` - } `json:"team"` +type InvitedTeams struct { + Teams []struct { + Id string `json:"id"` + Name string `json:"name"` + InviteId string `json:"invite_id"` + } `json:"invited_teams"` } -func (e *EnvironmentManager) captureInvite(inviteId string, vr *VerifyResponse) (*Invite, error) { +func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*Invite, error) { e.Log.Verbose() req, err := http.NewRequest( "GET", From f23c750296af07e73fbe5003da98e1127bcfc8af Mon Sep 17 00:00:00 2001 From: Chuck D'Antonio Date: Tue, 11 Feb 2025 11:37:01 -0500 Subject: [PATCH 3/4] Adapts member flow for API changes --- setup/pkg/fieldlabs/members.go | 218 +++++++++++++++++---------------- 1 file changed, 111 insertions(+), 107 deletions(-) diff --git a/setup/pkg/fieldlabs/members.go b/setup/pkg/fieldlabs/members.go index 6a02ad985..302b5079f 100644 --- a/setup/pkg/fieldlabs/members.go +++ b/setup/pkg/fieldlabs/members.go @@ -60,14 +60,14 @@ func (e *EnvironmentManager) getMembersMap() (map[string]MemberList, error) { return nil, errors.Wrap(err, "get members") } - membersJson, _ := json.Marshal(members) - fmt.Sprintf("members: %s", membersJson) + membersJson, _ := json.Marshal(members) + fmt.Sprintf("members: %s", membersJson) membersMap := make(map[string]MemberList) for i := 0; i < len(members); i += 1 { - memberJson, _ := json.Marshal(members) - fmt.Sprintf("member: %s", memberJson) - fmt.Sprintf("member: %s", members[i].Email) + memberJson, _ := json.Marshal(members) + fmt.Sprintf("member: %s", memberJson) + fmt.Sprintf("member: %s", members[i].Email) membersMap[members[i].Email] = members[i] } return membersMap, nil @@ -75,15 +75,15 @@ func (e *EnvironmentManager) getMembersMap() (map[string]MemberList, error) { // Delete team members created with multi-player mode func (e *EnvironmentManager) DeleteMember(id string) error { - url := fmt.Sprintf("%s/v1/team/member/%s", e.Params.IDOrigin, id) + requestUrl := fmt.Sprintf("%s/v1/team/member?id=%s", e.Params.IDOrigin, id) req, err := http.NewRequest( "DELETE", - url, + requestUrl, nil, ) if err != nil { - return errors.Wrap(err, fmt.Sprintf("DELETE %s/v1/team/member?user_id=%s", e.Params.IDOrigin, id)) + return errors.Wrap(err, fmt.Sprintf("DELETE %s", requestUrl)) } req.Header.Set("Authorization", e.Params.SessionToken) req.Header.Set("Accept", "application/json") @@ -98,13 +98,13 @@ func (e *EnvironmentManager) DeleteMember(id string) error { panic(err.Error()) } if resp.StatusCode != 204 { - return fmt.Errorf("DELETE /v1/team/member/%s %d: %s", id, resp.StatusCode, body) + return fmt.Errorf("DELETE %s %d: %s", requestUrl, resp.StatusCode, body) } return nil } func (e *EnvironmentManager) addMember(members map[string]MemberList, policies map[string]string) error { - inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" + inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" err := e.inviteMember(inviteEmail, members, policies) if err != nil { return err @@ -136,93 +136,106 @@ func (e *EnvironmentManager) addMember(members map[string]MemberList, policies m return nil } -type AcceptBody struct { - InviteId string `json:"invite_id"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - Password string `json:"password"` - ReplaceAccount bool `json:"replace_account"` - FromTeamSelection bool `json:"from_team_selection"` + +type VerifyResponse struct { + Token string `json:"token"` } -func (e *EnvironmentManager) acceptInvite(inviteId string, participantId string, vr *VerifyResponse) error { - h := sha256.Sum256([]byte(participantId)) - sum := fmt.Sprintf("%x", h) +type SignupResponse struct { + Token string `json:"token"` +} - ab := AcceptBody{InviteId: inviteId, FirstName: "Repl", LastName: "Replicated", Password: string(sum[0:20]), ReplaceAccount: false, FromTeamSelection: true} - acceptBodyBytes, err := json.Marshal(ab) +func (e *EnvironmentManager) signupMember(inviteEmail string) (*SignupResponse, error) { + signupBody := map[string]string{ + "email": inviteEmail, + } + signupBodyBytes, err := json.Marshal(signupBody) if err != nil { - return errors.Wrap(err, "marshal accept body") + return nil, errors.Wrap(err, "marshal signup body") } + requestUrl := fmt.Sprintf("%s/vendor/v1/signup", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/vendor/v1/signup/accept-invite", e.Params.IDOrigin), - bytes.NewReader(acceptBodyBytes), + requestUrl, + bytes.NewReader(signupBodyBytes), ) if err != nil { - return errors.Wrap(err, "build accept request") + return nil, errors.Wrap(err, "build signup request") } req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { - return errors.Wrap(err, "send accept request") + return nil, errors.Wrap(err, "send signup request") } defer resp.Body.Close() if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("POST /v1/signup/accept-invite %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } - return nil -} + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, errors.Wrap(err, "read body") + } + var body SignupResponse + if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { + return nil, errors.Wrap(err, "decode body") + } + return &body, nil -type InvitedTeams struct { - Teams []struct { - Id string `json:"id"` - Name string `json:"name"` - InviteId string `json:"invite_id"` - } `json:"invited_teams"` } -func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*Invite, error) { - e.Log.Verbose() +func (e *EnvironmentManager) inviteMember(inviteEmail string, members map[string]MemberList, policies map[string]string) error { + if _, memberExists := members[inviteEmail]; memberExists { + // This should never happen? + return nil + } + inviteBody := map[string]string{ + "email": inviteEmail, + "policy_id": policies[e.Params.ParticipantId], + } + inviteBodyBytes, err := json.Marshal(inviteBody) + if err != nil { + return errors.Wrap(err, "marshal invite body") + } + requestUrl := fmt.Sprintf("%s/vendor/v1/team/invite", e.Params.IDOrigin) req, err := http.NewRequest( - "GET", - fmt.Sprintf("%s/vendor/v1/signup/teams", e.Params.IDOrigin, inviteId), - nil, + "POST", + requestUrl, + bytes.NewReader(inviteBodyBytes), ) if err != nil { - return nil, errors.Wrap(err, "build signup teams request") + return errors.Wrap(err, "build invite request") } + req.Header.Set("Authorization", e.Params.SessionToken) req.Header.Set("Accept", "application/json") - req.Header.Set("Authorization", vr.Token) + req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { - return nil, errors.Wrap(err, "getting the invite") + return errors.Wrap(err, fmt.Sprintf("send invite request: %s", requestUrl)) } defer resp.Body.Close() - - if resp.StatusCode != 200 { - body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("GET /v1/invite/%s %d: %s", inviteId, resp.StatusCode, body) - } - bodyBytes, err := ioutil.ReadAll(resp.Body) - e.Log.Debug(fmt.Sprintf("GET /v1/invite/%s %d: %s", inviteId, resp.StatusCode, bodyBytes)) - if err != nil { - return nil, errors.Wrap(err, "read body") + // rate limit returned when already invited + if resp.StatusCode == 429 { + e.Log.ActionWithoutSpinner("Skipping invite %q due to 429 error", inviteEmail) + return nil } - var body Invite - if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { - return nil, errors.Wrap(err, "decode body") + if resp.StatusCode != 204 { + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } - return &body, nil + return nil } -type VerifyResponse struct { - Token string `json:"token"` +type InvitedTeams struct { + Teams []struct { + Id string `json:"id"` + Name string `json:"name"` + InviteId string `json:"invite_id"` + } `json:"invited_teams"` } func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, error) { @@ -233,13 +246,14 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if err != nil { return nil, errors.Wrap(err, "marshal verify body") } + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/verify", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/vendor/v1/signup/verify", e.Params.IDOrigin), + requestUrl, bytes.NewReader(verifyBodyBytes), ) if err != nil { - return nil, errors.Wrap(err, "build verify request") + return nil, errors.Wrap(err, fmt.Sprintf("build verify request: %s", requestUrl)) } req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") @@ -252,7 +266,7 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("POST /vendor/v1/signup/verify %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -262,93 +276,83 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { return nil, errors.Wrap(err, "decode body") } - e.Log.Debug(fmt.Sprintf("POST /vendor/v1/signup/verify %d: %s", resp.StatusCode, body)) return &body, nil } -type SignupResponse struct { - Token string `json:"token"` -} - -func (e *EnvironmentManager) signupMember(inviteEmail string) (*SignupResponse, error) { - signupBody := map[string]string{ - "email": inviteEmail, - } - signupBodyBytes, err := json.Marshal(signupBody) - if err != nil { - return nil, errors.Wrap(err, "marshal signup body") - } +func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*InvitedTeams, error) { + e.Log.Verbose() + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/teams", e.Params.IDOrigin) req, err := http.NewRequest( - "POST", - fmt.Sprintf("%s/vendor/v1/signup", e.Params.IDOrigin), - bytes.NewReader(signupBodyBytes), + "GET", + requestUrl, + nil, ) if err != nil { - return nil, errors.Wrap(err, "build signup request") + return nil, errors.Wrap(err, "build signup teams request") } req.Header.Set("Accept", "application/json") - req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", vr.Token) resp, err := http.DefaultClient.Do(req) if err != nil { - return nil, errors.Wrap(err, "send signup request") + return nil, errors.Wrap(err, "getting the invite") } defer resp.Body.Close() - if resp.StatusCode != 201 { + if resp.StatusCode != 200 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("POST /v1/signup %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("GET %s %d: %s", requestUrl, resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, errors.Wrap(err, "read body") } - var body SignupResponse + var body InvitedTeams if err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(&body); err != nil { return nil, errors.Wrap(err, "decode body") } return &body, nil +} +type AcceptBody struct { + InviteId string `json:"invite_id"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + Password string `json:"password"` + ReplaceAccount bool `json:"replace_account"` + FromTeamSelection bool `json:"from_team_selection"` } -func (e *EnvironmentManager) inviteMember(inviteEmail string, members map[string]MemberList, policies map[string]string) error { - if _, memberExists := members[inviteEmail]; memberExists { - // This should never happen? - return nil - } - inviteBody := map[string]string{ - "email": inviteEmail, - "policy_id": policies[e.Params.ParticipantId], - } - inviteBodyBytes, err := json.Marshal(inviteBody) +func (e *EnvironmentManager) acceptInvite(invite *InvitedTeams, participantId string, vr *VerifyResponse) error { + h := sha256.Sum256([]byte(participantId)) + sum := fmt.Sprintf("%x", h) + ab := AcceptBody{InviteId: (*invite).Teams[0].InviteId, FirstName: "Instruqt", LastName: "Participant", Password: string(sum[0:20]), ReplaceAccount: false, FromTeamSelection: true} + acceptBodyBytes, err := json.Marshal(ab) if err != nil { - return errors.Wrap(err, "marshal invite body") + return errors.Wrap(err, "marshal accept body") } + + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/accept-invite", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/vendor/v1/team/invite", e.Params.IDOrigin), - bytes.NewReader(inviteBodyBytes), + requestUrl, + bytes.NewReader(acceptBodyBytes), ) if err != nil { - return errors.Wrap(err, "build invite request") + return errors.Wrap(err, "build accept request") } - req.Header.Set("Authorization", e.Params.SessionToken) req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { - return errors.Wrap(err, "send invite request") + return errors.Wrap(err, fmt.Sprintf("send accept request: %s", requestUrl)) } defer resp.Body.Close() - // rate limit returned when already invited - if resp.StatusCode == 429 { - e.Log.ActionWithoutSpinner("Skipping invite %q due to 429 error", inviteEmail) - return nil - } - if resp.StatusCode != 204 { + + if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("POST /team/invite %d: %s", resp.StatusCode, body) + return fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } return nil } From 122a0dc449f9f0ff19fd400f045e4efe95d50106 Mon Sep 17 00:00:00 2001 From: Chuck D'Antonio Date: Wed, 12 Feb 2025 11:20:14 -0500 Subject: [PATCH 4/4] Fixes teardown and improves ergonomics --- setup/pkg/fieldlabs/environment_create.go | 174 ++++++++++----------- setup/pkg/fieldlabs/environment_destroy.go | 12 ++ setup/pkg/fieldlabs/members.go | 42 ++--- setup/pkg/fieldlabs/policy.go | 57 ++++++- 4 files changed, 170 insertions(+), 115 deletions(-) diff --git a/setup/pkg/fieldlabs/environment_create.go b/setup/pkg/fieldlabs/environment_create.go index 3c540bcba..f4b5ab009 100644 --- a/setup/pkg/fieldlabs/environment_create.go +++ b/setup/pkg/fieldlabs/environment_create.go @@ -1,12 +1,12 @@ package fieldlabs import ( + "encoding/json" "fmt" "io" "io/ioutil" "strings" "time" - "encoding/json" "github.com/pkg/errors" "github.com/replicatedhq/replicated/pkg/kotsclient" @@ -104,9 +104,9 @@ func (e *EnvironmentManager) Ensure(track *TrackSpec) error { if err != nil { return errors.Wrap(err, "add member") } - memberJson, _ := json.Marshal(members) - policyJson, _ := json.Marshal(policies) - e.Log.ActionWithSpinner("Added member: %s %s", memberJson, policyJson) + memberJson, _ := json.Marshal(members) + policyJson, _ := json.Marshal(policies) + e.Log.ActionWithSpinner("Added member: %s %s", memberJson, policyJson) err = e.createVendorTrack(*app, *track) if err != nil { @@ -123,90 +123,90 @@ func (e *EnvironmentManager) createVendorTrack(app types.App, trackSpec TrackSpe appTrackSlug := fmt.Sprintf("%s-%s", app.Slug, track.Spec.Slug) e.Log.ActionWithSpinner("Provision track %s", appTrackSlug) - // get the stable channel to assign for customer + // get the stable channel to assign for customer e.Log.ActionWithSpinner("Get stable channel") - channel, err := e.getChannel(track) - if err != nil { - return errors.Wrapf(err, "get Stable channel") - } - track.Status.Channel = channel - e.Log.ActionWithSpinner("Got channel: %s", channel) - - // Create customer - e.Log.ActionWithSpinner("Create customer") - if trackSpec.Customer != "" { - customer, err := e.getOrCreateCustomer(track) - if err != nil { - return errors.Wrapf(err, "create customer for track %q app %q", trackSpec.Slug, app.Slug) - } - track.Status.Customer = customer - } + channel, err := e.getChannel(track) + if err != nil { + return errors.Wrapf(err, "get Stable channel") + } + track.Status.Channel = channel + e.Log.ActionWithSpinner("Got channel: %s", channel) + + // Create customer + e.Log.ActionWithSpinner("Create customer") + if trackSpec.Customer != "" { + customer, err := e.getOrCreateCustomer(track) + if err != nil { + return errors.Wrapf(err, "create customer for track %q app %q", trackSpec.Slug, app.Slug) + } + track.Status.Customer = customer + } // load yaml for releases first to ensure directories exist - if trackSpec.YAMLDir != "" { - kotsYAML, err := readYAMLDir(fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) - - if err != nil { - return errors.Wrapf(err, "read yaml dir %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) - } - - for _, extraRelease := range track.Spec.ExtraReleases { - kotsYAML, err := readYAMLDir(fmt.Sprintf("%s/%s", e.VendorLoc, extraRelease.YAMLDir)) - if err != nil { - return errors.Wrapf(err, "read yaml dir %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) - } - track.Status.ExtraReleases = append(track.Status.ExtraReleases, ExtraReleaseStatus{ - Spec: extraRelease, - YAML: kotsYAML, - }) - - } - - release, err := e.Client.CreateRelease(app.ID, kotsYAML) - if err != nil { - return errors.Wrapf(err, "create release for %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) - } - - track.Status.Release = release - - e.Log.ActionWithSpinner("Promote release") - err = e.Client.PromoteRelease(app.ID, release.Sequence, "0.1.0", trackSpec.Slug, false, channel.ID) - if err != nil { - return errors.Wrapf(err, "promote release %d to channel %q", release.Sequence, channel.Slug) - } - - for _, extraRelease := range track.Status.ExtraReleases { - releaseInfo, err := e.Client.CreateRelease(app.ID, extraRelease.YAML) - if err != nil { - return errors.Wrapf(err, "create release for %q", fmt.Sprintf("%s/%s", e.VendorLoc, extraRelease.Spec.YAMLDir)) - } - extraRelease.Release = releaseInfo - - if extraRelease.Spec.PromoteChannel != "" { - - continue - } - } - - if trackSpec.K8sInstallerYAMLPath != "" { - kurlYAML, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) - if err != nil { - return errors.Wrapf(err, "read installer yaml %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) - } - - installer, err := e.Client.CreateInstaller(app.ID, string(kurlYAML)) - if err != nil { - return errors.Wrapf(err, "create installer from %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) - } - track.Status.Installer = installer - - err = e.Client.PromoteInstaller(app.ID, installer.Sequence, channel.ID, trackSpec.Slug) - if err != nil { - return errors.Wrapf(err, "promote installer %d to channel %q", installer.Sequence, channel.Slug) - } - } - } - e.Log.ActionWithSpinner("Provisioned") + if trackSpec.YAMLDir != "" { + kotsYAML, err := readYAMLDir(fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) + + if err != nil { + return errors.Wrapf(err, "read yaml dir %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) + } + + for _, extraRelease := range track.Spec.ExtraReleases { + kotsYAML, err := readYAMLDir(fmt.Sprintf("%s/%s", e.VendorLoc, extraRelease.YAMLDir)) + if err != nil { + return errors.Wrapf(err, "read yaml dir %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) + } + track.Status.ExtraReleases = append(track.Status.ExtraReleases, ExtraReleaseStatus{ + Spec: extraRelease, + YAML: kotsYAML, + }) + + } + + release, err := e.Client.CreateRelease(app.ID, kotsYAML) + if err != nil { + return errors.Wrapf(err, "create release for %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.YAMLDir)) + } + + track.Status.Release = release + + e.Log.ActionWithSpinner("Promote release") + err = e.Client.PromoteRelease(app.ID, release.Sequence, "0.1.0", trackSpec.Slug, false, channel.ID) + if err != nil { + return errors.Wrapf(err, "promote release %d to channel %q", release.Sequence, channel.Slug) + } + + for _, extraRelease := range track.Status.ExtraReleases { + releaseInfo, err := e.Client.CreateRelease(app.ID, extraRelease.YAML) + if err != nil { + return errors.Wrapf(err, "create release for %q", fmt.Sprintf("%s/%s", e.VendorLoc, extraRelease.Spec.YAMLDir)) + } + extraRelease.Release = releaseInfo + + if extraRelease.Spec.PromoteChannel != "" { + + continue + } + } + + if trackSpec.K8sInstallerYAMLPath != "" { + kurlYAML, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) + if err != nil { + return errors.Wrapf(err, "read installer yaml %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) + } + + installer, err := e.Client.CreateInstaller(app.ID, string(kurlYAML)) + if err != nil { + return errors.Wrapf(err, "create installer from %q", fmt.Sprintf("%s/%s", e.VendorLoc, trackSpec.K8sInstallerYAMLPath)) + } + track.Status.Installer = installer + + err = e.Client.PromoteInstaller(app.ID, installer.Sequence, channel.ID, trackSpec.Slug) + if err != nil { + return errors.Wrapf(err, "promote installer %d to channel %q", installer.Sequence, channel.Slug) + } + } + } + e.Log.ActionWithSpinner("Provisioned") return nil } @@ -251,8 +251,8 @@ func (e *EnvironmentManager) getOrCreateCustomer(track Track) (*types.Customer, } } - var createOpts = kotsclient.CreateCustomerOpts{ Name: track.Spec.Customer, AppID: track.Status.App.ID, Email: track.Spec.Customer + "@replicated-labs.com", ChannelID: track.Status.Channel.ID, ExpiresAt: OneWeek } - customer, err := e.Client.CreateCustomer(createOpts) + var createOpts = kotsclient.CreateCustomerOpts{Name: track.Spec.Customer, AppID: track.Status.App.ID, Email: track.Spec.Customer + "@replicated-labs.com", ChannelID: track.Status.Channel.ID, ExpiresAt: OneWeek} + customer, err := e.Client.CreateCustomer(createOpts) if err != nil { return nil, errors.Wrapf(err, "create customer for track %q app %q", track.Spec.Slug, track.Status.App.Slug) } diff --git a/setup/pkg/fieldlabs/environment_destroy.go b/setup/pkg/fieldlabs/environment_destroy.go index 66d404088..7b9b5d716 100644 --- a/setup/pkg/fieldlabs/environment_destroy.go +++ b/setup/pkg/fieldlabs/environment_destroy.go @@ -1,36 +1,48 @@ package fieldlabs import ( + "encoding/json" "github.com/pkg/errors" ) func (e *EnvironmentManager) Destroy(track *TrackSpec) error { + e.Log.Verbose() + e.Log.Debug("Destroying environment %s", e.Params.ParticipantId) + e.Log.Debug("Get policies") policies, err := e.getPolicies() if err != nil { return errors.Wrap(err, "get policies") } + + e.Log.Debug("Get member map") members, err := e.getMembersMap() if err != nil { return errors.Wrap(err, "get members") } inviteEmail := e.Params.ParticipantId + "@replicated-labs.com" + memberJson, _ := json.Marshal(members) + e.Log.Debug("Need to find %s in: %s", inviteEmail, memberJson) + e.Log.Debug("Delete member %s", inviteEmail) err = e.DeleteMember(members[inviteEmail].Id) if err != nil { return err } + e.Log.Debug("Delete policy id %s", policies[e.Params.ParticipantId]) err = e.DeletePolicyId(policies[e.Params.ParticipantId]) if err != nil { return err } // Delete the app + e.Log.Debug("List apps") apps, err := e.Client.ListApps() if err != nil { return errors.Wrapf(err, "list apps") } for _, app := range apps { if app.App.Name == track.Name+" "+e.Params.ParticipantId { + e.Log.Debug("Delete app %s", app.App.Name) err = e.Client.DeleteKOTSApp(app.App.ID) if err != nil { return errors.Wrapf(err, "delete app") diff --git a/setup/pkg/fieldlabs/members.go b/setup/pkg/fieldlabs/members.go index 302b5079f..ba921daed 100644 --- a/setup/pkg/fieldlabs/members.go +++ b/setup/pkg/fieldlabs/members.go @@ -20,6 +20,7 @@ type MemberList struct { // Get list of team members created with multi-player mode func (e *EnvironmentManager) GetMembers() ([]MemberList, error) { url := fmt.Sprintf("%s/v1/team/members", e.Params.IDOrigin) + e.Log.Debug(fmt.Sprintf("GET %s", url)) req, err := http.NewRequest( "GET", url, @@ -42,9 +43,10 @@ func (e *EnvironmentManager) GetMembers() ([]MemberList, error) { panic(err.Error()) } if resp.StatusCode != 200 { - return []MemberList{}, fmt.Errorf("GET /v1/team/members %d: %s", resp.StatusCode, body) + return []MemberList{}, fmt.Errorf("GET %d: %s", url, resp.StatusCode, body) } + e.Log.Debug(fmt.Sprintf("GET %s %d: %s", url, resp.StatusCode, body)) var members []MemberList err = json.Unmarshal([]byte(body), &members) if err != nil { @@ -76,6 +78,7 @@ func (e *EnvironmentManager) getMembersMap() (map[string]MemberList, error) { // Delete team members created with multi-player mode func (e *EnvironmentManager) DeleteMember(id string) error { requestUrl := fmt.Sprintf("%s/v1/team/member?id=%s", e.Params.IDOrigin, id) + e.Log.Debug(fmt.Sprintf("DELETE %s", requestUrl)) req, err := http.NewRequest( "DELETE", requestUrl, @@ -97,8 +100,8 @@ func (e *EnvironmentManager) DeleteMember(id string) error { if err != nil { panic(err.Error()) } - if resp.StatusCode != 204 { - return fmt.Errorf("DELETE %s %d: %s", requestUrl, resp.StatusCode, body) + if resp.StatusCode != 204 && resp.StatusCode != 200 { + return fmt.Errorf("DELETE %s %d: %s", requestUrl, resp.StatusCode, body) } return nil } @@ -136,7 +139,6 @@ func (e *EnvironmentManager) addMember(members map[string]MemberList, policies m return nil } - type VerifyResponse struct { Token string `json:"token"` } @@ -153,10 +155,10 @@ func (e *EnvironmentManager) signupMember(inviteEmail string) (*SignupResponse, if err != nil { return nil, errors.Wrap(err, "marshal signup body") } - requestUrl := fmt.Sprintf("%s/vendor/v1/signup", e.Params.IDOrigin) + requestUrl := fmt.Sprintf("%s/vendor/v1/signup", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - requestUrl, + requestUrl, bytes.NewReader(signupBodyBytes), ) if err != nil { @@ -200,10 +202,10 @@ func (e *EnvironmentManager) inviteMember(inviteEmail string, members map[string if err != nil { return errors.Wrap(err, "marshal invite body") } - requestUrl := fmt.Sprintf("%s/vendor/v1/team/invite", e.Params.IDOrigin) + requestUrl := fmt.Sprintf("%s/vendor/v1/team/invite", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - requestUrl, + requestUrl, bytes.NewReader(inviteBodyBytes), ) if err != nil { @@ -215,7 +217,7 @@ func (e *EnvironmentManager) inviteMember(inviteEmail string, members map[string resp, err := http.DefaultClient.Do(req) if err != nil { - return errors.Wrap(err, fmt.Sprintf("send invite request: %s", requestUrl)) + return errors.Wrap(err, fmt.Sprintf("send invite request: %s", requestUrl)) } defer resp.Body.Close() // rate limit returned when already invited @@ -246,14 +248,14 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if err != nil { return nil, errors.Wrap(err, "marshal verify body") } - requestUrl := fmt.Sprintf("%s/vendor/v1/signup/verify", e.Params.IDOrigin) + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/verify", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - requestUrl, + requestUrl, bytes.NewReader(verifyBodyBytes), ) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("build verify request: %s", requestUrl)) + return nil, errors.Wrap(err, fmt.Sprintf("build verify request: %s", requestUrl)) } req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") @@ -266,7 +268,7 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) + return nil, fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -281,10 +283,10 @@ func (e *EnvironmentManager) verifyMember(sr *SignupResponse) (*VerifyResponse, func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*InvitedTeams, error) { e.Log.Verbose() - requestUrl := fmt.Sprintf("%s/vendor/v1/signup/teams", e.Params.IDOrigin) + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/teams", e.Params.IDOrigin) req, err := http.NewRequest( "GET", - requestUrl, + requestUrl, nil, ) if err != nil { @@ -301,7 +303,7 @@ func (e *EnvironmentManager) captureInvite(vr *VerifyResponse) (*InvitedTeams, e if resp.StatusCode != 200 { body, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("GET %s %d: %s", requestUrl, resp.StatusCode, body) + return nil, fmt.Errorf("GET %s %d: %s", requestUrl, resp.StatusCode, body) } bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -332,10 +334,10 @@ func (e *EnvironmentManager) acceptInvite(invite *InvitedTeams, participantId st return errors.Wrap(err, "marshal accept body") } - requestUrl := fmt.Sprintf("%s/vendor/v1/signup/accept-invite", e.Params.IDOrigin) + requestUrl := fmt.Sprintf("%s/vendor/v1/signup/accept-invite", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - requestUrl, + requestUrl, bytes.NewReader(acceptBodyBytes), ) if err != nil { @@ -346,13 +348,13 @@ func (e *EnvironmentManager) acceptInvite(invite *InvitedTeams, participantId st resp, err := http.DefaultClient.Do(req) if err != nil { - return errors.Wrap(err, fmt.Sprintf("send accept request: %s", requestUrl)) + return errors.Wrap(err, fmt.Sprintf("send accept request: %s", requestUrl)) } defer resp.Body.Close() if resp.StatusCode != 201 { body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) + return fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } return nil } diff --git a/setup/pkg/fieldlabs/policy.go b/setup/pkg/fieldlabs/policy.go index fa79e2c4f..e3b1a20a6 100644 --- a/setup/pkg/fieldlabs/policy.go +++ b/setup/pkg/fieldlabs/policy.go @@ -51,9 +51,10 @@ type PolicyUpdate struct { } func (e *EnvironmentManager) getPolicies() (map[string]string, error) { + requestUrl := fmt.Sprintf("%s/vendor/v1/policies", e.Params.IDOrigin) req, err := http.NewRequest( "GET", - fmt.Sprintf("%s/vendor/v1/policies", e.Params.IDOrigin), + requestUrl, nil, ) if err != nil { @@ -71,7 +72,7 @@ func (e *EnvironmentManager) getPolicies() (map[string]string, error) { panic(err.Error()) } if resp.StatusCode != 200 { - return nil, fmt.Errorf("GET /vendor/v1/policies %d: %s", resp.StatusCode, body) + return nil, fmt.Errorf("GET %s %d: %s", requestUrl, resp.StatusCode, body) } var policies PolicyListResponse err = json.Unmarshal([]byte(body), &policies) @@ -115,9 +116,10 @@ func (e *EnvironmentManager) createRBAC(app types.App, policies map[string]strin if err != nil { return errors.Wrap(err, "marshal rbac body") } + requestUrl := fmt.Sprintf("%s/vendor/v1/policy", e.Params.IDOrigin) req, err := http.NewRequest( "POST", - fmt.Sprintf("%s/vendor/v1/policy", e.Params.IDOrigin), + requestUrl, bytes.NewReader(rbacBodyBytes), ) if err != nil { @@ -134,21 +136,60 @@ func (e *EnvironmentManager) createRBAC(app types.App, policies map[string]strin defer resp.Body.Close() if resp.StatusCode != 201 && resp.StatusCode != 200 { body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("POST /vendor/v1/policy %d: %s", resp.StatusCode, body) + return fmt.Errorf("POST %s %d: %s", requestUrl, resp.StatusCode, body) } return nil } +// Get a single policy by id +func (e *EnvironmentManager) GetPolicyId(id string) (*Policy, error) { + requestUrl := fmt.Sprintf("%s/vendor/v1/policy/%s", e.Params.IDOrigin, id) + e.Log.Debug(fmt.Sprintf("GET %s", requestUrl)) + req, err := http.NewRequest( + "GET", + requestUrl, + nil, + ) + + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("GET %s", requestUrl)) + } + req.Header.Set("Authorization", e.Params.SessionToken) + req.Header.Set("Accept", "application/json") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("send get request: %s", requestUrl)) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err.Error()) + } + if resp.StatusCode != 200 { + return nil, fmt.Errorf("GET %s %d %s", requestUrl, resp.StatusCode, body) + } + var policy Policy + err = json.Unmarshal([]byte(body), &policy) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("unmarshal %s", body)) + } + return &policy, nil +} + // Delete policies create through multi-player mode func (e *EnvironmentManager) DeletePolicyId(id string) error { - url := fmt.Sprintf("%s/vendor/v1/policy/%s", e.Params.IDOrigin, id) + requestUrl := fmt.Sprintf("%s/vendor/v1/policy/%s", e.Params.IDOrigin, id) + e.Log.Debug(fmt.Sprintf("DELETE %s", requestUrl)) req, err := http.NewRequest( "DELETE", - url, + requestUrl, nil, ) + policy, _ := e.GetPolicyId(id) + policyJson, _ := json.Marshal(policy) + e.Log.Debug(fmt.Sprintf("policy %s contains %s", policy.Name, policyJson)) if err != nil { return err } @@ -164,8 +205,8 @@ func (e *EnvironmentManager) DeletePolicyId(id string) error { if err != nil { panic(err.Error()) } - if resp.StatusCode != 204 { - return fmt.Errorf("GET /vendor/v1/policy %d: %s", resp.StatusCode, body) + if resp.StatusCode != 204 && resp.StatusCode != 200 { + return fmt.Errorf("DELETE %s %d: %s", requestUrl, resp.StatusCode, body) } return nil }