Skip to content

Commit

Permalink
add managedBy param to override user-agent
Browse files Browse the repository at this point in the history
  • Loading branch information
Craig O'Donnell committed Sep 8, 2023
1 parent bbcd099 commit 741aff7
Show file tree
Hide file tree
Showing 21 changed files with 265 additions and 103 deletions.
1 change: 1 addition & 0 deletions chart/templates/replicated-secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ stringData:
statusInformers:
{{- .Values.statusInformers | toYaml | nindent 6 }}
{{- end }}
managedBy: {{ .Values.managedBy | default "Helm" | quote }}
{{- if (.Values.integration).licenseID }}
integration-license-id: {{ .Values.integration.licenseID }}
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions chart/values.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ integration:
licenseID: ""
# enabled: false
mockData: ""

managedBy: Helm
21 changes: 3 additions & 18 deletions cmd/replicated/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import (
"strings"

"github.com/pkg/errors"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/replicated-sdk/pkg/apiserver"
"github.com/replicatedhq/replicated-sdk/pkg/config"
sdklicense "github.com/replicatedhq/replicated-sdk/pkg/license"
"github.com/replicatedhq/replicated-sdk/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -38,7 +36,6 @@ func APICmd() *cobra.Command {
return errors.New("either config file or integration license id must be specified")
}

