Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Registry support #1172

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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
10 changes: 8 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions cmd/dep/base_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestBaseImporter_IsTag(t *testing.T) {
h.Parallel()

ctx := newTestContext(h)
sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
h.Must(err)
defer sm.Release()

Expand Down Expand Up @@ -147,7 +147,7 @@ func TestBaseImporter_LookupVersionForLockedProject(t *testing.T) {
//h.Parallel()

ctx := newTestContext(h)
sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
h.Must(err)
defer sm.Release()

Expand Down Expand Up @@ -431,7 +431,7 @@ func (tc convertTestCase) Exec(t *testing.T, convert func(logger *log.Logger, sm
//h.Parallel()

ctx := newTestContext(h)
sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
h.Must(err)
defer sm.Release()

Expand Down
14 changes: 8 additions & 6 deletions cmd/dep/ensure.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func (cmd *ensureCommand) Register(fs *flag.FlagSet) {
fs.BoolVar(&cmd.add, "add", false, "add new dependencies, or populate Gopkg.toml with constraints for existing dependencies")
fs.BoolVar(&cmd.vendorOnly, "vendor-only", false, "populate vendor/ from Gopkg.lock without updating it first")
fs.BoolVar(&cmd.noVendor, "no-vendor", false, "update Gopkg.lock (if needed), but do not update vendor/")
fs.BoolVar(&cmd.noRegistry, "no-registry", false, "disable downloading dependencies using registry config")
Copy link
Member

Choose a reason for hiding this comment

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

OK, I'm gonna focus several interrelated things on this one line:

  1. This needs to be handled more globally, as it's relevant for dep status (and possibly even dep init)
  2. To that end, let's start by expressing it as an environment variable rather than as an explicit flag
  3. It should be processed in and stored as a flag on dep.Ctx, which will obviate the need for the additional parameter on Ctx.SourceManager().

The only crucial thing here is that the value of the environment variable itself be injected onto the dep.Ctx (rather than being read directly from the environment out of any Ctx method) so that tests can easily set their own values as needed.

in keeping with some other notes in this review, we may also end up just forcing this to always be on, so that the registry-based code is not reachable at all. (or maybe there's another hookpoint we'll pick)

Copy link

Choose a reason for hiding this comment

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

Wouldn't having this as an environment variable defeat the purpose of ease of use? Practically speaking, 'no-registry' is something you wouldn't want to keep around as a global flag but merely use it to initiate vendor population.
If the reason is that this flag has to apply to other commands then surely there are ways to achieve that without requiring an environment variable.

fs.BoolVar(&cmd.dryRun, "dry-run", false, "only report the changes that would be made")
}

Expand All @@ -134,6 +135,7 @@ type ensureCommand struct {
add bool
noVendor bool
vendorOnly bool
noRegistry bool
dryRun bool
}

Expand All @@ -152,7 +154,7 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
return err
}

sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(cmd.noRegistry)
if err != nil {
return err
}
Expand Down Expand Up @@ -245,7 +247,7 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
// that "verification" is supposed to look like (#121); in the meantime,
// we unconditionally write out vendor/ so that `dep ensure`'s behavior
// is maximally compatible with what it will eventually become.
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorAlways)
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, nil, dep.VendorAlways)
if err != nil {
return err
}
Expand All @@ -271,7 +273,7 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
if cmd.noVendor {
vendorBehavior = dep.VendorNever
}
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), vendorBehavior)
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), nil, vendorBehavior)
if err != nil {
return err
}
Expand All @@ -296,7 +298,7 @@ func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Proj
}
// Pass the same lock as old and new so that the writer will observe no
// difference and choose not to write it out.
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorAlways)
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, nil, dep.VendorAlways)
if err != nil {
return err
}
Expand Down Expand Up @@ -392,7 +394,7 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
return errors.Wrap(err, "ensure Solve()")
}

sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), dep.VendorOnChanged)
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), nil, dep.VendorOnChanged)
if err != nil {
return err
}
Expand Down Expand Up @@ -649,7 +651,7 @@ func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm
}
sort.Strings(reqlist)

sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), dep.VendorOnChanged)
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), nil, dep.VendorOnChanged)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/glide_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestGlideConfig_Import(t *testing.T) {
defer h.Cleanup()

ctx := newTestContext(h)
sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
h.Must(err)
defer sm.Release()

Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/godep_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestGodepConfig_Import(t *testing.T) {
sm, err := gps.NewSourceManager(gps.SourceManagerConfig{
Cachedir: h.Path(cacheDir),
Logger: log.New(test.Writer{TB: t}, "", 0),
})
}, nil)
h.Must(err)
defer sm.Release()

Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/govend_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func TestGovendConfig_Import(t *testing.T) {
h.TempCopy(filepath.Join(testProjectRoot, govendYAMLName), "init/govend/vendor.yml")

projectRoot := h.Path(testProjectRoot)
sm, err := gps.NewSourceManager(gps.SourceManagerConfig{Cachedir: h.Path(cacheDir)})
sm, err := gps.NewSourceManager(gps.SourceManagerConfig{Cachedir: h.Path(cacheDir)}, nil)
h.Must(err)
defer sm.Release()

Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/hash_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (hashinCommand) Run(ctx *dep.Ctx, args []string) error {
return err
}

sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/dep/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
}
p.ImportRoot = gps.ProjectRoot(ip)

sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
if err != nil {
return errors.Wrap(err, "getSourceManager")
}
Expand Down Expand Up @@ -210,7 +210,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
ctx.Err.Printf("Old vendor backed up to %v", vendorbak)
}

