Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

support additional replicated.app upstream formats #846

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion pkg/specs/replicatedapp/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"net/url"
"path/filepath"
"strings"

"github.com/replicatedhq/ship/pkg/specs/apptype"

Expand Down Expand Up @@ -165,7 +167,24 @@ func (r *resolver) resolveCloudRelease(selector *Selector) (*ShipRelease, error)
debug.Log("phase", "load-specs", "from", "gql", "addr", client.GQLServer.String())
release, err := client.GetRelease(selector)
if err != nil {
return nil, err
if selector.InstallationID == "" {
debug.Log("event", "spec-resolve", "from", selector, "error", err)
fmt.Printf("Please enter your license to continue: ")
Copy link
Member

@dexhorthy dexhorthy Feb 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use the mitchellh/cli components for prompting elsewhere in this project.

They are a little more succinct, and make this code easily testable

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'll find that to copy it!

var input string
fmt.Scanln(&input)
selector.InstallationID = input

err = r.updateUpstream(*selector)
if err != nil {
return nil, errors.Wrapf(err, "persist updated upstream")
}

release, err = client.GetRelease(selector)
}

if err != nil {
return nil, err
}
}

if err := r.persistSpec([]byte(release.Spec)); err != nil {
Expand Down Expand Up @@ -219,3 +238,23 @@ func (r *resolver) loadFakeEntitlements() (*api.Entitlements, error) {
}
return &entitlements, nil
}

// read the upstream, get the host/path, and replace the query params with the ones from the provided selector
func (r *resolver) updateUpstream(selector Selector) error {
currentState, err := r.StateManager.TryLoad()
if err != nil {
return errors.Wrap(err, "retrieve state")
}
currentUpstream := currentState.Upstream()

parsedUpstream, err := url.Parse(currentUpstream)
if err != nil {
return errors.Wrap(err, "parse upstream")
}

if !strings.HasSuffix(parsedUpstream.Path, "/") {
parsedUpstream.Path += "/"
}

return r.StateManager.SerializeUpstream(parsedUpstream.Path + "?" + selector.String())
}
54 changes: 54 additions & 0 deletions pkg/specs/replicatedapp/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"github.com/golang/mock/gomock"
"github.com/replicatedhq/ship/pkg/api"
"github.com/replicatedhq/ship/pkg/constants"
state2 "github.com/replicatedhq/ship/pkg/state"
"github.com/replicatedhq/ship/pkg/test-mocks/state"
"github.com/replicatedhq/ship/pkg/testing/logger"
"github.com/replicatedhq/ship/pkg/testing/matchers"
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -108,3 +110,55 @@ assets:
})
}
}

func Test_resolver_updateUpstream(t *testing.T) {
tests := []struct {
name string
initUpstream string
selector Selector
expectUpstream string
}{
{
name: "replicated.app",
initUpstream: "replicated.app",
selector: Selector{
CustomerID: "abc",
InstallationID: "xyz",
},
expectUpstream: "replicated.app/?customer_id=abc&installation_id=xyz",
},
{
name: "staging.replicated.app",
initUpstream: "staging.replicated.app",
selector: Selector{
CustomerID: "abc",
InstallationID: "xyz",
},
expectUpstream: "staging.replicated.app/?customer_id=abc&installation_id=xyz",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := require.New(t)

fs := afero.Afero{Fs: afero.NewMemMapFs()}

realState := state2.MManager{FS: fs, Logger: &logger.TestLogger{T: t}, V: viper.New()}

resolver := &resolver{
Logger: &logger.TestLogger{T: t},
StateManager: &realState,
}

req.NoError(realState.SerializeUpstream(tt.initUpstream))

err := resolver.updateUpstream(tt.selector)
req.NoError(err)

afterState, err := realState.TryLoad()
req.NoError(err)

req.Equal(tt.expectUpstream, afterState.Upstream())
})
}
}
10 changes: 10 additions & 0 deletions pkg/specs/replicatedapp/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package replicatedapp

import (
"net/url"
"regexp"
"strings"

"github.com/google/go-querystring/query"
Expand Down Expand Up @@ -30,6 +31,8 @@ func (s *Selector) String() string {
return v.Encode()
}

var pathQuery = regexp.MustCompile(`replicated\.app/([\w_\-/]+)`)

// this is less janky
func (s *Selector) UnmarshalFrom(url *url.URL) *Selector {
for key, values := range url.Query() {
Expand All @@ -48,6 +51,13 @@ func (s *Selector) UnmarshalFrom(url *url.URL) *Selector {
}
}

if s.CustomerID == "" && pathQuery.MatchString(url.Path) {
matches := pathQuery.FindStringSubmatch(url.Path)
if len(matches) == 2 {
s.CustomerID = matches[1]
}
}

if strings.HasPrefix(url.String(), "staging.replicated.app") {
s.Upstream = "https://pg.staging.replicated.com/graphql"
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/specs/replicatedapp/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ func TestUnmarshalSelector(t *testing.T) {
Upstream: "https://pg.staging.replicated.com/graphql",
},
},
{
name: "pathed app with customer id",
url: "replicated.app/app_id_here?customer_id=123&installation_id=456&release_id=789&release_semver=7.8.9",
want: &Selector{
CustomerID: "123",
InstallationID: "456",
ReleaseID: "789",
ReleaseSemver: "7.8.9",
},
},
{
name: "pathed app WITHOUT customer id",
url: "replicated.app/app_id_here?installation_id=456&release_id=789&release_semver=7.8.9",
want: &Selector{
CustomerID: "app_id_here",
InstallationID: "456",
ReleaseID: "789",
ReleaseSemver: "7.8.9",
},
},
{
name: "pathed app WITHOUT customer id and including forward slash in id",
url: "replicated.app/app/id/here?installation_id=456&release_id=789&release_semver=7.8.9",
want: &Selector{
CustomerID: "app/id/here",
InstallationID: "456",
ReleaseID: "789",
ReleaseSemver: "7.8.9",
},
},
}

for _, test := range tests {
Expand Down