diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 67023b07..3b8593fe 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -35,12 +35,12 @@ concurrency: jobs: build: if: github.repository == 'apache/cloudstack-kubernetes-provider' - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: Set Docker repository name run: echo "DOCKER_REPOSITORY=apache" >> $GITHUB_ENV - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c1e0f2e..4fafb4e2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,13 +25,13 @@ concurrency: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: go.mod diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 76364914..ed7750bd 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -30,9 +30,9 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: go-version-file: go.mod - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v9 diff --git a/.golangci.yml b/.golangci.yml index 5bc9b136..eaf3d813 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,53 +1,50 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -linters-settings: - goheader: - template: |- - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - +version: "2" +run: + modules-download-mode: readonly + issues-exit-code: 1 linters: enable: - goheader - gosec - - gosimple + - misspell - govet - ineffassign - - misspell - staticcheck - - typecheck - unused - -run: - modules-download-mode: readonly - timeout: 5m - issues-exit-code: 1 + settings: + goheader: + template: |- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Dockerfile b/Dockerfile index ba02c0dc..7b8145a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,8 +19,13 @@ FROM --platform=$BUILDPLATFORM golang:1.23 AS builder ARG BUILDPLATFORM ARG TARGETOS ARG TARGETARCH -COPY . /go/src/github.com/apache/cloudstack-kubernetes-provider + WORKDIR /go/src/github.com/apache/cloudstack-kubernetes-provider +COPY go.mod /go/src/github.com/apache/cloudstack-kubernetes-provider/go.mod +COPY go.sum /go/src/github.com/apache/cloudstack-kubernetes-provider/go.sum +RUN go mod download + +COPY . /go/src/github.com/apache/cloudstack-kubernetes-provider RUN make clean && CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} make FROM gcr.io/distroless/static:nonroot diff --git a/Makefile b/Makefile index aebd9ff7..01a70e0c 100644 --- a/Makefile +++ b/Makefile @@ -42,14 +42,21 @@ clean: cloudstack-ccm: ${CMD_SRC} go build -ldflags ${LDFLAGS} -o $@ $^ -test: +test: gofmt go test -v go vet - @(echo "gofmt -l"; FMTFILES="$$(gofmt -l .)"; if test -n "$${FMTFILES}"; then echo "Go files that need to be reformatted (use 'go fmt'):\n$${FMTFILES}"; exit 1; fi) -docker: +docker: gofmt docker build . -t apache/cloudstack-kubernetes-provider:${GIT_COMMIT_SHORT} docker tag apache/cloudstack-kubernetes-provider:${GIT_COMMIT_SHORT} apache/cloudstack-kubernetes-provider:latest ifneq (${GIT_IS_TAG},NOT_A_TAG) docker tag apache/cloudstack-kubernetes-provider:${GIT_COMMIT_SHORT} apache/cloudstack-kubernetes-provider:${GIT_TAG} endif + +lint: gofmt + @(echo "Running golangci-lint...") + golangci-lint run + +gofmt: + @(echo "Running gofmt...") + @(echo "gofmt -l"; FMTFILES="$$(gofmt -l .)"; if test -n "$${FMTFILES}"; then echo "Go files that need to be reformatted (use 'go fmt'):\n$${FMTFILES}"; exit 1; fi) diff --git a/README.md b/README.md index cdd0aaf1..b16ba926 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ Instead, it first obtains the name of the node from Kubernetes, then fetches inf ### Building -At least Go 1.21 is required to build cloudstack-ccm. +At least Go 1.23 is required to build cloudstack-ccm. To build the controller with correct versioning, some build flags need to be passed. A Makefile is provided that sets these build flags to automatically derived values. @@ -151,13 +151,50 @@ The CCM supports the same cloud-config configuration file format used by [the cs so you can simply point it to that. ```bash -./cloudstack-ccm --cloud-provider external-cloudstack --cloud-config ~/.cloud-config --master k8s-apiserver +./cloudstack-ccm --cloud-provider external-cloudstack --cloud-config ./cloud-config --kubeconfig ~/.kube/config ``` Replace k8s-apiserver with the host name of your Kubernetes development clusters's API server. If you don't have a 'real' CloudStack installation, you can also launch a local [simulator instance](https://hub.docker.com/r/cloudstack/simulator) instead. This is very useful for dry-run testing. +### Debugging + +You can use the VSCode extension [Go](https://marketplace.visualstudio.com/items?itemName=golang.go) to debug the CCM. +Add the following configuration to the `.vscode/launch.json` file to launch the CCM and debug it. + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch CloudStack CCM", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/cmd/cloudstack-ccm", + "env": {}, + "args": [ + "--cloud-provider=external-cloudstack", + "--cloud-config=${workspaceFolder}/cloud-config", + "--kubeconfig=${env:HOME}/.kube/config", + "--leader-elect=false", + "--v=4" + ], + "showLog": true, + "trace": "verbose" + }, + { + "name": "Attach to Process", + "type": "go", + "request": "attach", + "mode": "local", + "processId": 0 + } + ] +} +``` + ## Copyright Copyright 2019 The Apache Software Foundation diff --git a/cloudstack_loadbalancer.go b/cloudstack_loadbalancer.go index 7a3fd6b0..4e0ac6ab 100644 --- a/cloudstack_loadbalancer.go +++ b/cloudstack_loadbalancer.go @@ -200,11 +200,11 @@ func (cs *CSCloud) EnsureLoadBalancer(ctx context.Context, clusterName string, s for _, lbRule := range lb.rules { protocol := ProtocolFromLoadBalancer(lbRule.Protocol) if protocol == LoadBalancerProtocolInvalid { - return nil, fmt.Errorf("Error parsing protocol %v: %v", lbRule.Protocol, err) + return nil, fmt.Errorf("error parsing protocol %v: %v", lbRule.Protocol, err) } port, err := strconv.ParseInt(lbRule.Publicport, 10, 32) if err != nil { - return nil, fmt.Errorf("Error parsing port %s: %v", lbRule.Publicport, err) + return nil, fmt.Errorf("error parsing port %s: %v", lbRule.Publicport, err) } klog.V(4).Infof("Deleting firewall rules associated with load balancer rule: %v (%v:%v:%v)", lbRule.Name, protocol, lbRule.Publicip, port)