Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Chu Peng 楚鹏
minikube
提交
c3d962b5
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,体验更适合开发者的 AI 搜索 >>
提交
c3d962b5
编写于
2月 16, 2017
作者:
S
Steve Sloka
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow for addons to prompt for data input
上级
6bd1b251
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
361 addition
and
16 deletion
+361
-16
cmd/minikube/cmd/config/prompt.go
cmd/minikube/cmd/config/prompt.go
+89
-0
cmd/minikube/cmd/config/util.go
cmd/minikube/cmd/config/util.go
+56
-0
deploy/addons/registry-creds/registry-creds-rc.yaml
deploy/addons/registry-creds/registry-creds-rc.yaml
+18
-16
pkg/minikube/cluster/cluster.go
pkg/minikube/cluster/cluster.go
+198
-0
未找到文件。
cmd/minikube/cmd/config/prompt.go
0 → 100644
浏览文件 @
c3d962b5
/*
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
config
import
(
"bufio"
"fmt"
"log"
"os"
"strings"
)
// AskForYesNoConfirmation asks the user for confirmation. A user must type in "yes" or "no" and
// then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES", and "Yes" all count as
// confirmations. If the input is not recognized, it will ask again. The function does not return
// until it gets a valid response from the user.
func
AskForYesNoConfirmation
(
s
string
,
posResponses
,
negResponses
[]
string
)
bool
{
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
for
{
fmt
.
Printf
(
"%s [y/n]: "
,
s
)
response
,
err
:=
reader
.
ReadString
(
'\n'
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
response
=
strings
.
ToLower
(
strings
.
TrimSpace
(
response
))
if
containsString
(
posResponses
,
response
)
{
return
true
}
else
if
containsString
(
negResponses
,
response
)
{
return
false
}
else
{
fmt
.
Println
(
"Please type yes or no:"
)
return
AskForYesNoConfirmation
(
s
,
posResponses
,
negResponses
)
}
}
}
// AskForStaticValue asks for a single value to enter
func
AskForStaticValue
(
s
string
)
string
{
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
for
{
fmt
.
Printf
(
"%s"
,
s
)
response
,
err
:=
reader
.
ReadString
(
'\n'
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
response
=
strings
.
TrimSpace
(
response
)
// Can't have zero length
if
len
(
response
)
==
0
{
fmt
.
Println
(
"--Error, please enter a value:"
)
return
AskForStaticValue
(
s
)
}
return
response
}
}
// posString returns the first index of element in slice.
// If slice does not contain element, returns -1.
func
posString
(
slice
[]
string
,
element
string
)
int
{
for
index
,
elem
:=
range
slice
{
if
elem
==
element
{
return
index
}
}
return
-
1
}
// containsString returns true iff slice contains element
func
containsString
(
slice
[]
string
,
element
string
)
bool
{
return
!
(
posString
(
slice
,
element
)
==
-
1
)
}
cmd/minikube/cmd/config/util.go
浏览文件 @
c3d962b5
...
...
@@ -88,11 +88,67 @@ func GetClientType() machine.ClientType {
}
func
EnableOrDisableAddon
(
name
string
,
val
string
)
error
{
enable
,
err
:=
strconv
.
ParseBool
(
val
)
if
err
!=
nil
{
errors
.
Wrapf
(
err
,
"error attempted to parse enabled/disable value addon %s"
,
name
)
}
// allows for additional prompting of information when enabling addons
if
enable
{
switch
name
{
case
"registry-creds"
:
posResponses
:=
[]
string
{
"yes"
,
"y"
}
negResponses
:=
[]
string
{
"no"
,
"n"
}
enableAWSECR
:=
AskForYesNoConfirmation
(
"
\n
Do you want to enable AWS Elastic Container Registry?"
,
posResponses
,
negResponses
)
if
enableAWSECR
{
awsAccessID
:=
AskForStaticValue
(
"-- Enter AWS Access Key ID: "
)
awsAccessKey
:=
AskForStaticValue
(
"-- Enter AWS Secret Access Key: "
)
awsRegion
:=
AskForStaticValue
(
"-- Enter AWS Region: "
)
awsAccount
:=
AskForStaticValue
(
"-- Enter 12 digit AWS Account ID: "
)
cluster
.
CreateSecret
(
"kube-system"
,
"registry-creds-ecr"
,
map
[
string
]
string
{
"AWS_ACCESS_KEY_ID"
:
awsAccessID
,
"AWS_SECRET_ACCESS_KEY"
:
awsAccessKey
,
"aws-account"
:
awsAccount
,
"awsregion"
:
awsRegion
,
},
map
[
string
]
string
{
"app"
:
"registry-creds"
,
"cloud"
:
"ecr"
,
"kubernetes.io/minikube-addons"
:
"registry-creds"
,
})
}
enableGCR
:=
AskForYesNoConfirmation
(
"
\n
Do you want to enable Google Container Registry?"
,
posResponses
,
negResponses
)
if
enableGCR
{
fmt
.
Println
(
"-- Enter applicatoin_default_credentials.json as base64 by running following command:"
)
gcrApplicationDefaultCredentials
:=
AskForStaticValue
(
" base64 -w 0 $HOME/.config/gcloud/application_default_credentials.json: "
)
cluster
.
CreateSecret
(
"kube-system"
,
"registry-creds-gcr"
,
map
[
string
]
string
{
"application_default_credentials.json"
:
gcrApplicationDefaultCredentials
,
},
map
[
string
]
string
{
"app"
:
"registry-creds"
,
"cloud"
:
"gcr"
,
"kubernetes.io/minikube-addons"
:
"registry-creds"
,
})
}
break
}
}
else
{
// Cleanup existing secrets
cluster
.
DeleteSecret
(
"kube-system"
,
"registry-creds-ecr"
)
cluster
.
DeleteSecret
(
"kube-system"
,
"registry-creds-gcr"
)
}
//TODO(r2d4): config package should not reference API, pull this out
api
,
err
:=
machine
.
NewAPIClient
(
GetClientType
())
if
err
!=
nil
{
...
...
deploy/addons/registry-creds/registry-creds-rc.yaml
浏览文件 @
c3d962b5
apiVersion
:
v1
kind
:
ReplicationController
metadata
:
name
:
registry-creds
namespace
:
kube-system
labels
:
app
:
registry-creds
version
:
v1.5
kubernetes.io/cluster-service
:
"
true"
kubernetes.io/minikube-addons
:
registry-creds
version
:
v1.6
spec
:
replicas
:
1
selector
:
app
:
registry-creds
version
:
v1.5
kubernetes.io/cluster-service
:
"
true"
name
:
registry-creds
version
:
v1.6
template
:
metadata
:
labels
:
app
:
registry-creds
version
:
v1.5
kubernetes.io/cluster-service
:
"
true"
name
:
registry-creds
version
:
v1.6
spec
:
containers
:
-
image
:
upmcenterprises/registry-creds:1.
5
-
image
:
upmcenterprises/registry-creds:1.
6
name
:
registry-creds
imagePullPolicy
:
Always
env
:
-
name
:
AWS_ACCESS_KEY_ID
valueFrom
:
secretKeyRef
:
name
:
registry-creds
name
:
registry-creds
-ecr
key
:
AWS_ACCESS_KEY_ID
-
name
:
AWS_SECRET_ACCESS_KEY
valueFrom
:
secretKeyRef
:
name
:
registry-creds
name
:
registry-creds
-ecr
key
:
AWS_SECRET_ACCESS_KEY
-
name
:
awsaccount
valueFrom
:
secretKeyRef
:
name
:
registry-creds
name
:
registry-creds
-ecr
key
:
aws-account
-
name
:
awsregion
valueFrom
:
secretKeyRef
:
name
:
registry-creds-ecr
key
:
aws-region
volumeMounts
:
-
name
:
gcr-creds
mountPath
:
"
/root/.config/gcloud"
...
...
@@ -49,4 +48,7 @@ spec:
volumes
:
-
name
:
gcr-creds
secret
:
secretName
:
gcr-secret
secretName
:
registry-creds-gcr
items
:
-
key
:
application_default_credentials.json
path
:
application_default_credentials.json
\ No newline at end of file
pkg/minikube/cluster/cluster.go
浏览文件 @
c3d962b5
...
...
@@ -20,6 +20,7 @@ import (
"encoding/json"
"flag"
"fmt"
"html/template"
"net"
"os"
"path/filepath"
...
...
@@ -33,8 +34,11 @@ import (
"github.com/docker/machine/libmachine/host"
"github.com/docker/machine/libmachine/state"
"github.com/golang/glog"
"github.com/pkg/browser"
"github.com/pkg/errors"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/labels"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/sshutil"
...
...
@@ -449,3 +453,197 @@ func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) {
os
.
Exit
(
exitStatus
)
}
}
type
ServiceURL
struct
{
Namespace
string
Name
string
URLs
[]
string
}
type
ServiceURLs
[]
ServiceURL
func
GetServiceURLs
(
api
libmachine
.
API
,
namespace
string
,
t
*
template
.
Template
)
(
ServiceURLs
,
error
)
{
host
,
err
:=
CheckIfApiExistsAndLoad
(
api
)
if
err
!=
nil
{
return
nil
,
err
}
ip
,
err
:=
host
.
Driver
.
GetIP
()
if
err
!=
nil
{
return
nil
,
err
}
client
,
err
:=
GetKubernetesClient
()
if
err
!=
nil
{
return
nil
,
err
}
getter
:=
client
.
Services
(
namespace
)
svcs
,
err
:=
getter
.
List
(
kubeapi
.
ListOptions
{})
if
err
!=
nil
{
return
nil
,
err
}
var
serviceURLs
[]
ServiceURL
for
_
,
svc
:=
range
svcs
.
Items
{
urls
,
err
:=
getServiceURLsWithClient
(
client
,
ip
,
svc
.
Namespace
,
svc
.
Name
,
t
)
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
MissingNodePortError
);
ok
{
serviceURLs
=
append
(
serviceURLs
,
ServiceURL
{
Namespace
:
svc
.
Namespace
,
Name
:
svc
.
Name
})
continue
}
return
nil
,
err
}
serviceURLs
=
append
(
serviceURLs
,
ServiceURL
{
Namespace
:
svc
.
Namespace
,
Name
:
svc
.
Name
,
URLs
:
urls
})
}
return
serviceURLs
,
nil
}
// CheckService waits for the specified service to be ready by returning an error until the service is up
// The check is done by polling the endpoint associated with the service and when the endpoint exists, returning no error->service-online
func
CheckService
(
namespace
string
,
service
string
)
error
{
client
,
err
:=
GetKubernetesClient
()
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
endpoints
:=
client
.
Endpoints
(
namespace
)
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
endpoint
,
err
:=
endpoints
.
Get
(
service
)
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
return
checkEndpointReady
(
endpoint
)
}
func
checkEndpointReady
(
endpoint
*
v1
.
Endpoints
)
error
{
const
notReadyMsg
=
"Waiting, endpoint for service is not ready yet...
\n
"
if
len
(
endpoint
.
Subsets
)
==
0
{
fmt
.
Fprintf
(
os
.
Stderr
,
notReadyMsg
)
return
&
util
.
RetriableError
{
Err
:
errors
.
New
(
"Endpoint for service is not ready yet"
)}
}
for
_
,
subset
:=
range
endpoint
.
Subsets
{
if
len
(
subset
.
Addresses
)
==
0
{
fmt
.
Fprintf
(
os
.
Stderr
,
notReadyMsg
)
return
&
util
.
RetriableError
{
Err
:
errors
.
New
(
"No endpoints for service are ready yet"
)}
}
}
return
nil
}
func
WaitAndMaybeOpenService
(
api
libmachine
.
API
,
namespace
string
,
service
string
,
urlTemplate
*
template
.
Template
,
urlMode
bool
,
https
bool
)
{
if
err
:=
util
.
RetryAfter
(
20
,
func
()
error
{
return
CheckService
(
namespace
,
service
)
},
6
*
time
.
Second
);
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Could not find finalized endpoint being pointed to by %s: %s
\n
"
,
service
,
err
)
os
.
Exit
(
1
)
}
urls
,
err
:=
GetServiceURLsForService
(
api
,
namespace
,
service
,
urlTemplate
)
if
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
fmt
.
Fprintln
(
os
.
Stderr
,
"Check that minikube is running and that you have specified the correct namespace (-n flag)."
)
os
.
Exit
(
1
)
}
for
_
,
url
:=
range
urls
{
if
https
{
url
=
strings
.
Replace
(
url
,
"http"
,
"https"
,
1
)
}
if
urlMode
||
!
strings
.
HasPrefix
(
url
,
"http"
)
{
fmt
.
Fprintln
(
os
.
Stdout
,
url
)
}
else
{
fmt
.
Fprintln
(
os
.
Stdout
,
"Opening kubernetes service "
+
namespace
+
"/"
+
service
+
" in default browser..."
)
browser
.
OpenURL
(
url
)
}
}
}
func
GetServiceListByLabel
(
namespace
string
,
key
string
,
value
string
)
(
*
v1
.
ServiceList
,
error
)
{
client
,
err
:=
GetKubernetesClient
()
if
err
!=
nil
{
return
&
v1
.
ServiceList
{},
&
util
.
RetriableError
{
Err
:
err
}
}
services
:=
client
.
Services
(
namespace
)
if
err
!=
nil
{
return
&
v1
.
ServiceList
{},
&
util
.
RetriableError
{
Err
:
err
}
}
return
getServiceListFromServicesByLabel
(
services
,
key
,
value
)
}
func
getServiceListFromServicesByLabel
(
services
corev1
.
ServiceInterface
,
key
string
,
value
string
)
(
*
v1
.
ServiceList
,
error
)
{
selector
:=
labels
.
SelectorFromSet
(
labels
.
Set
(
map
[
string
]
string
{
key
:
value
}))
serviceList
,
err
:=
services
.
List
(
kubeapi
.
ListOptions
{
LabelSelector
:
selector
})
if
err
!=
nil
{
return
&
v1
.
ServiceList
{},
&
util
.
RetriableError
{
Err
:
err
}
}
return
serviceList
,
nil
}
// CreateSecret creates or modifies secrets
func
CreateSecret
(
namespace
,
name
string
,
dataValues
map
[
string
]
string
,
labels
map
[
string
]
string
)
error
{
client
,
err
:=
GetKubernetesClient
()
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
secrets
:=
client
.
Secrets
(
namespace
)
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
secret
,
_
:=
secrets
.
Get
(
name
)
// Delete existing secret
if
len
(
secret
.
Name
)
>
0
{
err
=
DeleteSecret
(
namespace
,
name
)
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
}
// convert strings to data secrets
data
:=
map
[
string
][]
byte
{}
for
key
,
value
:=
range
dataValues
{
data
[
key
]
=
[]
byte
(
value
)
}
// Create Secret
secretObj
:=
&
v1
.
Secret
{
ObjectMeta
:
v1
.
ObjectMeta
{
Name
:
name
,
Labels
:
labels
,
},
Data
:
data
,
Type
:
v1
.
SecretTypeOpaque
,
}
_
,
err
=
secrets
.
Create
(
secretObj
)
if
err
!=
nil
{
fmt
.
Println
(
"err: "
,
err
)
return
&
util
.
RetriableError
{
Err
:
err
}
}
return
nil
}
// DeleteSecret deletes a secret from a namespace
func
DeleteSecret
(
namespace
,
name
string
)
error
{
client
,
err
:=
GetKubernetesClient
()
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
secrets
:=
client
.
Secrets
(
namespace
)
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
err
=
secrets
.
Delete
(
name
,
&
kubeapi
.
DeleteOptions
{})
if
err
!=
nil
{
return
&
util
.
RetriableError
{
Err
:
err
}
}
return
nil
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录