Merge pull request #1415 from dhiltgen/fix_panic_master

Fix panic in display only case for license - forward port #1408 to master
This commit is contained in:
Sebastiaan van Stijn 2018-11-15 00:55:48 +01:00 committed by GitHub
commit 29625f6124
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 23 deletions

View File

@ -24,11 +24,13 @@ type activateOptions struct {
quiet bool quiet bool
displayOnly bool displayOnly bool
sockPath string sockPath string
licenseLoginFunc func(ctx context.Context, authConfig *types.AuthConfig) (licenseutils.HubUser, error)
} }
// newActivateCommand creates a new `docker engine activate` command // newActivateCommand creates a new `docker engine activate` command
func newActivateCommand(dockerCli command.Cli) *cobra.Command { func newActivateCommand(dockerCli command.Cli) *cobra.Command {
var options activateOptions var options activateOptions
options.licenseLoginFunc = licenseutils.Login
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "activate [OPTIONS]", Use: "activate [OPTIONS]",
@ -60,7 +62,7 @@ https://hub.docker.com/ then specify the file with the '--license' flag.
flags.StringVar(&options.registryPrefix, "registry-prefix", clitypes.RegistryPrefix, "Override the default location where engine images are pulled") flags.StringVar(&options.registryPrefix, "registry-prefix", clitypes.RegistryPrefix, "Override the default location where engine images are pulled")
flags.StringVar(&options.image, "engine-image", "", "Specify engine image") flags.StringVar(&options.image, "engine-image", "", "Specify engine image")
flags.StringVar(&options.format, "format", "", "Pretty-print licenses using a Go template") flags.StringVar(&options.format, "format", "", "Pretty-print licenses using a Go template")
flags.BoolVar(&options.displayOnly, "display-only", false, "only display the available licenses and exit") flags.BoolVar(&options.displayOnly, "display-only", false, "only display license information and exit")
flags.BoolVar(&options.quiet, "quiet", false, "Only display available licenses by ID") flags.BoolVar(&options.quiet, "quiet", false, "Only display available licenses by ID")
flags.StringVar(&options.sockPath, "containerd", "", "override default location of containerd endpoint") flags.StringVar(&options.sockPath, "containerd", "", "override default location of containerd endpoint")
@ -90,6 +92,9 @@ func runActivate(cli command.Cli, options activateOptions) error {
if license, err = getLicenses(ctx, authConfig, cli, options); err != nil { if license, err = getLicenses(ctx, authConfig, cli, options); err != nil {
return err return err
} }
if options.displayOnly {
return nil
}
} else { } else {
if license, err = licenseutils.LoadLocalIssuedLicense(ctx, options.licenseFile); err != nil { if license, err = licenseutils.LoadLocalIssuedLicense(ctx, options.licenseFile); err != nil {
return err return err
@ -136,7 +141,7 @@ Restart docker with 'systemctl restart docker' to complete the activation.`)
} }
func getLicenses(ctx context.Context, authConfig *types.AuthConfig, cli command.Cli, options activateOptions) (*model.IssuedLicense, error) { func getLicenses(ctx context.Context, authConfig *types.AuthConfig, cli command.Cli, options activateOptions) (*model.IssuedLicense, error) {
user, err := licenseutils.Login(ctx, authConfig) user, err := options.licenseLoginFunc(ctx, authConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,14 +1,19 @@
package engine package engine
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"testing" "testing"
"time"
"github.com/docker/cli/internal/licenseutils"
"github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test"
clitypes "github.com/docker/cli/types" clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/docker/licensing"
"github.com/docker/licensing/model"
"gotest.tools/assert" "gotest.tools/assert"
"gotest.tools/fs" "gotest.tools/fs"
"gotest.tools/golden" "gotest.tools/golden"
@ -71,3 +76,73 @@ func TestActivateExpiredLicenseDryRun(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
golden.Assert(t, c.OutBuffer().String(), "expired-license-display-only.golden") golden.Assert(t, c.OutBuffer().String(), "expired-license-display-only.golden")
} }
type mockLicenseClient struct{}
func (c mockLicenseClient) LoginViaAuth(ctx context.Context, username, password string) (authToken string, err error) {
return "", fmt.Errorf("not implemented")
}
func (c mockLicenseClient) GetHubUserOrgs(ctx context.Context, authToken string) (orgs []model.Org, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) GetHubUserByName(ctx context.Context, username string) (user *model.User, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) VerifyLicense(ctx context.Context, license model.IssuedLicense) (res *model.CheckResponse, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) GenerateNewTrialSubscription(ctx context.Context, authToken, dockerID, email string) (subscriptionID string, err error) {
return "", fmt.Errorf("not implemented")
}
func (c mockLicenseClient) ListSubscriptions(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) {
expires := time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC)
return []*model.Subscription{
{
State: "active",
Expires: &expires,
},
}, nil
}
func (c mockLicenseClient) ListSubscriptionsDetails(ctx context.Context, authToken, dockerID string) (response []*model.SubscriptionDetail, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) DownloadLicenseFromHub(ctx context.Context, authToken, subscriptionID string) (license *model.IssuedLicense, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) ParseLicense(license []byte) (parsedLicense *model.IssuedLicense, err error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) StoreLicense(ctx context.Context, dclnt licensing.WrappedDockerClient, licenses *model.IssuedLicense, localRootDir string) error {
return fmt.Errorf("not implemented")
}
func (c mockLicenseClient) LoadLocalLicense(ctx context.Context, dclnt licensing.WrappedDockerClient) (*model.Subscription, error) {
return nil, fmt.Errorf("not implemented")
}
func (c mockLicenseClient) SummarizeLicense(res *model.CheckResponse, keyID string) *model.Subscription {
return nil
}
func TestActivateDisplayOnlyHub(t *testing.T) {
isRoot = func() bool { return true }
c := test.NewFakeCli(&verClient{client.Client{}, types.Version{}, nil, types.Info{}, nil})
c.SetContainerizedEngineClient(
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{}, nil
},
)
hubUser := licenseutils.HubUser{
Client: mockLicenseClient{},
}
options := activateOptions{
licenseLoginFunc: func(ctx context.Context, authConfig *types.AuthConfig) (licenseutils.HubUser, error) {
return hubUser, nil
},
displayOnly: true,
}
c.OutBuffer().Reset()
err := runActivate(c, options)
assert.NilError(t, err)
golden.Assert(t, c.OutBuffer().String(), "expired-hub-license-display-only.golden")
}

View File

@ -0,0 +1,3 @@
Looking for existing licenses for ...
NUM OWNER PRODUCT ID EXPIRES PRICING COMPONENTS
0 2010-01-01 00:00:00 +0000 UTC

View File

@ -20,7 +20,7 @@ import (
// HubUser wraps a licensing client and holds key information // HubUser wraps a licensing client and holds key information
// for a user to avoid multiple lookups // for a user to avoid multiple lookups
type HubUser struct { type HubUser struct {
client licensing.Client Client licensing.Client
token string token string
User model.User User model.User
Orgs []model.Org Orgs []model.Org
@ -73,7 +73,7 @@ func Login(ctx context.Context, authConfig *types.AuthConfig) (HubUser, error) {
return HubUser{}, err return HubUser{}, err
} }
return HubUser{ return HubUser{
client: lclient, Client: lclient,
token: token, token: token,
User: *user, User: *user,
Orgs: orgs, Orgs: orgs,
@ -83,12 +83,12 @@ func Login(ctx context.Context, authConfig *types.AuthConfig) (HubUser, error) {
// GetAvailableLicenses finds all available licenses for a given account and their orgs // GetAvailableLicenses finds all available licenses for a given account and their orgs
func (u HubUser) GetAvailableLicenses(ctx context.Context) ([]LicenseDisplay, error) { func (u HubUser) GetAvailableLicenses(ctx context.Context) ([]LicenseDisplay, error) {
subs, err := u.client.ListSubscriptions(ctx, u.token, u.User.ID) subs, err := u.Client.ListSubscriptions(ctx, u.token, u.User.ID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, org := range u.Orgs { for _, org := range u.Orgs {
orgSub, err := u.client.ListSubscriptions(ctx, u.token, org.ID) orgSub, err := u.Client.ListSubscriptions(ctx, u.token, org.ID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -134,16 +134,16 @@ func (u HubUser) GetAvailableLicenses(ctx context.Context) ([]LicenseDisplay, er
// GenerateTrialLicense will generate a new trial license for the specified user or org // GenerateTrialLicense will generate a new trial license for the specified user or org
func (u HubUser) GenerateTrialLicense(ctx context.Context, targetID string) (*model.IssuedLicense, error) { func (u HubUser) GenerateTrialLicense(ctx context.Context, targetID string) (*model.IssuedLicense, error) {
subID, err := u.client.GenerateNewTrialSubscription(ctx, u.token, targetID, u.User.Email) subID, err := u.Client.GenerateNewTrialSubscription(ctx, u.token, targetID, u.User.Email)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return u.client.DownloadLicenseFromHub(ctx, u.token, subID) return u.Client.DownloadLicenseFromHub(ctx, u.token, subID)
} }
// GetIssuedLicense will download a license by ID // GetIssuedLicense will download a license by ID
func (u HubUser) GetIssuedLicense(ctx context.Context, ID string) (*model.IssuedLicense, error) { func (u HubUser) GetIssuedLicense(ctx context.Context, ID string) (*model.IssuedLicense, error) {
return u.client.DownloadLicenseFromHub(ctx, u.token, ID) return u.Client.DownloadLicenseFromHub(ctx, u.token, ID)
} }
// LoadLocalIssuedLicense will load a local license file // LoadLocalIssuedLicense will load a local license file

View File

@ -43,7 +43,7 @@ func TestGetOrgByID(t *testing.T) {
func TestGetAvailableLicensesListFail(t *testing.T) { func TestGetAvailableLicensesListFail(t *testing.T) {
ctx := context.Background() ctx := context.Background()
user := HubUser{ user := HubUser{
client: &fakeLicensingClient{ Client: &fakeLicensingClient{
listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) { listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) {
return nil, fmt.Errorf("list subscriptions error") return nil, fmt.Errorf("list subscriptions error")
}, },
@ -59,7 +59,7 @@ func TestGetAvailableLicensesOrgFail(t *testing.T) {
Orgs: []model.Org{ Orgs: []model.Org{
{ID: "orgid"}, {ID: "orgid"},
}, },
client: &fakeLicensingClient{ Client: &fakeLicensingClient{
listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) { listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) {
if dockerID == "orgid" { if dockerID == "orgid" {
return nil, fmt.Errorf("list subscriptions org error") return nil, fmt.Errorf("list subscriptions org error")
@ -86,7 +86,7 @@ func TestGetAvailableLicensesHappy(t *testing.T) {
Orgname: "orgname", Orgname: "orgname",
}, },
}, },
client: &fakeLicensingClient{ Client: &fakeLicensingClient{
listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) { listSubscriptionsFunc: func(ctx context.Context, authToken, dockerID string) (response []*model.Subscription, err error) {
if dockerID == "orgid" { if dockerID == "orgid" {
return []*model.Subscription{ return []*model.Subscription{
@ -146,7 +146,7 @@ func TestGetAvailableLicensesHappy(t *testing.T) {
func TestGenerateTrialFail(t *testing.T) { func TestGenerateTrialFail(t *testing.T) {
ctx := context.Background() ctx := context.Background()
user := HubUser{ user := HubUser{
client: &fakeLicensingClient{ Client: &fakeLicensingClient{
generateNewTrialSubscriptionFunc: func(ctx context.Context, authToken, dockerID, email string) (subscriptionID string, err error) { generateNewTrialSubscriptionFunc: func(ctx context.Context, authToken, dockerID, email string) (subscriptionID string, err error) {
return "", fmt.Errorf("generate trial failure") return "", fmt.Errorf("generate trial failure")
}, },
@ -160,7 +160,7 @@ func TestGenerateTrialFail(t *testing.T) {
func TestGenerateTrialHappy(t *testing.T) { func TestGenerateTrialHappy(t *testing.T) {
ctx := context.Background() ctx := context.Background()
user := HubUser{ user := HubUser{
client: &fakeLicensingClient{ Client: &fakeLicensingClient{
generateNewTrialSubscriptionFunc: func(ctx context.Context, authToken, dockerID, email string) (subscriptionID string, err error) { generateNewTrialSubscriptionFunc: func(ctx context.Context, authToken, dockerID, email string) (subscriptionID string, err error) {
return "subid", nil return "subid", nil
}, },
@ -174,7 +174,7 @@ func TestGenerateTrialHappy(t *testing.T) {
func TestGetIssuedLicense(t *testing.T) { func TestGetIssuedLicense(t *testing.T) {
ctx := context.Background() ctx := context.Background()
user := HubUser{ user := HubUser{
client: &fakeLicensingClient{}, Client: &fakeLicensingClient{},
} }
id := "idgoeshere" id := "idgoeshere"
_, err := user.GetIssuedLicense(ctx, id) _, err := user.GetIssuedLicense(ctx, id)