mirror of https://github.com/kubernetes/kops.git
kubetest2 - Add manifest template support
I'm updating the test-e2e make target as I go to make the presubmit job use it but soon I'll work on how we'll actually configure and invoke kubetest2 from our variety of jobs
This commit is contained in:
parent
695be2666c
commit
196e678205
1
Makefile
1
Makefile
|
|
@ -198,6 +198,7 @@ test-e2e:
|
||||||
--cloud-provider=aws \
|
--cloud-provider=aws \
|
||||||
--kops-binary-path=/home/prow/go/src/k8s.io/kops/bazel-bin/cmd/kops/linux-amd64/kops \
|
--kops-binary-path=/home/prow/go/src/k8s.io/kops/bazel-bin/cmd/kops/linux-amd64/kops \
|
||||||
--kubernetes-version=v1.19.4 \
|
--kubernetes-version=v1.19.4 \
|
||||||
|
--template-path=tests/e2e/templates/simple.yaml.tmpl \
|
||||||
--test=kops \
|
--test=kops \
|
||||||
-- \
|
-- \
|
||||||
--test-package-version=v1.19.4 \
|
--test-package-version=v1.19.4 \
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ go 1.15
|
||||||
require (
|
require (
|
||||||
github.com/octago/sflags v0.2.0
|
github.com/octago/sflags v0.2.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
k8s.io/klog/v2 v2.4.0
|
k8s.io/klog/v2 v2.4.0
|
||||||
sigs.k8s.io/kubetest2 v0.0.0-20201130212850-d9dad7c8699c
|
sigs.k8s.io/kubetest2 v0.0.0-20201130212850-d9dad7c8699c
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1493,6 +1493,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,10 @@ func (d *deployer) verifyKopsFlags() error {
|
||||||
return errors.New("unsupported --cloud-provider value")
|
return errors.New("unsupported --cloud-provider value")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.StateStore == "" {
|
||||||
|
d.StateStore = stateStore(d.CloudProvider)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +98,7 @@ func (d *deployer) env() []string {
|
||||||
vars = append(vars, []string{
|
vars = append(vars, []string{
|
||||||
fmt.Sprintf("PATH=%v", os.Getenv("PATH")),
|
fmt.Sprintf("PATH=%v", os.Getenv("PATH")),
|
||||||
fmt.Sprintf("HOME=%v", os.Getenv("HOME")),
|
fmt.Sprintf("HOME=%v", os.Getenv("HOME")),
|
||||||
fmt.Sprintf("KOPS_STATE_STORE=%v", stateStore(d.CloudProvider)),
|
fmt.Sprintf("KOPS_STATE_STORE=%v", d.StateStore),
|
||||||
fmt.Sprintf("KOPS_FEATURE_FLAGS=%v", d.featureFlags()),
|
fmt.Sprintf("KOPS_FEATURE_FLAGS=%v", d.featureFlags()),
|
||||||
"KOPS_RUN_TOO_NEW_VERSION=1",
|
"KOPS_RUN_TOO_NEW_VERSION=1",
|
||||||
}...)
|
}...)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ type deployer struct {
|
||||||
KopsBinaryPath string `flag:"kops-binary-path" desc:"The path to kops executable used for testing"`
|
KopsBinaryPath string `flag:"kops-binary-path" desc:"The path to kops executable used for testing"`
|
||||||
StateStore string `flag:"-"`
|
StateStore string `flag:"-"`
|
||||||
|
|
||||||
|
TemplatePath string `flag:"template-path" desc:"The path to the manifest template used for cluster creation"`
|
||||||
|
|
||||||
KubernetesVersion string `flag:"kubernetes-version" desc:"The kubernetes version to use in the cluster"`
|
KubernetesVersion string `flag:"kubernetes-version" desc:"The kubernetes version to use in the cluster"`
|
||||||
|
|
||||||
SSHPrivateKeyPath string `flag:"ssh-private-key" desc:"The path to the private key used for SSH access to instances"`
|
SSHPrivateKeyPath string `flag:"ssh-private-key" desc:"The path to the private key used for SSH access to instances"`
|
||||||
|
|
@ -58,6 +60,9 @@ type deployer struct {
|
||||||
AdminAccess string `flag:"admin-access" desc:"The CIDR to restrict kubernetes API access"`
|
AdminAccess string `flag:"admin-access" desc:"The CIDR to restrict kubernetes API access"`
|
||||||
|
|
||||||
BuildOptions *builder.BuildOptions
|
BuildOptions *builder.BuildOptions
|
||||||
|
|
||||||
|
// manifestPath is the location of the rendered manifest based on TemplatePath
|
||||||
|
manifestPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// assert that New implements types.NewDeployer
|
// assert that New implements types.NewDeployer
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 deployer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
"sigs.k8s.io/kubetest2/pkg/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// replace performs a `kops replace` followed by `kops update cluster --yes`
|
||||||
|
func (d *deployer) replace() error {
|
||||||
|
args := []string{
|
||||||
|
d.KopsBinaryPath, "replace",
|
||||||
|
"--filename", d.manifestPath,
|
||||||
|
"--force",
|
||||||
|
"--name", d.ClusterName,
|
||||||
|
}
|
||||||
|
klog.Info(strings.Join(args, " "))
|
||||||
|
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.SetEnv(d.env()...)
|
||||||
|
|
||||||
|
exec.InheritOutput(cmd)
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{
|
||||||
|
d.KopsBinaryPath, "create", "secret", "sshpublickey",
|
||||||
|
"admin",
|
||||||
|
"-i", d.SSHPublicKeyPath,
|
||||||
|
"--name", d.ClusterName,
|
||||||
|
}
|
||||||
|
klog.Info(strings.Join(args, " "))
|
||||||
|
cmd = exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.SetEnv(d.env()...)
|
||||||
|
|
||||||
|
exec.InheritOutput(cmd)
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{
|
||||||
|
d.KopsBinaryPath, "update", "cluster", "--yes",
|
||||||
|
"--name", d.ClusterName,
|
||||||
|
}
|
||||||
|
klog.Info(strings.Join(args, " "))
|
||||||
|
|
||||||
|
cmd = exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.SetEnv(d.env()...)
|
||||||
|
|
||||||
|
exec.InheritOutput(cmd)
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 deployer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
"sigs.k8s.io/kubetest2/pkg/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// renderTemplate will render the manifest template with the provided values,
|
||||||
|
// setting the deployer's manifestPath
|
||||||
|
func (d *deployer) renderTemplate(values map[string]interface{}) error {
|
||||||
|
dir, err := ioutil.TempDir("", "kops-template")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
valuesBytes, err := yaml.Marshal(values)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
valuesPath := path.Join(dir, "values.yaml")
|
||||||
|
ioutil.WriteFile(valuesPath, valuesBytes, 0644)
|
||||||
|
|
||||||
|
manifestPath := path.Join(dir, "manifest.yaml")
|
||||||
|
d.manifestPath = manifestPath
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
d.KopsBinaryPath, "toolbox", "template",
|
||||||
|
"--template", d.TemplatePath,
|
||||||
|
"--output", manifestPath,
|
||||||
|
"--values", valuesPath,
|
||||||
|
}
|
||||||
|
klog.Info(strings.Join(args, " "))
|
||||||
|
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.SetEnv(d.env()...)
|
||||||
|
|
||||||
|
exec.InheritOutput(cmd)
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *deployer) templateValues(zones []string, publicIP string) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"cloudProvider": d.CloudProvider,
|
||||||
|
"clusterName": d.ClusterName,
|
||||||
|
"kubernetesVersion": d.KubernetesVersion,
|
||||||
|
"publicIP": publicIP,
|
||||||
|
"stateStore": d.StateStore,
|
||||||
|
"zones": zones,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package deployer
|
package deployer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
osexec "os/exec"
|
osexec "os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -43,6 +44,38 @@ func (d *deployer) Up() error {
|
||||||
adminAccess = publicIP
|
adminAccess = publicIP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zones, err := d.zones()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.TemplatePath != "" {
|
||||||
|
values := d.templateValues(zones, adminAccess)
|
||||||
|
if err := d.renderTemplate(values); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.replace(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := d.createCluster(zones, adminAccess)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isUp, err := d.IsUp()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if isUp {
|
||||||
|
klog.V(1).Infof("cluster reported as up")
|
||||||
|
} else {
|
||||||
|
klog.Errorf("cluster reported as down")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *deployer) createCluster(zones []string, adminAccess string) error {
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
d.KopsBinaryPath, "create", "cluster",
|
d.KopsBinaryPath, "create", "cluster",
|
||||||
"--name", d.ClusterName,
|
"--name", d.ClusterName,
|
||||||
|
|
@ -83,20 +116,10 @@ func (d *deployer) Up() error {
|
||||||
cmd.SetEnv(d.env()...)
|
cmd.SetEnv(d.env()...)
|
||||||
|
|
||||||
exec.InheritOutput(cmd)
|
exec.InheritOutput(cmd)
|
||||||
err = cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
isUp, err := d.IsUp()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if isUp {
|
|
||||||
klog.V(1).Infof("cluster reported as up")
|
|
||||||
} else {
|
|
||||||
klog.Errorf("cluster reported as down")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,3 +156,13 @@ func (d *deployer) verifyUpFlags() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *deployer) zones() ([]string, error) {
|
||||||
|
switch d.CloudProvider {
|
||||||
|
case "aws":
|
||||||
|
return aws.RandomZones(1)
|
||||||
|
case "gce":
|
||||||
|
return gce.RandomZones(1)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unsupported CloudProvider: %v", d.CloudProvider)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
{{$zone := index .zones 0}}
|
||||||
|
apiVersion: kops.k8s.io/v1alpha2
|
||||||
|
kind: Cluster
|
||||||
|
metadata:
|
||||||
|
name: {{.clusterName}}
|
||||||
|
spec:
|
||||||
|
kubernetesApiAccess:
|
||||||
|
- {{.publicIP}}
|
||||||
|
channel: stable
|
||||||
|
cloudProvider: {{.cloudProvider}}
|
||||||
|
configBase: "{{.stateStore}}/{{.clusterName}}"
|
||||||
|
etcdClusters:
|
||||||
|
- etcdMembers:
|
||||||
|
- instanceGroup: master-{{$zone}}
|
||||||
|
name: {{$zone}}
|
||||||
|
name: main
|
||||||
|
- etcdMembers:
|
||||||
|
- instanceGroup: master-{{$zone}}
|
||||||
|
name: {{$zone}}
|
||||||
|
name: events
|
||||||
|
iam: {}
|
||||||
|
kubelet:
|
||||||
|
anonymousAuth: false
|
||||||
|
kubernetesVersion: {{.kubernetesVersion}}
|
||||||
|
masterInternalName: api.internal.{{.clusterName}}
|
||||||
|
masterPublicName: api.{{.clusterName}}
|
||||||
|
networkCIDR: 172.20.0.0/16
|
||||||
|
networking:
|
||||||
|
kubenet: {}
|
||||||
|
nodePortAccess:
|
||||||
|
- 0.0.0.0/0
|
||||||
|
nonMasqueradeCIDR: 100.64.0.0/10
|
||||||
|
sshAccess:
|
||||||
|
- {{.publicIP}}
|
||||||
|
topology:
|
||||||
|
masters: public
|
||||||
|
nodes: public
|
||||||
|
subnets:
|
||||||
|
- cidr: 172.20.32.0/19
|
||||||
|
name: {{$zone}}
|
||||||
|
type: Public
|
||||||
|
zone: {{$zone}}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: kops.k8s.io/v1alpha2
|
||||||
|
kind: InstanceGroup
|
||||||
|
metadata:
|
||||||
|
name: nodes-{{$zone}}
|
||||||
|
labels:
|
||||||
|
kops.k8s.io/cluster: {{.clusterName}}
|
||||||
|
spec:
|
||||||
|
associatePublicIp: true
|
||||||
|
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201112.1
|
||||||
|
machineType: t3.medium
|
||||||
|
maxSize: 4
|
||||||
|
minSize: 4
|
||||||
|
role: Node
|
||||||
|
subnets:
|
||||||
|
- {{$zone}}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: kops.k8s.io/v1alpha2
|
||||||
|
kind: InstanceGroup
|
||||||
|
metadata:
|
||||||
|
name: master-{{$zone}}
|
||||||
|
labels:
|
||||||
|
kops.k8s.io/cluster: {{.clusterName}}
|
||||||
|
spec:
|
||||||
|
associatePublicIp: true
|
||||||
|
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201112.1
|
||||||
|
machineType: c5.large
|
||||||
|
maxSize: 1
|
||||||
|
minSize: 1
|
||||||
|
role: Master
|
||||||
|
subnets:
|
||||||
|
- {{$zone}}
|
||||||
|
|
||||||
Loading…
Reference in New Issue