var err error
var replicatedConfig = new(config.ReplicatedConfig)
if configFilePath != "" {
configFile, err := os.ReadFile(configFilePath)
Expand All @@ -59,23 +56,10 @@ func APICmd() *cobra.Command {
return errors.New("only one of license in the config file or integration license id can be specified")
}

var license *kotsv1beta1.License
if replicatedConfig.License != "" {
if license, err = sdklicense.LoadLicenseFromBytes([]byte(replicatedConfig.License)); err != nil {
return errors.Wrap(err, "failed to parse license from base64")
}
} else if integrationLicenseID != "" {
if license, err = sdklicense.GetLicenseByID(integrationLicenseID, replicatedConfig.ReplicatedAppEndpoint); err != nil {
return errors.Wrap(err, "failed to get license by id for integration license id")
}
if license.Spec.LicenseType != "dev" {
return errors.New("integration license must be a dev license")
}
}

params := apiserver.APIServerParams{
Context: cmd.Context(),
License: license,
LicenseBytes: []byte(replicatedConfig.License),
IntegrationLicenseID: integrationLicenseID,
LicenseFields: replicatedConfig.LicenseFields,
AppName: replicatedConfig.AppName,
ChannelID: replicatedConfig.ChannelID,
Expand All @@ -87,6 +71,7 @@ func APICmd() *cobra.Command {
VersionLabel: replicatedConfig.VersionLabel,
ReplicatedAppEndpoint: replicatedConfig.ReplicatedAppEndpoint,
StatusInformers: replicatedConfig.StatusInformers,
ManagedBy: replicatedConfig.ManagedBy,
Namespace: namespace,
}
apiserver.Start(params)
Expand Down
4 changes: 1 addition & 3 deletions pact/custom_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ func TestSendCustomApplicationMetrics(t *testing.T) {
ChannelID: license.Spec.ChannelID,
ChannelSequence: channelSequence,
}
if err := store.InitInMemory(storeOptions); err != nil {
t.Fatalf("Error on InitInMemory: %v", err)
}
store.InitInMemory(storeOptions)
defer store.SetStore(nil)

if err := pact.Verify(func() error {
Expand Down
4 changes: 4 additions & 0 deletions pact/heartbeat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func TestSendAppHeartbeat(t *testing.T) {
{
name: "successful heartbeat",
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
mockStore.EXPECT().GetLicense().Return(&v1beta1.License{
Spec: v1beta1.LicenseSpec{
LicenseID: "sdk-heartbeat-customer-0-license",
Expand Down Expand Up @@ -90,6 +91,7 @@ func TestSendAppHeartbeat(t *testing.T) {
{
name: "expired license heartbeat should return error",
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
mockStore.EXPECT().GetLicense().Return(&v1beta1.License{
Spec: v1beta1.LicenseSpec{
LicenseID: "sdk-heartbeat-customer-2-license",
Expand Down Expand Up @@ -141,6 +143,7 @@ func TestSendAppHeartbeat(t *testing.T) {
{
name: "nonexistent license heartbeat should return error",
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
mockStore.EXPECT().GetLicense().Return(&v1beta1.License{
Spec: v1beta1.LicenseSpec{
LicenseID: "sdk-heartbeat-customer-nonexistent-license",
Expand Down Expand Up @@ -192,6 +195,7 @@ func TestSendAppHeartbeat(t *testing.T) {
{
name: "unauthenticated heartbeat should return error",
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
mockStore.EXPECT().GetLicense().Return(&v1beta1.License{
Spec: v1beta1.LicenseSpec{
LicenseID: "sdk-heartbeat-customer-0-license",
Expand Down
36 changes: 30 additions & 6 deletions pact/license_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import (
"reflect"
"testing"

"github.com/golang/mock/gomock"
"github.com/pact-foundation/pact-go/dsl"
"github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/replicated-sdk/pkg/license"
mock_store "github.com/replicatedhq/replicated-sdk/pkg/store/mock"
)

func TestGetLatestLicense(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockStore := mock_store.NewMockStore(ctrl)

sdkCustomerLicenseString := `apiVersion: kots.io/v1beta1
kind: License
metadata:
Expand Down Expand Up @@ -46,11 +53,12 @@ spec:
endpoint string
}
tests := []struct {
name string
args args
pactInteraction func()
want *license.LicenseData
wantErr bool
name string
args args
mockStoreExpectations func()
pactInteraction func()
want *license.LicenseData
wantErr bool
}{
{
name: "successful license sync",
Expand All @@ -63,6 +71,9 @@ spec:
},
},
},
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
},
pactInteraction: func() {
pact.
AddInteraction().
Expand Down Expand Up @@ -98,6 +109,9 @@ spec:
},
},
},
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
},
pactInteraction: func() {
pact.
AddInteraction().
Expand Down Expand Up @@ -128,6 +142,9 @@ spec:
},
},
},
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
},
pactInteraction: func() {
pact.
AddInteraction().
Expand Down Expand Up @@ -158,6 +175,9 @@ spec:
},
},
},
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
},
pactInteraction: func() {
pact.
AddInteraction().
Expand Down Expand Up @@ -189,6 +209,9 @@ spec:
},
},
},
mockStoreExpectations: func() {
mockStore.EXPECT().GetUserAgent().Return("Replicated-SDK/v0.0.0-unknown")
},
pactInteraction: func() {
pact.
AddInteraction().
Expand All @@ -211,9 +234,10 @@ spec:
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockStoreExpectations()
tt.pactInteraction()
if err := pact.Verify(func() error {
got, err := license.GetLatestLicense(tt.args.license, tt.args.endpoint)
got, err := license.GetLatestLicense(mockStore, tt.args.license, tt.args.endpoint)
if (err != nil) != tt.wantErr {
t.Errorf("GetLatestLicense() error = %v, wantErr %v", err, tt.wantErr)
}
Expand Down
97 changes: 58 additions & 39 deletions pkg/apiserver/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package apiserver
import (
"github.com/cenkalti/backoff/v4"
"github.com/pkg/errors"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/replicated-sdk/pkg/appstate"
appstatetypes "github.com/replicatedhq/replicated-sdk/pkg/appstate/types"
"github.com/replicatedhq/replicated-sdk/pkg/heartbeat"
Expand All @@ -18,19 +19,72 @@ import (
)

func bootstrap(params APIServerParams) error {
verifiedLicense, err := sdklicense.VerifySignature(params.License)
storeOptions := store.InitInMemoryStoreOptions{
LicenseFields: params.LicenseFields,
AppName: params.AppName,
ChannelSequence: params.ChannelSequence,
ReleaseSequence: params.ReleaseSequence,
ReleaseCreatedAt: params.ReleaseCreatedAt,
ReleaseNotes: params.ReleaseNotes,
VersionLabel: params.VersionLabel,
ReplicatedAppEndpoint: params.ReplicatedAppEndpoint,
ManagedBy: params.ManagedBy,
Namespace: params.Namespace,
}
store.InitInMemory(storeOptions)

clientset, err := k8sutil.GetClientset()
if err != nil {
return errors.Wrap(err, "failed to get clientset")
}

// retrieve replicated and app ids
replicatedID, appID, err := util.GetReplicatedAndAppIDs(clientset, params.Namespace)
if err != nil {
return errors.Wrap(err, "failed to get replicated and app ids")
}
if replicatedID == "" {
return backoff.Permanent(errors.New("Replicated ID not found"))
}
if appID == "" {
return backoff.Permanent(errors.New("App ID not found"))
}
store.GetStore().SetReplicatedID(replicatedID)
store.GetStore().SetAppID(appID)

var unverifiedLicense *kotsv1beta1.License
if len(params.LicenseBytes) > 0 {
l, err := sdklicense.LoadLicenseFromBytes(params.LicenseBytes)
if err != nil {
return errors.Wrap(err, "failed to parse license from base64")
}
unverifiedLicense = l
} else if params.IntegrationLicenseID != "" {
l, err := sdklicense.GetLicenseByID(store.GetStore(), params.IntegrationLicenseID, params.ReplicatedAppEndpoint)
if err != nil {
return backoff.Permanent(errors.Wrap(err, "failed to get license by id for integration license id"))
}
unverifiedLicense = l
if unverifiedLicense.Spec.LicenseType != "dev" {
return errors.New("integration license must be a dev license")
}
}

verifiedLicense, err := sdklicense.VerifySignature(unverifiedLicense)
if err != nil {
return backoff.Permanent(errors.Wrap(err, "failed to verify license signature"))
}

if !util.IsAirgap() {
// sync license
licenseData, err := sdklicense.GetLatestLicense(verifiedLicense, params.ReplicatedAppEndpoint)
licenseData, err := sdklicense.GetLatestLicense(store.GetStore(), verifiedLicense, params.ReplicatedAppEndpoint)
if err != nil {
return errors.Wrap(err, "failed to get latest license")
}
verifiedLicense = licenseData.License
}
store.GetStore().SetLicense(verifiedLicense)
store.GetStore().SetAppSlug(verifiedLicense.Spec.AppSlug)

// check license expiration
expired, err := sdklicense.LicenseIsExpired(verifiedLicense)
Expand All @@ -41,18 +95,6 @@ func bootstrap(params APIServerParams) error {
return backoff.Permanent(errors.New("License is expired"))
}

// retrieve replicated and app ids
replicatedID, appID, err := util.GetReplicatedAndAppIDs(params.Namespace)
if err != nil {
return errors.Wrap(err, "failed to get replicated and app ids")
}
if replicatedID == "" {
return backoff.Permanent(errors.New("Replicated ID not found"))
}
if appID == "" {
return backoff.Permanent(errors.New("App ID not found"))
}

channelID := params.ChannelID
if channelID == "" {
channelID = verifiedLicense.Spec.ChannelID
Expand All @@ -62,31 +104,8 @@ func bootstrap(params APIServerParams) error {
if channelName == "" {
channelName = verifiedLicense.Spec.ChannelName
}

storeOptions := store.InitInMemoryStoreOptions{
ReplicatedID: replicatedID,
AppID: appID,
License: verifiedLicense,
LicenseFields: params.LicenseFields,
AppName: params.AppName,
ChannelID: channelID,
ChannelName: channelName,
ChannelSequence: params.ChannelSequence,
ReleaseSequence: params.ReleaseSequence,
ReleaseCreatedAt: params.ReleaseCreatedAt,
ReleaseNotes: params.ReleaseNotes,
VersionLabel: params.VersionLabel,
ReplicatedAppEndpoint: params.ReplicatedAppEndpoint,
Namespace: params.Namespace,
}
if err := store.InitInMemory(storeOptions); err != nil {
return errors.Wrap(err, "failed to init store")
}

clientset, err := k8sutil.GetClientset()
if err != nil {
return errors.Wrap(err, "failed to get clientset")
}
store.GetStore().SetChannelID(channelID)
store.GetStore().SetChannelName(channelName)

isIntegrationModeEnabled, err := integration.IsEnabled(params.Context, clientset, store.GetStore().GetNamespace(), store.GetStore().GetLicense())
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions pkg/apiserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/cenkalti/backoff/v4"
"github.com/gorilla/mux"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
appstatetypes "github.com/replicatedhq/replicated-sdk/pkg/appstate/types"
"github.com/replicatedhq/replicated-sdk/pkg/buildversion"
"github.com/replicatedhq/replicated-sdk/pkg/handlers"
Expand All @@ -17,7 +16,8 @@ import (

type APIServerParams struct {
Context context.Context
License *kotsv1beta1.License
LicenseBytes []byte
IntegrationLicenseID string
LicenseFields sdklicensetypes.LicenseFields
AppName string
ChannelID string
Expand All @@ -29,6 +29,7 @@ type APIServerParams struct {
VersionLabel string
ReplicatedAppEndpoint string
StatusInformers []appstatetypes.StatusInformerString
ManagedBy string
Namespace string
}

Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type ReplicatedConfig struct {
VersionLabel string `yaml:"versionLabel"`
ReplicatedAppEndpoint string `yaml:"replicatedAppEndpoint"`
StatusInformers []appstatetypes.StatusInformerString `yaml:"statusInformers"`
ManagedBy string `yaml:"managedBy"`
}

func ParseReplicatedConfig(config []byte) (*ReplicatedConfig, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/handlers/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func GetAppUpdates(w http.ResponseWriter, r *http.Request) {
license := store.GetStore().GetLicense()
updates := store.GetStore().GetUpdates()

licenseData, err := sdklicense.GetLatestLicense(license, store.GetStore().GetReplicatedAppEndpoint())
licenseData, err := sdklicense.GetLatestLicense(store.GetStore(), license, store.GetStore().GetReplicatedAppEndpoint())
if err != nil {
logger.Error(errors.Wrap(err, "failed to get latest license"))
JSONCached(w, http.StatusOK, updates)
Expand Down
Loading

0 comments on commit 741aff7

Please sign in to comment.