Skip to content

Commit 2c5b485

Browse files
authored
Merge pull request #364 from CecileRobertMichon/e2e-tests-improvements
Add 3 control plane cluster E2E test
2 parents c3cb013 + 4396e97 commit 2c5b485

File tree

9 files changed

+754
-384
lines changed

9 files changed

+754
-384
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,6 @@ bazel-*
4949

5050
# Tilt files.
5151
.tiltbuild
52+
53+
# junit output
54+
test/e2e/junit.e2e_suite.*.xml

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ test-integration: ## Run integration tests
9393
test-e2e: ## Run e2e tests
9494
PULL_POLICY=IfNotPresent $(MAKE) docker-build
9595
MANAGER_IMAGE=$(CONTROLLER_IMG)-$(ARCH):$(TAG) \
96-
go test ./test/e2e -v -tags=e2e -ginkgo.v -ginkgo.trace -count=1 -timeout=30m
96+
go test ./test/e2e -v -tags=e2e -ginkgo.v -ginkgo.trace -count=1 -timeout=60m
9797

9898
$(KUBECTL) $(KUBE_APISERVER) $(ETCD): ## install test asset kubectl, kube-apiserver, etcd
9999
source ./scripts/fetch_ext_bins.sh && fetch_tools

test/e2e/azure_suite_test.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
1818

19-
package e2e_test
19+
package e2e
2020

