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 }