Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
95700aa6
Commit
95700aa6
authored
Jan 22, 2025
by
Brad Davidson
Committed by
Brad Davidson
Jan 27, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update p2p boostrap helpers for Spegel v0.0.30
Signed-off-by:
Brad Davidson
<
brad.davidson@rancher.com
>
parent
e808d3e8
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
191 additions
and
86 deletions
+191
-86
token.go
pkg/clientaccess/token.go
+44
-12
bootstrap.go
pkg/spegel/bootstrap.go
+108
-56
spegel.go
pkg/spegel/spegel.go
+39
-18
No files found.
pkg/clientaccess/token.go
View file @
95700aa6
...
@@ -48,6 +48,9 @@ var (
...
@@ -48,6 +48,9 @@ var (
// ClientOption is a callback to mutate the http client prior to use
// ClientOption is a callback to mutate the http client prior to use
type
ClientOption
func
(
*
http
.
Client
)
type
ClientOption
func
(
*
http
.
Client
)
// RequestOption is a callback to mutate the http request prior to use
type
RequestOption
func
(
*
http
.
Request
)
// Info contains fields that track parsed parts of a cluster join token
// Info contains fields that track parsed parts of a cluster join token
type
Info
struct
{
type
Info
struct
{
*
kubeadm
.
BootstrapTokenString
*
kubeadm
.
BootstrapTokenString
...
@@ -240,7 +243,7 @@ func parseToken(token string) (*Info, error) {
...
@@ -240,7 +243,7 @@ func parseToken(token string) (*Info, error) {
// If the CA bundle is not empty but does not contain any valid certs, it validates using
// If the CA bundle is not empty but does not contain any valid certs, it validates using
// an empty CA bundle (which will always fail).
// an empty CA bundle (which will always fail).
// If valid cert+key paths can be loaded from the provided paths, they are used for client cert auth.
// If valid cert+key paths can be loaded from the provided paths, they are used for client cert auth.
func
GetHTTPClient
(
cacerts
[]
byte
,
certFile
,
keyFile
string
,
option
...
ClientOption
)
*
http
.
Client
{
func
GetHTTPClient
(
cacerts
[]
byte
,
certFile
,
keyFile
string
,
option
s
...
any
)
*
http
.
Client
{
if
len
(
cacerts
)
==
0
{
if
len
(
cacerts
)
==
0
{
return
defaultClient
return
defaultClient
}
}
...
@@ -265,8 +268,10 @@ func GetHTTPClient(cacerts []byte, certFile, keyFile string, option ...ClientOpt
...
@@ -265,8 +268,10 @@ func GetHTTPClient(cacerts []byte, certFile, keyFile string, option ...ClientOpt
},
},
}
}
for
_
,
o
:=
range
option
{
for
_
,
o
:=
range
options
{
o
(
client
)
if
clientOption
,
ok
:=
o
.
(
ClientOption
);
ok
{
clientOption
(
client
)
}
}
}
return
client
return
client
}
}
...
@@ -278,8 +283,14 @@ func WithTimeout(d time.Duration) ClientOption {
...
@@ -278,8 +283,14 @@ func WithTimeout(d time.Duration) ClientOption {
}
}
}
}
func
WithHeader
(
k
,
v
string
)
RequestOption
{
return
func
(
r
*
http
.
Request
)
{
r
.
Header
.
Add
(
k
,
v
)
}
}
// Get makes a request to a subpath of info's BaseURL
// Get makes a request to a subpath of info's BaseURL
func
(
i
*
Info
)
Get
(
path
string
,
option
...
ClientOption
)
([]
byte
,
error
)
{
func
(
i
*
Info
)
Get
(
path
string
,
option
s
...
any
)
([]
byte
,
error
)
{
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -290,11 +301,12 @@ func (i *Info) Get(path string, option ...ClientOption) ([]byte, error) {
...
@@ -290,11 +301,12 @@ func (i *Info) Get(path string, option ...ClientOption) ([]byte, error) {
}
}
p
.
Scheme
=
u
.
Scheme
p
.
Scheme
=
u
.
Scheme
p
.
Host
=
u
.
Host
p
.
Host
=
u
.
Host
return
get
(
p
.
String
(),
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
option
...
),
i
.
Username
,
i
.
Password
,
i
.
Token
())
client
:=
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
options
...
)
return
get
(
p
.
String
(),
client
,
i
.
Username
,
i
.
Password
,
i
.
Token
(),
options
...
)
}
}
// Put makes a request to a subpath of info's BaseURL
// Put makes a request to a subpath of info's BaseURL
func
(
i
*
Info
)
Put
(
path
string
,
body
[]
byte
,
option
...
ClientOption
)
error
{
func
(
i
*
Info
)
Put
(
path
string
,
body
[]
byte
,
option
s
...
any
)
error
{
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -305,11 +317,12 @@ func (i *Info) Put(path string, body []byte, option ...ClientOption) error {
...
@@ -305,11 +317,12 @@ func (i *Info) Put(path string, body []byte, option ...ClientOption) error {
}
}
p
.
Scheme
=
u
.
Scheme
p
.
Scheme
=
u
.
Scheme
p
.
Host
=
u
.
Host
p
.
Host
=
u
.
Host
return
put
(
p
.
String
(),
body
,
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
option
...
),
i
.
Username
,
i
.
Password
,
i
.
Token
())
client
:=
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
options
...
)
return
put
(
p
.
String
(),
body
,
client
,
i
.
Username
,
i
.
Password
,
i
.
Token
(),
options
...
)
}
}
// Post makes a request to a subpath of info's BaseURL
// Post makes a request to a subpath of info's BaseURL
func
(
i
*
Info
)
Post
(
path
string
,
body
[]
byte
,
option
...
ClientOption
)
([]
byte
,
error
)
{
func
(
i
*
Info
)
Post
(
path
string
,
body
[]
byte
,
option
s
...
any
)
([]
byte
,
error
)
{
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -320,7 +333,8 @@ func (i *Info) Post(path string, body []byte, option ...ClientOption) ([]byte, e
...
@@ -320,7 +333,8 @@ func (i *Info) Post(path string, body []byte, option ...ClientOption) ([]byte, e
}
}
p
.
Scheme
=
u
.
Scheme
p
.
Scheme
=
u
.
Scheme
p
.
Host
=
u
.
Host
p
.
Host
=
u
.
Host
return
post
(
p
.
String
(),
body
,
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
option
...
),
i
.
Username
,
i
.
Password
,
i
.
Token
())
client
:=
GetHTTPClient
(
i
.
CACerts
,
i
.
CertFile
,
i
.
KeyFile
,
options
...
)
return
post
(
p
.
String
(),
body
,
client
,
i
.
Username
,
i
.
Password
,
i
.
Token
(),
options
...
)
}
}
// setServer sets the BaseURL and CACerts fields of the Info by connecting to the server
// setServer sets the BaseURL and CACerts fields of the Info by connecting to the server
...
@@ -402,7 +416,7 @@ func getCACerts(u url.URL) ([]byte, error) {
...
@@ -402,7 +416,7 @@ func getCACerts(u url.URL) ([]byte, error) {
// get makes a request to a url using a provided client and credentials,
// get makes a request to a url using a provided client and credentials,
// returning the response body.
// returning the response body.
func
get
(
u
string
,
client
*
http
.
Client
,
username
,
password
,
token
string
)
([]
byte
,
error
)
{
func
get
(
u
string
,
client
*
http
.
Client
,
username
,
password
,
token
string
,
options
...
any
)
([]
byte
,
error
)
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
u
,
nil
)
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
u
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -414,6 +428,12 @@ func get(u string, client *http.Client, username, password, token string) ([]byt
...
@@ -414,6 +428,12 @@ func get(u string, client *http.Client, username, password, token string) ([]byt
req
.
SetBasicAuth
(
username
,
password
)
req
.
SetBasicAuth
(
username
,
password
)
}
}
for
_
,
o
:=
range
options
{
if
requestOption
,
ok
:=
o
.
(
RequestOption
);
ok
{
requestOption
(
req
)
}
}
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -424,7 +444,7 @@ func get(u string, client *http.Client, username, password, token string) ([]byt
...
@@ -424,7 +444,7 @@ func get(u string, client *http.Client, username, password, token string) ([]byt
// put makes a request to a url using a provided client and credentials,
// put makes a request to a url using a provided client and credentials,
// only an error is returned
// only an error is returned
func
put
(
u
string
,
body
[]
byte
,
client
*
http
.
Client
,
username
,
password
,
token
string
)
error
{
func
put
(
u
string
,
body
[]
byte
,
client
*
http
.
Client
,
username
,
password
,
token
string
,
options
...
any
)
error
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodPut
,
u
,
bytes
.
NewBuffer
(
body
))
req
,
err
:=
http
.
NewRequest
(
http
.
MethodPut
,
u
,
bytes
.
NewBuffer
(
body
))
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -436,6 +456,12 @@ func put(u string, body []byte, client *http.Client, username, password, token s
...
@@ -436,6 +456,12 @@ func put(u string, body []byte, client *http.Client, username, password, token s
req
.
SetBasicAuth
(
username
,
password
)
req
.
SetBasicAuth
(
username
,
password
)
}
}
for
_
,
o
:=
range
options
{
if
requestOption
,
ok
:=
o
.
(
RequestOption
);
ok
{
requestOption
(
req
)
}
}
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -447,7 +473,7 @@ func put(u string, body []byte, client *http.Client, username, password, token s
...
@@ -447,7 +473,7 @@ func put(u string, body []byte, client *http.Client, username, password, token s
// post makes a request to a url using a provided client and credentials,
// post makes a request to a url using a provided client and credentials,
// returning the response body and error.
// returning the response body and error.
func
post
(
u
string
,
body
[]
byte
,
client
*
http
.
Client
,
username
,
password
,
token
string
)
([]
byte
,
error
)
{
func
post
(
u
string
,
body
[]
byte
,
client
*
http
.
Client
,
username
,
password
,
token
string
,
options
...
any
)
([]
byte
,
error
)
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodPost
,
u
,
bytes
.
NewBuffer
(
body
))
req
,
err
:=
http
.
NewRequest
(
http
.
MethodPost
,
u
,
bytes
.
NewBuffer
(
body
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -459,6 +485,12 @@ func post(u string, body []byte, client *http.Client, username, password, token
...
@@ -459,6 +485,12 @@ func post(u string, body []byte, client *http.Client, username, password, token
req
.
SetBasicAuth
(
username
,
password
)
req
.
SetBasicAuth
(
username
,
password
)
}
}
for
_
,
o
:=
range
options
{
if
requestOption
,
ok
:=
o
.
(
RequestOption
);
ok
{
requestOption
(
req
)
}
}
resp
,
err
:=
client
.
Do
(
req
)
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
pkg/spegel/bootstrap.go
View file @
95700aa6
...
@@ -2,7 +2,7 @@ package spegel
...
@@ -2,7 +2,7 @@ package spegel
import
(
import
(
"context"
"context"
"
math/rand
"
"
encoding/json
"
"os"
"os"
"path/filepath"
"path/filepath"
"strings"
"strings"
...
@@ -17,6 +17,7 @@ import (
...
@@ -17,6 +17,7 @@ import (
"github.com/rancher/wrangler/v3/pkg/merr"
"github.com/rancher/wrangler/v3/pkg/merr"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
"github.com/spegel-org/spegel/pkg/routing"
"github.com/spegel-org/spegel/pkg/routing"
"golang.org/x/sync/errgroup"
v1
"k8s.io/api/core/v1"
v1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
...
@@ -39,13 +40,20 @@ func NewSelfBootstrapper() routing.Bootstrapper {
...
@@ -39,13 +40,20 @@ func NewSelfBootstrapper() routing.Bootstrapper {
return
&
selfBootstrapper
{}
return
&
selfBootstrapper
{}
}
}
func
(
s
*
selfBootstrapper
)
Run
(
_
context
.
Context
,
id
string
)
error
{
func
(
s
*
selfBootstrapper
)
Run
(
ctx
context
.
Context
,
id
string
)
error
{
s
.
id
=
id
s
.
id
=
id
return
nil
return
waitForDone
(
ctx
)
}
}
func
(
s
*
selfBootstrapper
)
Get
()
(
*
peer
.
AddrInfo
,
error
)
{
func
(
s
*
selfBootstrapper
)
Get
(
ctx
context
.
Context
)
([]
peer
.
AddrInfo
,
error
)
{
return
peer
.
AddrInfoFromString
(
s
.
id
)
if
s
.
id
==
""
{
return
nil
,
errors
.
New
(
"p2p peer not ready"
)
}
self
,
err
:=
peer
.
AddrInfoFromString
(
s
.
id
)
if
err
!=
nil
{
return
nil
,
err
}
return
[]
peer
.
AddrInfo
{
*
self
},
nil
}
}
type
agentBootstrapper
struct
{
type
agentBootstrapper
struct
{
...
@@ -53,6 +61,8 @@ type agentBootstrapper struct {
...
@@ -53,6 +61,8 @@ type agentBootstrapper struct {
token
string
token
string
clientCert
string
clientCert
string
clientKey
string
clientKey
string
kubeConfig
string
info
*
clientaccess
.
Info
}
}
// NewAgentBootstrapper returns a p2p bootstrapper that retrieves a peer address from its server
// NewAgentBootstrapper returns a p2p bootstrapper that retrieves a peer address from its server
...
@@ -60,56 +70,36 @@ func NewAgentBootstrapper(server, token, dataDir string) routing.Bootstrapper {
...
@@ -60,56 +70,36 @@ func NewAgentBootstrapper(server, token, dataDir string) routing.Bootstrapper {
return
&
agentBootstrapper
{
return
&
agentBootstrapper
{
clientCert
:
filepath
.
Join
(
dataDir
,
"agent"
,
"client-kubelet.crt"
),
clientCert
:
filepath
.
Join
(
dataDir
,
"agent"
,
"client-kubelet.crt"
),
clientKey
:
filepath
.
Join
(
dataDir
,
"agent"
,
"client-kubelet.key"
),
clientKey
:
filepath
.
Join
(
dataDir
,
"agent"
,
"client-kubelet.key"
),
kubeConfig
:
filepath
.
Join
(
dataDir
,
"agent"
,
"kubelet.kubeconfig"
),
server
:
server
,
server
:
server
,
token
:
token
,
token
:
token
,
}
}
}
}
func
(
c
*
agentBootstrapper
)
Run
(
_
context
.
Context
,
_
string
)
error
{
func
(
c
*
agentBootstrapper
)
Run
(
ctx
context
.
Context
,
id
string
)
error
{
return
nil
if
c
.
server
!=
""
&&
c
.
token
!=
""
{
}
func
(
c
*
agentBootstrapper
)
Get
()
(
*
peer
.
AddrInfo
,
error
)
{
if
c
.
server
==
""
||
c
.
token
==
""
{
return
nil
,
errors
.
New
(
"cannot get addresses without server and token"
)
}
withCert
:=
clientaccess
.
WithClientCertificate
(
c
.
clientCert
,
c
.
clientKey
)
withCert
:=
clientaccess
.
WithClientCertificate
(
c
.
clientCert
,
c
.
clientKey
)
info
,
err
:=
clientaccess
.
ParseAndValidateToken
(
c
.
server
,
c
.
token
,
withCert
)
info
,
err
:=
clientaccess
.
ParseAndValidateToken
(
c
.
server
,
c
.
token
,
withCert
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
errors
.
Wrap
(
err
,
"failed to validate join token"
)
}
}
c
.
info
=
info
addr
,
err
:=
info
.
Get
(
"/v1-"
+
version
.
Program
+
"/p2p"
)
if
err
!=
nil
{
return
nil
,
err
}
}
addrInfo
,
err
:=
peer
.
AddrInfoFromString
(
string
(
addr
))
client
,
err
:=
util
.
GetClientSet
(
c
.
kubeConfig
)
return
addrInfo
,
err
if
err
!=
nil
{
}
return
errors
.
Wrap
(
err
,
"failed to create kubernetes client"
)
type
serverBootstrapper
struct
{
controlConfig
*
config
.
Control
}
// NewServerBootstrapper returns a p2p bootstrapper that returns an address from a random other cluster member.
func
NewServerBootstrapper
(
controlConfig
*
config
.
Control
)
routing
.
Bootstrapper
{
return
&
serverBootstrapper
{
controlConfig
:
controlConfig
,
}
}
}
nodes
:=
client
.
CoreV1
()
.
Nodes
()
func
(
s
*
serverBootstrapper
)
Run
(
_
context
.
Context
,
id
string
)
error
{
go
wait
.
PollUntilContextCancel
(
ctx
,
1
*
time
.
Second
,
true
,
func
(
ctx
context
.
Context
)
(
bool
,
error
)
{
s
.
controlConfig
.
Runtime
.
ClusterControllerStarts
[
"spegel-p2p"
]
=
func
(
ctx
context
.
Context
)
{
nodes
:=
s
.
controlConfig
.
Runtime
.
Core
.
Core
()
.
V1
()
.
Node
()
_
=
wait
.
PollUntilContextCancel
(
ctx
,
1
*
time
.
Second
,
true
,
func
(
ctx
context
.
Context
)
(
bool
,
error
)
{
nodeName
:=
os
.
Getenv
(
"NODE_NAME"
)
nodeName
:=
os
.
Getenv
(
"NODE_NAME"
)
if
nodeName
==
""
{
if
nodeName
==
""
{
return
false
,
nil
return
false
,
nil
}
}
node
,
err
:=
nodes
.
Get
(
nodeName
,
metav1
.
GetOptions
{})
node
,
err
:=
nodes
.
Get
(
ctx
,
nodeName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
if
err
!=
nil
{
logrus
.
Debugf
(
"Failed to update P2P address annotations and labels: %v"
,
err
)
return
false
,
nil
return
false
,
nil
}
}
...
@@ -122,17 +112,62 @@ func (s *serverBootstrapper) Run(_ context.Context, id string) error {
...
@@ -122,17 +112,62 @@ func (s *serverBootstrapper) Run(_ context.Context, id string) error {
}
}
node
.
Labels
[
P2pEnabledLabel
]
=
"true"
node
.
Labels
[
P2pEnabledLabel
]
=
"true"
if
_
,
err
=
nodes
.
Update
(
node
);
err
!=
nil
{
if
_
,
err
=
nodes
.
Update
(
ctx
,
node
,
metav1
.
UpdateOptions
{});
err
!=
nil
{
logrus
.
Debugf
(
"Failed to update P2P address annotations and labels: %v"
,
err
)
return
false
,
nil
return
false
,
nil
}
}
logrus
.
Infof
(
"Node P2P address annotations and labels added: %s"
,
id
)
logrus
.
Infof
(
"Node P2P address annotations and labels added: %s"
,
id
)
return
true
,
nil
return
true
,
nil
})
})
return
waitForDone
(
ctx
)
}
func
(
c
*
agentBootstrapper
)
Get
(
ctx
context
.
Context
)
([]
peer
.
AddrInfo
,
error
)
{
if
c
.
server
==
""
||
c
.
token
==
""
{
return
nil
,
errors
.
New
(
"cannot get addresses without server and token"
)
}
if
c
.
info
==
nil
{
return
nil
,
errors
.
New
(
"client not ready"
)
}
addr
,
err
:=
c
.
info
.
Get
(
"/v1-"
+
version
.
Program
+
"/p2p"
,
clientaccess
.
WithHeader
(
"Accept"
,
"application/json"
))
if
err
!=
nil
{
return
nil
,
err
}
// If the response cannot be decoded as a JSON list of addresses, fall back
// to using it as a legacy single-address response.
addrs
:=
[]
string
{}
if
err
:=
json
.
Unmarshal
(
addr
,
&
addrs
);
err
!=
nil
{
addrs
=
append
(
addrs
,
string
(
addr
))
}
addrInfos
:=
[]
peer
.
AddrInfo
{}
for
_
,
addr
:=
range
addrs
{
if
addrInfo
,
err
:=
peer
.
AddrInfoFromString
(
addr
);
err
==
nil
{
addrInfos
=
append
(
addrInfos
,
*
addrInfo
)
}
}
return
addrInfos
,
nil
}
type
serverBootstrapper
struct
{
controlConfig
*
config
.
Control
}
// NewServerBootstrapper returns a p2p bootstrapper that returns an address from the Kubernetes node list
func
NewServerBootstrapper
(
controlConfig
*
config
.
Control
)
routing
.
Bootstrapper
{
return
&
serverBootstrapper
{
controlConfig
:
controlConfig
,
}
}
return
nil
}
}
func
(
s
*
serverBootstrapper
)
Get
()
(
addrInfo
*
peer
.
AddrInfo
,
err
error
)
{
func
(
s
*
serverBootstrapper
)
Run
(
ctx
context
.
Context
,
_
string
)
error
{
return
waitForDone
(
ctx
)
}
func
(
s
*
serverBootstrapper
)
Get
(
ctx
context
.
Context
)
([]
peer
.
AddrInfo
,
error
)
{
if
s
.
controlConfig
.
Runtime
.
Core
==
nil
{
if
s
.
controlConfig
.
Runtime
.
Core
==
nil
{
return
nil
,
util
.
ErrCoreNotReady
return
nil
,
util
.
ErrCoreNotReady
}
}
...
@@ -146,8 +181,9 @@ func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) {
...
@@ -146,8 +181,9 @@ func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
for
_
,
i
:=
range
rand
.
Perm
(
len
(
nodeList
.
Items
))
{
node
:=
nodeList
.
Items
[
i
]
addrs
:=
[]
peer
.
AddrInfo
{}
for
_
,
node
:=
range
nodeList
.
Items
{
if
node
.
Name
==
nodeName
{
if
node
.
Name
==
nodeName
{
// don't return our own address
// don't return our own address
continue
continue
...
@@ -159,12 +195,12 @@ func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) {
...
@@ -159,12 +195,12 @@ func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) {
if
val
,
ok
:=
node
.
Annotations
[
P2pAddressAnnotation
];
ok
{
if
val
,
ok
:=
node
.
Annotations
[
P2pAddressAnnotation
];
ok
{
for
_
,
addr
:=
range
strings
.
Split
(
val
,
","
)
{
for
_
,
addr
:=
range
strings
.
Split
(
val
,
","
)
{
if
info
,
err
:=
peer
.
AddrInfoFromString
(
addr
);
err
==
nil
{
if
info
,
err
:=
peer
.
AddrInfoFromString
(
addr
);
err
==
nil
{
return
info
,
nil
addrs
=
append
(
addrs
,
*
info
)
}
}
}
}
}
}
}
}
return
nil
,
errors
.
New
(
"no ready p2p peers found"
)
return
addrs
,
nil
}
}
type
chainingBootstrapper
struct
{
type
chainingBootstrapper
struct
{
...
@@ -172,6 +208,7 @@ type chainingBootstrapper struct {
...
@@ -172,6 +208,7 @@ type chainingBootstrapper struct {
}
}
// NewChainingBootstrapper returns a p2p bootstrapper that passes through to a list of bootstrappers.
// NewChainingBootstrapper returns a p2p bootstrapper that passes through to a list of bootstrappers.
// Addressess are returned from all boostrappers that return successfully.
func
NewChainingBootstrapper
(
bootstrappers
...
routing
.
Bootstrapper
)
routing
.
Bootstrapper
{
func
NewChainingBootstrapper
(
bootstrappers
...
routing
.
Bootstrapper
)
routing
.
Bootstrapper
{
return
&
chainingBootstrapper
{
return
&
chainingBootstrapper
{
bootstrappers
:
bootstrappers
,
bootstrappers
:
bootstrappers
,
...
@@ -179,23 +216,38 @@ func NewChainingBootstrapper(bootstrappers ...routing.Bootstrapper) routing.Boot
...
@@ -179,23 +216,38 @@ func NewChainingBootstrapper(bootstrappers ...routing.Bootstrapper) routing.Boot
}
}
func
(
c
*
chainingBootstrapper
)
Run
(
ctx
context
.
Context
,
id
string
)
error
{
func
(
c
*
chainingBootstrapper
)
Run
(
ctx
context
.
Context
,
id
string
)
error
{
errs
:=
merr
.
Errors
{}
eg
,
ctx
:=
errgroup
.
WithContext
(
ctx
)
for
_
,
b
:=
range
c
.
bootstrappers
{
for
i
:=
range
c
.
bootstrappers
{
if
err
:=
b
.
Run
(
ctx
,
id
);
err
!=
nil
{
b
:=
c
.
bootstrappers
[
i
]
errs
=
append
(
errs
,
err
)
eg
.
Go
(
func
()
error
{
}
return
b
.
Run
(
ctx
,
id
)
})
}
}
return
merr
.
NewErrors
(
errs
...
)
return
eg
.
Wait
(
)
}
}
func
(
c
*
chainingBootstrapper
)
Get
(
)
(
*
peer
.
AddrInfo
,
error
)
{
func
(
c
*
chainingBootstrapper
)
Get
(
ctx
context
.
Context
)
([]
peer
.
AddrInfo
,
error
)
{
errs
:=
merr
.
Errors
{}
errs
:=
merr
.
Errors
{}
for
_
,
b
:=
range
c
.
bootstrappers
{
addrs
:=
[]
peer
.
AddrInfo
{}
addr
,
err
:=
b
.
Get
()
for
i
:=
range
c
.
bootstrappers
{
if
err
==
nil
{
b
:=
c
.
bootstrappers
[
i
]
return
addr
,
nil
as
,
err
:=
b
.
Get
(
ctx
)
}
if
err
!=
nil
{
errs
=
append
(
errs
,
err
)
errs
=
append
(
errs
,
err
)
}
else
{
addrs
=
append
(
addrs
,
as
...
)
}
}
}
if
len
(
addrs
)
==
0
{
return
nil
,
merr
.
NewErrors
(
errs
...
)
return
nil
,
merr
.
NewErrors
(
errs
...
)
}
return
addrs
,
nil
}
func
waitForDone
(
ctx
context
.
Context
)
error
{
<-
ctx
.
Done
()
if
err
:=
ctx
.
Err
();
err
!=
nil
&&
!
errors
.
Is
(
err
,
context
.
Canceled
)
{
return
err
}
return
nil
}
}
pkg/spegel/spegel.go
View file @
95700aa6
...
@@ -2,6 +2,7 @@ package spegel
...
@@ -2,6 +2,7 @@ package spegel
import
(
import
(
"context"
"context"
"encoding/json"
"fmt"
"fmt"
"log"
"log"
"net"
"net"
...
@@ -131,7 +132,7 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
...
@@ -131,7 +132,7 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
if
logrus
.
IsLevelEnabled
(
logrus
.
DebugLevel
)
{
if
logrus
.
IsLevelEnabled
(
logrus
.
DebugLevel
)
{
level
=
ipfslog
.
LevelDebug
level
=
ipfslog
.
LevelDebug
stdlog
:=
log
.
New
(
logrus
.
StandardLogger
()
.
Writer
(),
"spegel "
,
log
.
LstdFlags
)
stdlog
:=
log
.
New
(
logrus
.
StandardLogger
()
.
Writer
(),
"spegel "
,
log
.
LstdFlags
)
logger
:=
stdr
.
NewWithOptions
(
stdlog
,
stdr
.
Options
{
Verbosity
:
ptr
.
To
(
10
)})
logger
:=
stdr
.
NewWithOptions
(
stdlog
,
stdr
.
Options
{
Verbosity
:
ptr
.
To
(
7
)})
ctx
=
logr
.
NewContext
(
ctx
,
logger
)
ctx
=
logr
.
NewContext
(
ctx
,
logger
)
}
}
ipfslog
.
SetAllLoggers
(
level
)
ipfslog
.
SetAllLoggers
(
level
)
...
@@ -197,7 +198,7 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
...
@@ -197,7 +198,7 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
}
}
router
,
err
:=
routing
.
NewP2PRouter
(
ctx
,
routerAddr
,
c
.
Bootstrapper
,
c
.
RegistryPort
,
opts
...
)
router
,
err
:=
routing
.
NewP2PRouter
(
ctx
,
routerAddr
,
c
.
Bootstrapper
,
c
.
RegistryPort
,
opts
...
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"failed to create
p2p
router"
)
return
errors
.
Wrap
(
err
,
"failed to create
P2P
router"
)
}
}
go
router
.
Run
(
ctx
)
go
router
.
Run
(
ctx
)
...
@@ -216,13 +217,10 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
...
@@ -216,13 +217,10 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
registry
.
WithLogger
(
logr
.
FromContextOrDiscard
(
ctx
)),
registry
.
WithLogger
(
logr
.
FromContextOrDiscard
(
ctx
)),
}
}
reg
:=
registry
.
NewRegistry
(
ociClient
,
router
,
registryOpts
...
)
reg
:=
registry
.
NewRegistry
(
ociClient
,
router
,
registryOpts
...
)
regSvr
:=
reg
.
Server
(
":"
+
c
.
RegistryPort
)
regSvr
,
err
:=
reg
.
Server
(
":"
+
c
.
RegistryPort
)
if
err
!=
nil
{
// Close router on shutdown
return
errors
.
Wrap
(
err
,
"failed to create embedded registry server"
)
go
func
()
{
}
<-
ctx
.
Done
()
router
.
Close
()
}()
// Track images available in containerd and publish via p2p router
// Track images available in containerd and publish via p2p router
go
state
.
Track
(
ctx
,
ociClient
,
router
,
resolveLatestTag
)
go
state
.
Track
(
ctx
,
ociClient
,
router
,
resolveLatestTag
)
...
@@ -232,29 +230,52 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
...
@@ -232,29 +230,52 @@ func (c *Config) Start(ctx context.Context, nodeConfig *config.Node) error {
return
err
return
err
}
}
mRouter
.
PathPrefix
(
"/v2"
)
.
Handler
(
regSvr
.
Handler
)
mRouter
.
PathPrefix
(
"/v2"
)
.
Handler
(
regSvr
.
Handler
)
mRouter
.
PathPrefix
(
"/v1-
"
+
version
.
Program
+
"
/p2p"
)
.
Handler
(
c
.
peerInfo
())
mRouter
.
PathPrefix
(
"/v1-
{program}
/p2p"
)
.
Handler
(
c
.
peerInfo
())
// Wait up to 5 seconds for the p2p network to find peers. This will return
// Wait up to 5 seconds for the p2p network to find peers. This will return
// immediately if the node is bootstrapping from itself.
// immediately if the node is bootstrapping from itself.
_
=
wait
.
PollUntilContextTimeout
(
ctx
,
time
.
Second
,
resolveTimeout
,
true
,
func
(
_
context
.
Context
)
(
bool
,
error
)
{
if
err
:=
wait
.
PollUntilContextTimeout
(
ctx
,
time
.
Second
,
resolveTimeout
,
true
,
func
(
_
context
.
Context
)
(
bool
,
error
)
{
return
router
.
Ready
()
ready
,
_
:=
router
.
Ready
(
ctx
)
})
return
ready
,
nil
});
err
!=
nil
{
logrus
.
Warnf
(
"Failed to wait for P2P mesh to become ready, will retry in the background: %v"
,
err
)
}
return
nil
return
nil
}
}
// peerInfo sends a peer address retrieved from the bootstrapper via HTTP
// peerInfo sends a peer address retrieved from the bootstrapper via HTTP
func
(
c
*
Config
)
peerInfo
()
http
.
HandlerFunc
{
func
(
c
*
Config
)
peerInfo
()
http
.
HandlerFunc
{
return
http
.
HandlerFunc
(
func
(
resp
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
return
http
.
HandlerFunc
(
func
(
resp
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
info
,
err
:=
c
.
Bootstrapper
.
Get
(
req
.
Context
())
if
err
!=
nil
||
len
(
info
)
==
0
{
http
.
Error
(
resp
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
addrs
:=
[]
string
{}
for
_
,
ai
:=
range
info
{
for
_
,
ma
:=
range
ai
.
Addrs
{
addrs
=
append
(
addrs
,
fmt
.
Sprintf
(
"%s/p2p/%s"
,
ma
,
ai
.
ID
))
}
}
client
,
_
,
_
:=
net
.
SplitHostPort
(
req
.
RemoteAddr
)
client
,
_
,
_
:=
net
.
SplitHostPort
(
req
.
RemoteAddr
)
info
,
err
:=
c
.
Bootstrapper
.
Get
()
if
req
.
Header
.
Get
(
"Accept"
)
==
"application/json"
{
b
,
err
:=
json
.
Marshal
(
addrs
)
if
err
!=
nil
{
if
err
!=
nil
{
http
.
Error
(
resp
,
"Internal Error"
,
http
.
StatusInternalServerError
)
http
.
Error
(
resp
,
err
.
Error
()
,
http
.
StatusInternalServerError
)
return
return
}
}
logrus
.
Debugf
(
"Serving p2p peer addr %s to client at %s"
,
info
,
client
)
logrus
.
Debugf
(
"Serving p2p peer addrs %v to client at %s"
,
addrs
,
client
)
resp
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
resp
.
WriteHeader
(
http
.
StatusOK
)
resp
.
WriteHeader
(
http
.
StatusOK
)
resp
.
Write
(
b
)
return
}
logrus
.
Debugf
(
"Serving p2p peer addr %v to client at %s"
,
addrs
[
0
],
client
)
resp
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain"
)
resp
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain"
)
fmt
.
Fprintf
(
resp
,
"%s/p2p/%s"
,
info
.
Addrs
[
0
]
.
String
(),
info
.
ID
.
String
())
resp
.
WriteHeader
(
http
.
StatusOK
)
resp
.
Write
([]
byte
(
addrs
[
0
]))
})
})
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment