installer: orginize bootstrapper, improve service IP handling
diff --git a/core/installer/soft/client.go b/core/installer/soft/client.go
index 2a820a0..635ee0e 100644
--- a/core/installer/soft/client.go
+++ b/core/installer/soft/client.go
@@ -5,7 +5,9 @@
"golang.org/x/crypto/ssh"
"log"
"net"
+ "net/netip"
"os"
+ "regexp"
"strings"
"github.com/go-git/go-billy/v5/memfs"
@@ -15,14 +17,13 @@
)
type Client struct {
- IP string
- port int
+ Addr netip.AddrPort
Signer ssh.Signer
log *log.Logger
pemBytes []byte
}
-func NewClient(ip string, port int, clientPrivateKey []byte, log *log.Logger) (*Client, error) {
+func NewClient(addr netip.AddrPort, clientPrivateKey []byte, log *log.Logger) (*Client, error) {
signer, err := ssh.ParsePrivateKey(clientPrivateKey)
if err != nil {
return nil, err
@@ -30,8 +31,7 @@
log.SetPrefix("SOFT-SERVE: ")
log.Printf("Created signer")
return &Client{
- ip,
- port,
+ addr,
signer,
log,
clientPrivateKey,
@@ -64,7 +64,7 @@
func (ss *Client) RunCommand(args ...string) error {
cmd := strings.Join(args, " ")
log.Printf("Running command %s", cmd)
- client, err := ssh.Dial("tcp", ss.addressSSH(), ss.sshClientConfig())
+ client, err := ssh.Dial("tcp", ss.Addr.String(), ss.sshClientConfig())
if err != nil {
return err
}
@@ -88,18 +88,66 @@
return ss.RunCommand("repo", "collab", "add", repo, user)
}
-func (ss *Client) GetRepo(name string) (*git.Repository, error) {
- return git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
- URL: ss.GetRepoAddress(name),
- Auth: ss.authSSH(),
+type Repository struct {
+ *git.Repository
+ Addr RepositoryAddress
+}
+
+func (ss *Client) GetRepo(name string) (*Repository, error) {
+ return CloneRepo(RepositoryAddress{ss.Addr, name}, ss.Signer)
+}
+
+type RepositoryAddress struct {
+ Addr netip.AddrPort
+ Name string
+}
+
+func ParseRepositoryAddress(addr string) (RepositoryAddress, error) {
+ items := regexp.MustCompile(`ssh://.*)/(.*)`).FindStringSubmatch(addr)
+ if len(items) != 2 {
+ return RepositoryAddress{}, fmt.Errorf("Invalid address")
+ }
+ ipPort, err := netip.ParseAddrPort(items[1])
+ if err != nil {
+ return RepositoryAddress{}, err
+ }
+ return RepositoryAddress{ipPort, items[2]}, nil
+}
+
+func (r RepositoryAddress) FullAddress() string {
+ return fmt.Sprintf("ssh://%s/%s", r.Addr, r.Name)
+}
+
+func CloneRepo(addr RepositoryAddress, signer ssh.Signer) (*Repository, error) {
+ c, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
+ URL: addr.FullAddress(),
+ Auth: &gitssh.PublicKeys{
+ User: "git",
+ Signer: signer,
+ HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{
+ HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ // TODO(giolekva): verify server public key
+ fmt.Printf("--- %+v\n", ssh.MarshalAuthorizedKey(key))
+ return nil
+ },
+ },
+ },
RemoteName: "origin",
ReferenceName: "refs/heads/master",
Depth: 1,
InsecureSkipTLS: true,
Progress: os.Stdout,
})
+ if err != nil {
+ return nil, err
+ }
+ return &Repository{
+ Repository: c,
+ Addr: addr,
+ }, nil
}
+// TODO(giolekva): dead code
func (ss *Client) authSSH() gitssh.AuthMethod {
a, err := gitssh.NewPublicKeys("git", ss.pemBytes, "")
if err != nil {
@@ -149,7 +197,7 @@
return nil
},
}
- _, err := ssh.Dial("tcp", ss.addressSSH(), config)
+ _, err := ssh.Dial("tcp", ss.Addr.String(), config)
if err != nil {
return nil, err
}
@@ -175,9 +223,5 @@
}
func (ss *Client) addressGit() string {
- return fmt.Sprintf("ssh://%s", ss.addressSSH())
-}
-
-func (ss *Client) addressSSH() string {
- return fmt.Sprintf("%s:%d", ss.IP, ss.port)
+ return fmt.Sprintf("ssh://%s", ss.Addr)
}