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 all 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
59 changes: 53 additions & 6 deletions pkg/specs/replicatedapp/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"net/url"
"path/filepath"

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

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/mitchellh/cli"
"github.com/pkg/errors"
"github.com/spf13/afero"
"github.com/spf13/viper"
yaml "gopkg.in/yaml.v2"

"github.com/replicatedhq/ship/pkg/api"
"github.com/replicatedhq/ship/pkg/constants"
"github.com/replicatedhq/ship/pkg/helpers/flags"
"github.com/replicatedhq/ship/pkg/specs/apptype"
"github.com/replicatedhq/ship/pkg/state"
"github.com/spf13/afero"
"github.com/spf13/viper"
yaml "gopkg.in/yaml.v2"
)

type shaSummer func([]byte) string
Expand All @@ -27,6 +30,7 @@ type resolver struct {
Client *GraphQLClient
FS afero.Afero
StateManager state.Manager
UI cli.Ui
ShaSummer shaSummer
Runbook string
SetChannelName string
Expand All @@ -43,11 +47,13 @@ func NewAppResolver(
fs afero.Afero,
graphql *GraphQLClient,
stateManager state.Manager,
ui cli.Ui,
) Resolver {
return &resolver{
Logger: logger,
Client: graphql,
FS: fs,
UI: ui,
Runbook: flags.GetCurrentOrDeprecatedString(v, "runbook", "studio-file"),
SetChannelName: flags.GetCurrentOrDeprecatedString(v, "set-channel-name", "studio-channel-name"),
SetChannelIcon: flags.GetCurrentOrDeprecatedString(v, "set-channel-icon", "studio-channel-icon"),
Expand Down Expand Up @@ -165,7 +171,28 @@ 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)

var input string
input, err = r.UI.Ask("Please enter your license to continue: ")
if err != nil {
return nil, errors.Wrapf(err, "enter license from CLI")
}

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 +246,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