Skip to content

Commit 005b553

Browse files
committed
support integration test
1 parent ee8a45f commit 005b553

File tree

15 files changed

+364
-97
lines changed

15 files changed

+364
-97
lines changed

.github/workflows/cover.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: actions/checkout@master
11-
- run: "make test-cover"
11+
- run: "make unit-test-cover"
1212
- uses: codecov/codecov-action@v2

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ vet: ## Run go vet against code.
5858
go vet ./...
5959

6060
.PHONY: lint
61-
lint: ## Run golangci-lint
61+
lint: golangci-lint ## Run golangci-lint
6262
$(GOLANGCI_LINT) run
6363

6464
CLUSTER_NAME := cappx-test
@@ -77,15 +77,25 @@ SETUP_ENVTEST_VER := v0.0.0-20211110210527-619e6b92dab9
7777
SETUP_ENVTEST := $(LOCALBIN)/setup-envtest
7878

7979
.PHONY: test
80-
test: manifests generate fmt $(SETUP_ENVTEST)
80+
test: generate manifests fmt $(SETUP_ENVTEST) ## Run unit and integration test
8181
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... $(TEST_ARGS)
8282

83+
.PHONY: unit-test ## Run unit tests
84+
unit-test: generate manifests fmt $(SETUP_ENVTEST)
85+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... --ginkgo.label-filter=unit $(TEST_ARGS)
86+
8387
.PHONY: test-cover
8488
test-cover: ## Run unit and integration tests and generate coverage report
8589
$(MAKE) test TEST_ARGS="$(TEST_ARGS) -coverprofile=coverage.out"
8690
go tool cover -func=coverage.out -o coverage.txt
8791
go tool cover -html=coverage.out -o coverage.html
8892

93+
.PHONY: unit-test-cover
94+
unit-test-cover: ## Run unit tests and generate coverage report
95+
$(MAKE) unit-test TEST_ARGS="$(TEST_ARGS) -coverprofile=coverage.out"
96+
go tool cover -func=coverage.out -o coverage.txt
97+
go tool cover -html=coverage.out -o coverage.html
98+
8999
##@ Build
90100

91101
.PHONY: build

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,22 @@ Because Proxmox-VE does not provide LBaaS solution, CAPPX does not follow the [t
102102

103103
ProxmoxMachine controller follows the [typical infra-machine logic](https://cluster-api.sigs.k8s.io/developer/providers/machine-infrastructure.html#behavior). To bootstrap your machine, CAPPX supports only `cloud-config` type bootstrap data secret. CAPPX is mainly tested with [KubeadmControlPlane](https://github.com/kubernetes-sigs/cluster-api/tree/main/controlplane/kubeadm) and [KubeadmBootstrap](https://github.com/kubernetes-sigs/cluster-api/tree/main/bootstrap/kubeadm).
104104

105+
## Development
106+
107+
### Testing
108+
#### Unit Testing
109+
```
110+
make unit-test
111+
```
112+
#### Unit and Integration Testing
113+
```
114+
export PROXMOX_URL=https://X.X.X.X:8006/api2/json
115+
export PROXMOX_PASSWORD=password
116+
export PROXMOX_USER=user@pam
117+
118+
make test
119+
```
120+
105121
## Contributing
106122

107123
Are you interested in contributing to cluster-api-provider-proxmox? Do not hesitate to open GitHub issues.

cloud/cloudinit/user_test.go

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
package cloudinit_test
22

33
import (
4-
"reflect"
54
"testing"
65

6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
79
infrav1 "github.com/sp-yduck/cluster-api-provider-proxmox/api/v1beta1"
810
"github.com/sp-yduck/cluster-api-provider-proxmox/cloud/cloudinit"
911
)
1012

11-
func TestParseUser(t *testing.T) {
12-
testYaml := `
13+
func TestCloudInit(t *testing.T) {
14+
RegisterFailHandler(Fail)
15+
RunSpecs(t, "CloudInit Suite")
16+
}
17+
18+
var _ = Describe("ParseUserDatas", Label("unit", "cloudinit"), func() {
19+
BeforeEach(func() {})
20+
AfterEach(func() {})
21+
22+
Context("correct format", func() {
23+
It("should no error", func() {
24+
testYaml := `
1325
write_files:
1426
- path: /run/kubeadm/kubeadm.yaml
1527
owner: root:root
@@ -22,52 +34,46 @@ runcmd:
2234
- "chmod +x /usr/local/bin/kubectl"
2335
- "reboot now"
2436
`
25-
_, err := cloudinit.ParseUserData(testYaml)
26-
if err != nil {
27-
t.Errorf("failed to parse user: %v", err)
28-
}
37+
userData, err := cloudinit.ParseUserData(testYaml)
38+
Expect(err).NotTo(HaveOccurred())
39+
Expect(userData).NotTo(BeNil())
40+
})
41+
})
2942

30-
testYaml = `
43+
Context("incorrect format", func() {
44+
It("should error", func() {
45+
testYaml := `
3146
write_files:
3247
- path: /run/kubeadm/kubeadm.yaml
3348
owner: root:root
3449
permissions: '0640'
3550
content: |
3651
asdfasdfasdf
3752
`
38-
user, err := cloudinit.ParseUserData(testYaml)
39-
if err == nil {
40-
t.Errorf("should returns an error. user=%v", *user)
41-
}
42-
}
53+
userData, err := cloudinit.ParseUserData(testYaml)
54+
Expect(err).To(HaveOccurred())
55+
Expect(userData).To(BeNil())
56+
})
57+
})
58+
})
4359