2121
import (
2222
"bufio"
@@ -54,23 +54,13 @@ func TestE2E(t *testing.T) {
5454
junitReporter := reporters.NewJUnitReporter(junitPath)
5555

5656
RegisterFailHandler(Fail)
57-
RunSpecsWithDefaultAndCustomReporters(t, "CAPZ e2e suite", []Reporter{junitReporter})
57+
RunSpecsWithDefaultAndCustomReporters(t, "capz e2e suite", []Reporter{junitReporter})
5858
}
5959

6060
var (
6161
ctx = context.Background()
6262
creds auth.Creds
6363
mgmt *kind.Cluster
64-
65-
// TODO Parameterize some of these variables
66-
location = "westus2"
67-
vmSize = "Standard_B2ms"
68-
namespace = "default"
69-
k8sVersion = "v1.16.2"
70-
imageOffer = "capi"
71-
imagePublisher = "cncf-upstream"
72-
imageSKU = "k8s-1dot16-ubuntu-1804"
73-
imageVersion = "latest"
7464
)
7565

7666
var _ = BeforeSuite(func() {

test/e2e/azure_test.go

Lines changed: 43 additions & 250 deletions
Original file line numberDiff line numberDiff line change
@@ -16,277 +16,70 @@ See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
1818

19-
package e2e_test
19+
package e2e
2020

2121
import (
22-
"crypto/rand"
23-
"crypto/rsa"
24-
"encoding/base64"
25-
"fmt"
2622
"time"
2723

2824
. "github.com/onsi/ginkgo"
29-
. "github.com/onsi/gomega"
3025

31-
"github.com/pkg/errors"
32-
"golang.org/x/crypto/ssh"
33-
corev1 "k8s.io/api/core/v1"
34-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35-
bootstrapv1 "sigs.k8s.io/cluster-api-bootstrap-provider-kubeadm/api/v1alpha2"
36-
kubeadmv1beta1 "sigs.k8s.io/cluster-api-bootstrap-provider-kubeadm/kubeadm/v1beta1"
3726
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1alpha2"
3827
"sigs.k8s.io/cluster-api-provider-azure/test/e2e/framework"
3928
capiv1 "sigs.k8s.io/cluster-api/api/v1alpha2"
40-
"sigs.k8s.io/cluster-api/util"
4129
)
4230

4331
var _ = Describe("CAPZ e2e tests", func() {
4432
Describe("Cluster creation", func() {
4533

46-
clusterGen := &ClusterGenerator{}
47-
nodeGen := &NodeGenerator{}
34+
var (
35+
clusterGen *ClusterGenerator
36+
nodeGen *NodeGenerator
37+
cluster *capiv1.Cluster
38+
infraCluster *infrav1.AzureCluster
39+
machineDeploymentGen = &MachineDeploymentGenerator{}
40+
)
41+
42+
BeforeEach(func() {
43+
clusterGen = &ClusterGenerator{}
44+
nodeGen = &NodeGenerator{}
45+
cluster, infraCluster = clusterGen.GenerateCluster(namespace)
46+
})
4847

49-
Context("Create one controlplane cluster", func() {
50-
It("Should create a single node cluster and delete it before exiting", func() {
51-
cluster, infraCluster := clusterGen.GenerateCluster(namespace)
52-
node := nodeGen.GenerateNode(cluster.GetName())
53-
OneNodeCluster(&OneNodeClusterInput{
48+
AfterEach(func() {
49+
By("cleaning up e2e resources")
50+
framework.CleanUp(&framework.CleanUpInput{
51+
Management: mgmt,
52+
Cluster: cluster,
53+
DeleteTimeout: 20 * time.Minute,
54+
})
55+
})
56+
57+
Context("Create single controlplane cluster", func() {
58+
It("Should create a single node cluster", func() {
59+
nodes := []framework.Node{nodeGen.GenerateNode(creds, cluster.GetName())}
60+
ControlPlaneCluster(&ControlPlaneClusterInput{
5461
Management: mgmt,
5562
Cluster: cluster,
5663
InfraCluster: infraCluster,
57-
Node: node,
58-
CreateTimeout: 60 * time.Minute,
59-
})
60-
framework.CleanUp(&framework.CleanUpInput{
61-
Management: mgmt,
62-
Cluster: cluster,
64+
Nodes: nodes,
65+
CreateTimeout: 30 * time.Minute,
6366
})
6467
})
6568
})
6669

67-
// TODO: Deploy multiple Control Plane
68-
// TODO: Deploy Addons
69-
// TODO: Deploy MachineDeployments
70-
// TODO: Scale up
71-
// TODO: Scale down
70+
Context("Create multiple controlplane cluster with machine deployments", func() {
71+
It("Should create a 3 node cluster", func() {
72+
nodes := []framework.Node{nodeGen.GenerateNode(creds, cluster.GetName()), nodeGen.GenerateNode(creds, cluster.GetName()), nodeGen.GenerateNode(creds, cluster.GetName())}
73+
machineDeployment := machineDeploymentGen.Generate(creds, cluster.GetNamespace(), cluster.GetName(), 1)
74+
ControlPlaneCluster(&ControlPlaneClusterInput{
75+
Management: mgmt,
76+
Cluster: cluster,
77+
InfraCluster: infraCluster,
78+
Nodes: nodes,
79+
MachineDeployment: machineDeployment,
80+
CreateTimeout: 30 * time.Minute,
81+
})
82+
})
83+
})
7284
})
7385
})
74-
75-
type ClusterGenerator struct{}
76-
77-
func (c *ClusterGenerator) GenerateCluster(namespace string) (*capiv1.Cluster, *infrav1.AzureCluster) {
78-
name := "capz-" + util.RandomString(6)
79-
vnetName := name + "-vnet"
80-
infraCluster := &infrav1.AzureCluster{
81-
ObjectMeta: metav1.ObjectMeta{
82-
Namespace: namespace,
83-
Name: name,
84-
},
85-
Spec: infrav1.AzureClusterSpec{
86-
Location: location,
87-
ResourceGroup: name,
88-
NetworkSpec: infrav1.NetworkSpec{
89-
Vnet: infrav1.VnetSpec{Name: vnetName},
90-
},
91-
},
92-
}
93-
cluster := &capiv1.Cluster{
94-
ObjectMeta: metav1.ObjectMeta{
95-
Namespace: namespace,
96-
Name: name,
97-
},
98-
Spec: capiv1.ClusterSpec{
99-
ClusterNetwork: &capiv1.ClusterNetwork{
100-
Pods: &capiv1.NetworkRanges{CIDRBlocks: []string{"192.168.0.0/16"}},
101-
},
102-
InfrastructureRef: &corev1.ObjectReference{
103-
APIVersion: infrav1.GroupVersion.String(),
104-
Kind: framework.TypeToKind(infraCluster),
105-
Namespace: infraCluster.GetNamespace(),
106-
Name: infraCluster.GetName(),
107-
},
108-
},
109-
}
110-
return cluster, infraCluster
111-
}
112-
113-
type NodeGenerator struct {
114-
counter int
115-
}
116-
117-
func (n *NodeGenerator) GenerateNode(clusterName string) framework.Node {
118-
sshkey, err := sshkey()
119-
Expect(err).NotTo(HaveOccurred())
120-
121-
firstControlPlane := n.counter == 0
122-
name := fmt.Sprintf("%s-controlplane-%d", clusterName, n.counter)
123-
n.counter++
124-
125-
infraMachine := &infrav1.AzureMachine{
126-
ObjectMeta: metav1.ObjectMeta{
127-
Namespace: namespace,
128-
Name: name,
129-
},
130-
Spec: infrav1.AzureMachineSpec{
131-
VMSize: vmSize,
132-
Location: location,
133-
SSHPublicKey: sshkey,
134-
Image: &infrav1.Image{
135-
Offer: &imageOffer,
136-
Publisher: &imagePublisher,
137-
SKU: &imageSKU,
138-
Version: &imageVersion,
139-
},
140-
OSDisk: infrav1.OSDisk{
141-
DiskSizeGB: 30,
142-
OSType: "Linux",
143-
ManagedDisk: infrav1.ManagedDisk{
144-
StorageAccountType: "Premium_LRS",
145-
},
146-
},
147-
},
148-
}
149-
bootstrapConfig := &bootstrapv1.KubeadmConfig{
150-
ObjectMeta: metav1.ObjectMeta{
151-
Namespace: namespace,
152-
Name: name,
153-
},
154-
Spec: bootstrapv1.KubeadmConfigSpec{
155-
Files: []bootstrapv1.File{
156-
{
157-
Owner: "root:root",
158-
Path: "/etc/kubernetes/azure.json",
159-
Permissions: "0644",
160-
Content: cloudConfig(clusterName),
161-
},
162-
},
163-
InitConfiguration: &kubeadmv1beta1.InitConfiguration{},
164-
JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{},
165-
},
166-
}
167-
registrationOptions := kubeadmv1beta1.NodeRegistrationOptions{
168-
Name: "{{ ds.meta_data[\"local_hostname\"] }}",
169-
KubeletExtraArgs: map[string]string{
170-
"cloud-provider": "azure",
171-
"cloud-config": "/etc/kubernetes/azure.json",
172-
},
173-
}
174-
175-
if firstControlPlane {
176-
cpInitConfiguration(bootstrapConfig, registrationOptions)
177-
} else {
178-
cpJoinConfiguration(bootstrapConfig, registrationOptions)
179-
}
180-
181-
machine := &capiv1.Machine{
182-
ObjectMeta: metav1.ObjectMeta{
183-
Namespace: namespace,
184-
Name: name,
185-
Labels: map[string]string{
186-
capiv1.MachineControlPlaneLabelName: "true",
187-
capiv1.MachineClusterLabelName: clusterName,
188-
},
189-
},
190-
Spec: capiv1.MachineSpec{
191-
Bootstrap: capiv1.Bootstrap{
192-
ConfigRef: &corev1.ObjectReference{
193-
APIVersion: bootstrapv1.GroupVersion.String(),
194-
Kind: framework.TypeToKind(bootstrapConfig),
195-
Namespace: bootstrapConfig.GetNamespace(),
196-
Name: bootstrapConfig.GetName(),
197-
},
198-
},
199-
InfrastructureRef: corev1.ObjectReference{
200-
APIVersion: infrav1.GroupVersion.String(),
201-
Kind: framework.TypeToKind(infraMachine),
202-
Namespace: infraMachine.GetNamespace(),
203-
Name: infraMachine.GetName(),
204-
},
205-
Version: &k8sVersion,
206-
},
207-
}
208-
return framework.Node{
209-
Machine: machine,
210-
InfraMachine: infraMachine,
211-
BootstrapConfig: bootstrapConfig,
212-
}
213-
}
214-
215-
func cloudConfig(cn string) string {
216-
// TODO This is ugly
217-
return fmt.Sprintf(`{
218-
"cloud": "AzurePublicCloud",
219-
"tenantId": "%s",
220-
"subscriptionId": "%s",
221-
"aadClientId": "%s",
222-
"aadClientSecret": "%s",
223-
"resourceGroup": "%s",
224-
"securityGroupName": "%s-controlplane-nsg",
225-
"location": "westus2",
226-
"vmType": "standard",
227-
"vnetName": "%s-vnet",
228-
"vnetResourceGroup": "%s",
229-
"subnetName": "%s-controlplane-subnet",
230-
"routeTableName": "%s-node-routetable",
231-
"userAssignedID": "%s",
232-
"loadBalancerSku": "standard",
233-
"maximumLoadBalancerRuleCount": 250,
234-
"useManagedIdentityExtension": false,
235-
"useInstanceMetadata": true
236-
}`, creds.TenantID, creds.SubscriptionID, creds.ClientID, creds.ClientSecret, cn, cn, cn, cn, cn, cn, cn)
237-
}
238-
239-
func sshkey() (string, error) {
240-
// TODO Load from AZURE_SSH_PUBLIC_KEY_FILE if set
241-
prv, err := rsa.GenerateKey(rand.Reader, 2048)
242-
if err != nil {
243-
return "", errors.Wrap(err, "Failed to generate private key")
244-
}
245-
pub, err := ssh.NewPublicKey(&prv.PublicKey)
246-
if err != nil {
247-
return "", errors.Wrap(err, "Failed to generate public key")
248-
}
249-
return base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(pub)), nil
250-
}
251-
252-
func cpInitConfiguration(kubeadmConfig *bootstrapv1.KubeadmConfig, registrationOptions kubeadmv1beta1.NodeRegistrationOptions) {
253-
kubeadmConfig.Spec.ClusterConfiguration = &kubeadmv1beta1.ClusterConfiguration{
254-
APIServer: kubeadmv1beta1.APIServer{
255-
ControlPlaneComponent: kubeadmv1beta1.ControlPlaneComponent{
256-
ExtraArgs: map[string]string{
257-
"cloud-provider": "azure",
258-
"cloud-config": "/etc/kubernetes/azure.json",
259-
},
260-
ExtraVolumes: []kubeadmv1beta1.HostPathMount{
261-
{
262-
Name: "cloud-config",
263-
HostPath: "/etc/kubernetes/azure.json",
264-
MountPath: "/etc/kubernetes/azure.json",
265-
ReadOnly: true,
266-
},
267-
},
268-
},
269-
TimeoutForControlPlane: &metav1.Duration{Duration: 20 * time.Minute},
270-
},
271-
ControllerManager: kubeadmv1beta1.ControlPlaneComponent{
272-
ExtraArgs: map[string]string{
273-
"allocate-node-cidrs": "false",
274-
"cloud-provider": "azure",
275-
"cloud-config": "/etc/kubernetes/azure.json",
276-
},
277-
ExtraVolumes: []kubeadmv1beta1.HostPathMount{
278-
{
279-
Name: "cloud-config",
280-
HostPath: "/etc/kubernetes/azure.json",
281-
MountPath: "/etc/kubernetes/azure.json",
282-
ReadOnly: true,
283-
},
284-
},
285-
},
286-
}
287-
kubeadmConfig.Spec.InitConfiguration = &kubeadmv1beta1.InitConfiguration{NodeRegistration: registrationOptions}
288-
}
289-
290-
func cpJoinConfiguration(kubeadmConfig *bootstrapv1.KubeadmConfig, registrationOptions kubeadmv1beta1.NodeRegistrationOptions) {
291-
kubeadmConfig.Spec.JoinConfiguration = &kubeadmv1beta1.JoinConfiguration{NodeRegistration: registrationOptions, ControlPlane: nil}
292-
}

0 commit comments

Comments
 (0)