Skip to content

Commit 0c586e8

Browse files
feat(dependency): add specific agent protocol for dependency (#62)
* feat(dependency): add specific agent for dependency * fix(service): add agent to .lock * feature(deps): clean code + add tests + gofmt * feature(deps): rename agent to protocol
1 parent 2b9c395 commit 0c586e8

File tree

10 files changed

+148
-57
lines changed

10 files changed

+148
-57
lines changed

cmd/up.go

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"os"
5-
"path/filepath"
65
"strings"
76

87
"github.com/mitchellh/go-homedir"
@@ -12,15 +11,6 @@ import (
1211
"github.com/stormcat24/protodep/service"
1312
)
1413

15-
var (
16-
authProvider helper.AuthProvider
17-
)
18-
19-
type protoResource struct {
20-
source string
21-
relativeDest string
22-
}
23-
2414
var upCmd = &cobra.Command{
2515
Use: "up",
2616
Short: "Populate .proto vendors existing protodep.toml and lock",
@@ -84,27 +74,22 @@ var upCmd = &cobra.Command{
8474
return err
8575
}
8676

87-
if useHttps {
88-
authProvider = helper.NewAuthProvider(helper.WithHTTPS(basicAuthUsername, basicAuthPassword))
89-
} else {
90-
if identityFile == "" && password == "" {
91-
authProvider = helper.NewAuthProvider()
92-
} else {
93-
identifyPath := filepath.Join(homeDir, ".ssh", identityFile)
94-
isSSH, err := helper.IsAvailableSSH(identifyPath)
95-
if err != nil {
96-
return err
97-
}
98-
if isSSH {
99-
authProvider = helper.NewAuthProvider(helper.WithPemFile(identifyPath, password))
100-
} else {
101-
logger.Warn("The identity file path has been passed but is not available. Falling back to ssh-agent, the default authentication method.")
102-
authProvider = helper.NewAuthProvider()
103-
}
104-
}
77+
conf := helper.SyncConfig{
78+
UseHttps: useHttps,
79+
HomeDir: homeDir,
80+
TargetDir: pwd,
81+
OutputDir: pwd,
82+
BasicAuthUsername: basicAuthUsername,
83+
BasicAuthPassword: basicAuthPassword,
84+
IdentityFile: identityFile,
85+
IdentityPassword: password,
86+
}
87+
88+
updateService, err := service.NewSync(&conf)
89+
if err != nil {
90+
return err
10591
}
10692

107-
updateService := service.NewSync(authProvider, homeDir, pwd, pwd)
10893
return updateService.Resolve(isForceUpdate, isCleanupCache)
10994
},
11095
}

cmd/version.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ const art = `
1717
\|__| \|__|\|__|\|_______| \|__| \|_______|\|_______|\|_______|\|__|`
1818

1919
var versionCmd = &cobra.Command{
20-
Use: "version",
20+
Use: "version",
2121
Short: "Show protodep version",
2222
RunE: func(cdm *cobra.Command, args []string) error {
2323
fmt.Println(art)
2424
fmt.Println("")
2525
fmt.Println(version.Get())
2626
return nil
2727
},
28-
}
28+
}

dependency/dependency_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@ func TestLoad(t *testing.T) {
2323
require.Equal(t, "github.com/protocolbuffers/protobuf/src", withBranch.Target)
2424
require.Equal(t, "master", withBranch.Branch)
2525
require.Equal(t, "", withBranch.Revision)
26+
require.Equal(t, "", withBranch.Protocol)
2627

2728
require.Equal(t, "github.com/grpc-ecosystem/grpc-gateway/examples/examplepb", withRevision.Target)
2829
require.Equal(t, "", withRevision.Branch)
2930
require.Equal(t, "v1.2.2", withRevision.Revision)
3031
require.Equal(t, "grpc-gateway/examplepb", withRevision.Path)
32+
require.Equal(t, "ssh", withRevision.Protocol)
3133

3234
require.Equal(t, "github.com/kubernetes/helm/_proto/hapi", withIgnore.Target)
3335
require.Equal(t, "", withIgnore.Branch)
3436
require.Equal(t, "v2.8.1", withIgnore.Revision)
3537
require.Equal(t, []string{"./release", "./rudder", "./services", "./version"}, withIgnore.Ignores)
38+
require.Equal(t, "https", withIgnore.Protocol)
3639
}

dependency/protodep.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ proto_outdir = "./proto"
88
target = "github.com/grpc-ecosystem/grpc-gateway/examples/examplepb"
99
revision = "v1.2.2"
1010
path = "grpc-gateway/examplepb"
11+
protocol = "ssh"
1112

1213
[[dependencies]]
1314
target = "github.com/kubernetes/helm/_proto/hapi"
1415
revision = "v2.8.1"
15-
ignores = ["./release", "./rudder", "./services", "./version"]
16+
ignores = ["./release", "./rudder", "./services", "./version"]
17+
protocol = "https"

