cloudfoundry/cf-k8s-controllers

View on GitHub
api/handlers/buildpack.go

Summary

Maintainability
A
45 mins
Test Coverage
package handlers

import (
    "context"
    "net/http"
    "net/url"
    "sort"

    "code.cloudfoundry.org/korifi/api/authorization"
    apierrors "code.cloudfoundry.org/korifi/api/errors"
    "code.cloudfoundry.org/korifi/api/payloads"
    "code.cloudfoundry.org/korifi/api/presenter"
    "code.cloudfoundry.org/korifi/api/repositories"
    "code.cloudfoundry.org/korifi/api/routing"

    "github.com/go-logr/logr"
)

const (
    BuildpacksPath = "/v3/buildpacks"
)

//counterfeiter:generate -o fake -fake-name BuildpackRepository . BuildpackRepository
type BuildpackRepository interface {
    ListBuildpacks(ctx context.Context, authInfo authorization.Info) ([]repositories.BuildpackRecord, error)
}

type Buildpack struct {
    serverURL        url.URL
    buildpackRepo    BuildpackRepository
    requestValidator RequestValidator
}

func NewBuildpack(
    serverURL url.URL,
    buildpackRepo BuildpackRepository,
    requestValidator RequestValidator,
) *Buildpack {
    return &Buildpack{
        serverURL:        serverURL,
        buildpackRepo:    buildpackRepo,
        requestValidator: requestValidator,
    }
}

func (h *Buildpack) list(r *http.Request) (*routing.Response, error) {
    authInfo, _ := authorization.InfoFromContext(r.Context())
    logger := logr.FromContextOrDiscard(r.Context()).WithName("handlers.build.list")

    buildpackListFilter := new(payloads.BuildpackList)
    if err := h.requestValidator.DecodeAndValidateURLValues(r, buildpackListFilter); err != nil {
        return nil, apierrors.LogAndReturn(logger, err, "Unable to parse request query parameters")
    }

    buildpacks, err := h.buildpackRepo.ListBuildpacks(r.Context(), authInfo)
    if err != nil {
        return nil, apierrors.LogAndReturn(logger, err, "Failed to fetch buildpacks from Kubernetes")
    }

    h.sortList(buildpacks, buildpackListFilter.OrderBy)

    return routing.NewResponse(http.StatusOK).WithBody(presenter.ForList(presenter.ForBuildpack, buildpacks, h.serverURL, *r.URL)), nil
}

// nolint:dupl
func (h *Buildpack) sortList(bpList []repositories.BuildpackRecord, order string) {
    switch order {
    case "":
    case "created_at":
        sort.Slice(bpList, func(i, j int) bool { return timePtrAfter(&bpList[j].CreatedAt, &bpList[i].CreatedAt) })
    case "-created_at":
        sort.Slice(bpList, func(i, j int) bool { return timePtrAfter(&bpList[i].CreatedAt, &bpList[j].CreatedAt) })
    case "updated_at":
        sort.Slice(bpList, func(i, j int) bool { return timePtrAfter(bpList[j].UpdatedAt, bpList[i].UpdatedAt) })
    case "-updated_at":
        sort.Slice(bpList, func(i, j int) bool { return timePtrAfter(bpList[i].UpdatedAt, bpList[j].UpdatedAt) })
    case "position":
        sort.Slice(bpList, func(i, j int) bool { return bpList[i].Position < bpList[j].Position })
    case "-position":
        sort.Slice(bpList, func(i, j int) bool { return bpList[i].Position > bpList[j].Position })
    }
}

func (h *Buildpack) UnauthenticatedRoutes() []routing.Route {
    return nil
}

func (h *Buildpack) AuthenticatedRoutes() []routing.Route {
    return []routing.Route{
        {Method: "GET", Pattern: BuildpacksPath, Handler: h.list},
    }
}