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
f0ea0a09
Unverified
Commit
f0ea0a09
authored
Oct 25, 2021
by
Brian Downs
Committed by
GitHub
Oct 25, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backport bootstrap release 1.21 (#4313)
parent
63bcc307
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
857 additions
and
155 deletions
+857
-155
go.mod
go.mod
+2
-2
bootstrap.go
pkg/bootstrap/bootstrap.go
+35
-12
bootstrap_test.go
pkg/bootstrap/bootstrap_test.go
+46
-0
server.go
pkg/cli/server/server.go
+11
-0
kubeconfig.go
pkg/clientaccess/kubeconfig.go
+1
-1
token.go
pkg/clientaccess/token.go
+31
-31
token_test.go
pkg/clientaccess/token_test.go
+1
-1
bootstrap.go
pkg/cluster/bootstrap.go
+294
-29
bootstrap_test.go
pkg/cluster/bootstrap_test.go
+254
-0
cluster.go
pkg/cluster/cluster.go
+5
-12
https.go
pkg/cluster/https.go
+3
-1
storage.go
pkg/cluster/storage.go
+38
-7
deps.go
pkg/daemons/control/deps/deps.go
+61
-0
server.go
pkg/daemons/control/server.go
+1
-56
etcd.go
pkg/etcd/etcd.go
+1
-1
runtime.go
tests/util/runtime.go
+71
-0
modules.txt
vendor/modules.txt
+2
-2
No files found.
go.mod
View file @
f0ea0a09
...
@@ -116,8 +116,8 @@ require (
...
@@ -116,8 +116,8 @@ require (
go.etcd.io/etcd v0.5.0-alpha.5.0.20201208200253-50621aee4aea
go.etcd.io/etcd v0.5.0-alpha.5.0.20201208200253-50621aee4aea
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/sys v0.0.0-20210
426230700-d19ff857e887
golang.org/x/sys v0.0.0-20210
603081109-ebe580a85c40
google.golang.org/grpc v1.3
7
.0
google.golang.org/grpc v1.3
8
.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.21.5
k8s.io/api v0.21.5
k8s.io/apimachinery v0.21.5
k8s.io/apimachinery v0.21.5
...
...
pkg/bootstrap/bootstrap.go
View file @
f0ea0a09
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"net/http"
"net/http"
"os"
"os"
"path/filepath"
"path/filepath"
"time"
"github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/config"
...
@@ -15,17 +16,19 @@ import (
...
@@ -15,17 +16,19 @@ import (
func
Handler
(
bootstrap
*
config
.
ControlRuntimeBootstrap
)
http
.
Handler
{
func
Handler
(
bootstrap
*
config
.
ControlRuntimeBootstrap
)
http
.
Handler
{
return
http
.
HandlerFunc
(
func
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
return
http
.
HandlerFunc
(
func
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
rw
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
rw
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
Write
(
rw
,
bootstrap
)
ReadFromDisk
(
rw
,
bootstrap
)
})
})
}
}
func
Write
(
w
io
.
Writer
,
bootstrap
*
config
.
ControlRuntimeBootstrap
)
error
{
// ReadFromDisk reads the bootstrap data from the files on disk and
paths
,
err
:=
objToMap
(
bootstrap
)
// writes their content in JSON form to the given io.Writer.
func
ReadFromDisk
(
w
io
.
Writer
,
bootstrap
*
config
.
ControlRuntimeBootstrap
)
error
{
paths
,
err
:=
ObjToMap
(
bootstrap
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
return
nil
}
}
dataMap
:=
ma
p
[
string
][]
byte
{}
dataMap
:=
ma
ke
(
map
[
string
]
File
)
for
pathKey
,
path
:=
range
paths
{
for
pathKey
,
path
:=
range
paths
{
if
path
==
""
{
if
path
==
""
{
continue
continue
...
@@ -35,24 +38,45 @@ func Write(w io.Writer, bootstrap *config.ControlRuntimeBootstrap) error {
...
@@ -35,24 +38,45 @@ func Write(w io.Writer, bootstrap *config.ControlRuntimeBootstrap) error {
return
errors
.
Wrapf
(
err
,
"failed to read %s"
,
path
)
return
errors
.
Wrapf
(
err
,
"failed to read %s"
,
path
)
}
}
dataMap
[
pathKey
]
=
data
info
,
err
:=
os
.
Stat
(
path
)
if
err
!=
nil
{
return
err
}
dataMap
[
pathKey
]
=
File
{
Timestamp
:
info
.
ModTime
(),
Content
:
data
,
}
}
}
return
json
.
NewEncoder
(
w
)
.
Encode
(
dataMap
)
return
json
.
NewEncoder
(
w
)
.
Encode
(
dataMap
)
}
}
func
Read
(
r
io
.
Reader
,
bootstrap
*
config
.
ControlRuntimeBootstrap
)
error
{
// File is a representation of a certificate
paths
,
err
:=
objToMap
(
bootstrap
)
// or key file within the bootstrap context that contains
// the contents of the file as well as a timestamp from
// when the file was last modified.
type
File
struct
{
Timestamp
time
.
Time
Content
[]
byte
}
type
PathsDataformat
map
[
string
]
File
// WriteToDiskFromStorage writes the contents of the given reader to the paths
// derived from within the ControlRuntimeBootstrap.
func
WriteToDiskFromStorage
(
r
io
.
Reader
,
bootstrap
*
config
.
ControlRuntimeBootstrap
)
error
{
paths
,
err
:=
ObjToMap
(
bootstrap
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
files
:=
ma
p
[
string
][]
byte
{}
files
:=
ma
ke
(
PathsDataformat
)
if
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
&
files
);
err
!=
nil
{
if
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
&
files
);
err
!=
nil
{
return
err
return
err
}
}
for
pathKey
,
data
:=
range
files
{
for
pathKey
,
bsf
:=
range
files
{
path
,
ok
:=
paths
[
pathKey
]
path
,
ok
:=
paths
[
pathKey
]
if
!
ok
{
if
!
ok
{
continue
continue
...
@@ -61,8 +85,7 @@ func Read(r io.Reader, bootstrap *config.ControlRuntimeBootstrap) error {
...
@@ -61,8 +85,7 @@ func Read(r io.Reader, bootstrap *config.ControlRuntimeBootstrap) error {
if
err
:=
os
.
MkdirAll
(
filepath
.
Dir
(
path
),
0700
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
filepath
.
Dir
(
path
),
0700
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to mkdir %s"
,
filepath
.
Dir
(
path
))
return
errors
.
Wrapf
(
err
,
"failed to mkdir %s"
,
filepath
.
Dir
(
path
))
}
}
if
err
:=
ioutil
.
WriteFile
(
path
,
bsf
.
Content
,
0600
);
err
!=
nil
{
if
err
:=
ioutil
.
WriteFile
(
path
,
data
,
0600
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to write to %s"
,
path
)
return
errors
.
Wrapf
(
err
,
"failed to write to %s"
,
path
)
}
}
}
}
...
@@ -70,7 +93,7 @@ func Read(r io.Reader, bootstrap *config.ControlRuntimeBootstrap) error {
...
@@ -70,7 +93,7 @@ func Read(r io.Reader, bootstrap *config.ControlRuntimeBootstrap) error {
return
nil
return
nil
}
}
func
o
bjToMap
(
obj
interface
{})
(
map
[
string
]
string
,
error
)
{
func
O
bjToMap
(
obj
interface
{})
(
map
[
string
]
string
,
error
)
{
bytes
,
err
:=
json
.
Marshal
(
obj
)
bytes
,
err
:=
json
.
Marshal
(
obj
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
pkg/bootstrap/bootstrap_test.go
0 → 100644
View file @
f0ea0a09
package
bootstrap
import
(
"testing"
"github.com/rancher/k3s/pkg/daemons/config"
)
func
TestObjToMap
(
t
*
testing
.
T
)
{
type
args
struct
{
obj
interface
{}
}
tests
:=
[]
struct
{
name
string
args
args
want
map
[
string
]
string
wantErr
bool
}{
{
name
:
"Minimal Valid"
,
args
:
args
{
obj
:
&
config
.
ControlRuntimeBootstrap
{
ServerCA
:
"/var/lib/rancher/k3s/server/tls/server-ca.crt"
,
ServerCAKey
:
"/var/lib/rancher/k3s/server/tls/server-ca.key"
,
},
},
wantErr
:
false
,
},
{
name
:
"Minimal Invalid"
,
args
:
args
{
obj
:
1
,
},
wantErr
:
true
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
_
,
err
:=
ObjToMap
(
tt
.
args
.
obj
)
if
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"ObjToMap() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
return
}
})
}
}
pkg/cli/server/server.go
View file @
f0ea0a09
...
@@ -175,6 +175,17 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
...
@@ -175,6 +175,17 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
// delete local loadbalancers state for apiserver and supervisor servers
// delete local loadbalancers state for apiserver and supervisor servers
loadbalancer
.
ResetLoadBalancer
(
filepath
.
Join
(
cfg
.
DataDir
,
"agent"
),
loadbalancer
.
SupervisorServiceName
)
loadbalancer
.
ResetLoadBalancer
(
filepath
.
Join
(
cfg
.
DataDir
,
"agent"
),
loadbalancer
.
SupervisorServiceName
)
loadbalancer
.
ResetLoadBalancer
(
filepath
.
Join
(
cfg
.
DataDir
,
"agent"
),
loadbalancer
.
APIServerServiceName
)
loadbalancer
.
ResetLoadBalancer
(
filepath
.
Join
(
cfg
.
DataDir
,
"agent"
),
loadbalancer
.
APIServerServiceName
)
// at this point we're doing a restore. Check to see if we've
// passed in a token and if not, check if the token file exists.
// If it doesn't, return an error indicating the token is necessary.
if
cfg
.
Token
==
""
{
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
cfg
.
DataDir
,
"server/token"
));
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
return
errors
.
New
(
""
)
}
}
}
}
}
serverConfig
.
ControlConfig
.
ClusterReset
=
cfg
.
ClusterReset
serverConfig
.
ControlConfig
.
ClusterReset
=
cfg
.
ClusterReset
...
...
pkg/clientaccess/kubeconfig.go
View file @
f0ea0a09
...
@@ -9,7 +9,7 @@ import (
...
@@ -9,7 +9,7 @@ import (
)
)
// WriteClientKubeConfig generates a kubeconfig at destFile that can be used to connect to a server at url with the given certs and keys
// WriteClientKubeConfig generates a kubeconfig at destFile that can be used to connect to a server at url with the given certs and keys
func
WriteClientKubeConfig
(
destFile
string
,
url
string
,
serverCAFile
string
,
clientCertFile
string
,
clientKeyFile
string
)
error
{
func
WriteClientKubeConfig
(
destFile
,
url
,
serverCAFile
,
clientCertFile
,
clientKeyFile
string
)
error
{
serverCA
,
err
:=
ioutil
.
ReadFile
(
serverCAFile
)
serverCA
,
err
:=
ioutil
.
ReadFile
(
serverCAFile
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to read %s"
,
serverCAFile
)
return
errors
.
Wrapf
(
err
,
"failed to read %s"
,
serverCAFile
)
...
...
pkg/clientaccess/token.go
View file @
f0ea0a09
...
@@ -16,9 +16,15 @@ import (
...
@@ -16,9 +16,15 @@ import (
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
)
)
var
(
const
(
tokenPrefix
=
"K10"
tokenFormat
=
"%s%s::%s:%s"
caHashLength
=
sha256
.
Size
*
2
defaultClientTimeout
=
10
*
time
.
Second
defaultClientTimeout
=
10
*
time
.
Second
)
var
(
defaultClient
=
&
http
.
Client
{
defaultClient
=
&
http
.
Client
{
Timeout
:
defaultClientTimeout
,
Timeout
:
defaultClientTimeout
,
}
}
...
@@ -32,12 +38,6 @@ var (
...
@@ -32,12 +38,6 @@ var (
}
}
)
)
const
(
tokenPrefix
=
"K10"
tokenFormat
=
"%s%s::%s:%s"
caHashLength
=
sha256
.
Size
*
2
)
type
OverrideURLCallback
func
(
config
[]
byte
)
(
*
url
.
URL
,
error
)
type
OverrideURLCallback
func
(
config
[]
byte
)
(
*
url
.
URL
,
error
)
type
Info
struct
{
type
Info
struct
{
...
@@ -49,8 +49,8 @@ type Info struct {
...
@@ -49,8 +49,8 @@ type Info struct {
}
}
// String returns the token data, templated according to the token format
// String returns the token data, templated according to the token format
func
(
i
nfo
*
Info
)
String
()
string
{
func
(
i
*
Info
)
String
()
string
{
return
fmt
.
Sprintf
(
tokenFormat
,
tokenPrefix
,
hashCA
(
i
nfo
.
CACerts
),
info
.
Username
,
info
.
Password
)
return
fmt
.
Sprintf
(
tokenFormat
,
tokenPrefix
,
hashCA
(
i
.
CACerts
),
i
.
Username
,
i
.
Password
)
}
}
// ParseAndValidateToken parses a token, downloads and validates the server's CA bundle,
// ParseAndValidateToken parses a token, downloads and validates the server's CA bundle,
...
@@ -70,7 +70,7 @@ func ParseAndValidateToken(server string, token string) (*Info, error) {
...
@@ -70,7 +70,7 @@ func ParseAndValidateToken(server string, token string) (*Info, error) {
// ParseAndValidateToken parses a token with user override, downloads and
// ParseAndValidateToken parses a token with user override, downloads and
// validates the server's CA bundle, and validates it according to the caHash from the token if set.
// validates the server's CA bundle, and validates it according to the caHash from the token if set.
func
ParseAndValidateTokenForUser
(
server
string
,
token
string
,
username
string
)
(
*
Info
,
error
)
{
func
ParseAndValidateTokenForUser
(
server
,
token
,
username
string
)
(
*
Info
,
error
)
{
info
,
err
:=
parseToken
(
token
)
info
,
err
:=
parseToken
(
token
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -86,11 +86,11 @@ func ParseAndValidateTokenForUser(server string, token string, username string)
...
@@ -86,11 +86,11 @@ func ParseAndValidateTokenForUser(server string, token string, username string)
}
}
// setAndValidateServer updates the remote server's cert info, and validates it against the provided hash
// setAndValidateServer updates the remote server's cert info, and validates it against the provided hash
func
(
i
nfo
*
Info
)
setAndValidateServer
(
server
string
)
error
{
func
(
i
*
Info
)
setAndValidateServer
(
server
string
)
error
{
if
err
:=
i
nfo
.
setServer
(
server
);
err
!=
nil
{
if
err
:=
i
.
setServer
(
server
);
err
!=
nil
{
return
err
return
err
}
}
return
i
nfo
.
validateCAHash
()
return
i
.
validateCAHash
()
}
}
// validateCACerts returns a boolean indicating whether or not a CA bundle matches the provided hash,
// validateCACerts returns a boolean indicating whether or not a CA bundle matches the provided hash,
...
@@ -118,7 +118,7 @@ func ParseUsernamePassword(token string) (string, string, bool) {
...
@@ -118,7 +118,7 @@ func ParseUsernamePassword(token string) (string, string, bool) {
// parseToken parses a token into an Info struct
// parseToken parses a token into an Info struct
func
parseToken
(
token
string
)
(
*
Info
,
error
)
{
func
parseToken
(
token
string
)
(
*
Info
,
error
)
{
var
info
=
&
Info
{}
var
info
Info
if
len
(
token
)
==
0
{
if
len
(
token
)
==
0
{
return
nil
,
errors
.
New
(
"token must not be empty"
)
return
nil
,
errors
.
New
(
"token must not be empty"
)
...
@@ -150,7 +150,7 @@ func parseToken(token string) (*Info, error) {
...
@@ -150,7 +150,7 @@ func parseToken(token string) (*Info, error) {
info
.
Username
=
parts
[
0
]
info
.
Username
=
parts
[
0
]
info
.
Password
=
parts
[
1
]
info
.
Password
=
parts
[
1
]
return
info
,
nil
return
&
info
,
nil
}
}
// GetHTTPClient returns a http client that validates TLS server certificates using the provided CA bundle.
// GetHTTPClient returns a http client that validates TLS server certificates using the provided CA bundle.
...
@@ -177,25 +177,25 @@ func GetHTTPClient(cacerts []byte) *http.Client {
...
@@ -177,25 +177,25 @@ func GetHTTPClient(cacerts []byte) *http.Client {
}
}
// Get makes a request to a subpath of info's BaseURL
// Get makes a request to a subpath of info's BaseURL
func
(
i
nfo
*
Info
)
Get
(
path
string
)
([]
byte
,
error
)
{
func
(
i
*
Info
)
Get
(
path
string
)
([]
byte
,
error
)
{
u
,
err
:=
url
.
Parse
(
i
nfo
.
BaseURL
)
u
,
err
:=
url
.
Parse
(
i
.
BaseURL
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
u
.
Path
=
path
u
.
Path
=
path
return
get
(
u
.
String
(),
GetHTTPClient
(
i
nfo
.
CACerts
),
info
.
Username
,
info
.
Password
)
return
get
(
u
.
String
(),
GetHTTPClient
(
i
.
CACerts
),
i
.
Username
,
i
.
Password
)
}
}
// 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
// and storing the CA bundle.
// and storing the CA bundle.
func
(
i
nfo
*
Info
)
setServer
(
server
string
)
error
{
func
(
i
*
Info
)
setServer
(
server
string
)
error
{
url
,
err
:=
url
.
Parse
(
server
)
url
,
err
:=
url
.
Parse
(
server
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"Invalid server url, failed to parse: %s"
,
server
)
return
errors
.
Wrapf
(
err
,
"Invalid server url, failed to parse: %s"
,
server
)
}
}
if
url
.
Scheme
!=
"https"
{
if
url
.
Scheme
!=
"https"
{
return
fmt
.
Errorf
(
"only https:// URLs are supported, invalid scheme: %s"
,
server
)
return
errors
.
New
(
"only https:// URLs are supported, invalid scheme: "
+
server
)
}
}
for
strings
.
HasSuffix
(
url
.
Path
,
"/"
)
{
for
strings
.
HasSuffix
(
url
.
Path
,
"/"
)
{
...
@@ -207,25 +207,25 @@ func (info *Info) setServer(server string) error {
...
@@ -207,25 +207,25 @@ func (info *Info) setServer(server string) error {
return
err
return
err
}
}
i
nfo
.
BaseURL
=
url
.
String
()
i
.
BaseURL
=
url
.
String
()
i
nfo
.
CACerts
=
cacerts
i
.
CACerts
=
cacerts
return
nil
return
nil
}
}
// ValidateCAHash validates that info's caHash matches the CACerts hash.
// ValidateCAHash validates that info's caHash matches the CACerts hash.
func
(
i
nfo
*
Info
)
validateCAHash
()
error
{
func
(
i
*
Info
)
validateCAHash
()
error
{
if
len
(
i
nfo
.
caHash
)
>
0
&&
len
(
info
.
CACerts
)
==
0
{
if
len
(
i
.
caHash
)
>
0
&&
len
(
i
.
CACerts
)
==
0
{
// Warn if the user provided a CA hash but we're not going to validate because it's already trusted
// Warn if the user provided a CA hash but we're not going to validate because it's already trusted
logrus
.
Warn
(
"Cluster CA certificate is trusted by the host CA bundle. "
+
logrus
.
Warn
(
"Cluster CA certificate is trusted by the host CA bundle. "
+
"Token CA hash will not be validated."
)
"Token CA hash will not be validated."
)
}
else
if
len
(
i
nfo
.
caHash
)
==
0
&&
len
(
info
.
CACerts
)
>
0
{
}
else
if
len
(
i
.
caHash
)
==
0
&&
len
(
i
.
CACerts
)
>
0
{
// Warn if the CA is self-signed but the user didn't provide a hash to validate it against
// Warn if the CA is self-signed but the user didn't provide a hash to validate it against
logrus
.
Warn
(
"Cluster CA certificate is not trusted by the host CA bundle, but the token does not include a CA hash. "
+
logrus
.
Warn
(
"Cluster CA certificate is not trusted by the host CA bundle, but the token does not include a CA hash. "
+
"Use the full token from the server's node-token file to enable Cluster CA validation."
)
"Use the full token from the server's node-token file to enable Cluster CA validation."
)
}
else
if
len
(
i
nfo
.
CACerts
)
>
0
&&
len
(
info
.
caHash
)
>
0
{
}
else
if
len
(
i
.
CACerts
)
>
0
&&
len
(
i
.
caHash
)
>
0
{
// only verify CA hash if the server cert is not trusted by the OS CA bundle
// only verify CA hash if the server cert is not trusted by the OS CA bundle
if
ok
,
serverHash
:=
validateCACerts
(
i
nfo
.
CACerts
,
info
.
caHash
);
!
ok
{
if
ok
,
serverHash
:=
validateCACerts
(
i
.
CACerts
,
i
.
caHash
);
!
ok
{
return
fmt
.
Errorf
(
"token CA hash does not match the Cluster CA certificate hash: %s != %s"
,
i
nfo
.
caHash
,
serverHash
)
return
fmt
.
Errorf
(
"token CA hash does not match the Cluster CA certificate hash: %s != %s"
,
i
.
caHash
,
serverHash
)
}
}
}
}
return
nil
return
nil
...
@@ -288,18 +288,18 @@ func get(u string, client *http.Client, username, password string) ([]byte, erro
...
@@ -288,18 +288,18 @@ func get(u string, client *http.Client, username, password string) ([]byte, erro
return
ioutil
.
ReadAll
(
resp
.
Body
)
return
ioutil
.
ReadAll
(
resp
.
Body
)
}
}
func
FormatToken
(
token
string
,
certFile
string
)
(
string
,
error
)
{
func
FormatToken
(
token
,
certFile
string
)
(
string
,
error
)
{
if
len
(
token
)
==
0
{
if
len
(
token
)
==
0
{
return
token
,
nil
return
token
,
nil
}
}
certHash
:=
""
certHash
:=
""
if
len
(
certFile
)
>
0
{
if
len
(
certFile
)
>
0
{
b
ytes
,
err
:=
ioutil
.
ReadFile
(
certFile
)
b
,
err
:=
ioutil
.
ReadFile
(
certFile
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
nil
return
""
,
nil
}
}
digest
:=
sha256
.
Sum256
(
b
ytes
)
digest
:=
sha256
.
Sum256
(
b
)
certHash
=
tokenPrefix
+
hex
.
EncodeToString
(
digest
[
:
])
+
"::"
certHash
=
tokenPrefix
+
hex
.
EncodeToString
(
digest
[
:
])
+
"::"
}
}
return
certHash
+
token
,
nil
return
certHash
+
token
,
nil
...
...
pkg/clientaccess/token_test.go
View file @
f0ea0a09
...
@@ -320,7 +320,7 @@ func newTLSServer(t *testing.T, username, password string, sendWrongCA bool) *ht
...
@@ -320,7 +320,7 @@ func newTLSServer(t *testing.T, username, password string, sendWrongCA bool) *ht
}
}
bootstrapData
:=
&
config
.
ControlRuntimeBootstrap
{}
bootstrapData
:=
&
config
.
ControlRuntimeBootstrap
{}
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
if
err
:=
bootstrap
.
Write
(
w
,
bootstrapData
);
err
!=
nil
{
if
err
:=
bootstrap
.
ReadFromDisk
(
w
,
bootstrapData
);
err
!=
nil
{
t
.
Errorf
(
"failed to write bootstrap: %v"
,
err
)
t
.
Errorf
(
"failed to write bootstrap: %v"
,
err
)
}
}
return
return
...
...
pkg/cluster/bootstrap.go
View file @
f0ea0a09
This diff is collapsed.
Click to expand it.
pkg/cluster/bootstrap_test.go
0 → 100644
View file @
f0ea0a09
package
cluster
import
(
"bytes"
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/k3s-io/kine/pkg/endpoint"
"github.com/rancher/k3s/pkg/bootstrap"
"github.com/rancher/k3s/pkg/clientaccess"
"github.com/rancher/k3s/pkg/cluster/managed"
"github.com/rancher/k3s/pkg/daemons/config"
)
func
Test_isDirEmpty
(
t
*
testing
.
T
)
{
const
tmpDir
=
"test_dir"
type
args
struct
{
name
string
}
tests
:=
[]
struct
{
name
string
args
args
setup
func
()
error
teardown
func
()
error
want
bool
wantErr
bool
}{
{
name
:
"is empty"
,
args
:
args
{
name
:
tmpDir
,
},
setup
:
func
()
error
{
return
os
.
Mkdir
(
tmpDir
,
0700
)
},
teardown
:
func
()
error
{
return
os
.
RemoveAll
(
tmpDir
)
},
want
:
true
,
wantErr
:
false
,
},
{
name
:
"is not empty"
,
args
:
args
{
name
:
tmpDir
,
},
setup
:
func
()
error
{
os
.
Mkdir
(
tmpDir
,
0700
)
_
,
_
=
os
.
Create
(
filepath
.
Join
(
filepath
.
Dir
(
tmpDir
),
tmpDir
,
"test_file"
))
return
nil
},
teardown
:
func
()
error
{
return
os
.
RemoveAll
(
tmpDir
)
},
want
:
false
,
wantErr
:
false
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
defer
tt
.
teardown
()
if
err
:=
tt
.
setup
();
err
!=
nil
{
t
.
Errorf
(
"Setup for isDirEmpty() failed = %v"
,
err
)
return
}
got
,
err
:=
isDirEmpty
(
tt
.
args
.
name
)
if
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"isDirEmpty() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
return
}
if
got
!=
tt
.
want
{
t
.
Errorf
(
"isDirEmpty() = %+v
\n
Want = %+v"
,
got
,
tt
.
want
)
}
})
}
}
func
TestCluster_certDirsExist
(
t
*
testing
.
T
)
{
const
testDataDir
=
"/tmp/k3s/"
testTLSDir
:=
filepath
.
Join
(
testDataDir
,
"server"
,
"tls"
)
testTLSEtcdDir
:=
filepath
.
Join
(
testDataDir
,
"server"
,
"tls"
,
"etcd"
)
type
fields
struct
{
clientAccessInfo
*
clientaccess
.
Info
config
*
config
.
Control
runtime
*
config
.
ControlRuntime
managedDB
managed
.
Driver
etcdConfig
endpoint
.
ETCDConfig
shouldBootstrap
bool
storageStarted
bool
saveBootstrap
bool
}
tests
:=
[]
struct
{
name
string
fields
fields
setup
func
()
error
teardown
func
()
error
wantErr
bool
}{
{
name
:
"exists"
,
fields
:
fields
{
config
:
&
config
.
Control
{
DataDir
:
filepath
.
Join
(
testDataDir
,
"server"
),
},
},
setup
:
func
()
error
{
os
.
MkdirAll
(
testTLSEtcdDir
,
0700
)
_
,
_
=
os
.
Create
(
filepath
.
Join
(
testTLSDir
,
"test_file"
))
_
,
_
=
os
.
Create
(
filepath
.
Join
(
testTLSEtcdDir
,
"test_file"
))
return
nil
},
teardown
:
func
()
error
{
return
os
.
RemoveAll
(
testDataDir
)
},
wantErr
:
false
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
c
:=
&
Cluster
{
clientAccessInfo
:
tt
.
fields
.
clientAccessInfo
,
config
:
tt
.
fields
.
config
,
runtime
:
tt
.
fields
.
runtime
,
managedDB
:
tt
.
fields
.
managedDB
,
etcdConfig
:
tt
.
fields
.
etcdConfig
,
storageStarted
:
tt
.
fields
.
storageStarted
,
saveBootstrap
:
tt
.
fields
.
saveBootstrap
,
}
defer
tt
.
teardown
()
if
err
:=
tt
.
setup
();
err
!=
nil
{
t
.
Errorf
(
"Setup for Cluster.certDirsExist() failed = %v"
,
err
)
return
}
if
err
:=
c
.
certDirsExist
();
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"Cluster.certDirsExist() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
}
})
}
}
func
TestCluster_migrateBootstrapData
(
t
*
testing
.
T
)
{
type
fields
struct
{
clientAccessInfo
*
clientaccess
.
Info
config
*
config
.
Control
runtime
*
config
.
ControlRuntime
managedDB
managed
.
Driver
etcdConfig
endpoint
.
ETCDConfig
joining
bool
storageStarted
bool
saveBootstrap
bool
shouldBootstrap
bool
}
type
args
struct
{
ctx
context
.
Context
data
*
bytes
.
Buffer
files
bootstrap
.
PathsDataformat
}
tests
:=
[]
struct
{
name
string
args
args
setup
func
()
error
// Optional, delete if unused
teardown
func
()
error
// Optional, delete if unused
wantErr
bool
}{
{
name
:
"Success"
,
args
:
args
{
ctx
:
context
.
Background
(),
data
:
bytes
.
NewBuffer
([]
byte
(
`{"ServerCA": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ3ZEQ0NBYVFDQVFBd2R6RUxNQWtHQTFVRUJoTUNWVk14RFRBTEJnTlZCQWdNQkZWMFlXZ3hEekFOQmdOVgpCQWNNQmt4cGJtUnZiakVXTUJRR0ExVUVDZ3dOUkdsbmFVTmxjblFnU1c1akxqRVJNQThHQTFVRUN3d0lSR2xuCmFVTmxjblF4SFRBYkJnTlZCQU1NRkdWNFlXMXdiR1V1WkdsbmFXTmxjblF1WTI5dE1JSUJJakFOQmdrcWhraUcKOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTgrVG83ZCsya1BXZUJ2L29yVTNMVmJKd0RyU1FiZUthbUNtbwp3cDVicUR4SXdWMjB6cVJiN0FQVU9LWW9WRUZGT0VRczZUNmdJbW5Jb2xoYmlINm00emdaL0NQdldCT2taYytjCjFQbzJFbXZCeitBRDVzQmRUNWt6R1FBNk5iV3laR2xkeFJ0aE5MT3MxZWZPaGRuV0Z1aEkxNjJxbWNmbGdwaUkKV0R1d3E0QzlmK1lrZUpoTm45ZEY1K293bThjT1FtRHJWOE5OZGlUcWluOHEzcVlBSEhKUlcyOGdsSlVDWmtUWgp3SWFTUjZjckJROFRiWU5FMGRjK0NhYTNET0lrejFFT3NIV3pUeCtuMHpLZnFjYmdYaTRESngrQzFianB0WVBSCkJQWkw4REFlV3VBOGVidWRWVDQ0eUVwODJHOTYvR2djZjdGMzN4TXhlMHljK1hhNm93SURBUUFCb0FBd0RRWUoKS29aSWh2Y05BUUVGQlFBRGdnRUJBQjBrY3JGY2NTbUZEbXhveDBOZTAxVUlxU3NEcUhnTCtYbUhUWEp3cmU2RApoSlNad2J2RXRPSzBHMytkcjRGczExV3VVTnQ1cWNMc3g1YTh1azRHNkFLSE16dWhMc0o3WFpqZ21RWEdFQ3BZClE0bUMzeVQzWm9DR3BJWGJ3K2lQM2xtRUVYZ2FRTDBUeDVMRmwvb2tLYktZd0lxTml5S1dPTWo3WlIvd3hXZy8KWkRHUnM1NXh1b2VMREovWlJGZjliSStJYUNVZDFZcmZZY0hJbDNHODdBdityNDlZVndxUkRUMFZEVjd1TGdxbgoyOVhJMVBwVlVOQ1BRR245cC9lWDZRbzd2cERhUHliUnRBMlI3WExLalFhRjlvWFdlQ1VxeTFodkphYzlRRk8yCjk3T2IxYWxwSFBvWjdtV2lFdUp3akJQaWk2YTlNOUczMG5VbzM5bEJpMXc9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQ=="}`
)),
files
:
make
(
bootstrap
.
PathsDataformat
),
},
wantErr
:
false
,
},
{
name
:
"Invalid Old Format"
,
args
:
args
{
ctx
:
context
.
Background
(),
data
:
&
bytes
.
Buffer
{},
files
:
bootstrap
.
PathsDataformat
{
"ServerCA"
:
bootstrap
.
File
{
Timestamp
:
time
.
Now
(),
},
},
},
wantErr
:
true
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
if
err
:=
migrateBootstrapData
(
tt
.
args
.
ctx
,
tt
.
args
.
data
,
tt
.
args
.
files
);
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"Cluster.migrateBootstrapData() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
}
})
}
}
func
TestCluster_Snapshot
(
t
*
testing
.
T
)
{
type
fields
struct
{
clientAccessInfo
*
clientaccess
.
Info
config
*
config
.
Control
runtime
*
config
.
ControlRuntime
managedDB
managed
.
Driver
etcdConfig
endpoint
.
ETCDConfig
joining
bool
storageStarted
bool
saveBootstrap
bool
shouldBootstrap
bool
}
type
args
struct
{
ctx
context
.
Context
config
*
config
.
Control
}
tests
:=
[]
struct
{
name
string
fields
fields
args
args
wantErr
bool
}{
{
name
:
"Fail on non etcd cluster"
,
fields
:
fields
{},
args
:
args
{
ctx
:
context
.
Background
(),
},
wantErr
:
true
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
c
:=
&
Cluster
{
clientAccessInfo
:
tt
.
fields
.
clientAccessInfo
,
config
:
tt
.
fields
.
config
,
runtime
:
tt
.
fields
.
runtime
,
managedDB
:
tt
.
fields
.
managedDB
,
etcdConfig
:
tt
.
fields
.
etcdConfig
,
joining
:
tt
.
fields
.
joining
,
storageStarted
:
tt
.
fields
.
storageStarted
,
saveBootstrap
:
tt
.
fields
.
saveBootstrap
,
shouldBootstrap
:
tt
.
fields
.
shouldBootstrap
,
}
if
err
:=
c
.
Snapshot
(
tt
.
args
.
ctx
,
tt
.
args
.
config
);
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"Cluster.Snapshot() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
}
})
}
}
pkg/cluster/cluster.go
View file @
f0ea0a09
...
@@ -20,11 +20,11 @@ type Cluster struct {
...
@@ -20,11 +20,11 @@ type Cluster struct {
config
*
config
.
Control
config
*
config
.
Control
runtime
*
config
.
ControlRuntime
runtime
*
config
.
ControlRuntime
managedDB
managed
.
Driver
managedDB
managed
.
Driver
shouldBootstrap
bool
storageStarted
bool
etcdConfig
endpoint
.
ETCDConfig
etcdConfig
endpoint
.
ETCDConfig
joining
bool
joining
bool
storageStarted
bool
saveBootstrap
bool
saveBootstrap
bool
shouldBootstrap
bool
}
}
// Start creates the dynamic tls listener, http request handler,
// Start creates the dynamic tls listener, http request handler,
...
@@ -81,14 +81,7 @@ func (c *Cluster) Start(ctx context.Context) (<-chan struct{}, error) {
...
@@ -81,14 +81,7 @@ func (c *Cluster) Start(ctx context.Context) (<-chan struct{}, error) {
// if necessary, store bootstrap data to datastore
// if necessary, store bootstrap data to datastore
if
c
.
saveBootstrap
{
if
c
.
saveBootstrap
{
if
err
:=
c
.
save
(
ctx
);
err
!=
nil
{
if
err
:=
c
.
save
(
ctx
,
false
);
err
!=
nil
{
return
nil
,
err
}
}
// if necessary, record successful bootstrap
if
c
.
shouldBootstrap
{
if
err
:=
c
.
bootstrapped
();
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
}
}
...
@@ -106,7 +99,7 @@ func (c *Cluster) Start(ctx context.Context) (<-chan struct{}, error) {
...
@@ -106,7 +99,7 @@ func (c *Cluster) Start(ctx context.Context) (<-chan struct{}, error) {
for
{
for
{
select
{
select
{
case
<-
ready
:
case
<-
ready
:
if
err
:=
c
.
save
(
ctx
);
err
!=
nil
{
if
err
:=
c
.
save
(
ctx
,
false
);
err
!=
nil
{
panic
(
err
)
panic
(
err
)
}
}
...
@@ -153,7 +146,7 @@ func (c *Cluster) startStorage(ctx context.Context) error {
...
@@ -153,7 +146,7 @@ func (c *Cluster) startStorage(ctx context.Context) error {
return
nil
return
nil
}
}
// New creates an initial cluster using the provided configuration
// New creates an initial cluster using the provided configuration
.
func
New
(
config
*
config
.
Control
)
*
Cluster
{
func
New
(
config
*
config
.
Control
)
*
Cluster
{
return
&
Cluster
{
return
&
Cluster
{
config
:
config
,
config
:
config
,
...
...
pkg/cluster/https.go
View file @
f0ea0a09
...
@@ -79,7 +79,9 @@ func (c *Cluster) initClusterAndHTTPS(ctx context.Context) error {
...
@@ -79,7 +79,9 @@ func (c *Cluster) initClusterAndHTTPS(ctx context.Context) error {
// Create a HTTP server with the registered request handlers, using logrus for logging
// Create a HTTP server with the registered request handlers, using logrus for logging
server
:=
http
.
Server
{
server
:=
http
.
Server
{
Handler
:
handler
}
Handler
:
handler
,
}
if
logrus
.
IsLevelEnabled
(
logrus
.
DebugLevel
)
{
if
logrus
.
IsLevelEnabled
(
logrus
.
DebugLevel
)
{
server
.
ErrorLog
=
log
.
New
(
logrus
.
StandardLogger
()
.
Writer
(),
"Cluster-Http-Server "
,
log
.
LstdFlags
)
server
.
ErrorLog
=
log
.
New
(
logrus
.
StandardLogger
()
.
Writer
(),
"Cluster-Http-Server "
,
log
.
LstdFlags
)
}
else
{
}
else
{
...
...
pkg/cluster/storage.go
View file @
f0ea0a09
...
@@ -19,9 +19,9 @@ import (
...
@@ -19,9 +19,9 @@ import (
// snapshot of the cluster's CA certs and keys, encryption passphrases, etc - encrypted with the join token.
// snapshot of the cluster's CA certs and keys, encryption passphrases, etc - encrypted with the join token.
// This is used when bootstrapping a cluster from a managed database or external etcd cluster.
// This is used when bootstrapping a cluster from a managed database or external etcd cluster.
// This is NOT used with embedded etcd, which bootstraps over HTTP.
// This is NOT used with embedded etcd, which bootstraps over HTTP.
func
(
c
*
Cluster
)
save
(
ctx
context
.
Context
)
error
{
func
(
c
*
Cluster
)
save
(
ctx
context
.
Context
,
override
bool
)
error
{
buf
:=
&
bytes
.
Buffer
{}
buf
:=
&
bytes
.
Buffer
{}
if
err
:=
bootstrap
.
Write
(
buf
,
&
c
.
runtime
.
ControlRuntimeBootstrap
);
err
!=
nil
{
if
err
:=
bootstrap
.
ReadFromDisk
(
buf
,
&
c
.
runtime
.
ControlRuntimeBootstrap
);
err
!=
nil
{
return
err
return
err
}
}
token
:=
c
.
config
.
Token
token
:=
c
.
config
.
Token
...
@@ -47,14 +47,20 @@ func (c *Cluster) save(ctx context.Context) error {
...
@@ -47,14 +47,20 @@ func (c *Cluster) save(ctx context.Context) error {
return
err
return
err
}
}
_
,
err
=
c
.
getBootstrapKeyFromStorage
(
ctx
,
storageClient
,
normalizedToken
,
token
)
if
_
,
err
:=
c
.
getBootstrapKeyFromStorage
(
ctx
,
storageClient
,
normalizedToken
,
token
);
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
storageClient
.
Create
(
ctx
,
storageKey
(
normalizedToken
),
data
);
err
!=
nil
{
if
err
:=
storageClient
.
Create
(
ctx
,
storageKey
(
normalizedToken
),
data
);
err
!=
nil
{
if
err
.
Error
()
==
"key exists"
{
if
err
.
Error
()
==
"key exists"
{
logrus
.
Warnln
(
"bootstrap key already exists"
)
logrus
.
Warn
(
"bootstrap key already exists"
)
if
override
{
bsd
,
err
:=
c
.
bootstrapKeyData
(
ctx
,
storageClient
)
if
err
!=
nil
{
return
err
}
return
storageClient
.
Update
(
ctx
,
storageKey
(
normalizedToken
),
bsd
.
Modified
,
data
)
}
return
nil
return
nil
}
else
if
strings
.
Contains
(
err
.
Error
(),
"not supported for learner"
)
{
}
else
if
strings
.
Contains
(
err
.
Error
(),
"not supported for learner"
)
{
logrus
.
Debug
(
"skipping bootstrap data save on learner"
)
logrus
.
Debug
(
"skipping bootstrap data save on learner"
)
...
@@ -66,9 +72,25 @@ func (c *Cluster) save(ctx context.Context) error {
...
@@ -66,9 +72,25 @@ func (c *Cluster) save(ctx context.Context) error {
return
nil
return
nil
}
}
// bootstrapKeyData lists keys stored in the datastore with the prefix "/bootstrap", and
// will return the first such key. It will return an error if not exactly one key is found.
func
(
c
*
Cluster
)
bootstrapKeyData
(
ctx
context
.
Context
,
storageClient
client
.
Client
)
(
*
client
.
Value
,
error
)
{
bootstrapList
,
err
:=
storageClient
.
List
(
ctx
,
"/bootstrap"
,
0
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
bootstrapList
)
==
0
{
return
nil
,
errors
.
New
(
"no bootstrap data found"
)
}
if
len
(
bootstrapList
)
>
1
{
return
nil
,
errors
.
New
(
"found multiple bootstrap keys in storage"
)
}
return
&
bootstrapList
[
0
],
nil
}
// storageBootstrap loads data from the datastore into the ControlRuntimeBootstrap struct.
// storageBootstrap loads data from the datastore into the ControlRuntimeBootstrap struct.
// The storage key and encryption passphrase are both derived from the join token.
// The storage key and encryption passphrase are both derived from the join token.
// token is either passed
// token is either passed
.
func
(
c
*
Cluster
)
storageBootstrap
(
ctx
context
.
Context
)
error
{
func
(
c
*
Cluster
)
storageBootstrap
(
ctx
context
.
Context
)
error
{
if
err
:=
c
.
startStorage
(
ctx
);
err
!=
nil
{
if
err
:=
c
.
startStorage
(
ctx
);
err
!=
nil
{
return
err
return
err
...
@@ -110,7 +132,7 @@ func (c *Cluster) storageBootstrap(ctx context.Context) error {
...
@@ -110,7 +132,7 @@ func (c *Cluster) storageBootstrap(ctx context.Context) error {
return
err
return
err
}
}
return
bootstrap
.
Read
(
bytes
.
NewBuffer
(
data
),
&
c
.
r
untime
.
ControlRuntimeBootstrap
)
return
c
.
ReconcileBootstrapData
(
ctx
,
bytes
.
NewReader
(
data
),
&
c
.
config
.
R
untime
.
ControlRuntimeBootstrap
)
}
}
// getBootstrapKeyFromStorage will list all keys that has prefix /bootstrap and will check for key that is
// getBootstrapKeyFromStorage will list all keys that has prefix /bootstrap and will check for key that is
...
@@ -157,6 +179,7 @@ func (c *Cluster) getBootstrapKeyFromStorage(ctx context.Context, storageClient
...
@@ -157,6 +179,7 @@ func (c *Cluster) getBootstrapKeyFromStorage(ctx context.Context, storageClient
// found then it will still strip the token from any additional info
// found then it will still strip the token from any additional info
func
readTokenFromFile
(
serverToken
,
certs
,
dataDir
string
)
(
string
,
error
)
{
func
readTokenFromFile
(
serverToken
,
certs
,
dataDir
string
)
(
string
,
error
)
{
tokenFile
:=
filepath
.
Join
(
dataDir
,
"token"
)
tokenFile
:=
filepath
.
Join
(
dataDir
,
"token"
)
b
,
err
:=
ioutil
.
ReadFile
(
tokenFile
)
b
,
err
:=
ioutil
.
ReadFile
(
tokenFile
)
if
err
!=
nil
{
if
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
if
os
.
IsNotExist
(
err
)
{
...
@@ -168,6 +191,7 @@ func readTokenFromFile(serverToken, certs, dataDir string) (string, error) {
...
@@ -168,6 +191,7 @@ func readTokenFromFile(serverToken, certs, dataDir string) (string, error) {
}
}
return
""
,
err
return
""
,
err
}
}
// strip the token from any new line if its read from file
// strip the token from any new line if its read from file
return
string
(
bytes
.
TrimRight
(
b
,
"
\n
"
)),
nil
return
string
(
bytes
.
TrimRight
(
b
,
"
\n
"
)),
nil
}
}
...
@@ -178,6 +202,7 @@ func normalizeToken(token string) (string, error) {
...
@@ -178,6 +202,7 @@ func normalizeToken(token string) (string, error) {
if
!
ok
{
if
!
ok
{
return
password
,
errors
.
New
(
"failed to normalize token"
)
return
password
,
errors
.
New
(
"failed to normalize token"
)
}
}
return
password
,
nil
return
password
,
nil
}
}
...
@@ -186,6 +211,7 @@ func normalizeToken(token string) (string, error) {
...
@@ -186,6 +211,7 @@ func normalizeToken(token string) (string, error) {
// then migrate those and resave only with the normalized token
// then migrate those and resave only with the normalized token
func
(
c
*
Cluster
)
migrateOldTokens
(
ctx
context
.
Context
,
bootstrapList
[]
client
.
Value
,
storageClient
client
.
Client
,
emptyStringKey
,
tokenKey
,
token
,
oldToken
string
)
error
{
func
(
c
*
Cluster
)
migrateOldTokens
(
ctx
context
.
Context
,
bootstrapList
[]
client
.
Value
,
storageClient
client
.
Client
,
emptyStringKey
,
tokenKey
,
token
,
oldToken
string
)
error
{
oldTokenKey
:=
storageKey
(
oldToken
)
oldTokenKey
:=
storageKey
(
oldToken
)
for
_
,
bootstrapKV
:=
range
bootstrapList
{
for
_
,
bootstrapKV
:=
range
bootstrapList
{
// checking for empty string bootstrap key
// checking for empty string bootstrap key
if
string
(
bootstrapKV
.
Key
)
==
emptyStringKey
{
if
string
(
bootstrapKV
.
Key
)
==
emptyStringKey
{
...
@@ -200,6 +226,7 @@ func (c *Cluster) migrateOldTokens(ctx context.Context, bootstrapList []client.V
...
@@ -200,6 +226,7 @@ func (c *Cluster) migrateOldTokens(ctx context.Context, bootstrapList []client.V
}
}
}
}
}
}
return
nil
return
nil
}
}
...
@@ -209,10 +236,12 @@ func doMigrateToken(ctx context.Context, storageClient client.Client, keyValue c
...
@@ -209,10 +236,12 @@ func doMigrateToken(ctx context.Context, storageClient client.Client, keyValue c
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
encryptedData
,
err
:=
encrypt
(
newToken
,
data
)
encryptedData
,
err
:=
encrypt
(
newToken
,
data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
// saving the new encrypted data with the right token key
// saving the new encrypted data with the right token key
if
err
:=
storageClient
.
Create
(
ctx
,
newTokenKey
,
encryptedData
);
err
!=
nil
{
if
err
:=
storageClient
.
Create
(
ctx
,
newTokenKey
,
encryptedData
);
err
!=
nil
{
if
err
.
Error
()
==
"key exists"
{
if
err
.
Error
()
==
"key exists"
{
...
@@ -224,10 +253,12 @@ func doMigrateToken(ctx context.Context, storageClient client.Client, keyValue c
...
@@ -224,10 +253,12 @@ func doMigrateToken(ctx context.Context, storageClient client.Client, keyValue c
return
err
return
err
}
}
}
}
logrus
.
Infof
(
"created bootstrap key %s"
,
newTokenKey
)
logrus
.
Infof
(
"created bootstrap key %s"
,
newTokenKey
)
// deleting the old key
// deleting the old key
if
err
:=
storageClient
.
Delete
(
ctx
,
oldTokenKey
,
keyValue
.
Modified
);
err
!=
nil
{
if
err
:=
storageClient
.
Delete
(
ctx
,
oldTokenKey
,
keyValue
.
Modified
);
err
!=
nil
{
logrus
.
Warnf
(
"failed to delete old bootstrap key %s"
,
oldTokenKey
)
logrus
.
Warnf
(
"failed to delete old bootstrap key %s"
,
oldTokenKey
)
}
}
return
nil
return
nil
}
}
pkg/daemons/control/deps/deps.go
View file @
f0ea0a09
...
@@ -89,6 +89,67 @@ func KubeConfig(dest, url, caCert, clientCert, clientKey string) error {
...
@@ -89,6 +89,67 @@ func KubeConfig(dest, url, caCert, clientCert, clientKey string) error {
return
kubeconfigTemplate
.
Execute
(
output
,
&
data
)
return
kubeconfigTemplate
.
Execute
(
output
,
&
data
)
}
}
// CreateRuntimeCertFiles is responsible for filling out all the
// .crt and .key filenames for a ControlRuntime.
func
CreateRuntimeCertFiles
(
config
*
config
.
Control
,
runtime
*
config
.
ControlRuntime
)
{
runtime
.
ClientCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-ca.crt"
)
runtime
.
ClientCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-ca.key"
)
runtime
.
ServerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"server-ca.crt"
)
runtime
.
ServerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"server-ca.key"
)
runtime
.
RequestHeaderCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"request-header-ca.crt"
)
runtime
.
RequestHeaderCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"request-header-ca.key"
)
runtime
.
IPSECKey
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"ipsec.psk"
)
runtime
.
ServiceKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"service.key"
)
runtime
.
PasswdFile
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"passwd"
)
runtime
.
NodePasswdFile
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"node-passwd"
)
runtime
.
KubeConfigAdmin
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"admin.kubeconfig"
)
runtime
.
KubeConfigController
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"controller.kubeconfig"
)
runtime
.
KubeConfigScheduler
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"scheduler.kubeconfig"
)
runtime
.
KubeConfigAPIServer
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"api-server.kubeconfig"
)
runtime
.
KubeConfigCloudController
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"cloud-controller.kubeconfig"
)
runtime
.
ClientAdminCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-admin.crt"
)
runtime
.
ClientAdminKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-admin.key"
)
runtime
.
ClientControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-controller.crt"
)
runtime
.
ClientControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-controller.key"
)
runtime
.
ClientCloudControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-cloud-controller.crt"
)
runtime
.
ClientCloudControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-cloud-controller.key"
)
runtime
.
ClientSchedulerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-scheduler.crt"
)
runtime
.
ClientSchedulerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-scheduler.key"
)
runtime
.
ClientKubeAPICert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-apiserver.crt"
)
runtime
.
ClientKubeAPIKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-apiserver.key"
)
runtime
.
ClientKubeProxyCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-proxy.crt"
)
runtime
.
ClientKubeProxyKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-proxy.key"
)
runtime
.
ClientK3sControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-controller.crt"
)
runtime
.
ClientK3sControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-controller.key"
)
runtime
.
ServingKubeAPICert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kube-apiserver.crt"
)
runtime
.
ServingKubeAPIKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kube-apiserver.key"
)
runtime
.
ClientKubeletKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kubelet.key"
)
runtime
.
ServingKubeletKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kubelet.key"
)
runtime
.
ClientAuthProxyCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-auth-proxy.crt"
)
runtime
.
ClientAuthProxyKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-auth-proxy.key"
)
runtime
.
ETCDServerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-ca.crt"
)
runtime
.
ETCDServerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-ca.key"
)
runtime
.
ETCDPeerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-ca.crt"
)
runtime
.
ETCDPeerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-ca.key"
)
runtime
.
ServerETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-client.crt"
)
runtime
.
ServerETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-client.key"
)
runtime
.
PeerServerClientETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-server-client.crt"
)
runtime
.
PeerServerClientETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-server-client.key"
)
runtime
.
ClientETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"client.crt"
)
runtime
.
ClientETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"client.key"
)
if
config
.
EncryptSecrets
{
runtime
.
EncryptionConfig
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"encryption-config.json"
)
}
}
// GenServerDeps is responsible for generating the cluster dependencies
// GenServerDeps is responsible for generating the cluster dependencies
// needed to successfully bootstrap a cluster.
// needed to successfully bootstrap a cluster.
func
GenServerDeps
(
config
*
config
.
Control
,
runtime
*
config
.
ControlRuntime
)
error
{
func
GenServerDeps
(
config
*
config
.
Control
,
runtime
*
config
.
ControlRuntime
)
error
{
...
...
pkg/daemons/control/server.go
View file @
f0ea0a09
...
@@ -239,62 +239,7 @@ func prepare(ctx context.Context, config *config.Control, runtime *config.Contro
...
@@ -239,62 +239,7 @@ func prepare(ctx context.Context, config *config.Control, runtime *config.Contro
os
.
MkdirAll
(
filepath
.
Join
(
config
.
DataDir
,
"tls"
),
0700
)
os
.
MkdirAll
(
filepath
.
Join
(
config
.
DataDir
,
"tls"
),
0700
)
os
.
MkdirAll
(
filepath
.
Join
(
config
.
DataDir
,
"cred"
),
0700
)
os
.
MkdirAll
(
filepath
.
Join
(
config
.
DataDir
,
"cred"
),
0700
)
runtime
.
ClientCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-ca.crt"
)
deps
.
CreateRuntimeCertFiles
(
config
,
runtime
)
runtime
.
ClientCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-ca.key"
)
runtime
.
ServerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"server-ca.crt"
)
runtime
.
ServerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"server-ca.key"
)
runtime
.
RequestHeaderCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"request-header-ca.crt"
)
runtime
.
RequestHeaderCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"request-header-ca.key"
)
runtime
.
IPSECKey
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"ipsec.psk"
)
runtime
.
ServiceKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"service.key"
)
runtime
.
PasswdFile
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"passwd"
)
runtime
.
NodePasswdFile
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"node-passwd"
)
runtime
.
KubeConfigAdmin
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"admin.kubeconfig"
)
runtime
.
KubeConfigController
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"controller.kubeconfig"
)
runtime
.
KubeConfigScheduler
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"scheduler.kubeconfig"
)
runtime
.
KubeConfigAPIServer
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"api-server.kubeconfig"
)
runtime
.
KubeConfigCloudController
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"cloud-controller.kubeconfig"
)
runtime
.
ClientAdminCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-admin.crt"
)
runtime
.
ClientAdminKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-admin.key"
)
runtime
.
ClientControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-controller.crt"
)
runtime
.
ClientControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-controller.key"
)
runtime
.
ClientCloudControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-cloud-controller.crt"
)
runtime
.
ClientCloudControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-cloud-controller.key"
)
runtime
.
ClientSchedulerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-scheduler.crt"
)
runtime
.
ClientSchedulerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-scheduler.key"
)
runtime
.
ClientKubeAPICert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-apiserver.crt"
)
runtime
.
ClientKubeAPIKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-apiserver.key"
)
runtime
.
ClientKubeProxyCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-proxy.crt"
)
runtime
.
ClientKubeProxyKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kube-proxy.key"
)
runtime
.
ClientK3sControllerCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-controller.crt"
)
runtime
.
ClientK3sControllerKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-"
+
version
.
Program
+
"-controller.key"
)
runtime
.
ServingKubeAPICert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kube-apiserver.crt"
)
runtime
.
ServingKubeAPIKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kube-apiserver.key"
)
runtime
.
ClientKubeletKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-kubelet.key"
)
runtime
.
ServingKubeletKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"serving-kubelet.key"
)
runtime
.
ClientAuthProxyCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-auth-proxy.crt"
)
runtime
.
ClientAuthProxyKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"client-auth-proxy.key"
)
runtime
.
ETCDServerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-ca.crt"
)
runtime
.
ETCDServerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-ca.key"
)
runtime
.
ETCDPeerCA
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-ca.crt"
)
runtime
.
ETCDPeerCAKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-ca.key"
)
runtime
.
ServerETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-client.crt"
)
runtime
.
ServerETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"server-client.key"
)
runtime
.
PeerServerClientETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-server-client.crt"
)
runtime
.
PeerServerClientETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"peer-server-client.key"
)
runtime
.
ClientETCDCert
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"client.crt"
)
runtime
.
ClientETCDKey
=
filepath
.
Join
(
config
.
DataDir
,
"tls"
,
"etcd"
,
"client.key"
)
if
config
.
EncryptSecrets
{
runtime
.
EncryptionConfig
=
filepath
.
Join
(
config
.
DataDir
,
"cred"
,
"encryption-config.json"
)
}
cluster
:=
cluster
.
New
(
config
)
cluster
:=
cluster
.
New
(
config
)
...
...
pkg/etcd/etcd.go
View file @
f0ea0a09
...
@@ -178,7 +178,7 @@ func (e *ETCD) IsInitialized(ctx context.Context, config *config.Control) (bool,
...
@@ -178,7 +178,7 @@ func (e *ETCD) IsInitialized(ctx context.Context, config *config.Control) (bool,
}
else
if
os
.
IsNotExist
(
err
)
{
}
else
if
os
.
IsNotExist
(
err
)
{
return
false
,
nil
return
false
,
nil
}
else
{
}
else
{
return
false
,
errors
.
Wrap
f
(
err
,
"invalid state for wal directory %s"
,
dir
)
return
false
,
errors
.
Wrap
(
err
,
"invalid state for wal directory "
+
dir
)
}
}
}
}
...
...
tests/util/runtime.go
0 → 100644
View file @
f0ea0a09
package
util
import
(
"net"
"os"
"path/filepath"
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/control/deps"
)
// GenerateDataDir creates a temporary directory at "/tmp/k3s/<RANDOM_STRING>/".
// The latest directory created with this function is soft linked to "/tmp/k3s/latest/".
// This allows tests to replicate the "/var/lib/rancher/k3s" directory structure.
func
GenerateDataDir
(
cnf
*
config
.
Control
)
error
{
if
err
:=
os
.
MkdirAll
(
cnf
.
DataDir
,
0700
);
err
!=
nil
{
return
err
}
testDir
,
err
:=
os
.
MkdirTemp
(
cnf
.
DataDir
,
"*"
)
if
err
!=
nil
{
return
err
}
// Remove old symlink and add new one
os
.
Remove
(
filepath
.
Join
(
cnf
.
DataDir
,
"latest"
))
if
err
=
os
.
Symlink
(
testDir
,
filepath
.
Join
(
cnf
.
DataDir
,
"latest"
));
err
!=
nil
{
return
err
}
cnf
.
DataDir
=
testDir
cnf
.
DataDir
,
err
=
filepath
.
Abs
(
cnf
.
DataDir
)
if
err
!=
nil
{
return
err
}
return
nil
}
// CleanupDataDir removes the associated "/tmp/k3s/<RANDOM_STRING>"
// directory.
func
CleanupDataDir
(
cnf
*
config
.
Control
)
{
os
.
RemoveAll
(
cnf
.
DataDir
)
}
// GenerateRuntime creates a temporary data dir and configures
// config.ControlRuntime with all the appropriate certificate keys.
func
GenerateRuntime
(
cnf
*
config
.
Control
)
error
{
runtime
:=
&
config
.
ControlRuntime
{}
if
err
:=
GenerateDataDir
(
cnf
);
err
!=
nil
{
return
err
}
runtime
.
AgentReady
=
make
(
chan
struct
{})
os
.
MkdirAll
(
filepath
.
Join
(
cnf
.
DataDir
,
"tls"
),
0700
)
os
.
MkdirAll
(
filepath
.
Join
(
cnf
.
DataDir
,
"cred"
),
0700
)
deps
.
CreateRuntimeCertFiles
(
cnf
,
runtime
)
if
err
:=
deps
.
GenServerDeps
(
cnf
,
runtime
);
err
!=
nil
{
return
err
}
cnf
.
Runtime
=
runtime
return
nil
}
func
ClusterIPNet
()
*
net
.
IPNet
{
_
,
clusterIPNet
,
_
:=
net
.
ParseCIDR
(
"10.42.0.0/16"
)
return
clusterIPNet
}
func
ServiceIPNet
()
*
net
.
IPNet
{
_
,
serviceIPNet
,
_
:=
net
.
ParseCIDR
(
"10.43.0.0/16"
)
return
serviceIPNet
}
vendor/modules.txt
View file @
f0ea0a09
...
@@ -1251,7 +1251,7 @@ golang.org/x/oauth2/jwt
...
@@ -1251,7 +1251,7 @@ golang.org/x/oauth2/jwt
golang.org/x/sync/errgroup
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
golang.org/x/sync/semaphore
golang.org/x/sync/singleflight
golang.org/x/sync/singleflight
# golang.org/x/sys v0.0.0-20210
426230700-d19ff857e887
=> golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073
# golang.org/x/sys v0.0.0-20210
603081109-ebe580a85c40
=> golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073
## explicit
## explicit
golang.org/x/sys/cpu
golang.org/x/sys/cpu
golang.org/x/sys/execabs
golang.org/x/sys/execabs
...
@@ -1357,7 +1357,7 @@ google.golang.org/appengine/urlfetch
...
@@ -1357,7 +1357,7 @@ google.golang.org/appengine/urlfetch
google.golang.org/genproto/googleapis/api/httpbody
google.golang.org/genproto/googleapis/api/httpbody
google.golang.org/genproto/googleapis/rpc/status
google.golang.org/genproto/googleapis/rpc/status
google.golang.org/genproto/protobuf/field_mask
google.golang.org/genproto/protobuf/field_mask
# google.golang.org/grpc v1.3
7
.0 => google.golang.org/grpc v1.27.1
# google.golang.org/grpc v1.3
8
.0 => google.golang.org/grpc v1.27.1
## explicit
## explicit
google.golang.org/grpc
google.golang.org/grpc
google.golang.org/grpc/attributes
google.golang.org/grpc/attributes
...
...
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