Manual changes to remove localkube.
parent
18a84504c8
commit
15b035748c
59
Makefile
59
Makefile
|
@ -49,8 +49,6 @@ PYTHON := $(shell command -v python || echo "docker run --rm -it -v $(shell pwd)
|
|||
BUILD_OS := $(shell uname -s)
|
||||
|
||||
LOCALKUBE_VERSION := $(shell $(PYTHON) hack/get_k8s_version.py --k8s-version-only 2>&1)
|
||||
LOCALKUBE_BUCKET ?= minikube/k8sReleases
|
||||
LOCALKUBE_UPLOAD_LOCATION := gs://${LOCALKUBE_BUCKET}
|
||||
TAG ?= $(LOCALKUBE_VERSION)
|
||||
STORAGE_PROVISIONER_TAG := v1.8.1
|
||||
|
||||
|
@ -61,7 +59,6 @@ LOCALKUBE_LDFLAGS := "$(K8S_VERSION_LDFLAGS) $(MINIKUBE_LDFLAGS) -s -w"
|
|||
|
||||
MAKEDEPEND := GOPATH=$(GOPATH) ./makedepend.sh
|
||||
|
||||
LOCALKUBEFILES := ./cmd/localkube/
|
||||
MINIKUBEFILES := ./cmd/minikube/
|
||||
HYPERKIT_FILES := ./cmd/drivers/hyperkit
|
||||
STORAGE_PROVISIONER_FILES := ./cmd/storage-provisioner
|
||||
|
@ -80,12 +77,6 @@ endef
|
|||
|
||||
ifeq ($(BUILD_IN_DOCKER),y)
|
||||
MINIKUBE_BUILD_IN_DOCKER=y
|
||||
LOCALKUBE_BUILD_IN_DOCKER=y
|
||||
endif
|
||||
|
||||
# If not on linux, localkube must be built in docker
|
||||
ifneq ($(BUILD_OS),Linux)
|
||||
LOCALKUBE_BUILD_IN_DOCKER=y
|
||||
endif
|
||||
|
||||
# If we are already running in docker,
|
||||
|
@ -93,7 +84,6 @@ endif
|
|||
# The _BUILD_IN_DOCKER variables should not be modified after this conditional.
|
||||
ifeq ($(IN_DOCKER),1)
|
||||
MINIKUBE_BUILD_IN_DOCKER=n
|
||||
LOCALKUBE_BUILD_IN_DOCKER=n
|
||||
endif
|
||||
|
||||
ifeq ($(GOOS),windows)
|
||||
|
@ -102,17 +92,6 @@ endif
|
|||
out/minikube$(IS_EXE): out/minikube-$(GOOS)-$(GOARCH)$(IS_EXE)
|
||||
cp $< $@
|
||||
|
||||
out/localkube.d:
|
||||
GOOS=linux GOARCH=$(GOARCH) $(MAKEDEPEND) out/localkube $(ORG) $(LOCALKUBEFILES) $^ > $@
|
||||
|
||||
-include out/localkube.d
|
||||
out/localkube:
|
||||
ifeq ($(LOCALKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
|
||||
else
|
||||
CGO_ENABLED=1 go build -ldflags=$(LOCALKUBE_LDFLAGS) -o $(BUILD_DIR)/localkube ./cmd/localkube
|
||||
endif
|
||||
|
||||
out/minikube-windows-amd64.exe: out/minikube-windows-amd64
|
||||
cp out/minikube-windows-amd64 out/minikube-windows-amd64.exe
|
||||
|
||||
|
@ -182,20 +161,14 @@ test-pkg/%:
|
|||
go test -v -test.timeout=30m $(REPOPATH)/$* --tags="$(MINIKUBE_BUILD_TAGS)"
|
||||
|
||||
.PHONY: depend
|
||||
depend: out/localkube.d out/minikube.d out/test.d out/docker-machine-driver-hyperkit.d out/storage-provisioner.d out/docker-machine-driver-kvm2.d
|
||||
depend: out/minikube.d out/test.d out/docker-machine-driver-hyperkit.d out/storage-provisioner.d out/docker-machine-driver-kvm2.d
|
||||
|
||||
.PHONY: all
|
||||
all: cross drivers e2e-cross images out/localkube
|
||||
all: cross drivers e2e-cross images
|
||||
|
||||
.PHONY: drivers
|
||||
drivers: out/docker-machine-driver-hyperkit out/docker-machine-driver-kvm2
|
||||
|
||||
.PHONY: images
|
||||
images: localkube-image localkube-dind-image localkube-dind-image-devshell
|
||||
gcloud docker -- push $(REGISTRY)/localkube-image:$(TAG)
|
||||
gcloud docker -- push $(REGISTRY)/localkube-dind-image:$(TAG)
|
||||
gcloud docker -- push $(REGISTRY)/localkube-dind-image-devshell:$(TAG)
|
||||
|
||||
.PHONY: integration
|
||||
integration: out/minikube
|
||||
go test -v -test.timeout=30m $(REPOPATH)/test/integration --tags="$(MINIKUBE_INTEGRATION_BUILD_TAGS)" $(TEST_ARGS)
|
||||
|
@ -228,7 +201,7 @@ e2e-cross: e2e-linux-amd64 e2e-darwin-amd64 e2e-windows-amd64.exe
|
|||
|
||||
.PHONY: checksum
|
||||
checksum:
|
||||
for f in out/localkube out/minikube-linux-amd64 out/minikube-darwin-amd64 out/minikube-windows-amd64.exe out/minikube.iso; do \
|
||||
for f in out/minikube-linux-amd64 out/minikube-darwin-amd64 out/minikube-windows-amd64.exe out/minikube.iso; do \
|
||||
if [ -f "$${f}" ]; then \
|
||||
openssl sha256 "$${f}" | awk '{print $$2}' > "$${f}.sha256" ; \
|
||||
fi ; \
|
||||
|
@ -304,36 +277,10 @@ install-hyperkit-driver: out/docker-machine-driver-hyperkit
|
|||
check-release:
|
||||
go test -v ./deploy/minikube/release_sanity_test.go -tags=release
|
||||
|
||||
.PHONY: release-localkube
|
||||
release-localkube: out/localkube checksum
|
||||
gsutil cp out/localkube $(LOCALKUBE_UPLOAD_LOCATION)/$(LOCALKUBE_VERSION)/localkube-linux-amd64
|
||||
gsutil cp out/localkube.sha256 $(LOCALKUBE_UPLOAD_LOCATION)/$(LOCALKUBE_VERSION)/localkube-linux-amd64.sha256
|
||||
|
||||
.PHONY: update-releases
|
||||
update-releases:
|
||||
gsutil cp deploy/minikube/k8s_releases.json gs://minikube/k8s_releases.json
|
||||
|
||||
localkube-image: out/localkube
|
||||
# TODO(aprindle) make addons placed into container configurable
|
||||
docker build -t $(REGISTRY)/localkube-image:$(TAG) -f deploy/docker/Dockerfile .
|
||||
@echo ""
|
||||
@echo "${REGISTRY}/localkube-image:$(TAG) successfully built"
|
||||
@echo "See https://github.com/kubernetes/minikube/tree/master/deploy/docker for instructions on how to run image"
|
||||
|
||||
localkube-dind-image: out/localkube
|
||||
# TODO(aprindle) make addons placed into container configurable
|
||||
docker build -t $(REGISTRY)/localkube-dind-image:$(TAG) -f deploy/docker/localkube-dind/Dockerfile .
|
||||
@echo ""
|
||||
@echo "${REGISTRY}/localkube-dind-image:$(TAG) successfully built"
|
||||
@echo "See https://github.com/kubernetes/minikube/tree/master/deploy/docker for instructions on how to run image"
|
||||
|
||||
localkube-dind-image-devshell: out/localkube
|
||||
# TODO(aprindle) make addons placed into container configurable
|
||||
docker build -t $(REGISTRY)/localkube-dind-image-devshell:$(TAG) -f deploy/docker/localkube-dind/Dockerfile .
|
||||
@echo ""
|
||||
@echo "${REGISTRY}/localkube-dind-image-devshell:$(TAG) successfully built"
|
||||
@echo "See https://github.com/kubernetes/minikube/tree/master/deploy/docker for instructions on how to run image"
|
||||
|
||||
buildroot-image: $(ISO_BUILD_IMAGE) # convenient alias to build the docker container
|
||||
$(ISO_BUILD_IMAGE): deploy/iso/minikube-iso/Dockerfile
|
||||
docker build $(ISO_DOCKER_EXTRA_ARGS) -t $@ -f $< $(dir $<)
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
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 (
|
||||
"net"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/minikube/pkg/localkube"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func NewLocalkubeServer() *localkube.LocalkubeServer {
|
||||
_, defaultServiceCIDR, _ := net.ParseCIDR(util.DefaultServiceCIDR)
|
||||
return &localkube.LocalkubeServer{
|
||||
Containerized: false,
|
||||
DNSDomain: util.DefaultDNSDomain,
|
||||
LocalkubeDirectory: util.DefaultLocalkubeDirectory,
|
||||
APIServerAddress: net.ParseIP("0.0.0.0"),
|
||||
APIServerPort: util.APIServerPort,
|
||||
APIServerInsecureAddress: net.ParseIP("127.0.0.1"),
|
||||
APIServerInsecurePort: 0,
|
||||
APIServerName: constants.APIServerName,
|
||||
ShouldGenerateKubeconfig: false,
|
||||
ShouldGenerateCerts: true,
|
||||
ShowVersion: false,
|
||||
ServiceClusterIPRange: *defaultServiceCIDR,
|
||||
RuntimeConfig: map[string]string{"api/all": "true"},
|
||||
ExtraConfig: util.ExtraOptionSlice{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags adds flags for a specific LocalkubeServer
|
||||
func AddFlags(s *localkube.LocalkubeServer) {
|
||||
flag.BoolVar(&s.Containerized, "containerized", s.Containerized, "If kubelet should run in containerized mode")
|
||||
flag.BoolVar(&s.EnableDNS, "enable-dns", s.EnableDNS, "DEPRECATED: Please run kube-dns as a cluster addon")
|
||||
flag.StringVar(&s.DNSDomain, "dns-domain", s.DNSDomain, "The cluster dns domain")
|
||||
flag.StringVar(&s.LocalkubeDirectory, "localkube-directory", s.LocalkubeDirectory, "The directory localkube will store files in")
|
||||
flag.IPNetVar(&s.ServiceClusterIPRange, "service-cluster-ip-range", s.ServiceClusterIPRange, "The service-cluster-ip-range for the apiserver")
|
||||
flag.IPVar(&s.APIServerAddress, "apiserver-address", s.APIServerAddress, "The address the apiserver will listen securely on")
|
||||
flag.IntVar(&s.APIServerPort, "apiserver-port", s.APIServerPort, "The port the apiserver will listen securely on")
|
||||
flag.IPVar(&s.APIServerInsecureAddress, "apiserver-insecure-address", s.APIServerInsecureAddress, "The address the apiserver will listen insecurely on")
|
||||
flag.IntVar(&s.APIServerInsecurePort, "apiserver-insecure-port", s.APIServerInsecurePort, "The port the apiserver will listen insecurely on")
|
||||
flag.StringVar(&s.APIServerName, "apiserver-name", s.APIServerName, "The apiserver name which is used in the generated certificate for localkube/kubernetes. This can be used if you want to make the API server available from outside the machine")
|
||||
|
||||
flag.BoolVar(&s.ShouldGenerateKubeconfig, "generate-kubeconfig", s.ShouldGenerateKubeconfig, "If localkube should generate its own kubeconfig")
|
||||
flag.BoolVar(&s.ShouldGenerateCerts, "generate-certs", s.ShouldGenerateCerts, "If localkube should generate it's own certificates")
|
||||
flag.BoolVar(&s.ShowVersion, "show-version", s.ShowVersion, "If localkube should just print the version and exit.")
|
||||
flag.BoolVar(&s.ShowHostIP, "host-ip", s.ShowHostIP, "If localkube should just print the host IP and exit.")
|
||||
flag.Var(&s.RuntimeConfig, "runtime-config", "A set of key=value pairs that describe runtime configuration that may be passed to apiserver. apis/<groupVersion> key can be used to turn on/off specific api versions. apis/<groupVersion>/<resource> can be used to turn on/off specific resources. api/all and api/legacy are special keys to control all and legacy api versions respectively.")
|
||||
flag.IPVar(&s.NodeIP, "node-ip", s.NodeIP, "IP address of the node. If set, kubelet will use this IP address for the node.")
|
||||
flag.StringVar(&s.ContainerRuntime, "container-runtime", "", "The container runtime to be used")
|
||||
flag.StringVar(&s.RemoteRuntimeEndpoint, "remote-runtime-endpoint", "", "The container runtime endpoint (CRI) to be used (if this is set, then --container-runtime is forced as 'remote')")
|
||||
flag.StringVar(&s.RemoteImageEndpoint, "remote-image-endpoint", "", "The container image endpoint (CRI) to be used (if this is set, then --container-runtime is forced as 'remote')")
|
||||
flag.StringVar(&s.NetworkPlugin, "network-plugin", "", "The name of the network plugin")
|
||||
flag.StringVar(&s.FeatureGates, "feature-gates", "", "A set of key=value pairs that describe feature gates for alpha/experimental features.")
|
||||
flag.Var(&s.ExtraConfig, "extra-config", "A set of key=value pairs that describe configuration that may be passed to different components. The key should be '.' separated, and the first part before the dot is the component to apply the configuration to.")
|
||||
|
||||
// These two come from vendor/ packages that use flags. We should hide them
|
||||
flag.CommandLine.MarkHidden("google-json-key")
|
||||
flag.CommandLine.MarkHidden("log-flush-frequency")
|
||||
|
||||
// Parse them
|
||||
flag.Parse()
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
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 (
|
||||
goflag "flag"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "localkube",
|
||||
Short: "localkube is an all-in-one kubernetes binary.",
|
||||
Long: `localkube is an all-in-one kubernetes binary that runs all Kubernetes server binaries.`,
|
||||
Run: func(command *cobra.Command, args []string) {
|
||||
StartLocalkube()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/kubelet/types"
|
||||
"k8s.io/minikube/pkg/localkube"
|
||||
"k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
// The main instance of the current localkube server that is started
|
||||
var Server *localkube.LocalkubeServer
|
||||
|
||||
func StartLocalkube() {
|
||||
|
||||
if Server.ShowVersion {
|
||||
fmt.Println("localkube version:", version.GetVersion())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if Server.ShowHostIP {
|
||||
hostIP, _ := Server.GetHostIP()
|
||||
fmt.Println("localkube host ip: ", hostIP.String())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Println("localkube should run as root!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
SetupServer(Server)
|
||||
Server.StartAll()
|
||||
|
||||
defer Server.StopAll()
|
||||
|
||||
interruptChan := make(chan os.Signal, 1)
|
||||
signal.Notify(interruptChan, os.Interrupt)
|
||||
|
||||
<-interruptChan
|
||||
fmt.Println("Shutting down...")
|
||||
}
|
||||
|
||||
func SetupServer(s *localkube.LocalkubeServer) {
|
||||
if s.ContainerRuntime == "remote" && s.RemoteRuntimeEndpoint == "" {
|
||||
panic("Failed to connect to --container-runtime='remote' with no --container-runtime-endpoint")
|
||||
}
|
||||
// localkube flags can handle `--container-runtime=remote --remote-runtime-endpoint=/var/run/crio/crio.sock --remote-image-endpoint=/var/run/crio/crio.sock`,
|
||||
// but this allows for a convenience of just e.g.`--container-runtime=crio` and the same for minikube
|
||||
switch s.ContainerRuntime {
|
||||
case "crio", "cri-o":
|
||||
s.ContainerRuntime = "remote"
|
||||
s.RemoteRuntimeEndpoint = "unix:///var/run/crio/crio.sock"
|
||||
s.RemoteImageEndpoint = "unix:///var/run/crio/crio.sock"
|
||||
}
|
||||
|
||||
if s.ShouldGenerateCerts {
|
||||
if err := s.GenerateCerts(); err != nil {
|
||||
fmt.Println("Failed to create certificates!")
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if s.ShouldGenerateKubeconfig {
|
||||
if err := s.GenerateKubeconfig(); err != nil {
|
||||
fmt.Println("Failed to create kubeconfig!")
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set feature gates
|
||||
if s.FeatureGates != "" {
|
||||
glog.Infof("Setting Feature Gates: %s", s.FeatureGates)
|
||||
err := feature.DefaultFeatureGate.Set(s.FeatureGates)
|
||||
if err != nil {
|
||||
fmt.Printf("Error setting feature gates: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup capabilities. This can only be done once per binary.
|
||||
allSources, _ := types.GetValidatedSources([]string{types.AllSource})
|
||||
c := capabilities.Capabilities{
|
||||
AllowPrivileged: true,
|
||||
PrivilegedSources: capabilities.PrivilegedSources{
|
||||
HostNetworkSources: allSources,
|
||||
HostIPCSources: allSources,
|
||||
HostPIDSources: allSources,
|
||||
},
|
||||
}
|
||||
capabilities.Initialize(c)
|
||||
|
||||
// setup etcd
|
||||
etcd, err := s.NewEtcd(s.GetEtcdDataDirectory())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Start etcd first
|
||||
etcd.Start()
|
||||
|
||||
// setup access to etcd
|
||||
netIP, _ := s.GetHostIP()
|
||||
fmt.Printf("localkube host ip address: %s\n", netIP.String())
|
||||
|
||||
// setup apiserver
|
||||
apiserver := s.NewAPIServer()
|
||||
s.AddServer(apiserver)
|
||||
|
||||
// setup controller-manager
|
||||
controllerManager := s.NewControllerManagerServer()
|
||||
s.AddServer(controllerManager)
|
||||
|
||||
// setup scheduler
|
||||
scheduler := s.NewSchedulerServer()
|
||||
s.AddServer(scheduler)
|
||||
|
||||
// setup kubelet
|
||||
kubelet := s.NewKubeletServer()
|
||||
s.AddServer(kubelet)
|
||||
|
||||
// setup proxy
|
||||
proxy := s.NewProxyServer()
|
||||
s.AddServer(proxy)
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"k8s.io/minikube/cmd/localkube/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Create the localkube server and parse the flags
|
||||
cmd.Server = cmd.NewLocalkubeServer()
|
||||
cmd.AddFlags(cmd.Server)
|
||||
|
||||
if err := cmd.RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
|
@ -36,8 +36,8 @@ var (
|
|||
// logsCmd represents the logs command
|
||||
var logsCmd = &cobra.Command{
|
||||
Use: "logs",
|
||||
Short: "Gets the logs of the running localkube instance, used for debugging minikube, not user code",
|
||||
Long: `Gets the logs of the running localkube instance, used for debugging minikube, not user code.`,
|
||||
Short: "Gets the logs of the running instance, used for debugging minikube, not user code",
|
||||
Long: `Gets the logs of the running instance, used for debugging minikube, not user code.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
|
|
|
@ -35,7 +35,6 @@ import (
|
|||
"k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper/localkube"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/notify"
|
||||
|
@ -47,7 +46,6 @@ var dirs = [...]string{
|
|||
constants.MakeMiniPath("machines"),
|
||||
constants.MakeMiniPath("cache"),
|
||||
constants.MakeMiniPath("cache", "iso"),
|
||||
constants.MakeMiniPath("cache", "localkube"),
|
||||
constants.MakeMiniPath("config"),
|
||||
constants.MakeMiniPath("addons"),
|
||||
constants.MakeMiniPath("files"),
|
||||
|
@ -173,17 +171,6 @@ func GetClusterBootstrapper(api libmachine.API, bootstrapperName string) (bootst
|
|||
var b bootstrapper.Bootstrapper
|
||||
var err error
|
||||
switch bootstrapperName {
|
||||
case bootstrapper.BootstrapperTypeLocalkube:
|
||||
if viper.GetBool(config.ShowBootstrapperDeprecationNotification) {
|
||||
fmt.Fprintln(os.Stderr, `WARNING: The localkube bootstrapper is now deprecated and support for it
|
||||
will be removed in a future release. Please consider switching to the kubeadm bootstrapper, which
|
||||
is intended to replace the localkube bootstrapper. To disable this message, run
|
||||
[minikube config set ShowBootstrapperDeprecationNotification false]`)
|
||||
}
|
||||
b, err = localkube.NewLocalkubeBootstrapper(api)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting localkube bootstrapper")
|
||||
}
|
||||
case bootstrapper.BootstrapperTypeKubeadm:
|
||||
b, err = kubeadm.NewKubeadmBootstrapper(api)
|
||||
if err != nil {
|
||||
|
|
|
@ -40,7 +40,6 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
cfg "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/kubernetes_versions"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
pkgutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/kubeconfig"
|
||||
|
@ -376,19 +375,6 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_
|
|||
}
|
||||
}
|
||||
|
||||
func validateK8sVersion(version string) {
|
||||
validVersion, err := kubernetes_versions.IsValidLocalkubeVersion(version, constants.KubernetesVersionGCSURL)
|
||||
if err != nil {
|
||||
glog.Errorln("Error getting valid kubernetes versions", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if !validVersion {
|
||||
fmt.Println("Invalid Kubernetes version.")
|
||||
kubernetes_versions.PrintKubernetesVersionsFromGCS(os.Stdout)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
startCmd.Flags().Bool(keepContext, constants.DefaultKeepContext, "This will keep the existing kubectl context and will create a minikube context.")
|
||||
startCmd.Flags().Bool(createMount, false, "This will start the mount daemon and automatically mount files into minikube")
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/minikube/pkg/localkube"
|
||||
"k8s.io/minikube/pkg/storage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -33,7 +33,7 @@ func main() {
|
|||
}
|
||||
flag.Parse()
|
||||
|
||||
if err := localkube.StartStorageProvisioner(); err != nil {
|
||||
if err := storage.StartStorageProvisioner(); err != nil {
|
||||
glog.Exit(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,3 @@ cp -r ${KUBE_ROOT}/pkg/generated/openapi ${MINIKUBE_ROOT}/vendor/k8s.io/kubernet
|
|||
|
||||
godep::remove_staging_from_json
|
||||
git checkout -- ${MINIKUBE_ROOT}/vendor/golang.org/x/sys/windows
|
||||
|
||||
pushd ${MINIKUBE_ROOT} >/dev/null
|
||||
git apply ${MINIKUBE_ROOT}/hack/tpr-patch.diff
|
||||
git apply ${MINIKUBE_ROOT}/hack/kube-proxy-patch.diff
|
||||
popd >/dev/null
|
||||
|
||||
|
|
|
@ -43,13 +43,3 @@ gsutil -m cp out/* gs://$BUCKET/releases/$TAGNAME/
|
|||
|
||||
# Bump latest
|
||||
gsutil cp -r gs://$BUCKET/releases/$TAGNAME/* gs://$BUCKET/releases/latest/
|
||||
|
||||
# Upload localkube containers
|
||||
TAG="$(docker images "gcr.io/k8s-minikube/localkube-image" --format="{{.Tag}}" | head -n 1)"
|
||||
gcloud docker -- push gcr.io/k8s-minikube/localkube-image:$TAG
|
||||
|
||||
TAG="$(docker images "gcr.io/k8s-minikube/localkube-dind-image" --format="{{.Tag}}" | head -n 1)"
|
||||
gcloud docker -- push gcr.io/k8s-minikube/localkube-dind-image:$TAG
|
||||
|
||||
TAG="$(docker images "gcr.io/k8s-minikube/localkube-dind-image-devshell" --format="{{.Tag}}" | head -n 1)"
|
||||
gcloud docker -- push gcr.io/k8s-minikube/localkube-dind-image-devshell:$TAG
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
diff --git b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go
|
||||
index 2f9ea2ea..35a7c14e 100644
|
||||
--- b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go
|
||||
+++ a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server.go
|
||||
@@ -318,6 +318,10 @@ func (o *Options) ApplyDefaults(in *kubeproxyconfig.KubeProxyConfiguration) (*ku
|
||||
return out, nil
|
||||
}
|
||||
|
||||
+func (o *Options) SetConfig(in *kubeproxyconfig.KubeProxyConfiguration) {
|
||||
+ o.config = in
|
||||
+}
|
||||
+
|
||||
// NewProxyCommand creates a *cobra.Command object with default parameters
|
||||
func NewProxyCommand() *cobra.Command {
|
||||
opts := NewOptions()
|
||||
diff --git b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go
|
||||
index 380e83e2..51bb09fd 100644
|
||||
--- b/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go
|
||||
+++ a/vendor/k8s.io/kubernetes/cmd/kube-proxy/app/server_others.go
|
||||
@@ -72,7 +72,7 @@ func newProxyServer(
|
||||
if c, err := configz.New(proxyconfigapi.GroupName); err == nil {
|
||||
c.Set(config)
|
||||
} else {
|
||||
- return nil, fmt.Errorf("unable to register configz: %s", err)
|
||||
+ glog.Warningf("unable to register configz: %s", err)
|
||||
}
|
||||
|
||||
protocol := utiliptables.ProtocolIpv4
|
||||
diff --git b/vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go a/vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go
|
||||
index 93982f89..a116da41 100644
|
||||
--- b/vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go
|
||||
+++ a/vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go
|
||||
@@ -380,7 +380,7 @@ func NewSchedulerServer(config *componentconfig.KubeSchedulerConfiguration, mast
|
||||
if c, err := configz.New("componentconfig"); err == nil {
|
||||
c.Set(config)
|
||||
} else {
|
||||
- return nil, fmt.Errorf("unable to register configz: %s", err)
|
||||
+ glog.Warningf("unable to register configz: %s", err)
|
||||
}
|
||||
|
||||
// Prepare some Kube clients.
|
|
@ -1,18 +0,0 @@
|
|||
diff --git a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go b/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go
|
||||
index f2e32c88c..f1c96c43d 100644
|
||||
--- a/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go
|
||||
+++ b/vendor/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go
|
||||
@@ -282,7 +282,12 @@ func (m *APIRegistrationManager) RESTMapper(versionPatterns ...schema.GroupVersi
|
||||
for enabledVersion := range m.enabledVersions {
|
||||
if !unionedGroups.Has(enabledVersion.Group) {
|
||||
unionedGroups.Insert(enabledVersion.Group)
|
||||
- groupMeta := m.groupMetaMap[enabledVersion.Group]
|
||||
+ groupMeta, found := m.groupMetaMap[enabledVersion.Group]
|
||||
+ // TODO(r2d4): hack until tprs are decoupled from restMapper
|
||||
+ if !found {
|
||||
+ glog.Warningf("Could not find groupMeta for %s", enabledVersion.Group)
|
||||
+ continue
|
||||
+ }
|
||||
unionMapper = append(unionMapper, groupMeta.RESTMapper)
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"net"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/minikube/pkg/util"
|
||||
|
||||
"github.com/coreos/etcd/embed"
|
||||
|
||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
apiserver "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||
)
|
||||
|
||||
func (lk LocalkubeServer) NewAPIServer() Server {
|
||||
return NewSimpleServer("apiserver", serverInterval, StartAPIServer(lk), readyFunc(lk))
|
||||
}
|
||||
|
||||
func StartAPIServer(lk LocalkubeServer) func() error {
|
||||
config := options.NewServerRunOptions()
|
||||
|
||||
config.SecureServing.BindAddress = lk.APIServerAddress
|
||||
config.SecureServing.BindPort = lk.APIServerPort
|
||||
|
||||
config.InsecureServing.BindAddress = lk.APIServerInsecureAddress
|
||||
config.InsecureServing.BindPort = lk.APIServerInsecurePort
|
||||
|
||||
config.Authentication.ClientCert.ClientCA = lk.GetCAPublicKeyCertPath()
|
||||
|
||||
config.SecureServing.ServerCert.CertKey.CertFile = lk.GetPublicKeyCertPath()
|
||||
config.SecureServing.ServerCert.CertKey.KeyFile = lk.GetPrivateKeyCertPath()
|
||||
config.Admission.PluginNames = util.DefaultAdmissionControllers
|
||||
// use localkube etcd
|
||||
|
||||
config.Etcd.StorageConfig.ServerList = []string{embed.DefaultListenClientURLs}
|
||||
config.Etcd.StorageConfig.Type = storagebackend.StorageTypeETCD3
|
||||
|
||||
// set Service IP range
|
||||
config.ServiceClusterIPRange = lk.ServiceClusterIPRange
|
||||
config.Etcd.EnableWatchCache = true
|
||||
|
||||
config.Features = &apiserveroptions.FeatureOptions{
|
||||
EnableProfiling: true,
|
||||
}
|
||||
|
||||
// defaults from apiserver command
|
||||
config.GenericServerRunOptions.MinRequestTimeout = 1800
|
||||
|
||||
config.AllowPrivileged = true
|
||||
|
||||
config.APIEnablement = &genericoptions.APIEnablementOptions{
|
||||
RuntimeConfig: lk.RuntimeConfig,
|
||||
}
|
||||
|
||||
config.ProxyClientCertFile = lk.GetProxyClientPublicKeyCertPath()
|
||||
config.ProxyClientKeyFile = lk.GetProxyClientPrivateKeyCertPath()
|
||||
config.Authentication.RequestHeader.AllowedNames =
|
||||
[]string{}
|
||||
config.Authentication.RequestHeader.UsernameHeaders =
|
||||
[]string{"X-Remote-User"}
|
||||
config.Authentication.RequestHeader.GroupHeaders =
|
||||
[]string{"X-Remote-Group"}
|
||||
config.Authentication.RequestHeader.ExtraHeaderPrefixes =
|
||||
[]string{"X-Remote-Extra-"}
|
||||
config.Authentication.RequestHeader.ClientCAFile =
|
||||
lk.GetProxyClientCAPublicKeyCertPath()
|
||||
|
||||
lk.SetExtraConfigForComponent("apiserver", &config)
|
||||
|
||||
return func() error {
|
||||
stop := make(chan struct{})
|
||||
return apiserver.Run(config, stop)
|
||||
}
|
||||
}
|
||||
|
||||
func readyFunc(lk LocalkubeServer) HealthCheck {
|
||||
return healthCheck(lk.GetAPIServerProtocol()+path.Join(
|
||||
net.JoinHostPort("localhost", strconv.Itoa(lk.APIServerPort)), "healthz"), lk)
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
controllerManager "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
||||
"k8s.io/kubernetes/cmd/kube-controller-manager/app/config"
|
||||
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func (lk LocalkubeServer) NewControllerManagerServer() Server {
|
||||
return NewSimpleServer("controller-manager", serverInterval, StartControllerManagerServer(lk), noop)
|
||||
}
|
||||
|
||||
func StartControllerManagerServer(lk LocalkubeServer) func() error {
|
||||
opts := options.NewKubeControllerManagerOptions()
|
||||
|
||||
opts.Generic.Kubeconfig = util.DefaultKubeConfigPath
|
||||
|
||||
// defaults from command
|
||||
opts.Generic.ComponentConfig.DeletingPodsQps = 0.1
|
||||
opts.Generic.ComponentConfig.DeletingPodsBurst = 10
|
||||
opts.Generic.ComponentConfig.NodeEvictionRate = 0.1
|
||||
|
||||
opts.Generic.ComponentConfig.EnableProfiling = true
|
||||
opts.Generic.ComponentConfig.VolumeConfiguration.EnableHostPathProvisioning = true
|
||||
opts.Generic.ComponentConfig.VolumeConfiguration.EnableDynamicProvisioning = true
|
||||
opts.Generic.ComponentConfig.ServiceAccountKeyFile = lk.GetPrivateKeyCertPath()
|
||||
opts.Generic.ComponentConfig.RootCAFile = lk.GetCAPublicKeyCertPath()
|
||||
|
||||
lk.SetExtraConfigForComponent("controller-manager", &opts)
|
||||
|
||||
cfg := config.Config{}
|
||||
if err := opts.ApplyTo(&cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return func() error {
|
||||
return controllerManager.Run(cfg.Complete())
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/embed"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
// EtcdName is the name of the extra-config component for etcd
|
||||
EtcdName = "etcd"
|
||||
)
|
||||
|
||||
// EtcdServer is a Server which manages an Etcd cluster
|
||||
type EtcdServer struct {
|
||||
Etcd *embed.Etcd
|
||||
Config *embed.Config
|
||||
}
|
||||
|
||||
// NewEtcd creates a new default etcd Server using 'dataDir' for persistence. Panics if could not be configured.
|
||||
func (lk LocalkubeServer) NewEtcd(dataDir string) (*EtcdServer, error) {
|
||||
cfg := embed.NewConfig()
|
||||
cfg.Dir = dataDir
|
||||
|
||||
lk.SetExtraConfigForComponent(EtcdName, &cfg)
|
||||
return &EtcdServer{
|
||||
Config: cfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start starts the etcd server and listening for client connections
|
||||
func (e *EtcdServer) Start() {
|
||||
var err error
|
||||
e.Etcd, err = embed.StartEtcd(e.Config)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error starting up etcd: %s", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-e.Etcd.Server.ReadyNotify():
|
||||
glog.Infoln("Etcd server is ready")
|
||||
case <-time.After(60 * time.Second):
|
||||
e.Etcd.Server.Stop() // trigger a shutdown
|
||||
glog.Fatalf("Etcd took too long to start")
|
||||
}
|
||||
}
|
||||
|
||||
// Stop closes all connections and stops the Etcd server
|
||||
func (e *EtcdServer) Stop() {
|
||||
if e.Etcd != nil {
|
||||
e.Etcd.Server.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the servers unique name
|
||||
func (e EtcdServer) Name() string {
|
||||
return e.Config.Name
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
kubelet "k8s.io/kubernetes/cmd/kubelet/app"
|
||||
"k8s.io/kubernetes/cmd/kubelet/app/options"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func (lk LocalkubeServer) NewKubeletServer() Server {
|
||||
return NewSimpleServer("kubelet", serverInterval, StartKubeletServer(lk), noop)
|
||||
}
|
||||
|
||||
func StartKubeletServer(lk LocalkubeServer) func() error {
|
||||
config, err := options.NewKubeletServer()
|
||||
if err != nil {
|
||||
return func() error { return err }
|
||||
}
|
||||
dnsIP, err := util.GetDNSIP(lk.ServiceClusterIPRange.String())
|
||||
if err != nil {
|
||||
return func() error { return err }
|
||||
}
|
||||
|
||||
// Master details
|
||||
config.KubeConfig = util.DefaultKubeConfigPath
|
||||
|
||||
// Set containerized based on the flag
|
||||
config.Containerized = lk.Containerized
|
||||
|
||||
config.AllowPrivileged = true
|
||||
config.StaticPodPath = "/etc/kubernetes/manifests"
|
||||
|
||||
// Networking
|
||||
config.ClusterDomain = lk.DNSDomain
|
||||
config.ClusterDNS = []string{dnsIP.String()}
|
||||
// For kubenet plugin.
|
||||
config.PodCIDR = "10.180.1.0/24"
|
||||
|
||||
config.NodeIP = lk.NodeIP.String()
|
||||
config.FailSwapOn = false
|
||||
|
||||
if lk.NetworkPlugin != "" {
|
||||
config.NetworkPluginName = lk.NetworkPlugin
|
||||
}
|
||||
|
||||
// Runtime
|
||||
if lk.ContainerRuntime != "" {
|
||||
config.ContainerRuntime = lk.ContainerRuntime
|
||||
}
|
||||
if lk.RemoteRuntimeEndpoint != "" {
|
||||
config.RemoteRuntimeEndpoint = lk.RemoteRuntimeEndpoint
|
||||
}
|
||||
if lk.RemoteImageEndpoint != "" {
|
||||
config.RemoteImageEndpoint = lk.RemoteImageEndpoint
|
||||
}
|
||||
lk.SetExtraConfigForComponent("kubelet", &config)
|
||||
|
||||
// Use the host's resolver config
|
||||
if lk.Containerized {
|
||||
config.ResolverConfig = "/rootfs/etc/resolv.conf"
|
||||
} else {
|
||||
config.ResolverConfig = "/etc/resolv.conf"
|
||||
}
|
||||
|
||||
return func() error {
|
||||
return kubelet.Run(config, nil)
|
||||
}
|
||||
}
|
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/minikube/pkg/util/kubeconfig"
|
||||
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
const serverInterval = 200
|
||||
|
||||
// LocalkubeServer provides a fully functional Kubernetes cluster running entirely through goroutines
|
||||
type LocalkubeServer struct {
|
||||
// Inherits Servers
|
||||
Servers
|
||||
|
||||
// Options
|
||||
Containerized bool
|
||||
EnableDNS bool
|
||||
DNSDomain string
|
||||
LocalkubeDirectory string
|
||||
ServiceClusterIPRange net.IPNet
|
||||
APIServerAddress net.IP
|
||||
APIServerPort int
|
||||
APIServerInsecureAddress net.IP
|
||||
APIServerInsecurePort int
|
||||
APIServerName string
|
||||
ShouldGenerateCerts bool
|
||||
ShouldGenerateKubeconfig bool
|
||||
ShowVersion bool
|
||||
ShowHostIP bool
|
||||
RuntimeConfig flag.ConfigurationMap
|
||||
NodeIP net.IP
|
||||
ContainerRuntime string
|
||||
RemoteRuntimeEndpoint string
|
||||
RemoteImageEndpoint string
|
||||
NetworkPlugin string
|
||||
FeatureGates string
|
||||
ExtraConfig util.ExtraOptionSlice
|
||||
}
|
||||
|
||||
func (lk *LocalkubeServer) AddServer(server Server) {
|
||||
lk.Servers = append(lk.Servers, server)
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetEtcdDataDirectory() string {
|
||||
return path.Join(lk.LocalkubeDirectory, "etcd")
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetDNSDataDirectory() string {
|
||||
return path.Join(lk.LocalkubeDirectory, "dns")
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetCertificateDirectory() string {
|
||||
return path.Join(lk.LocalkubeDirectory, "certs")
|
||||
}
|
||||
func (lk LocalkubeServer) GetPrivateKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "apiserver.key")
|
||||
}
|
||||
func (lk LocalkubeServer) GetPublicKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "apiserver.crt")
|
||||
}
|
||||
func (lk LocalkubeServer) GetCAPrivateKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "ca.key")
|
||||
}
|
||||
func (lk LocalkubeServer) GetCAPublicKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "ca.crt")
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetProxyClientPrivateKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "proxy-client.key")
|
||||
}
|
||||
func (lk LocalkubeServer) GetProxyClientPublicKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "proxy-client.crt")
|
||||
}
|
||||
func (lk LocalkubeServer) GetProxyClientCAPublicKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "proxy-client-ca.crt")
|
||||
}
|
||||
func (lk LocalkubeServer) GetProxyClientCAPrivateKeyCertPath() string {
|
||||
return path.Join(lk.GetCertificateDirectory(), "proxy-client-ca.key")
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetAPIServerSecureURL() string {
|
||||
return fmt.Sprintf("https://%s:%d", lk.APIServerAddress.String(), lk.APIServerPort)
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetAPIServerInsecureURL() string {
|
||||
if lk.APIServerInsecurePort != 0 {
|
||||
return fmt.Sprintf("http://%s:%d", lk.APIServerInsecureAddress.String(), lk.APIServerInsecurePort)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetAPIServerProtocol() string {
|
||||
if lk.APIServerInsecurePort != 0 {
|
||||
return "http://"
|
||||
}
|
||||
return "https://"
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetTransport() (*http.Transport, error) {
|
||||
if lk.APIServerInsecurePort != 0 {
|
||||
return &http.Transport{}, nil
|
||||
}
|
||||
cert, err := tls.LoadX509KeyPair(lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return &http.Transport{}, err
|
||||
}
|
||||
|
||||
// Load CA cert
|
||||
caCert, err := ioutil.ReadFile(lk.GetCAPublicKeyCertPath())
|
||||
if err != nil {
|
||||
glog.Warning(err)
|
||||
return &http.Transport{}, err
|
||||
}
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
return &http.Transport{TLSClientConfig: tlsConfig}, nil
|
||||
}
|
||||
|
||||
// Get the host's public IP address
|
||||
func (lk LocalkubeServer) GetHostIP() (net.IP, error) {
|
||||
return utilnet.ChooseBindAddress(net.ParseIP("0.0.0.0"))
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) getExtraConfigForComponent(component string) []util.ExtraOption {
|
||||
e := []util.ExtraOption{}
|
||||
for _, c := range lk.ExtraConfig {
|
||||
if c.Component == component {
|
||||
e = append(e, c)
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) SetExtraConfigForComponent(component string, config interface{}) {
|
||||
extra := lk.getExtraConfigForComponent(component)
|
||||
for _, e := range extra {
|
||||
glog.Infof("Setting %s to %s on %s.\n", e.Key, e.Value, component)
|
||||
if err := util.FindAndSet(e.Key, config, e.Value); err != nil {
|
||||
glog.Warningf("Unable to set %s to %s. Error: %s", e.Key, e.Value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GetFeatureGates() (map[string]bool, error) {
|
||||
fg := map[string]bool{}
|
||||
if lk.FeatureGates == "" {
|
||||
return fg, nil
|
||||
}
|
||||
gates := strings.Split(lk.FeatureGates, ",")
|
||||
for _, g := range gates {
|
||||
|
||||
kvp := strings.SplitN(g, "=", 2)
|
||||
if len(kvp) != 2 {
|
||||
return nil, fmt.Errorf("invalid feature gate specification: %s", g)
|
||||
}
|
||||
value, err := strconv.ParseBool(kvp[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid feature gate specification: %s", g)
|
||||
}
|
||||
fg[kvp[0]] = value
|
||||
}
|
||||
return fg, nil
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) loadCert(path string) (*x509.Certificate, error) {
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decoded, _ := pem.Decode(contents)
|
||||
if decoded == nil {
|
||||
return nil, fmt.Errorf("Unable to decode certificate.")
|
||||
}
|
||||
|
||||
return x509.ParseCertificate(decoded.Bytes)
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) shouldGenerateCerts(ips []net.IP) bool {
|
||||
if !(util.CanReadFile(lk.GetPublicKeyCertPath()) &&
|
||||
util.CanReadFile(lk.GetPrivateKeyCertPath())) {
|
||||
fmt.Println("Regenerating certs because the files aren't readable")
|
||||
return true
|
||||
}
|
||||
|
||||
cert, err := lk.loadCert(lk.GetPublicKeyCertPath())
|
||||
if err != nil {
|
||||
fmt.Println("Regenerating certs because there was an error loading the certificate: ", err)
|
||||
return true
|
||||
}
|
||||
|
||||
certIPs := map[string]bool{}
|
||||
for _, certIP := range cert.IPAddresses {
|
||||
certIPs[certIP.String()] = true
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
if _, ok := certIPs[ip.String()]; !ok {
|
||||
fmt.Println("Regenerating certs becase an IP is missing: ", ip)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) shouldGenerateCACerts() bool {
|
||||
if !(util.CanReadFile(lk.GetCAPublicKeyCertPath()) &&
|
||||
util.CanReadFile(lk.GetCAPrivateKeyCertPath())) {
|
||||
fmt.Println("Regenerating CA certs because the files aren't readable")
|
||||
return true
|
||||
}
|
||||
|
||||
_, err := lk.loadCert(lk.GetCAPublicKeyCertPath())
|
||||
if err != nil {
|
||||
fmt.Println("Regenerating CA certs because there was an error loading the certificate: ", err)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GenerateKubeconfig() error {
|
||||
if !lk.ShouldGenerateKubeconfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
// setup kubeconfig
|
||||
kubeConfigFile := util.DefaultKubeConfigPath
|
||||
glog.Infof("Setting up kubeconfig at: %s", kubeConfigFile)
|
||||
kubeHost := "http://127.0.0.1:" + strconv.Itoa(lk.APIServerInsecurePort)
|
||||
|
||||
//TODO(aaron-prindle) configure this so that it can generate secure certs as well
|
||||
kubeCfgSetup := &kubeconfig.KubeConfigSetup{
|
||||
ClusterName: lk.APIServerName,
|
||||
ClusterServerAddress: kubeHost,
|
||||
KeepContext: false,
|
||||
}
|
||||
|
||||
kubeCfgSetup.SetKubeConfigFile(kubeConfigFile)
|
||||
|
||||
if err := kubeconfig.SetupKubeConfig(kubeCfgSetup); err != nil {
|
||||
glog.Errorln("Error setting up kubeconfig: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) getAllIPs() ([]net.IP, error) {
|
||||
serviceIP, err := util.GetServiceClusterIP(lk.ServiceClusterIPRange.String())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting service cluster ip")
|
||||
}
|
||||
ips := []net.IP{serviceIP}
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ipnet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
fmt.Println("Skipping: ", addr)
|
||||
continue
|
||||
}
|
||||
ips = append(ips, ipnet.IP)
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (lk LocalkubeServer) GenerateCerts() error {
|
||||
if !lk.shouldGenerateCACerts() {
|
||||
fmt.Println(
|
||||
"Using these existing CA certs: ", lk.GetCAPublicKeyCertPath(),
|
||||
lk.GetCAPrivateKeyCertPath(), lk.GetProxyClientCAPublicKeyCertPath(),
|
||||
lk.GetProxyClientCAPrivateKeyCertPath(),
|
||||
)
|
||||
} else {
|
||||
fmt.Println("Creating CA cert")
|
||||
if err := util.GenerateCACert(
|
||||
lk.GetCAPublicKeyCertPath(), lk.GetCAPrivateKeyCertPath(),
|
||||
lk.APIServerName,
|
||||
); err != nil {
|
||||
fmt.Println("Failed to create CA cert: ", err)
|
||||
return err
|
||||
}
|
||||
fmt.Println("Creating proxy client CA cert")
|
||||
if err := util.GenerateCACert(
|
||||
lk.GetProxyClientCAPublicKeyCertPath(),
|
||||
lk.GetProxyClientCAPrivateKeyCertPath(), "proxyClientCA",
|
||||
); err != nil {
|
||||
fmt.Println("Failed to create proxy client CA cert: ", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := lk.getAllIPs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !lk.shouldGenerateCerts(ips) {
|
||||
fmt.Println(
|
||||
"Using these existing certs: ", lk.GetPublicKeyCertPath(),
|
||||
lk.GetPrivateKeyCertPath(), lk.GetProxyClientPublicKeyCertPath(),
|
||||
lk.GetProxyClientPrivateKeyCertPath(),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
fmt.Println("Creating cert with IPs: ", ips)
|
||||
|
||||
if err := util.GenerateSignedCert(
|
||||
lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath(), "minikube", ips,
|
||||
util.GetAlternateDNS(lk.DNSDomain), lk.GetCAPublicKeyCertPath(),
|
||||
lk.GetCAPrivateKeyCertPath(),
|
||||
); err != nil {
|
||||
fmt.Println("Failed to create cert: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := util.GenerateSignedCert(
|
||||
lk.GetProxyClientPublicKeyCertPath(), lk.GetProxyClientPrivateKeyCertPath(),
|
||||
"aggregator", []net.IP{}, []string{},
|
||||
lk.GetProxyClientCAPublicKeyCertPath(),
|
||||
lk.GetProxyClientCAPrivateKeyCertPath(),
|
||||
); err != nil {
|
||||
fmt.Println("Failed to create proxy client cert: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/tests"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
var testIPs = []net.IP{net.ParseIP("1.2.3.4")}
|
||||
|
||||
func TestGenerateCerts(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
|
||||
|
||||
_, ipRange, _ := net.ParseCIDR(util.DefaultServiceCIDR)
|
||||
lk := LocalkubeServer{
|
||||
LocalkubeDirectory: tempDir,
|
||||
ServiceClusterIPRange: *ipRange,
|
||||
}
|
||||
|
||||
if err := lk.GenerateCerts(); err != nil {
|
||||
t.Fatalf("Unexpected error generating certs: %s", err)
|
||||
}
|
||||
|
||||
for _, f := range []string{"apiserver.crt", "apiserver.key"} {
|
||||
p := filepath.Join(tempDir, "certs", f)
|
||||
_, err := os.Stat(p)
|
||||
if os.IsNotExist(err) {
|
||||
t.Fatalf("Certificate not created: %s", p)
|
||||
}
|
||||
}
|
||||
_, err := lk.loadCert(filepath.Join(tempDir, "certs", "apiserver.crt"))
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing cert: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldGenerateCertsNoFiles(t *testing.T) {
|
||||
lk := LocalkubeServer{LocalkubeDirectory: "baddir"}
|
||||
if !lk.shouldGenerateCerts(testIPs) {
|
||||
t.Fatalf("No certs exist, we should generate.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldGenerateCertsOneFile(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
|
||||
ioutil.WriteFile(filepath.Join(tempDir, "certs", "apiserver.crt"), []byte(""), 0644)
|
||||
lk := LocalkubeServer{LocalkubeDirectory: tempDir}
|
||||
if !lk.shouldGenerateCerts(testIPs) {
|
||||
t.Fatalf("Not all certs exist, we should generate.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldGenerateCertsBadFiles(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
|
||||
for _, f := range []string{"apiserver.crt", "apiserver.key"} {
|
||||
ioutil.WriteFile(filepath.Join(tempDir, "certs", f), []byte(""), 0644)
|
||||
}
|
||||
lk := LocalkubeServer{LocalkubeDirectory: tempDir}
|
||||
if !lk.shouldGenerateCerts(testIPs) {
|
||||
t.Fatalf("Certs are badly formatted, we should generate.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldGenerateCertsMismatchedIP(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
|
||||
|
||||
_, ipRange, _ := net.ParseCIDR(util.DefaultServiceCIDR)
|
||||
lk := LocalkubeServer{
|
||||
LocalkubeDirectory: tempDir,
|
||||
ServiceClusterIPRange: *ipRange,
|
||||
}
|
||||
|
||||
lk.GenerateCerts()
|
||||
|
||||
if !lk.shouldGenerateCerts([]net.IP{net.ParseIP("4.3.2.1")}) {
|
||||
t.Fatalf("IPs don't match, we should generate.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldNotGenerateCerts(t *testing.T) {
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
|
||||
|
||||
_, ipRange, _ := net.ParseCIDR(util.DefaultServiceCIDR)
|
||||
lk := LocalkubeServer{
|
||||
LocalkubeDirectory: tempDir,
|
||||
ServiceClusterIPRange: *ipRange,
|
||||
}
|
||||
lk.GenerateCerts()
|
||||
ips, _ := lk.getAllIPs()
|
||||
if lk.shouldGenerateCerts(ips) {
|
||||
t.Fatalf("IPs match, we should not generate.")
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
kubeproxy "k8s.io/kubernetes/cmd/kube-proxy/app"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
MasqueradeBit = int32(14)
|
||||
OOMScoreAdj = int32(qos.KubeProxyOOMScoreAdj)
|
||||
)
|
||||
|
||||
func (lk LocalkubeServer) NewProxyServer() Server {
|
||||
return NewSimpleServer("proxy", serverInterval, StartProxyServer(lk), noop)
|
||||
}
|
||||
|
||||
func StartProxyServer(lk LocalkubeServer) func() error {
|
||||
bindaddress := lk.APIServerAddress.String()
|
||||
if lk.APIServerInsecurePort != 0 {
|
||||
bindaddress = lk.APIServerInsecureAddress.String()
|
||||
}
|
||||
|
||||
opts := kubeproxy.NewOptions()
|
||||
fg, err := lk.GetFeatureGates()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config := &kubeproxyconfig.KubeProxyConfiguration{
|
||||
OOMScoreAdj: &OOMScoreAdj,
|
||||
ClientConnection: kubeproxyconfig.ClientConnectionConfiguration{
|
||||
Burst: 10,
|
||||
QPS: 5,
|
||||
KubeConfigFile: util.DefaultKubeConfigPath,
|
||||
},
|
||||
ConfigSyncPeriod: v1.Duration{Duration: 15 * time.Minute},
|
||||
IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeBit: &MasqueradeBit,
|
||||
SyncPeriod: v1.Duration{Duration: 30 * time.Second},
|
||||
MinSyncPeriod: v1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
BindAddress: bindaddress,
|
||||
Mode: kubeproxyconfig.ProxyModeIPTables,
|
||||
FeatureGates: fg,
|
||||
// Disable the healthz check
|
||||
HealthzBindAddress: "",
|
||||
}
|
||||
if _, err := opts.ApplyDefaults(config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
lk.SetExtraConfigForComponent("proxy", &config)
|
||||
opts.SetConfig(config)
|
||||
|
||||
return func() error {
|
||||
return opts.Run()
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
type HealthCheck func() bool
|
||||
|
||||
func healthCheck(addr string, lk LocalkubeServer) HealthCheck {
|
||||
return func() bool {
|
||||
glog.Infof("Performing healthcheck on %s\n", addr)
|
||||
|
||||
transport, err := lk.GetTransport()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
client := http.Client{Transport: transport}
|
||||
|
||||
resp, err := client.Get(addr)
|
||||
if err != nil {
|
||||
glog.Errorf("Error performing healthcheck: %s", err)
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
glog.Errorf("Error reading healthcheck response: %s", err)
|
||||
return false
|
||||
}
|
||||
glog.Infof("Got healthcheck response: %s", body)
|
||||
return string(body) == "ok"
|
||||
}
|
||||
}
|
||||
|
||||
func noop() bool {
|
||||
return true
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/tests"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func TestBasicHealthCheck(t *testing.T) {
|
||||
|
||||
tcs := []struct {
|
||||
body string
|
||||
statusCode int
|
||||
shouldSucceed bool
|
||||
}{
|
||||
{"ok", 200, true},
|
||||
{"notok", 200, false},
|
||||
}
|
||||
|
||||
tempDir := tests.MakeTempDir()
|
||||
defer os.RemoveAll(tempDir)
|
||||
_, ipnet, err := net.ParseCIDR(util.DefaultServiceCIDR)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing default service cidr range: %s", err)
|
||||
}
|
||||
lk := LocalkubeServer{
|
||||
LocalkubeDirectory: tempDir,
|
||||
ServiceClusterIPRange: *ipnet,
|
||||
}
|
||||
lk.GenerateCerts()
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath())
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to load server certs.")
|
||||
}
|
||||
|
||||
caCert, err := ioutil.ReadFile(lk.GetCAPublicKeyCertPath())
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to load CA certs.")
|
||||
}
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
tls := tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ClientCAs: caCertPool,
|
||||
}
|
||||
|
||||
tls.BuildNameToCertificate()
|
||||
|
||||
for _, tc := range tcs {
|
||||
// Do this in a func so we can use defer.
|
||||
doTest := func() {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(tc.statusCode)
|
||||
io.WriteString(w, tc.body)
|
||||
}
|
||||
server := httptest.NewUnstartedServer(http.HandlerFunc(handler))
|
||||
defer server.Close()
|
||||
server.TLS = &tls
|
||||
server.StartTLS()
|
||||
|
||||
hcFunc := healthCheck(server.URL, lk)
|
||||
result := hcFunc()
|
||||
if result != tc.shouldSucceed {
|
||||
t.Errorf("Expected healthcheck to return %v. Got %v", result, tc.shouldSucceed)
|
||||
}
|
||||
}
|
||||
doTest()
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
scheduler "k8s.io/kubernetes/cmd/kube-scheduler/app"
|
||||
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func (lk LocalkubeServer) NewSchedulerServer() Server {
|
||||
return NewSimpleServer("scheduler", serverInterval, StartSchedulerServer(lk), noop)
|
||||
}
|
||||
|
||||
func StartSchedulerServer(lk LocalkubeServer) func() error {
|
||||
config := &componentconfig.KubeSchedulerConfiguration{}
|
||||
opts, err := scheduler.NewOptions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config, err = opts.ApplyDefaults(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// master details
|
||||
config.ClientConnection.KubeConfigFile = util.DefaultKubeConfigPath
|
||||
|
||||
// defaults from command
|
||||
config.EnableProfiling = true
|
||||
|
||||
lk.SetExtraConfigForComponent("scheduler", &config)
|
||||
|
||||
return func() error {
|
||||
s, err := scheduler.NewSchedulerServer(config, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.Run(nil)
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// Server represents a component that Kubernetes depends on. It allows for the management of
|
||||
// the lifecycle of the component.
|
||||
type Server interface {
|
||||
// Start immediately starts the component.
|
||||
Start()
|
||||
|
||||
// Stop begins the process of stopping the component.
|
||||
Stop()
|
||||
|
||||
// Name returns a unique identifier for the component.
|
||||
Name() string
|
||||
|
||||
Ready() (bool, error)
|
||||
}
|
||||
|
||||
// SimpleServer provides a minimal implementation of Server.
|
||||
type SimpleServer struct {
|
||||
ComponentName string
|
||||
Interval time.Duration
|
||||
|
||||
serverRoutine func() error
|
||||
stopChannel chan struct{}
|
||||
readyFunc func() bool
|
||||
}
|
||||
|
||||
func NewSimpleServer(componentName string, msInterval int32, serverRoutine func() error, ready HealthCheck) *SimpleServer {
|
||||
return &SimpleServer{
|
||||
ComponentName: componentName,
|
||||
Interval: time.Duration(msInterval) * time.Millisecond,
|
||||
|
||||
serverRoutine: serverRoutine,
|
||||
stopChannel: make(chan struct{}),
|
||||
readyFunc: ready,
|
||||
}
|
||||
}
|
||||
|
||||
// Start calls startup function.
|
||||
func (s *SimpleServer) Start() {
|
||||
go util.Until(s.serverRoutine, os.Stdout, s.ComponentName, s.Interval, s.stopChannel)
|
||||
}
|
||||
|
||||
// Stop calls shutdown function.
|
||||
func (s *SimpleServer) Stop() {
|
||||
close(s.stopChannel)
|
||||
}
|
||||
|
||||
// Name returns the name of the service.
|
||||
func (s SimpleServer) Name() string {
|
||||
return s.ComponentName
|
||||
}
|
||||
|
||||
func (s SimpleServer) Ready() (bool, error) {
|
||||
return s.readyFunc(), nil
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
// Servers allows operations to be performed on many servers at once.
|
||||
// Uses slice to preserve ordering.
|
||||
type Servers []Server
|
||||
|
||||
// Get returns a server matching name, returns nil if server doesn't exit.
|
||||
func (servers Servers) Get(name string) (Server, error) {
|
||||
for _, server := range servers {
|
||||
if server.Name() == name {
|
||||
return server, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("server '%s' does not exist", name)
|
||||
}
|
||||
|
||||
// StartAll starts all services, starting from 0th item and ascending.
|
||||
func (servers Servers) StartAll() {
|
||||
|
||||
for _, server := range servers {
|
||||
fmt.Printf("Starting %s...\n", server.Name())
|
||||
server.Start()
|
||||
fmt.Printf("Waiting for %s to be healthy...\n", server.Name())
|
||||
wait.PollInfinite(time.Second, server.Ready)
|
||||
fmt.Printf("%s is ready!\n", server.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// StopAll stops all services, starting with the last item.
|
||||
func (servers Servers) StopAll() {
|
||||
for i := len(servers) - 1; i >= 0; i-- {
|
||||
server := servers[i]
|
||||
fmt.Printf("Stopping %s...\n", server.Name())
|
||||
server.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// Start is a helper method to start the Server specified, returns error if server doesn't exist.
|
||||
func (servers Servers) Start(serverName string) error {
|
||||
server, err := servers.Get(serverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
server.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop is a helper method to start the Server specified, returns error if server doesn't exist.
|
||||
func (servers Servers) Stop(serverName string) error {
|
||||
server, err := servers.Get(serverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
server.Stop()
|
||||
return nil
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
gflag "flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
// Kill any running instances.
|
||||
|
||||
var localkubeStartCmdTemplate = "/usr/local/bin/localkube {{.Flags}} --generate-certs=false --logtostderr=true --enable-dns=false"
|
||||
|
||||
var startCommandNoSystemdTemplate = `
|
||||
# Run with nohup so it stays up. Redirect logs to useful places.
|
||||
sudo sh -c 'PATH=/usr/local/sbin:$PATH GODEBUG=netdns=go nohup {{.LocalkubeStartCmd}} > {{.Stdout}} 2> {{.Stderr}} < /dev/null & echo $! > {{.Pidfile}} &'
|
||||
`
|
||||
|
||||
var localkubeSystemdTmpl = `[Unit]
|
||||
Description=Localkube
|
||||
Documentation=https://github.com/kubernetes/minikube/tree/master/pkg/localkube
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
Environment=GODEBUG=netdns=go
|
||||
|
||||
ExecStart={{.LocalkubeStartCmd}}
|
||||
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
|
||||
var startCommandTemplate = "if [[ `systemctl` =~ -\\.mount ]] &>/dev/null;" + `then
|
||||
{{.StartCommandSystemd}}
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable localkube.service
|
||||
sudo systemctl restart localkube.service || true
|
||||
else
|
||||
sudo killall localkube || true
|
||||
{{.StartCommandNoSystemd}}
|
||||
fi
|
||||
`
|
||||
|
||||
func GetStartCommand(kubernetesConfig config.KubernetesConfig) (string, error) {
|
||||
localkubeStartCommand, err := GenLocalkubeStartCmd(kubernetesConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
startCommandNoSystemd, err := GetStartCommandNoSystemd(kubernetesConfig, localkubeStartCommand)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
startCommandSystemd, err := GetStartCommandSystemd(kubernetesConfig, localkubeStartCommand)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
t := template.Must(template.New("startCommand").Parse(startCommandTemplate))
|
||||
buf := bytes.Buffer{}
|
||||
data := struct {
|
||||
StartCommandNoSystemd string
|
||||
StartCommandSystemd string
|
||||
}{
|
||||
StartCommandNoSystemd: startCommandNoSystemd,
|
||||
StartCommandSystemd: startCommandSystemd,
|
||||
}
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func GetStartCommandNoSystemd(kubernetesConfig config.KubernetesConfig, localkubeStartCmd string) (string, error) {
|
||||
t := template.Must(template.New("startCommand").Parse(startCommandNoSystemdTemplate))
|
||||
buf := bytes.Buffer{}
|
||||
data := struct {
|
||||
LocalkubeStartCmd string
|
||||
Stdout string
|
||||
Stderr string
|
||||
Pidfile string
|
||||
}{
|
||||
LocalkubeStartCmd: localkubeStartCmd,
|
||||
Stdout: constants.RemoteLocalKubeOutPath,
|
||||
Stderr: constants.RemoteLocalKubeErrPath,
|
||||
Pidfile: constants.LocalkubePIDPath,
|
||||
}
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func GetStartCommandSystemd(kubernetesConfig config.KubernetesConfig, localkubeStartCmd string) (string, error) {
|
||||
t, err := template.New("localkubeConfig").Parse(localkubeSystemdTmpl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf := bytes.Buffer{}
|
||||
data := struct {
|
||||
LocalkubeStartCmd string
|
||||
}{
|
||||
LocalkubeStartCmd: localkubeStartCmd,
|
||||
}
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("printf %%s \"%s\" | sudo tee %s", buf.String(),
|
||||
constants.LocalkubeServicePath), nil
|
||||
}
|
||||
|
||||
func GenLocalkubeStartCmd(kubernetesConfig config.KubernetesConfig) (string, error) {
|
||||
flagVals := make([]string, len(constants.LogFlags))
|
||||
for _, logFlag := range constants.LogFlags {
|
||||
if logVal := gflag.Lookup(logFlag); logVal != nil && logVal.Value.String() != logVal.DefValue {
|
||||
flagVals = append(flagVals, fmt.Sprintf("--%s %s", logFlag, logVal.Value.String()))
|
||||
}
|
||||
}
|
||||
|
||||
if kubernetesConfig.ContainerRuntime != "" {
|
||||
flagVals = append(flagVals, "--container-runtime="+kubernetesConfig.ContainerRuntime)
|
||||
}
|
||||
|
||||
if kubernetesConfig.NetworkPlugin != "" {
|
||||
flagVals = append(flagVals, "--network-plugin="+kubernetesConfig.NetworkPlugin)
|
||||
}
|
||||
|
||||
if kubernetesConfig.FeatureGates != "" {
|
||||
flagVals = append(flagVals, "--feature-gates="+kubernetesConfig.FeatureGates)
|
||||
}
|
||||
|
||||
if kubernetesConfig.APIServerName != constants.APIServerName {
|
||||
flagVals = append(flagVals, "--apiserver-name="+kubernetesConfig.APIServerName)
|
||||
}
|
||||
|
||||
if kubernetesConfig.DNSDomain != "" {
|
||||
flagVals = append(flagVals, "--dns-domain="+kubernetesConfig.DNSDomain)
|
||||
}
|
||||
|
||||
if kubernetesConfig.NodeIP != "127.0.0.1" {
|
||||
flagVals = append(flagVals, "--node-ip="+kubernetesConfig.NodeIP)
|
||||
}
|
||||
|
||||
for _, e := range kubernetesConfig.ExtraOptions {
|
||||
flagVals = append(flagVals, fmt.Sprintf("--extra-config=%s", e.String()))
|
||||
}
|
||||
flags := strings.Join(flagVals, " ")
|
||||
|
||||
t := template.Must(template.New("localkubeStartCmd").Parse(localkubeStartCmdTemplate))
|
||||
buf := bytes.Buffer{}
|
||||
data := struct {
|
||||
Flags string
|
||||
APIServerName string
|
||||
}{
|
||||
Flags: flags,
|
||||
APIServerName: kubernetesConfig.APIServerName,
|
||||
}
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
const logsTemplate = "if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; " + `then
|
||||
sudo journalctl {{.Flags}} -u localkube
|
||||
else
|
||||
tail -n +1 {{.Flags}} {{.RemoteLocalkubeErrPath}} {{.RemoteLocalkubeOutPath}}
|
||||
fi
|
||||
`
|
||||
|
||||
func GetLogsCommand(follow bool) (string, error) {
|
||||
t, err := template.New("logsTemplate").Parse(logsTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var flags []string
|
||||
if follow {
|
||||
flags = append(flags, "-f")
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
data := struct {
|
||||
RemoteLocalkubeErrPath string
|
||||
RemoteLocalkubeOutPath string
|
||||
Flags string
|
||||
}{
|
||||
RemoteLocalkubeErrPath: constants.RemoteLocalKubeErrPath,
|
||||
RemoteLocalkubeOutPath: constants.RemoteLocalKubeOutPath,
|
||||
Flags: strings.Join(flags, " "),
|
||||
}
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
var localkubeStatusCommand = fmt.Sprintf("if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; "+`then
|
||||
sudo systemctl is-active localkube &>/dev/null && echo "Running" || echo "Stopped"
|
||||
else
|
||||
if ps $(cat %s) &>/dev/null; then
|
||||
echo "Running"
|
||||
else
|
||||
echo "Stopped"
|
||||
fi
|
||||
fi
|
||||
`, constants.LocalkubePIDPath)
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
gflag "flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func TestGetStartCommandCustomValues(t *testing.T) {
|
||||
flagMap := map[string]string{
|
||||
"v": "10",
|
||||
"vmodule": "cluster*=5",
|
||||
}
|
||||
flagMapToSetFlags(flagMap)
|
||||
startCommand, err := GetStartCommand(config.KubernetesConfig{})
|
||||
if err != nil {
|
||||
t.Fatalf("Error generating start command: %s", err)
|
||||
}
|
||||
|
||||
for flag, val := range flagMap {
|
||||
if val != "" {
|
||||
if expectedFlag := getSingleFlagValue(flag, val); !strings.Contains(startCommand, getSingleFlagValue(flag, val)) {
|
||||
t.Fatalf("Expected GetStartCommand to contain: %s.", expectedFlag)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStartCommandExtraOptions(t *testing.T) {
|
||||
k := config.KubernetesConfig{
|
||||
ExtraOptions: util.ExtraOptionSlice{
|
||||
util.ExtraOption{Component: "a", Key: "b", Value: "c"},
|
||||
util.ExtraOption{Component: "d", Key: "e.f", Value: "g"},
|
||||
},
|
||||
}
|
||||
startCommand, err := GetStartCommand(k)
|
||||
if err != nil {
|
||||
t.Fatalf("Error generating start command: %s", err)
|
||||
}
|
||||
for _, arg := range []string{"--extra-config=a.b=c", "--extra-config=d.e.f=g"} {
|
||||
if !strings.Contains(startCommand, arg) {
|
||||
t.Fatalf("Error, expected to find argument: %s. Got: %s", arg, startCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func flagMapToSetFlags(flagMap map[string]string) {
|
||||
for flag, val := range flagMap {
|
||||
gflag.Set(flag, val)
|
||||
}
|
||||
}
|
||||
func getSingleFlagValue(flag, val string) string {
|
||||
return fmt.Sprintf("--%s %s", flag, val)
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type LocalkubeBootstrapper struct {
|
||||
cmd bootstrapper.CommandRunner
|
||||
}
|
||||
|
||||
func NewLocalkubeBootstrapper(api libmachine.API) (*LocalkubeBootstrapper, error) {
|
||||
h, err := api.Load(config.GetMachineName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting api client")
|
||||
}
|
||||
var cmd bootstrapper.CommandRunner
|
||||
// The none driver executes commands directly on the host
|
||||
if h.Driver.DriverName() == constants.DriverNone {
|
||||
cmd = &bootstrapper.ExecRunner{}
|
||||
} else {
|
||||
client, err := sshutil.NewSSHClient(h.Driver)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting ssh client")
|
||||
}
|
||||
cmd = bootstrapper.NewSSHRunner(client)
|
||||
}
|
||||
return &LocalkubeBootstrapper{
|
||||
cmd: cmd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetClusterLogs
|
||||
// If follow is specified, it will tail the logs
|
||||
func (lk *LocalkubeBootstrapper) GetClusterLogsTo(follow bool, out io.Writer) error {
|
||||
logsCommand, err := GetLogsCommand(follow)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting logs command")
|
||||
}
|
||||
|
||||
if follow {
|
||||
err = lk.cmd.CombinedOutputTo(logsCommand, out)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting cluster logs")
|
||||
}
|
||||
} else {
|
||||
logs, err := lk.cmd.CombinedOutput(logsCommand)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting cluster logs")
|
||||
}
|
||||
fmt.Fprint(out, logs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetClusterStatus gets the status of localkube from the host VM.
|
||||
func (lk *LocalkubeBootstrapper) GetClusterStatus() (string, error) {
|
||||
s, err := lk.cmd.CombinedOutput(localkubeStatusCommand)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = strings.TrimSpace(s)
|
||||
if state.Running.String() == s {
|
||||
return state.Running.String(), nil
|
||||
} else if state.Stopped.String() == s {
|
||||
return state.Stopped.String(), nil
|
||||
} else {
|
||||
return "", fmt.Errorf("Error: Unrecognize output from GetLocalkubeStatus: %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
// StartCluster starts a k8s cluster on the specified Host.
|
||||
func (lk *LocalkubeBootstrapper) StartCluster(kubernetesConfig config.KubernetesConfig) error {
|
||||
startCommand, err := GetStartCommand(kubernetesConfig)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Error generating start command: %s", err)
|
||||
}
|
||||
err = lk.cmd.Run(startCommand) //needs to be sudo for none driver
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Error running ssh command: %s", startCommand)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lk *LocalkubeBootstrapper) RestartCluster(kubernetesConfig config.KubernetesConfig) error {
|
||||
return lk.StartCluster(kubernetesConfig)
|
||||
}
|
||||
|
||||
func (lk *LocalkubeBootstrapper) UpdateCluster(config config.KubernetesConfig) error {
|
||||
if config.ShouldLoadCachedImages {
|
||||
// Make best effort to load any cached images
|
||||
go machine.LoadImages(lk.cmd, constants.LocalkubeCachedImages, constants.ImageCacheDir)
|
||||
}
|
||||
|
||||
copyableFiles := []assets.CopyableFile{}
|
||||
var localkubeFile assets.CopyableFile
|
||||
var err error
|
||||
|
||||
//add url/file/bundled localkube to file list
|
||||
lCacher := localkubeCacher{config}
|
||||
localkubeFile, err = lCacher.fetchLocalkubeFromURI()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error updating localkube from uri")
|
||||
}
|
||||
copyableFiles = append(copyableFiles, localkubeFile)
|
||||
|
||||
// custom addons
|
||||
if err := assets.AddMinikubeDirAssets(©ableFiles); err != nil {
|
||||
return errors.Wrap(err, "adding minikube dir assets")
|
||||
}
|
||||
// bundled addons
|
||||
for _, addonBundle := range assets.Addons {
|
||||
if isEnabled, err := addonBundle.IsEnabled(); err == nil && isEnabled {
|
||||
for _, addon := range addonBundle.Assets {
|
||||
copyableFiles = append(copyableFiles, addon)
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range copyableFiles {
|
||||
if err := lk.cmd.Copy(f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lk *LocalkubeBootstrapper) SetupCerts(k8s config.KubernetesConfig) error {
|
||||
return bootstrapper.SetupCerts(lk.cmd, k8s)
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
download "github.com/jimmidyson/go-download"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// localkubeCacher is a struct with methods designed for caching localkube
|
||||
type localkubeCacher struct {
|
||||
k8sConf config.KubernetesConfig
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) getLocalkubeCacheFilepath() string {
|
||||
return filepath.Join(constants.GetMinipath(), "cache", "localkube",
|
||||
filepath.Base(url.QueryEscape("localkube-"+l.k8sConf.KubernetesVersion)))
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) getLocalkubeSha256CacheFilepath() string {
|
||||
return l.getLocalkubeCacheFilepath() + ".sha256"
|
||||
}
|
||||
|
||||
func localkubeURIWasSpecified(config config.KubernetesConfig) bool {
|
||||
// see if flag is different than default -> it was passed by user
|
||||
return config.KubernetesVersion != constants.DefaultKubernetesVersion
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) isLocalkubeCached() bool {
|
||||
url, err := util.GetLocalkubeDownloadURL(l.k8sConf.KubernetesVersion, constants.LocalkubeLinuxFilename)
|
||||
if err != nil {
|
||||
glog.Warningf("Unable to get localkube checksum url...continuing.")
|
||||
return true
|
||||
}
|
||||
opts := download.FileOptions{
|
||||
Mkdirs: download.MkdirAll,
|
||||
}
|
||||
|
||||
if err := download.ToFile(url+".sha256", l.getLocalkubeSha256CacheFilepath(), opts); err != nil {
|
||||
glog.Warningf("Unable to check localkube checksum... continuing.")
|
||||
return true
|
||||
}
|
||||
|
||||
if _, err := os.Stat(l.getLocalkubeCacheFilepath()); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
localkubeSha256, err := ioutil.ReadFile(l.getLocalkubeSha256CacheFilepath())
|
||||
if err != nil {
|
||||
glog.Infof("Error reading localkube checksum: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
h := sha256.New()
|
||||
f, err := os.Open(l.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
glog.Infof("Error opening localkube for checksum verification: %s", err)
|
||||
return false
|
||||
}
|
||||
if _, err := io.Copy(h, f); err != nil {
|
||||
glog.Infof("Error copying contents to hasher: %s", err)
|
||||
}
|
||||
|
||||
actualChecksum := hex.EncodeToString(h.Sum(nil))
|
||||
if strings.TrimSpace(string(localkubeSha256)) != actualChecksum {
|
||||
glog.Infof("Localkube checksums do not match actual: %s expected: %s", actualChecksum, string(localkubeSha256))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) downloadAndCacheLocalkube() error {
|
||||
url, err := util.GetLocalkubeDownloadURL(l.k8sConf.KubernetesVersion, constants.LocalkubeLinuxFilename)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting localkube download url")
|
||||
}
|
||||
opts := download.FileOptions{
|
||||
Mkdirs: download.MkdirAll,
|
||||
Options: download.Options{
|
||||
ProgressBars: &download.ProgressBarOptions{
|
||||
MaxWidth: 80,
|
||||
},
|
||||
},
|
||||
}
|
||||
fmt.Println("Downloading localkube binary")
|
||||
if err := download.ToFile(url, l.getLocalkubeCacheFilepath(), opts); err != nil {
|
||||
return errors.Wrap(err, "downloading localkube")
|
||||
}
|
||||
if err := download.ToFile(url+".sha256", l.getLocalkubeSha256CacheFilepath(), opts); err != nil {
|
||||
return errors.Wrap(err, "downloading localkube checksum")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) fetchLocalkubeFromURI() (assets.CopyableFile, error) {
|
||||
urlObj, err := url.Parse(l.k8sConf.KubernetesVersion)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error parsing --kubernetes-version url")
|
||||
}
|
||||
if urlObj.Scheme == constants.FileScheme {
|
||||
return l.genLocalkubeFileFromFile()
|
||||
}
|
||||
return l.genLocalkubeFileFromURL()
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) genLocalkubeFileFromURL() (assets.CopyableFile, error) {
|
||||
if !l.isLocalkubeCached() {
|
||||
glog.Infoln("Localkube not cached or checksum does not match, downloading...")
|
||||
if err := l.downloadAndCacheLocalkube(); err != nil {
|
||||
return nil, errors.Wrap(err, "Error attempting to download and cache localkube")
|
||||
}
|
||||
} else {
|
||||
glog.Infoln("Using cached localkube")
|
||||
}
|
||||
localkubeFile, err := assets.NewFileAsset(l.getLocalkubeCacheFilepath(), "/usr/local/bin", "localkube", "0777")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error creating localkube asset from url")
|
||||
}
|
||||
return localkubeFile, nil
|
||||
}
|
||||
|
||||
func (l *localkubeCacher) genLocalkubeFileFromFile() (assets.CopyableFile, error) {
|
||||
path := strings.TrimPrefix(l.k8sConf.KubernetesVersion, "file://")
|
||||
path = filepath.FromSlash(path)
|
||||
localkubeFile, err := assets.NewFileAsset(path, "/usr/local/bin", "localkube", "0777")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error creating localkube asset from file")
|
||||
}
|
||||
return localkubeFile, nil
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
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 localkube
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
func TestStartCluster(t *testing.T) {
|
||||
expectedStartCmd, err := GetStartCommand(config.KubernetesConfig{})
|
||||
if err != nil {
|
||||
t.Fatalf("generating start command: %s", err)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
description string
|
||||
startCmd string
|
||||
}{
|
||||
{
|
||||
description: "start cluster success",
|
||||
startCmd: expectedStartCmd,
|
||||
},
|
||||
{
|
||||
description: "start cluster failure",
|
||||
startCmd: "something else",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := bootstrapper.NewFakeCommandRunner()
|
||||
f.SetCommandToOutput(map[string]string{test.startCmd: "ok"})
|
||||
l := LocalkubeBootstrapper{f}
|
||||
err := l.StartCluster(config.KubernetesConfig{})
|
||||
if err != nil && test.startCmd == expectedStartCmd {
|
||||
t.Errorf("Error starting cluster: %s", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateCluster(t *testing.T) {
|
||||
defaultCfg := config.KubernetesConfig{
|
||||
KubernetesVersion: constants.DefaultKubernetesVersion,
|
||||
}
|
||||
defaultAddons := []string{
|
||||
"deploy/addons/kube-dns/kube-dns-cm.yaml",
|
||||
"deploy/addons/kube-dns/kube-dns-svc.yaml",
|
||||
"deploy/addons/addon-manager.yaml",
|
||||
"deploy/addons/dashboard/dashboard-rc.yaml",
|
||||
"deploy/addons/dashboard/dashboard-svc.yaml",
|
||||
"deploy/addons/storageclass/storageclass.yaml",
|
||||
"deploy/addons/kube-dns/kube-dns-controller.yaml",
|
||||
}
|
||||
cases := []struct {
|
||||
description string
|
||||
k8s config.KubernetesConfig
|
||||
expectedFiles []string
|
||||
shouldErr bool
|
||||
}{
|
||||
{
|
||||
description: "transfer localkube correct",
|
||||
k8s: defaultCfg,
|
||||
expectedFiles: []string{"out/localkube"},
|
||||
},
|
||||
{
|
||||
description: "addons are transferred",
|
||||
k8s: defaultCfg,
|
||||
expectedFiles: defaultAddons,
|
||||
},
|
||||
{
|
||||
description: "no localkube version",
|
||||
k8s: config.KubernetesConfig{},
|
||||
shouldErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := bootstrapper.NewFakeCommandRunner()
|
||||
l := LocalkubeBootstrapper{f}
|
||||
err := l.UpdateCluster(test.k8s)
|
||||
if err != nil && !test.shouldErr {
|
||||
t.Errorf("Error updating cluster: %s", err)
|
||||
return
|
||||
}
|
||||
if err == nil && test.shouldErr {
|
||||
t.Error("Didn't get error, but expected to")
|
||||
return
|
||||
}
|
||||
for _, expectedFile := range test.expectedFiles {
|
||||
_, err := f.GetFileToContents(expectedFile)
|
||||
if err != nil {
|
||||
t.Errorf("Expected file %s, but was not present", expectedFile)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLocalkubeStatus(t *testing.T) {
|
||||
cases := []struct {
|
||||
description string
|
||||
statusCmdMap map[string]string
|
||||
expectedStatus string
|
||||
shouldErr bool
|
||||
}{
|
||||
{
|
||||
description: "get status running",
|
||||
statusCmdMap: map[string]string{localkubeStatusCommand: "Running"},
|
||||
expectedStatus: "Running",
|
||||
},
|
||||
{
|
||||
description: "get status stopped",
|
||||
statusCmdMap: map[string]string{localkubeStatusCommand: "Stopped"},
|
||||
expectedStatus: "Stopped",
|
||||
},
|
||||
{
|
||||
description: "get status unknown status",
|
||||
statusCmdMap: map[string]string{localkubeStatusCommand: "Recalculating..."},
|
||||
shouldErr: true,
|
||||
},
|
||||
{
|
||||
description: "get status error",
|
||||
statusCmdMap: map[string]string{"a": "b"},
|
||||
shouldErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := bootstrapper.NewFakeCommandRunner()
|
||||
f.SetCommandToOutput(test.statusCmdMap)
|
||||
l := LocalkubeBootstrapper{f}
|
||||
actualStatus, err := l.GetClusterStatus()
|
||||
if err != nil && !test.shouldErr {
|
||||
t.Errorf("Error getting localkube status: %s", err)
|
||||
return
|
||||
}
|
||||
if err == nil && test.shouldErr {
|
||||
t.Error("Didn't get error, but expected to")
|
||||
return
|
||||
}
|
||||
if test.expectedStatus != actualStatus {
|
||||
t.Errorf("Expected status: %s, Actual status: %s", test.expectedStatus, actualStatus)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHostLogs(t *testing.T) {
|
||||
logs, err := GetLogsCommand(false)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting logs command: %s", err)
|
||||
}
|
||||
logsf, err := GetLogsCommand(true)
|
||||
if err != nil {
|
||||
t.Fatalf("Error gettings logs -f command: %s", err)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
description string
|
||||
logsCmdMap map[string]string
|
||||
follow bool
|
||||
shouldErr bool
|
||||
}{
|
||||
{
|
||||
description: "get logs correct",
|
||||
logsCmdMap: map[string]string{logs: "fee"},
|
||||
},
|
||||
{
|
||||
description: "follow logs correct",
|
||||
logsCmdMap: map[string]string{logsf: "fi"},
|
||||
follow: true,
|
||||
},
|
||||
{
|
||||
description: "get logs incorrect",
|
||||
logsCmdMap: map[string]string{"fo": "fum"},
|
||||
shouldErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
for _, test := range cases {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := bootstrapper.NewFakeCommandRunner()
|
||||
f.SetCommandToOutput(test.logsCmdMap)
|
||||
l := LocalkubeBootstrapper{f}
|
||||
err := l.GetClusterLogsTo(test.follow, &b)
|
||||
if err != nil && !test.shouldErr {
|
||||
t.Errorf("Error getting localkube logs: %s", err)
|
||||
return
|
||||
}
|
||||
if err == nil && test.shouldErr {
|
||||
t.Error("Didn't get error, but expected to")
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package localkube
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
Loading…
Reference in New Issue