Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Chu Peng 楚鹏
minikube
提交
b0440fc9
M
minikube
项目概览
Chu Peng 楚鹏
/
minikube
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
minikube
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b0440fc9
编写于
5月 16, 2016
作者:
D
dlorenc
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #73 from ethernetdan/kubeconfig
Setup kubeconfig on cluster start
上级
a3ff9d75
77c1d0ce
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
375 addition
and
5 deletion
+375
-5
cmd/minikube/cmd/start.go
cmd/minikube/cmd/start.go
+61
-5
pkg/minikube/constants/constants.go
pkg/minikube/constants/constants.go
+7
-0
pkg/minikube/kubeconfig/config.go
pkg/minikube/kubeconfig/config.go
+102
-0
pkg/minikube/kubeconfig/config_test.go
pkg/minikube/kubeconfig/config_test.go
+205
-0
未找到文件。
cmd/minikube/cmd/start.go
浏览文件 @
b0440fc9
...
@@ -24,8 +24,10 @@ import (
...
@@ -24,8 +24,10 @@ import (
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine"
"github.com/spf13/cobra"
"github.com/spf13/cobra"
cfg
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/kubeconfig"
)
)
// startCmd represents the start command
// startCmd represents the start command
...
@@ -74,11 +76,19 @@ func runStart(cmd *cobra.Command, args []string) {
...
@@ -74,11 +76,19 @@ func runStart(cmd *cobra.Command, args []string) {
kubeHost
=
strings
.
Replace
(
kubeHost
,
"tcp://"
,
"https://"
,
-
1
)
kubeHost
=
strings
.
Replace
(
kubeHost
,
"tcp://"
,
"https://"
,
-
1
)
kubeHost
=
strings
.
Replace
(
kubeHost
,
":2376"
,
":443"
,
-
1
)
kubeHost
=
strings
.
Replace
(
kubeHost
,
":2376"
,
":443"
,
-
1
)
fmt
.
Printf
(
"Kubernetes is available at %s.
\n
"
,
kubeHost
)
fmt
.
Printf
(
"Kubernetes is available at %s.
\n
"
,
kubeHost
)
// setup kubeconfig
name
:=
constants
.
MinikubeContext
certAuth
:=
constants
.
MakeMiniPath
(
"apiserver.crt"
)
clientCert
:=
constants
.
MakeMiniPath
(
"apiserver.crt"
)
clientKey
:=
constants
.
MakeMiniPath
(
"apiserver.key"
)
if
active
,
err
:=
setupKubeconfig
(
name
,
kubeHost
,
certAuth
,
clientCert
,
clientKey
);
err
!=
nil
{
log
.
Println
(
"Error setting up kubeconfig: "
,
err
)
os
.
Exit
(
1
)
}
else
if
!
active
{
fmt
.
Println
(
"Run this command to use the cluster: "
)
fmt
.
Println
(
"Run this command to use the cluster: "
)
fmt
.
Printf
(
"kubectl config set-cluster minikube --server=%s --certificate-authority=$HOME/.minikube/apiserver.crt
\n
"
,
kubeHost
)
fmt
.
Printf
(
"kubectl config use-context %s
\n
"
,
name
)
fmt
.
Println
(
"kubectl config set-credentials minikube --client-certificate=$HOME/.minikube/apiserver.crt --client-key=$HOME/.minikube/apiserver.key"
)
}
fmt
.
Println
(
"kubectl config set-context minikube --cluster=minikube --user=minikube"
)
fmt
.
Println
(
"kubectl config use-context minikube"
)
if
err
:=
cluster
.
GetCreds
(
host
);
err
!=
nil
{
if
err
:=
cluster
.
GetCreds
(
host
);
err
!=
nil
{
log
.
Println
(
"Error configuring authentication: "
,
err
)
log
.
Println
(
"Error configuring authentication: "
,
err
)
...
@@ -86,6 +96,52 @@ func runStart(cmd *cobra.Command, args []string) {
...
@@ -86,6 +96,52 @@ func runStart(cmd *cobra.Command, args []string) {
}
}
}
}
// setupKubeconfig reads config from disk, adds the minikube settings, and writes it back.
// activeContext is true when minikube is the CurrentContext
// If no CurrentContext is set, the given name will be used.
func
setupKubeconfig
(
name
,
server
,
certAuth
,
cliCert
,
cliKey
string
)
(
activeContext
bool
,
err
error
)
{
configFile
:=
constants
.
KubeconfigPath
// read existing config or create new if does not exist
config
,
err
:=
kubeconfig
.
ReadConfigOrNew
(
configFile
)
if
err
!=
nil
{
return
false
,
err
}
clusterName
:=
name
cluster
:=
cfg
.
NewCluster
()
cluster
.
Server
=
server
cluster
.
CertificateAuthority
=
certAuth
config
.
Clusters
[
clusterName
]
=
cluster
// user
userName
:=
name
user
:=
cfg
.
NewAuthInfo
()
user
.
ClientCertificate
=
cliCert
user
.
ClientKey
=
cliKey
config
.
AuthInfos
[
userName
]
=
user
// context
contextName
:=
name
context
:=
cfg
.
NewContext
()
context
.
Cluster
=
clusterName
context
.
AuthInfo
=
userName
config
.
Contexts
[
contextName
]
=
context
// set current context to minikube if unset
if
len
(
config
.
CurrentContext
)
==
0
{
config
.
CurrentContext
=
contextName
}
// write back to disk
if
err
:=
kubeconfig
.
WriteConfig
(
config
,
configFile
);
err
!=
nil
{
return
false
,
err
}
// activeContext if current matches name
return
name
==
config
.
CurrentContext
,
nil
}
func
init
()
{
func
init
()
{
startCmd
.
Flags
()
.
StringVarP
(
&
minikubeISO
,
"iso-url"
,
""
,
"https://storage.googleapis.com/tinykube/minikube.iso"
,
"Location of the minikube iso"
)
startCmd
.
Flags
()
.
StringVarP
(
&
minikubeISO
,
"iso-url"
,
""
,
"https://storage.googleapis.com/tinykube/minikube.iso"
,
"Location of the minikube iso"
)
RootCmd
.
AddCommand
(
startCmd
)
RootCmd
.
AddCommand
(
startCmd
)
...
...
pkg/minikube/constants/constants.go
浏览文件 @
b0440fc9
...
@@ -27,6 +27,13 @@ const MachineName = "minikubeVM"
...
@@ -27,6 +27,13 @@ const MachineName = "minikubeVM"
// Fix for windows
// Fix for windows
var
Minipath
=
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".minikube"
)
var
Minipath
=
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".minikube"
)
// TODO: Fix for windows
// KubeconfigPath is the path to the Kubernetes client config
var
KubeconfigPath
=
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".kube"
,
"config"
)
// MinikubeContext is the kubeconfig context name used for minikube
const
MinikubeContext
=
"minikube"
// MakeMiniPath is a utility to calculate a relative path to our directory.
// MakeMiniPath is a utility to calculate a relative path to our directory.
func
MakeMiniPath
(
fileName
string
)
string
{
func
MakeMiniPath
(
fileName
string
)
string
{
return
filepath
.
Join
(
Minipath
,
fileName
)
return
filepath
.
Join
(
Minipath
,
fileName
)
...
...
pkg/minikube/kubeconfig/config.go
0 → 100644
浏览文件 @
b0440fc9
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
kubeconfig
import
(
"fmt"
"io/ioutil"
"os"
"path/filepath"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/latest"
"k8s.io/kubernetes/pkg/runtime"
)
// ReadConfigOrNew retrieves Kubernetes client configuration from a file.
// If no files exists, an empty configuration is returned.
func
ReadConfigOrNew
(
filename
string
)
(
*
api
.
Config
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
filename
)
if
os
.
IsNotExist
(
err
)
{
return
api
.
NewConfig
(),
nil
}
else
if
err
!=
nil
{
return
nil
,
err
}
// decode config, empty if no bytes
config
,
err
:=
decode
(
data
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"could not read config: %v"
,
err
)
}
// initialize nil maps
if
config
.
AuthInfos
==
nil
{
config
.
AuthInfos
=
map
[
string
]
*
api
.
AuthInfo
{}
}
if
config
.
Clusters
==
nil
{
config
.
Clusters
=
map
[
string
]
*
api
.
Cluster
{}
}
if
config
.
Contexts
==
nil
{
config
.
Contexts
=
map
[
string
]
*
api
.
Context
{}
}
return
config
,
nil
}
// WriteConfig encodes the configuration and writes it to the given file.
// If the file exists, it's contents will be overwritten.
func
WriteConfig
(
config
*
api
.
Config
,
filename
string
)
error
{
if
config
==
nil
{
fmt
.
Errorf
(
"could not write to '%s': config can't be nil"
,
filename
)
}
// encode config to YAML
data
,
err
:=
runtime
.
Encode
(
latest
.
Codec
,
config
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"could not write to '%s': failed to encode config: %v"
,
filename
,
err
)
}
// create parent dir if doesn't exist
dir
:=
filepath
.
Dir
(
filename
)
if
_
,
err
:=
os
.
Stat
(
dir
);
os
.
IsNotExist
(
err
)
{
if
err
=
os
.
MkdirAll
(
dir
,
0755
);
err
!=
nil
{
return
err
}
}
// write with restricted permissions
if
err
:=
ioutil
.
WriteFile
(
filename
,
data
,
0600
);
err
!=
nil
{
return
err
}
return
nil
}
// decode reads a Config object from bytes.
// Returns empty config if no bytes.
func
decode
(
data
[]
byte
)
(
*
api
.
Config
,
error
)
{
// if no data, return empty config
if
len
(
data
)
==
0
{
return
api
.
NewConfig
(),
nil
}
config
,
_
,
err
:=
latest
.
Codec
.
Decode
(
data
,
nil
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
return
config
.
(
*
api
.
Config
),
nil
}
pkg/minikube/kubeconfig/config_test.go
0 → 100644
浏览文件 @
b0440fc9
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
kubeconfig
import
(
"io/ioutil"
"os"
"path/filepath"
"testing"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
)
func
TestEmptyConfig
(
t
*
testing
.
T
)
{
tmp
:=
tempFile
(
t
,
[]
byte
{})
defer
os
.
Remove
(
tmp
)
cfg
,
err
:=
ReadConfigOrNew
(
tmp
)
if
err
!=
nil
{
t
.
Fatalf
(
"could not read config: %v"
,
err
)
}
if
len
(
cfg
.
AuthInfos
)
!=
0
{
t
.
Fail
()
}
if
len
(
cfg
.
Clusters
)
!=
0
{
t
.
Fail
()
}
if
len
(
cfg
.
Contexts
)
!=
0
{
t
.
Fail
()
}
}
func
TestNewConfig
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
".kube"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
RemoveAll
(
dir
)
// setup minikube config
expected
:=
api
.
NewConfig
()
minikubeConfig
(
expected
)
// write actual
filename
:=
filepath
.
Join
(
dir
,
"config"
)
err
=
WriteConfig
(
expected
,
filename
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
actual
,
err
:=
ReadConfigOrNew
(
filename
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
configEquals
(
actual
,
expected
)
{
t
.
Fatal
(
"configs did not match"
)
}
}
// tempFile creates a temporary with the provided bytes as its contents.
// The caller is responsible for deleting file after use.
func
tempFile
(
t
*
testing
.
T
,
data
[]
byte
)
string
{
tmp
,
err
:=
ioutil
.
TempFile
(
""
,
"kubeconfig"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
len
(
data
)
>
0
{
if
_
,
err
:=
tmp
.
Write
(
data
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
if
err
:=
tmp
.
Close
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
tmp
.
Name
()
}
// minikubeConfig returns a config that reasonably approximates a localkube cluster
func
minikubeConfig
(
config
*
api
.
Config
)
{
// cluster
clusterName
:=
"minikube"
cluster
:=
api
.
NewCluster
()
cluster
.
Server
=
"https://192.168.99.100:443"
cluster
.
CertificateAuthority
=
"/home/tux/.minikube/apiserver.crt"
config
.
Clusters
[
clusterName
]
=
cluster
// user
userName
:=
"minikube"
user
:=
api
.
NewAuthInfo
()
user
.
ClientCertificate
=
"/home/tux/.minikube/apiserver.crt"
user
.
ClientKey
=
"/home/tux/.minikube/apiserver.key"
config
.
AuthInfos
[
userName
]
=
user
// context
contextName
:=
"minikube"
context
:=
api
.
NewContext
()
context
.
Cluster
=
clusterName
context
.
AuthInfo
=
userName
config
.
Contexts
[
contextName
]
=
context
config
.
CurrentContext
=
contextName
}
// configEquals checks if configs are identical
func
configEquals
(
a
,
b
*
api
.
Config
)
bool
{
if
a
.
Kind
!=
b
.
Kind
{
return
false
}
if
a
.
APIVersion
!=
b
.
APIVersion
{
return
false
}
if
a
.
Preferences
.
Colors
!=
b
.
Preferences
.
Colors
{
return
false
}
if
len
(
a
.
Extensions
)
!=
len
(
b
.
Extensions
)
{
return
false
}
// clusters
if
len
(
a
.
Clusters
)
!=
len
(
b
.
Clusters
)
{
return
false
}
for
k
,
aCluster
:=
range
a
.
Clusters
{
bCluster
,
exists
:=
b
.
Clusters
[
k
]
if
!
exists
{
return
false
}
if
aCluster
.
LocationOfOrigin
!=
bCluster
.
LocationOfOrigin
||
aCluster
.
Server
!=
bCluster
.
Server
||
aCluster
.
APIVersion
!=
bCluster
.
APIVersion
||
aCluster
.
InsecureSkipTLSVerify
!=
bCluster
.
InsecureSkipTLSVerify
||
aCluster
.
CertificateAuthority
!=
bCluster
.
CertificateAuthority
||
len
(
aCluster
.
CertificateAuthorityData
)
!=
len
(
bCluster
.
CertificateAuthorityData
)
||
len
(
aCluster
.
Extensions
)
!=
len
(
bCluster
.
Extensions
)
{
return
false
}
}
// users
if
len
(
a
.
AuthInfos
)
!=
len
(
b
.
AuthInfos
)
{
return
false
}
for
k
,
aAuth
:=
range
a
.
AuthInfos
{
bAuth
,
exists
:=
b
.
AuthInfos
[
k
]
if
!
exists
{
return
false
}
if
aAuth
.
LocationOfOrigin
!=
bAuth
.
LocationOfOrigin
||
aAuth
.
ClientCertificate
!=
bAuth
.
ClientCertificate
||
len
(
aAuth
.
ClientCertificateData
)
!=
len
(
bAuth
.
ClientCertificateData
)
||
aAuth
.
ClientKey
!=
bAuth
.
ClientKey
||
len
(
aAuth
.
ClientKeyData
)
!=
len
(
bAuth
.
ClientKeyData
)
||
aAuth
.
Token
!=
bAuth
.
Token
||
aAuth
.
Username
!=
bAuth
.
Username
||
aAuth
.
Password
!=
bAuth
.
Password
||
len
(
aAuth
.
Extensions
)
!=
len
(
bAuth
.
Extensions
)
{
return
false
}
}
// contexts
if
len
(
a
.
Contexts
)
!=
len
(
b
.
Contexts
)
{
return
false
}
for
k
,
aContext
:=
range
a
.
Contexts
{
bContext
,
exists
:=
b
.
Contexts
[
k
]
if
!
exists
{
return
false
}
if
aContext
.
LocationOfOrigin
!=
bContext
.
LocationOfOrigin
||
aContext
.
Cluster
!=
bContext
.
Cluster
||
aContext
.
AuthInfo
!=
bContext
.
AuthInfo
||
aContext
.
Namespace
!=
bContext
.
Namespace
||
len
(
aContext
.
Extensions
)
!=
len
(
aContext
.
Extensions
)
{
return
false
}
}
return
true
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录