diff --git a/.github/workflows/test-and-ci.yml b/.github/workflows/test-and-ci.yml new file mode 100644 index 0000000..d8c82de --- /dev/null +++ b/.github/workflows/test-and-ci.yml @@ -0,0 +1,45 @@ +name: Testing and CI to github registry. + +on: + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + + +jobs: + test-build-and-push-image: + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + + steps: + - uses: actions/checkout@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: make + + - name: Test using Go test + run: make test + + - name: Build docker image + run: docker build --target release -t ghcr.io/${{ github.repository_owner }}/resource-manager:${{ github.sha }} . + if: github.event_name == 'push' + + - name: Log in to Github Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + if: github.event_name == 'push' + + - name: Push docker image + run: docker push ghcr.io/${{ github.repository_owner }}/resource-manager:${{ github.sha }} + if: github.event_name == 'push' diff --git a/Dockerfile b/Dockerfile index fd23a1f..d048c96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.16 as builder +FROM golang:1.18 as builder WORKDIR /workspace # Copy the Go Modules manifests @@ -23,7 +23,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot +FROM gcr.io/distroless/static:nonroot as release WORKDIR / COPY --from=builder /workspace/manager . # copy channels diff --git a/Makefile b/Makefile index ac877f8..de153d1 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ ifeq ($(USE_IMAGE_DIGESTS), true) endif # Image URL to use all building/pushing image targets -IMG ?= controller:latest +IMG ?= resource-manager:latest # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION = 1.24 diff --git a/config/samples/Rmanager-deployment.yaml b/config/samples/Rmanager-deployment.yaml new file mode 100644 index 0000000..688cb60 --- /dev/null +++ b/config/samples/Rmanager-deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: resource-management.tikalk.com/v1alpha1 +kind: ResourceManager +metadata: + name: resource-manager-sample +spec: + active: true + dry-run: false + resources: "deployment" + selector: + matchLabels: + tobedeleted: yes + action: "delete" + condition: + - type: expiry + after: "1m" + # OR + # - type: time + # interval: daily + # time: "20:59:59" +#status: diff --git a/controllers/handlers/deployment.go b/controllers/handlers/deployment.go new file mode 100644 index 0000000..342ecc2 --- /dev/null +++ b/controllers/handlers/deployment.go @@ -0,0 +1,63 @@ +package handlers + +import ( + "fmt" + + utils "github.com/tikalk/resource-manager/controllers/utils" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// keep everything in a struct + +// HandledeploymentObj handle deployment objects that related to the resource-manager controller +func (d Obj) HandleDeployObj() { + // get all the deployments with the desired selector labels + deploy, err := GetDeployByLabel(d) + if err != nil { + d.L.Error(err, fmt.Sprintf("%v: cannot list deployments\n", d.Name)) + } + + if len(deploy) <= 0 { + fmt.Printf("%v: did not found any deployments with the requested label\n", d.Name) + return + } + + fmt.Printf("found %v deployments with the requested label\n", len(deploy)) + + for _, dep := range deploy { + expired, secondsUntilExpire := utils.IsObjExpired(dep.CreationTimestamp, d.Spec.Condition[0].After) + if expired { + switch d.Spec.Action { + case "delete": + fmt.Printf("deployment '%s' has been expired and will be deleted \n", dep.Name) + err := d.C.Delete(d.Ctx, dep.DeepCopy(), &client.DeleteOptions{}) + if err != nil { + d.L.Error(err, fmt.Sprintf("cannot delete deployments\n %v", dep.Name)) + } + fmt.Printf("%v: deployment '%v' has been deleted \n", d.Name, dep.Name) + } + } else { + fmt.Printf("%v: %v seconds has left to deployment '%s' \n", d.Name, secondsUntilExpire, dep.Name) + + } + } +} + +// GetdeploymentsByLabel get only deployments that contains a specific label +func GetDeployByLabel(d Obj) ([]appsv1.Deployment, error) { + + var listOfDeployments []appsv1.Deployment + depListObj := &appsv1.DeploymentList{} + + if err := d.C.List(d.Ctx, depListObj, &client.ListOptions{ + LabelSelector: labels.SelectorFromSet(d.Spec.Selector.MatchLabels), + }); err != nil { + d.L.Error(err, fmt.Sprintf("%v: unable to fetch deployments", d.Name)) + return nil, err + } + + listOfDeployments = append(listOfDeployments, depListObj.Items...) + return listOfDeployments, nil +} diff --git a/controllers/handlers/types.go b/controllers/handlers/types.go index ed68303..cd5fbc4 100644 --- a/controllers/handlers/types.go +++ b/controllers/handlers/types.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "github.com/go-logr/logr" resourcemanagmentv1alpha1 "github.com/tikalk/resource-manager/api/v1alpha1" "k8s.io/apimachinery/pkg/types" diff --git a/controllers/resourcemanager_controller.go b/controllers/resourcemanager_controller.go index 8b832f7..9364515 100644 --- a/controllers/resourcemanager_controller.go +++ b/controllers/resourcemanager_controller.go @@ -132,20 +132,30 @@ func (r *ResourceManagerReconciler) Reconcile(ctx context.Context, req ctrl.Requ }, Stop: make(chan bool), } + case "deployment": + // add the function and its stop-channel to collection + collection[h.Name] = FHandler{ + F: func(stop chan bool) { + for { + select { + case <-stop: + l.Info(fmt.Sprintf("%s Got stop signal!\n", h.Name)) + return + default: + h.HandleDeployObj() + time.Sleep(5 * time.Second) + } + } + }, + Stop: make(chan bool), + } + } - // export to new var - c := collection[h.Name] - - // execute in a new thread + // export to new var + c := collection[h.Name] - go c.F(c.Stop) - } - // - //deploy := &appsv1.DeploymentList{} - //err = r.Client.List(ctx, deploy, &client.ListOptions{}) - //fmt.Printf("There are %d deployments in the cluster\n", len(deploy.Items)) - // - //l.Info(fmt.Sprintf("Done reconcile 12-- obj %s", name)) + // execute in a new thread + go c.F(c.Stop) return ctrl.Result{}, nil } diff --git a/controllers/resourcemanager_controller_test.go b/controllers/resourcemanager_controller_test.go index a71973e..c753574 100644 --- a/controllers/resourcemanager_controller_test.go +++ b/controllers/resourcemanager_controller_test.go @@ -2,12 +2,13 @@ package controllers import ( "context" + "time" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "time" resourcemanagmentv1alpha1 "github.com/tikalk/resource-manager/api/v1alpha1" ) @@ -70,7 +71,7 @@ var _ = Context("Inside of a ResourceManager", func() { // validate creation nsObj, _ := getResourceByName(ctx, myNamespaceObj.Name) Expect(string(nsObj.Status.Phase)).Should(Equal("Active")) - time.Sleep(10 * time.Second) + time.Sleep(15 * time.Second) }) diff --git a/go.sum b/go.sum index c27022b..aa00466 100644 --- a/go.sum +++ b/go.sum @@ -87,6 +87,7 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -503,6 +504,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=