提交 3fe4ef3e 编写于 作者: A Aaron Prindle

Added heapster to set of addons. Need to add test and repackage things to remove duplicated code.

上级 0d87323e
......@@ -130,6 +130,12 @@ var settings = []Setting{
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "heapster",
set: SetBool,
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
}
var ConfigCmd = &cobra.Command{
......
/*
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 (
"fmt"
"os"
"text/template"
"time"
"github.com/docker/machine/libmachine"
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/util"
)
var (
namespace string
https bool
addonsURLMode bool
addonsURLFormat string
addonsURLTemplate *template.Template
)
const defaultAddonsFormatTemplate = "http://{{.IP}}:{{.Port}}"
var addonsOpenCmd = &cobra.Command{
Use: "open ADDON_NAME",
Short: "Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list ",
Long: "Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list ",
PreRun: func(cmd *cobra.Command, args []string) {
t, err := template.New("addonsURL").Parse(addonsURLFormat)
if err != nil {
fmt.Fprintln(os.Stderr, "The value passed to --format is invalid:\n\n", err)
os.Exit(1)
}
addonsURLTemplate = t
},
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
fmt.Fprintln(os.Stderr, "usage: minikube addons open ADDON_NAME")
os.Exit(1)
}
addonName := args[0]
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 1)
addon, ok := assets.Addons[addonName] // validate addon input
if !ok {
fmt.Fprintln(os.Stderr, fmt.Sprintf(`addon '%s' is not a valid addon packaged with minikube.
To see the list of available addons run:
minikube addons list`, addonName))
os.Exit(1)
}
ok, err := addon.IsEnabled()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
if !ok {
fmt.Fprintln(os.Stderr, fmt.Sprintf(`addon '%s' is currently not enabled.
To enable this addon run:
minikube addons enable %s`, addonName, addonName))
os.Exit(1)
}
namespace := "kube-system"
key := "kubernetes.io/minikube-addons-endpoint"
if err := util.RetryAfter(20,
func() error {
_, err := cluster.GetServiceListByLabel(namespace, key, addonName)
if err != nil {
return err
}
return nil
}, 6*time.Second); err != nil {
fmt.Fprintf(os.Stderr, "Could not find endpoint for addon %s: %s\n", addonName, err)
os.Exit(1)
}
serviceList, err := cluster.GetServiceListByLabel(namespace, key, addonName)
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting service with namespace :%s and labels %s:%s: %s", namespace, key, addonName, err)
os.Exit(1)
}
for i := range serviceList.Items {
service := serviceList.Items[i].ObjectMeta.Name
cluster.WaitAndMaybeOpenService(api, namespace, service, addonsURLTemplate, addonsURLMode, https)
}
},
}
func init() {
AddonsCmd.AddCommand(addonsOpenCmd)
addonsOpenCmd.Flags().BoolVar(&addonsURLMode, "url", false, "Display the kubernetes addons URL in the CLI instead of opening it in the default browser")
addonsOpenCmd.Flags().BoolVar(&https, "https", false, "Open the addons URL with https instead of http")
addonsOpenCmd.PersistentFlags().StringVar(&addonsURLFormat, "format", defaultAddonsFormatTemplate, "Format to output addons URL in. This format will be applied to each url individually and they will be printed one at a time.")
AddonsCmd.AddCommand(addonsOpenCmd)
}
......@@ -49,7 +49,7 @@ var dashboardCmd = &cobra.Command{
namespace := "kube-system"
service := "kubernetes-dashboard"
if err := commonutil.RetryAfter(20, func() error { return CheckService(namespace, service) }, 6*time.Second); err != nil {
if err := commonutil.RetryAfter(20, func() error { return cluster.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)
}
......
......@@ -19,18 +19,13 @@ package cmd
import (
"fmt"
"os"
"strings"
"text/template"
"time"
"github.com/docker/machine/libmachine"
"github.com/pkg/browser"
"github.com/pkg/errors"
"github.com/spf13/cobra"
kubeapi "k8s.io/kubernetes/pkg/api"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/util"
)
var (
......@@ -46,7 +41,7 @@ var serviceCmd = &cobra.Command{
Use: "service [flags] SERVICE",
Short: "Gets the kubernetes URL(s) for the specified service in your local cluster",
Long: `Gets the kubernetes URL(s) for the specified service in your local cluster. In the case of multiple URLs they will be printed one at a time`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
PreRun: func(cmd *cobra.Command, args []string) {
t, err := template.New("serviceURL").Parse(serviceURLFormat)
if err != nil {
fmt.Fprintln(os.Stderr, "The value passed to --format is invalid:\n\n", err)
......@@ -71,28 +66,7 @@ var serviceCmd = &cobra.Command{
service, namespace))
os.Exit(1)
}
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 := cluster.GetServiceURLsForService(api, namespace, service, serviceURLTemplate)
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 serviceURLMode || !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)
}
}
cluster.WaitAndMaybeOpenService(api, namespace, service, serviceURLTemplate, serviceURLMode, https)
},
}
......@@ -119,37 +93,3 @@ func validateService(namespace string, service string) error {
}
return 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 := cluster.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)
}
const notReadyMsg = "Waiting, endpoint for service is not ready yet...\n"
func CheckEndpointReady(endpoint *kubeapi.Endpoints) error {
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
}
/*
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 cmd
import (
"testing"
kubeApi "k8s.io/kubernetes/pkg/api"
)
func TestCheckEndpointReady(t *testing.T) {
endpointNoSubsets := &kubeApi.Endpoints{}
if err := CheckEndpointReady(endpointNoSubsets); err == nil {
t.Fatalf("Endpoint had no subsets but CheckEndpointReady did not return an error")
}
endpointNotReady := &kubeApi.Endpoints{
Subsets: []kubeApi.EndpointSubset{
{Addresses: []kubeApi.EndpointAddress{},
NotReadyAddresses: []kubeApi.EndpointAddress{
{IP: "1.1.1.1"},
{IP: "2.2.2.2"},
{IP: "3.3.3.3"},
}}}}
if err := CheckEndpointReady(endpointNotReady); err == nil {
t.Fatalf("Endpoint had no Addresses but CheckEndpointReady did not return an error")
}
endpointReady := &kubeApi.Endpoints{
Subsets: []kubeApi.EndpointSubset{
{Addresses: []kubeApi.EndpointAddress{
{IP: "1.1.1.1"},
{IP: "2.2.2.2"},
},
NotReadyAddresses: []kubeApi.EndpointAddress{},
}},
}
if err := CheckEndpointReady(endpointReady); err != nil {
t.Fatalf("Endpoint was ready with at least one Address, but CheckEndpointReady returned an error")
}
}
......@@ -20,6 +20,7 @@ metadata:
labels:
component: kube-addon-manager
version: v5.1
kubernetes.io/minikube-addons: addon-manager
spec:
hostNetwork: true
containers:
......
......@@ -21,6 +21,7 @@ metadata:
app: kubernetes-dashboard
version: v1.4.2
kubernetes.io/cluster-service: "true"
kubernetes.io/minikube-addons: dashboard
spec:
replicas: 1
selector:
......
......@@ -21,6 +21,8 @@ metadata:
labels:
app: kubernetes-dashboard
kubernetes.io/cluster-service: "true"
kubernetes.io/minikube-addons: dashboard
kubernetes.io/minikube-addons-endpoint: dashboard
spec:
type: NodePort
ports:
......
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: monitoring-grafana
kubernetes.io/minikube-addons: heapster
kubernetes.io/minikube-addons-endpoint: heapster
name: monitoring-grafana
namespace: kube-system
spec:
type: NodePort
ports:
- port: 80
targetPort: 3000
selector:
kubernetes.io/cluster-service: "true"
name: influxGrafana
apiVersion: v1
kind: ReplicationController
metadata:
labels:
kubernetes.io/cluster-service: 'true'
k8s-app: heapster
name: heapster
kubernetes.io/minikube-addons: heapster
name: heapster
namespace: kube-system
spec:
replicas: 1
selector:
kubernetes.io/cluster-service: "true"
k8s-app: heapster
template:
metadata:
labels:
kubernetes.io/cluster-service: 'true'
k8s-app: heapster
spec:
containers:
- name: heapster
image: gcr.io/google_containers/heapster:v1.2.0
imagePullPolicy: IfNotPresent
command:
- /heapster
- --source=kubernetes
- --sink=influxdb:http://monitoring-influxdb:8086
- --metric_resolution=60s
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs
readOnly: true
volumes:
- name: ssl-certs
hostPath:
path: /etc/ssl/certs
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: heapster
kubernetes.io/minikube-addons: heapster
name: heapster
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 8082
selector:
kubernetes.io/cluster-service: "true"
k8s-app: heapster
# 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.
apiVersion: v1
kind: ReplicationController
metadata:
labels:
kubernetes.io/cluster-service: 'true'
name: influxGrafana
kubernetes.io/minikube-addons: heapster
name: influxdb-grafana
namespace: kube-system
spec:
replicas: 1
selector:
kubernetes.io/cluster-service: "true"
name: influxGrafana
template:
metadata:
labels:
kubernetes.io/cluster-service: 'true'
name: influxGrafana
spec:
containers:
- name: influxdb
image: kubernetes/heapster_influxdb:v0.6
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /data
name: influxdb-storage
- name: grafana
image: gcr.io/google_containers/heapster_grafana:v2.6.0-2
imagePullPolicy: IfNotPresent
env:
- name: INFLUXDB_SERVICE_URL
value: http://localhost:8086
# The following env variables are required to make Grafana accessible via
# the kubernetes api-server proxy. On production clusters, we recommend
# removing these env variables, setup auth for grafana, and expose the grafana
# service using a LoadBalancer or a public IP.
- name: GF_AUTH_BASIC_ENABLED
value: "false"
- name: GF_AUTH_ANONYMOUS_ENABLED
value: "true"
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
value: Admin
- name: GF_SERVER_ROOT_URL
value: /
volumeMounts:
- mountPath: /var
name: grafana-storage
volumes:
- name: influxdb-storage
emptyDir: {}
- name: grafana-storage
emptyDir: {}
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: monitoring-influxdb
kubernetes.io/minikube-addons: heapster
name: monitoring-influxdb
namespace: kube-system
spec:
ports:
- name: http
port: 8083
targetPort: 8083
- name: api
port: 8086
targetPort: 8086
selector:
kubernetes.io/cluster-service: "true"
name: influxGrafana
......@@ -315,6 +315,68 @@ _minikube_addons_list()
noun_aliases=()
}
_minikube_addons_open()
{
last_command="minikube_addons_open"
commands=()
flags=()
two_word_flags=()
local_nonpersistent_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--format=")
flags+=("--https")
local_nonpersistent_flags+=("--https")
flags+=("--url")
local_nonpersistent_flags+=("--url")
flags+=("--alsologtostderr")
flags+=("--log_backtrace_at=")
flags+=("--log_dir=")
flags+=("--logtostderr")
flags+=("--show-libmachine-logs")
flags+=("--stderrthreshold=")
flags+=("--v=")
two_word_flags+=("-v")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}
_minikube_addons_open()
{
last_command="minikube_addons_open"
commands=()
flags=()
two_word_flags=()
local_nonpersistent_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--format=")
flags+=("--https")
local_nonpersistent_flags+=("--https")
flags+=("--url")
local_nonpersistent_flags+=("--url")
flags+=("--alsologtostderr")
flags+=("--log_backtrace_at=")
flags+=("--log_dir=")
flags+=("--logtostderr")
flags+=("--show-libmachine-logs")
flags+=("--stderrthreshold=")
flags+=("--v=")
two_word_flags+=("-v")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}
_minikube_addons()
{
last_command="minikube_addons"
......@@ -322,6 +384,8 @@ _minikube_addons()
commands+=("disable")
commands+=("enable")
commands+=("list")
commands+=("open")
commands+=("open")
flags=()
two_word_flags=()
......
......@@ -37,4 +37,6 @@ For the list of accessible variables for the template, see the struct values her
* [minikube addons disable](minikube_addons_disable.md) - Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list
* [minikube addons enable](minikube_addons_enable.md) - Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list
* [minikube addons list](minikube_addons_list.md) - Lists all available minikube addons as well as there current status (enabled/disabled)
* [minikube addons open](minikube_addons_open.md) - Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list
* [minikube addons open](minikube_addons_open.md) - Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list
## minikube addons open
Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list
### Synopsis
Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list
```
minikube addons open ADDON_NAME
```
### Options
```
--format string Format to output addons URL in. This format will be applied to each url individually and they will be printed one at a time. (default "http://{{.IP}}:{{.Port}}")
--https Open the addons URL with https instead of http
--url Display the kubernetes addons URL in the CLI instead of opening it in the default browser
```
### Options inherited from parent commands
```
--alsologtostderr log to standard error as well as files
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory (default "")
--logtostderr log to standard error instead of files
--show-libmachine-logs Whether or not to show logs from libmachine.
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level log level for V logs
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [minikube addons](minikube_addons.md) - Modify minikube's kubernetes addons
......@@ -25,6 +25,7 @@ Configurable fields:
* dashboard
* addon-manager
* kube-dns
* heapster
```
minikube config SUBCOMMAND [flags]
......
......@@ -86,6 +86,33 @@ var Addons = map[string]*Addon{
"kube-dns-svc.yaml",
"0640"),
}, true, "kube-dns"),
"heapster": NewAddon([]*MemoryAsset{
NewMemoryAsset(
"deploy/addons/influxGrafana-rc.yaml",
constants.AddonsPath,
"influxGrafana-rc.yaml",
"0640"),
NewMemoryAsset(
"deploy/addons/grafana-svc.yaml",
constants.AddonsPath,
"grafana-svc.yaml",
"0640"),
NewMemoryAsset(
"deploy/addons/influxdb-svc.yaml",
constants.AddonsPath,
"influxdb-svc.yaml",
"0640"),
NewMemoryAsset(
"deploy/addons/heapster-rc.yaml",
constants.AddonsPath,
"heapster-rc.yaml",
"0640"),
NewMemoryAsset(
"deploy/addons/heapster-svc.yaml",
constants.AddonsPath,
"heapster-svc.yaml",
"0640"),
}, false, "heapster"),
}
func AddMinikubeAddonsDirToAssets(assetList *[]CopyableFile) {
......
......@@ -39,10 +39,12 @@ import (
"github.com/docker/machine/libmachine/state"
"github.com/golang/glog"
download "github.com/jimmidyson/go-download"
"github.com/pkg/browser"
"github.com/pkg/errors"
kubeapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
......@@ -683,3 +685,85 @@ func GetServiceURLs(api libmachine.API, namespace string, t *template.Template)
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 *kubeapi.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) (*kubeapi.ServiceList, error) {
client, err := GetKubernetesClient()
if err != nil {
return &kubeapi.ServiceList{}, &util.RetriableError{Err: err}
}
services := client.Services(namespace)
if err != nil {
return &kubeapi.ServiceList{}, &util.RetriableError{Err: err}
}
return getServiceListFromServicesByLabel(services, key, value)
}
func getServiceListFromServicesByLabel(services unversioned.ServiceInterface, key string, value string) (*kubeapi.ServiceList, error) {
selector := labels.SelectorFromSet(labels.Set(map[string]string{key: value}))
serviceList, err := services.List(kubeapi.ListOptions{LabelSelector: selector})
if err != nil {
return &kubeapi.ServiceList{}, &util.RetriableError{Err: err}
}
if len(serviceList.Items) == 0 {
return &kubeapi.ServiceList{}, &util.RetriableError{Err: err}
}
return serviceList, nil
}
......@@ -34,6 +34,8 @@ import (
"github.com/pkg/errors"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/watch"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/tests"
......@@ -779,3 +781,97 @@ func TestUpdateCustomAddons(t *testing.T) {
t.Fatalf("Custom addon not copied. Expected transfers to contain custom addon with content: %s. It was: %s", testContent2, transferred)
}
}
func TestCheckEndpointReady(t *testing.T) {
endpointNoSubsets := &api.Endpoints{}
if err := checkEndpointReady(endpointNoSubsets); err == nil {
t.Fatalf("Endpoint had no subsets but checkEndpointReady did not return an error")
}
endpointNotReady := &api.Endpoints{
Subsets: []api.EndpointSubset{
{Addresses: []api.EndpointAddress{},
NotReadyAddresses: []api.EndpointAddress{
{IP: "1.1.1.1"},
{IP: "2.2.2.2"},
{IP: "3.3.3.3"},
}}}}
if err := checkEndpointReady(endpointNotReady); err == nil {
t.Fatalf("Endpoint had no Addresses but checkEndpointReady did not return an error")
}
endpointReady := &api.Endpoints{
Subsets: []api.EndpointSubset{
{Addresses: []api.EndpointAddress{
{IP: "1.1.1.1"},
{IP: "2.2.2.2"},
},
NotReadyAddresses: []api.EndpointAddress{},
}},
}
if err := checkEndpointReady(endpointReady); err != nil {
t.Fatalf("Endpoint was ready with at least one Address, but checkEndpointReady returned an error")
}
}
type ServiceInterfaceMock struct {
ServiceList *api.ServiceList
}
func (s ServiceInterfaceMock) List(opts api.ListOptions) (*api.ServiceList, error) {
serviceList := &api.ServiceList{
Items: []api.Service{},
}
keyValArr := strings.Split(opts.LabelSelector.String(), "=")
for _, service := range s.ServiceList.Items {
if service.Spec.Selector[keyValArr[0]] == keyValArr[1] {
serviceList.Items = append(serviceList.Items, service)
}
}
return serviceList, nil
}
func (s ServiceInterfaceMock) Get(name string) (*api.Service, error) {
return nil, nil
}
func (s ServiceInterfaceMock) Create(*api.Service) (*api.Service, error) {
return nil, nil
}
func (s ServiceInterfaceMock) Update(*api.Service) (*api.Service, error) {
return nil, nil
}
func (s ServiceInterfaceMock) UpdateStatus(*api.Service) (*api.Service, error) {
return nil, nil
}
func (s ServiceInterfaceMock) Delete(name string) error {
return nil
}
func (s ServiceInterfaceMock) Watch(opts api.ListOptions) (watch.Interface, error) {
return nil, nil
}
func (s ServiceInterfaceMock) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper {
return nil
}
func TestGetServiceListFromServicesByLabel(t *testing.T) {
serviceList := &api.ServiceList{
Items: []api.Service{
{
Spec: api.ServiceSpec{
Selector: map[string]string{
"foo": "bar",
},
},
},
},
}
serviceIface := ServiceInterfaceMock{
ServiceList: serviceList,
}
if _, err := getServiceListFromServicesByLabel(serviceIface, "shouldError", "shouldError"); err == nil {
t.Fatalf("Service had no label match but getServiceListFromServicesByLabel did not return an error")
}
if _, err := getServiceListFromServicesByLabel(serviceIface, "foo", "bar"); err != nil {
t.Fatalf("Endpoint was ready with at least one Address, but getServiceListFromServicesByLabel returned an error")
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册