Skip to content
This repository was 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 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
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.

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
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))
}
}
}
149 changes: 149 additions & 0 deletions cmd/dep/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
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 (
"encoding/json"
"flag"
"fmt"
"github.com/golang/dep"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
"io/ioutil"
"net/http"
"net/url"
"path"
"syscall"
"path/filepath"
)

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)
rc, err := p.RegistryConfig.MarshalTOML()
if err != nil {
return err
}

if err = ioutil.WriteFile(filepath.Join(p.AbsRoot, dep.RegistryConfigName), rc, 0666); err != nil {
return errors.Wrap(err, "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"`
}
10 changes: 7 additions & 3 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 Expand Up @@ -124,6 +126,7 @@ func (c *Config) Run() (exitCode int) {
fs := flag.NewFlagSet(cmdName, flag.ContinueOnError)
fs.SetOutput(c.Stderr)
verbose := fs.Bool("v", false, "enable verbose logging")
noRegistry := fs.Bool("no-registry", false, "disable using registry config")

// Register the subcommand flags in there, too.
cmd.Register(fs)
Expand All @@ -147,9 +150,10 @@ func (c *Config) Run() (exitCode int) {

// Set up dep context.
ctx := &dep.Ctx{
Out: outLogger,
Err: errLogger,
Verbose: *verbose,
Out: outLogger,
Err: errLogger,
Verbose: *verbose,
NoRegistry: *noRegistry,
}

GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))
Expand Down
Loading