dependency/schema.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type ProtoDepDependency struct {
1515
Branch string `toml:"branch"`
1616
Path string `toml:"path"`
1717
Ignores []string `toml:"ignores"`
18+
Protocol string `toml:"protocol"`
1819
}
1920

2021
func (d *ProtoDepDependency) Repository() string {

helper/sync.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package helper
2+
3+
type SyncConfig struct {
4+
// UseHttps will force https on each proto dependencies fetch.
5+
UseHttps bool
6+
7+
// HomeDir is the home directory, used as root to find ssh identity files.
8+
HomeDir string
9+
10+
// TargetDir is the dependencies directory where protodep.toml files are located.
11+
TargetDir string
12+
13+
// OutputDir is the directory where proto files will be cloned.
14+
OutputDir string
15+
16+
// BasicAuthUsername is used if `https` mode is enable. Optional, only if dependency repository needs authentication.
17+
BasicAuthUsername string
18+
19+
// BasicAuthPassword is used if `https` mode is enable. Optional, only if dependency repository needs authentication.
20+
BasicAuthPassword string
21+
22+
// IdentityFile is used if `ssh` mode is enable. Optional, it is computed like {home}/.ssh/
23+
IdentityFile string
24+
25+
// IdentityPassword is used if `ssh` mode is enable. Optional, only if identity file needs a passphrase.
26+
IdentityPassword string
27+
}

service/protodep.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ proto_outdir = "./proto"
33
[[dependencies]]
44
target = "github.com/opensaasstudio/plasma/protobuf"
55
branch = "master"
6+
protocol = "ssh"
67

78
[[dependencies]]
89
target = "github.com/protocolbuffers/protobuf/src"
910
branch = "master"
10-
ignores = ["/google/protobuf/test_messages_proto3", "**/util/**/testdata/**", "**/protobuf/test_messages_proto2.proto"]
11+
ignores = ["/google/protobuf/test_messages_proto3", "**/util/**/testdata/**", "**/protobuf/test_messages_proto2.proto"]
12+
protocol = "https"

service/sync.go

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package service
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"os"
67
"path/filepath"
@@ -20,34 +21,41 @@ type protoResource struct {
2021

2122
type Sync interface {
2223
Resolve(forceUpdate bool, cleanupCache bool) error
24+
25+
SetHttpsAuthProvider(provider helper.AuthProvider)
26+
SetSshAuthProvider(provider helper.AuthProvider)
2327
}
2428

2529
type SyncImpl struct {
26-
authProvider helper.AuthProvider
27-
userHomeDir string
28-
targetDir string
29-
outputRootDir string
30+
conf *helper.SyncConfig
31+
32+
httpsProvider helper.AuthProvider
33+
sshProvider helper.AuthProvider
3034
}
3135

32-
func NewSync(authProvider helper.AuthProvider, userHomeDir string, targetDir string, outputRootDir string) Sync {
33-
return &SyncImpl{
34-
authProvider: authProvider,
35-
userHomeDir: userHomeDir,
36-
targetDir: targetDir,
37-
outputRootDir: outputRootDir,
36+
func NewSync(conf *helper.SyncConfig) (Sync, error) {
37+
s := &SyncImpl{
38+
conf: conf,
3839
}
40+
41+
err := s.initAuthProviders()
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
return s, nil
3947
}
4048

4149
func (s *SyncImpl) Resolve(forceUpdate bool, cleanupCache bool) error {
4250

43-
dep := dependency.NewDependency(s.targetDir, forceUpdate)
51+
dep := dependency.NewDependency(s.conf.TargetDir, forceUpdate)
4452
protodep, err := dep.Load()
4553
if err != nil {
4654
return err
4755
}
4856

4957
newdeps := make([]dependency.ProtoDepDependency, 0, len(protodep.Dependencies))
50-
protodepDir := filepath.Join(s.userHomeDir, ".protodep")
58+
protodepDir := filepath.Join(s.conf.HomeDir, ".protodep")
5159

5260
_, err = os.Stat(protodepDir)
5361
if cleanupCache && err == nil {
@@ -65,13 +73,28 @@ func (s *SyncImpl) Resolve(forceUpdate bool, cleanupCache bool) error {
6573
}
6674
}
6775

68-
outdir := filepath.Join(s.outputRootDir, protodep.ProtoOutdir)
76+
outdir := filepath.Join(s.conf.OutputDir, protodep.ProtoOutdir)
6977
if err := os.RemoveAll(outdir); err != nil {
7078
return err
7179
}
7280

7381
for _, dep := range protodep.Dependencies {
74-
gitrepo := repository.NewGitRepository(protodepDir, dep, s.authProvider)
82+
var authProvider helper.AuthProvider
83+
84+
if s.conf.UseHttps {
85+
authProvider = s.httpsProvider
86+
} else {
87+
switch dep.Protocol {
88+
case "https":
89+
authProvider = s.httpsProvider
90+
case "ssh", "":
91+
authProvider = s.sshProvider
92+
default:
93+
return fmt.Errorf("%s protocol is not accepted (ssh or https only)", dep.Protocol)
94+
}
95+
}
96+
97+
gitrepo := repository.NewGitRepository(protodepDir, dep, authProvider)
7598

7699
repo, err := gitrepo.Open()
77100
if err != nil {
@@ -119,6 +142,7 @@ func (s *SyncImpl) Resolve(forceUpdate bool, cleanupCache bool) error {
119142
Revision: repo.Hash,
120143
Path: repo.Dep.Path,
121144
Ignores: repo.Dep.Ignores,
145+
Protocol: repo.Dep.Protocol,
122146
})
123147
}
124148

@@ -136,6 +160,39 @@ func (s *SyncImpl) Resolve(forceUpdate bool, cleanupCache bool) error {
136160
return nil
137161
}
138162

163+
func (s *SyncImpl) SetHttpsAuthProvider(provider helper.AuthProvider) {
164+
s.httpsProvider = provider
165+
}
166+
167+
func (s *SyncImpl) SetSshAuthProvider(provider helper.AuthProvider) {
168+
s.sshProvider = provider
169+
}
170+
171+
func (s *SyncImpl) initAuthProviders() error {
172+
s.httpsProvider = helper.NewAuthProvider(helper.WithHTTPS(s.conf.BasicAuthUsername, s.conf.BasicAuthPassword))
173+
174+
if s.conf.IdentityFile == "" && s.conf.IdentityPassword == "" {
175+
s.sshProvider = helper.NewAuthProvider()
176+
177+
return nil
178+
}
179+
180+
identifyPath := filepath.Join(s.conf.HomeDir, ".ssh", s.conf.IdentityFile)
181+
isSSH, err := helper.IsAvailableSSH(identifyPath)
182+
if err != nil {
183+
return err
184+
}
185+
186+
if isSSH {
187+
s.sshProvider = helper.NewAuthProvider(helper.WithPemFile(identifyPath, s.conf.IdentityPassword))
188+
} else {
189+
logger.Warn("The identity file path has been passed but is not available. Falling back to ssh-agent, the default authentication method.")
190+
s.sshProvider = helper.NewAuthProvider()
191+
}
192+
193+
return nil
194+
}
195+
139196
func compileIngoresToGlob(ignores []string) []glob.Glob {
140197
globIngores := make([]glob.Glob, len(ignores))
141198

service/sync_test.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,36 @@ func TestSync(t *testing.T) {
2121
err = os.RemoveAll(dotProtoDir)
2222
require.NoError(t, err)
2323

24-
c := gomock.NewController(t)
25-
defer c.Finish()
26-
27-
authProviderMock := helper.NewMockAuthProvider(c)
28-
authProviderMock.EXPECT().AuthMethod().Return(nil, nil).AnyTimes()
29-
authProviderMock.EXPECT().GetRepositoryURL("github.com/protocolbuffers/protobuf").Return("https://github.com/protocolbuffers/protobuf.git")
30-
authProviderMock.EXPECT().GetRepositoryURL("github.com/opensaasstudio/plasma").Return("https://github.com/opensaasstudio/plasma.git")
31-
3224
pwd, err := os.Getwd()
3325
fmt.Println(pwd)
3426

3527
require.NoError(t, err)
3628

3729
outputRootDir := os.TempDir()
3830

39-
target := NewSync(authProviderMock, dotProtoDir, pwd, outputRootDir)
31+
conf := helper.SyncConfig{
32+
HomeDir: dotProtoDir,
33+
TargetDir: pwd,
34+
OutputDir: outputRootDir,
35+
}
36+
37+
target, err := NewSync(&conf)
38+
require.NoError(t, err)
39+
40+
c := gomock.NewController(t)
41+
defer c.Finish()
42+
43+
httpsAuthProviderMock := helper.NewMockAuthProvider(c)
44+
httpsAuthProviderMock.EXPECT().AuthMethod().Return(nil, nil).AnyTimes()
45+
httpsAuthProviderMock.EXPECT().GetRepositoryURL("github.com/protocolbuffers/protobuf").Return("https://github.com/protocolbuffers/protobuf.git")
46+
47+
sshAuthProviderMock := helper.NewMockAuthProvider(c)
48+
sshAuthProviderMock.EXPECT().AuthMethod().Return(nil, nil).AnyTimes()
49+
sshAuthProviderMock.EXPECT().GetRepositoryURL("github.com/opensaasstudio/plasma").Return("https://github.com/opensaasstudio/plasma.git")
50+
51+
target.SetHttpsAuthProvider(httpsAuthProviderMock)
52+
target.SetSshAuthProvider(sshAuthProviderMock)
53+
4054
// clone
4155
err = target.Resolve(false, false)
4256
require.NoError(t, err)

version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ func (i Info) String() string {
3333
i.GitCommitFull,
3434
i.BuildDate,
3535
)
36-
}
36+
}

0 commit comments

Comments
 (0)