sw, err := dep.NewSafeWriter(p.Manifest, nil, p.Lock, dep.VendorAlways)
sw, err := dep.NewSafeWriter(p.Manifest, nil, p.Lock, nil, dep.VendorAlways)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestGetDirectDependencies_ConsolidatesRootProjects(t *testing.T) {
defer h.Cleanup()

ctx := newTestContext(h)
sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
h.Must(err)
defer sm.Release()

Expand Down
3 changes: 3 additions & 0 deletions cmd/dep/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestIntegration(t *testing.T) {

test.NeedsExternalNetwork(t)
test.NeedsGit(t)
test.SetupRegistry(t)

wd, err := os.Getwd()
if err != nil {
Expand Down Expand Up @@ -134,10 +135,12 @@ func testIntegration(name, relPath, wd string, externalProc bool, run integratio
// Update manifest and lock
testCase.UpdateFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName))
testCase.UpdateFile(dep.LockName, testProj.ProjPath(dep.LockName))
testCase.UpdateFile(dep.RegistryConfigName, testProj.ProjPath(dep.RegistryConfigName))
} else {
// Check final manifest and lock
testCase.CompareFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName))
testCase.CompareFile(dep.LockName, testProj.ProjPath(dep.LockName))
testCase.CompareFile(dep.RegistryConfigName, testProj.ProjPath(dep.RegistryConfigName))
}
}
}
150 changes: 150 additions & 0 deletions cmd/dep/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package main
Copy link
Member

Choose a reason for hiding this comment

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

we need to hide this from normal builds until we're actually ready to ship the registry. feature-flag style, dep login needs to not even be recognized as a command until we flip the switch.

maybe we do this with build tags, or maybe something else, but we can't put new commands in front of our users until it's mostly baked.


import (
"flag"
"github.com/golang/dep"
"github.com/pkg/errors"
"fmt"
"path"
"net/http"
"syscall"
"golang.org/x/crypto/ssh/terminal"
"encoding/json"
"io/ioutil"
"net/url"
)

const loginShortHelp = `Login to a registry server and save configuration`
const loginLongHelp = `
Login to a remote registry server containing go dependencies and persist the login configuration.

If your registry allows anonymous access you can leave out the username and password parameters.
`

const noValue = "depNoInputProvided"

func (cmd *loginCommand) Name() string { return "login" }
func (cmd *loginCommand) Args() string { return "<url>" }
func (cmd *loginCommand) ShortHelp() string { return loginShortHelp }
func (cmd *loginCommand) LongHelp() string { return loginLongHelp }
func (cmd *loginCommand) Hidden() bool { return false }

func (cmd *loginCommand) Register(fs *flag.FlagSet) {
fs.StringVar(&cmd.user, "u", noValue, "provide username for registry")
fs.StringVar(&cmd.password, "p", noValue, "provide password for registry")
}

type loginCommand struct {
user string
password string
}

func (cmd *loginCommand) getProject(ctx *dep.Ctx) (*dep.Project, error) {
p, err := ctx.LoadProject()
if p != nil {
return p, err
}
p = new(dep.Project)
if err := p.SetRoot(ctx.WorkingDir); err != nil {
return nil, errors.Wrap(err, "NewProject")
}
return p, nil
}

func (cmd *loginCommand) Run(ctx *dep.Ctx, args []string) error {
if len(args) > 1 {
return errors.Errorf("too many args (%d)", len(args))
}

if len(args) != 1 {
return errors.New("registry URL is required")
}

p, err := cmd.getProject(ctx)
u, err := url.Parse(args[0])
if err != nil {
return err
}
u.Path = path.Join(u.Path, "api/v1/auth/token")

var token string
token, err = getToken(u.String(), cmd.user, cmd.password)
if err != nil {
return err
}

p.RegistryConfig = dep.NewRegistryConfig(args[0], token)

var sw *dep.SafeWriter
sw, err = dep.NewSafeWriter(nil, nil, nil, p.RegistryConfig, dep.VendorNever)
if err != nil {
return err
}

if err := sw.Write(p.AbsRoot, nil, false, ctx.Err); err != nil {
return errors.Wrap(err, "safe write of registry configuration")
}

return nil
}

func readUsername() (string, error) {
var user string
print("username: ")
_, err := fmt.Scanln(&user)
if err != nil {
return "", err
}
return user, nil
}

func readPassword() (string, error) {
print("password: ")
password, err := terminal.ReadPassword(int(syscall.Stdin))
if err != nil {
return "", err
}
println()
return string(password), nil
}

func getToken(url, user, password string) (string, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}

if user == noValue {
user, err = readUsername()
if err != nil {
return "", err
}
}
if password == noValue {
password, err = readPassword()
if err != nil {
return "", err
}
}

req.SetBasicAuth(user, string(password))

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", errors.Errorf("%s %s", url, http.StatusText(resp.StatusCode))
}
var bytes []byte
bytes, err = ioutil.ReadAll(resp.Body)

var loginResp rawLoginResp
err = json.Unmarshal(bytes, &loginResp)
return loginResp.Token, err
}

type rawLoginResp struct {
Token string `json:"token"`
}
2 changes: 2 additions & 0 deletions cmd/dep/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func (c *Config) Run() (exitCode int) {
&hashinCommand{},
&pruneCommand{},
&versionCommand{},
&loginCommand{},
&publishCommand{},
}

examples := [][2]string{
Expand Down
2 changes: 1 addition & 1 deletion cmd/dep/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (cmd *pruneCommand) Run(ctx *dep.Ctx, args []string) error {
return err
}

sm, err := ctx.SourceManager()
sm, err := ctx.SourceManager(false)
if err != nil {
return err
}
Expand Down
Loading