44-
func TestGenerateUserYaml(t *testing.T) {
45-
testYaml := `
46-
write_files:
47-
- path: /run/kubeadm/kubeadm.yaml
48-
owner: root:root
49-
permissions: '0640'
50-
content: |
51-
asdfasdfasdf
52-
runcmd:
53-
- 'kubeadm init --config /run/kubeadm/kubeadm.yaml && echo success > /run/cluster-api/bootstrap-success.complete'
54-
- "curl -L https://dl.k8s.io/release/v1.27.3/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl"
55-
- "chmod +x /usr/local/bin/kubectl"
56-
- "reboot now"
57-
`
60+
var _ = Describe("GenerateUserDataYaml", Label("unit", "cloudinit"), func() {
61+
BeforeEach(func() {})
62+
AfterEach(func() {})
5863

59-
uc, err := cloudinit.ParseUserData(testYaml)
60-
if err != nil {
61-
t.Fatalf("failed to parse user: %v", err)
62-
}
64+
Context("generate user-data yaml string", func() {
65+
It("should no error", func() {
66+
userData := infrav1.UserData{
67+
RunCmd: []string{"echo", "pwd"},
68+
}
69+
yaml, err := cloudinit.GenerateUserDataYaml(userData)
70+
Expect(err).NotTo(HaveOccurred())
71+
Expect(yaml).NotTo(BeNil())
72+
})
73+
})
74+
})
6375

64-
_, err = cloudinit.GenerateUserDataYaml(*uc)
65-
if err != nil {
66-
t.Fatalf("generate : %v", err)
67-
}
68-
}
69-
70-
func TestMergeUsers(t *testing.T) {
76+
var _ = Describe("MergeUserDatas", Label("unit", "cloudinit"), func() {
7177
a := infrav1.UserData{
7278
User: "override-user",
7379
RunCmd: []string{"command A", "command B"},
@@ -80,11 +86,8 @@ func TestMergeUsers(t *testing.T) {
8086
User: "override-user",
8187
RunCmd: []string{"command A", "command B", "command C"},
8288
}
89+
8390
c, err := cloudinit.MergeUserDatas(&a, &b)
84-
if err != nil {
85-
t.Errorf("failed to merge cloud init user data: %v", err)
86-
}
87-
if !reflect.DeepEqual(*c, expected) {
88-
t.Errorf("%v is expected to same as %v", *c, expected)
89-
}
90-
}
91+
Expect(err).NotTo(HaveOccurred())
92+
Expect(*c).To(Equal(expected))
93+
})
Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,68 @@
1-
package providerid
1+
package providerid_test
22

33
import (
44
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
9+
"github.com/sp-yduck/cluster-api-provider-proxmox/cloud/providerid"
510
)
611

7-
func TestNew(t *testing.T) {
8-
uuid := ""
9-
providerID, err := New(uuid)
10-
if err == nil {
11-
t.Errorf("err should not be nil. providerID=%s", providerID)
12-
}
13-
14-
uuid = "asdf"
15-
providerID, err = New(uuid)
16-
if err != nil || providerID.String() != "proxmox://asdf" {
17-
t.Errorf("failed to create providerID: %v", err)
18-
}
12+
func TestProviderID(t *testing.T) {
13+
RegisterFailHandler(Fail)
14+
RunSpecs(t, "ProviderID Suite")
1915
}
2016

21-
func TestUUID(t *testing.T) {
22-
pid := providerID{
23-
uuid: "asdf",
24-
}
25-
uuid := pid.UUID()
26-
if uuid != "asdf" {
27-
t.Errorf("should be asdf")
28-
}
29-
}
17+
var _ = Describe("New", Label("unit", "providerid"), func() {
18+
BeforeEach(func() {})
19+
AfterEach(func() {})
3020

31-
func TestString(t *testing.T) {
32-
pid := providerID{
33-
uuid: "asdf",
34-
}
35-
uuid := pid.String()
36-
if uuid != Prefix+"asdf" {
37-
t.Errorf("should be %sasdf", Prefix)
38-
}
39-
}
21+
Context("empty uuid", func() {
22+
It("should error", func() {
23+
uuid := ""
24+
_, err := providerid.New(uuid)
25+
Expect(err).To(HaveOccurred())
26+
})
27+
})
28+
29+
Context("non empty uuid", func() {
30+
It("should not error", func() {
31+
uuid := "asdf"
32+
providerID, err := providerid.New(uuid)
33+
Expect(err).NotTo(HaveOccurred())
34+
Expect(providerID.UUID()).To(Equal("asdf"))
35+
Expect(providerID.String()).To(Equal("proxmox://asdf"))
36+
})
37+
})
38+
})
39+
40+
var _ = Describe("UUID method", Label("unit", "providerid"), func() {
41+
pid, err := providerid.New("asdf")
42+
Expect(err).ToNot(HaveOccurred())
43+
44+
BeforeEach(func() {})
45+
AfterEach(func() {})
46+
47+
Context("uuid", func() {
48+
It("should not error", func() {
49+
uuid := pid.UUID()
50+
Expect(uuid).To(Equal("asdf"))
51+
})
52+
})
53+
})
54+
55+
var _ = Describe("String method", Label("unit", "providerid"), func() {
56+
pid, err := providerid.New("asdf")
57+
Expect(err).ToNot(HaveOccurred())
58+
59+
BeforeEach(func() {})
60+
AfterEach(func() {})
61+
62+
Context("string", func() {
63+
It("should not error", func() {
64+
providerID := pid.String()
65+
Expect(providerID).To(Equal("proxmox://asdf"))
66+
})
67+
})
68+
})

cloud/scope/clients_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ import (
1212
infrav1 "github.com/sp-yduck/cluster-api-provider-proxmox/api/v1beta1"
1313
)
1414

15-
var _ = Describe("newComputeService", func() {
16-
var (
17-
cluster *infrav1.ProxmoxCluster
18-
)
15+
var _ = Describe("newComputeService", Label("unit", "scope"), func() {
16+
var cluster *infrav1.ProxmoxCluster
1917

2018
Context("When SecretRef is not present in ProxmoxCluster", func() {
2119
BeforeEach(func() {

cloud/scope/suite_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package scope
22

33
import (
4-
// "os"
54
"path/filepath"
65
"testing"
76

cloud/services/compute/instance/cloudinit.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ func (s *Service) deleteCloudConfig(ctx context.Context) error {
4646
return storage.DeleteVolume(ctx, volumeID)
4747
}
4848

49+
// get cloud-config user datas from Secret and ProxmoxMachine
50+
// then merge them and set merged user data file to Proxmox Storage
4951
func (s *Service) reconcileCloudInitUser(ctx context.Context) error {
5052
log := log.FromContext(ctx)
5153

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package storage
2+
3+
import (
4+
"github.com/sp-yduck/proxmox-go/api"
5+
)
6+
7+
func GenerateVMStorageOptions(scope Scope) api.StorageCreateOptions {
8+
return generateVMStorageOptions(scope)
9+
}

cloud/services/compute/storage/reconcile.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,19 @@ func (s *Service) Reconcile(ctx context.Context) error {
3030
}
3131

3232
func (s *Service) Delete(ctx context.Context) error {
33+
log := log.FromContext(ctx)
34+
log.Info("Deleteing storage")
3335
return s.deleteStorage(ctx)
3436
}
3537

3638
// createOrGetStorage gets Proxmox Storage for VMs
3739
func (s *Service) createOrGetStorage(ctx context.Context) error {
40+
log := log.FromContext(ctx)
3841
opts := generateVMStorageOptions(s.scope)
3942
if err := s.getStorage(ctx, opts.Storage); err != nil {
4043
if rest.IsNotFound(err) {
41-
if err := s.createStorage(ctx, opts); err != nil {
42-
return err
43-
}
44+
log.Info("storage %s not found. it will be created")
45+
return s.createStorage(ctx, opts)
4446
}
4547
return err
4648
}
@@ -65,18 +67,22 @@ func (s *Service) createStorage(ctx context.Context, options api.StorageCreateOp
6567

6668
func (s *Service) deleteStorage(ctx context.Context) error {
6769
log := log.FromContext(ctx)
68-
nodes, err := s.client.Nodes(ctx)
70+
71+
var storage *proxmox.Storage
72+
storage, err := s.client.Storage(ctx, s.scope.Storage().Name)
6973
if err != nil {
74+
if rest.IsNotFound(err) {
75+
log.Info("storage not found or already deleted")
76+
return nil
77+
}
7078
return err
7179
}
7280

73-
var storage *proxmox.Storage
81+
nodes, err := s.client.Nodes(ctx)
82+
if err != nil {
83+
return err
84+
}
7485
for _, node := range nodes {
75-
storage, err = s.client.Storage(ctx, s.scope.Storage().Name)
76-
if err != nil {
77-
log.Info(err.Error())
78-
continue
79-
}
8086
storage.Node = node.Node
8187

8288
// check if storage is empty
@@ -91,7 +97,6 @@ func (s *Service) deleteStorage(ctx context.Context) error {
9197

9298
// delete
9399
if err := storage.Delete(ctx); err != nil {
94-
log.Info(err.Error())
95100
return err
96101
}
97102
return nil

0 commit comments

Comments
 (0)