Skip to content

Commit

Permalink
Merge pull request #6 from csatib02/chore/tidy-codebase
Browse files Browse the repository at this point in the history
chore: tidy codebase
  • Loading branch information
csatib02 authored Sep 3, 2024
2 parents f18e167 + 556f782 commit fb65c55
Show file tree
Hide file tree
Showing 17 changed files with 32 additions and 54 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ jobs:
outputs: type=docker,dest=image.tar

- name: Build and push Docker image
id: build
uses: docker/build-push-action@v6
if: ${{ inputs.publish == true }}
with:
Expand Down Expand Up @@ -96,7 +95,6 @@ jobs:
run: make lint-helm

- name: Helm package
id: build
run: make helm-chart

- name: Upload Helm chart artifact
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
needs: artifacts
strategy:
matrix:
KIND_K8S_VERSION: ["v1.28.9", "v1.29.4", "v1.30.0"]
KIND_K8S_VERSION: ["v1.29.0", "v1.30.0", "v1.31.0"]

steps:
- name: Checkout repository
Expand Down
20 changes: 11 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export PATH := $(abspath bin/):${PATH}

CONTAINER_IMAGE_REF = ghcr.io/csatib02/kube-pod-autocomplete:dev
PROJECT_NAME = kube-pod-autocomplete
CONTAINER_IMAGE_REF = ghcr.io/csatib02/${PROJECT_NAME}:dev

##@ General

Expand All @@ -16,16 +17,17 @@ help: ## Display this help

.PHONY: up
up: ## Start development environment
${KIND_BIN} create cluster --name kube-pod-autocomplete
${KIND_BIN} create cluster --name ${PROJECT_NAME}

.PHONY: down
down: ## Stop development environment
${KIND_BIN} delete cluster --name kube-pod-autocomplete
${KIND_BIN} delete cluster --name ${PROJECT_NAME}

.PHONY: deploy
deploy: ## Deploy kube-pod-autocomplete to the development environment
kubectl create ns kube-pod-autocomplete
${HELM_BIN} upgrade --install kube-pod-autocomplete deploy/charts/kube-pod-autocomplete --namespace kube-pod-autocomplete
deploy: container-image ## Deploy kube-pod-autocomplete to the development environment
kind load docker-image ${CONTAINER_IMAGE_REF} --name ${PROJECT_NAME}
kubectl create ns ${PROJECT_NAME}
${HELM_BIN} upgrade --install ${PROJECT_NAME} deploy/charts/${PROJECT_NAME} --namespace ${PROJECT_NAME} --set image.tag=dev

.PHONY: deploy-testdata
deploy-testdata: ## Deploy testdata to the development environment
Expand All @@ -38,7 +40,7 @@ deploy-testdata: ## Deploy testdata to the development environment
.PHONY: build
build: ## Build binary
@mkdir -p build
go build -race -o build/kube-pod-autocomplete .
go build -race -o build/${PROJECT_NAME} .

.PHONY: artifacts
artifacts: container-image helm-chart
Expand All @@ -51,7 +53,7 @@ container-image: ## Build container image
.PHONY: helm-chart
helm-chart: ## Build Helm chart
@mkdir -p build
$(HELM_BIN) package -d build/ deploy/charts/kube-pod-autocomplete
$(HELM_BIN) package -d build/ deploy/charts/${PROJECT_NAME}

##@ Checks

Expand Down Expand Up @@ -79,7 +81,7 @@ lint-go:

.PHONY: lint-helm
lint-helm:
$(HELM_BIN) lint deploy/charts/kube-pod-autocomplete
$(HELM_BIN) lint deploy/charts/${PROJECT_NAME}

.PHONY: fmt
fmt: ## Format code
Expand Down
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,8 @@
- Kube Pod Autocomplete is designed to be used in Kubernetes environment.
- Take a look at the [documentation](./docs/docs.md).

## TODO

- Consider adding garden config to simplify testing.

- Add search pods by label/ns/phase endpoint as a possible use-case.

## Development

Make sure Docker is installed.

Fetch required tools:

```shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ spec:
containers:
- name: {{ .Values.name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.containerPort }}
- containerPort: {{ .Values.service.containerPort }}
resources:
limits:
cpu: {{ .Values.resources.limits.cpu }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ spec:
ports:
- protocol: TCP
port: {{ .Values.service.servicePort }}
targetPort: {{ .Values.containerPort }}
externalPort: {{ .Values.service.externalPort }}
targetPort: {{ .Values.service.containerPort }}
3 changes: 1 addition & 2 deletions deploy/charts/kube-pod-autocomplete/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace: kube-pod-autocomplete
# General settings for the application
name: kube-pod-autocomplete
replicas: 1
containerPort: 8080

# image
image:
Expand All @@ -17,7 +16,7 @@ service:
name: kube-pod-autocomplete-service
type: ClusterIP
servicePort: 8080
externalPort: 8080
containerPort: 8080

# Service Account settings
serviceAccount:
Expand Down
4 changes: 3 additions & 1 deletion docs/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ make deploy-testdata
Port-forward to Kube Pod Autocomplete:

```shell
kubectl port-forward -n kube-pod-autocomplete $(kubectl get pods -n kube-pod-autocomplete -o jsonpath='{.items[0].metadata.name}') 8080:8080 1>/dev/null &
kubectl port-forward -n kube-pod-autocomplete "svc/$(kubectl get svc -n kube-pod-autocomplete -o jsonpath='{.items[0].metadata.name}')" 8080:8080 1>/dev/null &
```

Hit the endpoint:
Expand All @@ -50,3 +50,5 @@ curl -X GET http://localhost:8080/search/autocomplete/pods
- [ ] Add support for `caching`. (While the current implementation is fast with a small number of pods, but there can be problems in production environments.)
- [ ] `Generate` API specification from `OpenAPI spec`. (The current solution is a really simple POC, if the project is later expanded with additional endpoints code generation from the OpenAPI spec should be utilised.)
- [ ] `Improve End-to-End` Tests: (The existing end-to-end test setup is quite basic, using `cmd.Exec()` and port-forward to access the service is rather limited. Future improvements could include using an ingress controller like NGINX for more robust testing.)
- [ ] Add endpoints that can be called with the received suggestions. (E.g.: `search/:resource/:filters` or get the filters from the body.)
- [ ] Enable deploying with [Garden](https://garden.io/). (Garden helps a lot when it comes to manually testing a project, as new features are added, this should also be implemented.)
3 changes: 1 addition & 2 deletions e2e/deploy/kube-pod-autocomplete/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ namespace: kube-pod-autocomplete

name: kube-pod-autocomplete
replicas: 1
containerPort: 8080

service:
name: kube-pod-autocomplete-service
type: ClusterIP
servicePort: 8080
externalPort: 8080
containerPort: 8080

serviceAccount:
name: kube-pod-autocomplete-sa
Expand Down
11 changes: 4 additions & 7 deletions e2e/kpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const (
func TestKPAEndpoints(t *testing.T) {
endpoints := applyResource(features.New("validate endpoint functionality")).
Assess("pods are available", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
// check if test pods are running
// Check if test pods are running
err := wait.PollUntilContextTimeout(ctx, pollInterval, defaultTimeout, true, func(ctx context.Context) (bool, error) {
// get all pods with label: team=test
// Get all pods with label: team=test
pods := &corev1.PodList{}
err := cfg.Client().Resources().List(ctx, pods, func(opts *metav1.ListOptions) {
opts.LabelSelector = labels.Set{"team": "test"}.String()
Expand All @@ -53,26 +53,23 @@ func TestKPAEndpoints(t *testing.T) {
return ctx
}).Assess("check KPA response", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {

// start port forwarding
killProcess := startPortForwardingToService(t, "kube-pod-autocomplete-service", "kube-pod-autocomplete", "8080:8080")
defer killProcess()

// hit the /health endpoint
resp, err := http.Get(fmt.Sprintf(healthURL, "localhost", 8080))
require.NoError(t, err)
defer resp.Body.Close()

require.Equal(t, http.StatusOK, resp.StatusCode)

// hit the /search/autocomplete/pods endpoint
autocompleteUrl := fmt.Sprintf(autocompleteURL, "localhost", 8080, "pods")
resp, err = http.Get(autocompleteUrl)
require.NoError(t, err)
defer resp.Body.Close()

require.Equal(t, http.StatusOK, resp.StatusCode)

// check if the response body contains the expected filters
// Check if the response body contains the expected filters
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)

Expand Down Expand Up @@ -112,7 +109,7 @@ func applyResource(builder *features.FeatureBuilder) *features.FeatureBuilder {
func startPortForwardingToService(t *testing.T, svcName, ns, portMapping string) func() {
args := []string{"port-forward", fmt.Sprintf("svc/%s", svcName), portMapping, "-n", ns}
cmd := exec.Command("kubectl", args...)
cmd.Stderr = os.Stderr // redirect stderr to test output
cmd.Stderr = os.Stderr // Redirect stderr to test output
err := cmd.Start()
require.NoError(t, err)

Expand Down
4 changes: 1 addition & 3 deletions internal/handlers/autocomplete.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ func AutocompleteHandler(c *gin.Context) {
return
}

// Pretty-print the JSON response
prettyJSON, err := json.MarshalIndent(suggestions, "", " ")
if err != nil {
// Log the error and return the response as is
Expand All @@ -79,10 +78,9 @@ func AutocompleteHandler(c *gin.Context) {
return
}

c.Data(http.StatusOK, "application/json", prettyJSON)
c.Data(http.StatusOK, gin.MIMEJSON, prettyJSON)
}

// validateRequestedFilters validates the requestedFilters parameter
func validateRequestedFilters(requestedFilters []string) ([]string, error) {
validFilters := make([]string, 0, len(requestedFilters))
for _, filter := range requestedFilters {
Expand Down
9 changes: 2 additions & 7 deletions internal/services/autocomplete/autocomplete.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ func NewAutoCompleteService() (*Service, error) {

// GetAutocompleteSuggestions returns a list of suggestions (for the given query)
func (s *Service) GetAutocompleteSuggestions(ctx context.Context, req model.AutoCompleteRequest) (*model.AutocompleteSuggestions, error) {
// if no ResourceType is provided, default to Pod
if req.ResourceType == "" {
req.ResourceType = common.PodResourceType
}

filters, err := filter.NewFieldFilters(req.ResourceType, &req.Filters)
if err != nil {
return nil, fmt.Errorf("failed to get field filters: %w", err)
Expand All @@ -46,7 +41,7 @@ func (s *Service) GetAutocompleteSuggestions(ctx context.Context, req model.Auto
return s.extractSuggestions(resources, filters)
}

// extractSuggestions extracts suggestions from the given pods based on the requested filters
// extractSuggestions extracts suggestions from the given resources based on the requested filters
func (s *Service) extractSuggestions(resources common.Resources, filters *map[string]model.FieldFilter) (*model.AutocompleteSuggestions, error) {
suggestions := make([]model.Suggestion, 0, len(*filters))
for fieldName, fieldFilter := range *filters {
Expand Down Expand Up @@ -76,7 +71,7 @@ func (s *Service) extractSuggestions(resources common.Resources, filters *map[st
}
}

// These should be filter options on the UI
// These should be options on the UI
filterOptions := filter.Options{}

filterOptions.RemoveDuplicateValues(&suggestions)
Expand Down
1 change: 0 additions & 1 deletion internal/services/autocomplete/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ func NewFieldFilters(resourceType common.ResourceType, requestedFilters *[]strin
switch resourceType {
case common.PodResourceType:
return podfilter.GetFilters(requestedFilters), nil
// Add cases for other resource types here
default:
return nil, errors.New("unsupported resource type")
}
Expand Down
4 changes: 2 additions & 2 deletions internal/services/autocomplete/filter/filteroptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/csatib02/kube-pod-autocomplete/internal/services/autocomplete/model"
)

// FilterOptions defines additional options for filtering suggestions
// Options defines additional options for filtering suggestions
type Options struct{}

var ignoredKeys = map[string][]string{
Expand All @@ -33,7 +33,7 @@ func (o *Options) RemoveDuplicateValues(suggestions *[]model.Suggestion) {
}

// RemoveIgnoredKeys removes the ignored keys from the suggestions
// NOTE: IgnoreKeys should be retrieved from request parameters
// NOTE: ignoredKeys should be retrieved from request parameters
func (o *Options) RemoveIgnoredKeys(suggestions *[]model.Suggestion) {
filteredSuggestions := make([]model.Suggestion, 0, len(*suggestions))
for _, suggestion := range *suggestions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import "github.com/csatib02/kube-pod-autocomplete/pkg/common"
type AutoCompleteRequest struct {
ResourceType common.ResourceType `json:"resourceType"`
Filters []string `json:"filters"`
Query string `json:"query"` // Currently not used
Query string `json:"query"` // Currently unused
}
5 changes: 1 addition & 4 deletions internal/services/autocomplete/model/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package model

import "github.com/csatib02/kube-pod-autocomplete/pkg/common"

// FieldExtractor interface defines the method for extracting field values from a PodList
// NOTE: There is no actual difference between ListExtractor and MapExtractor,
// since when processing the extracted data, we can always check the type of the underlying data structure
// via FieldFilter.Type, but for the sake of clarity, I have defined two separate types.
// FieldExtractor interface defines the method for extracting field values from resources
type FieldExtractor interface {
Extract(common.Resources) any
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func (e *Error) Error() string {
return e.Message
}

// HandleHTTPError is a utility function to handle HTTP errors in Gin handlers.
// HandleHTTPError is a utility function to handle HTTP errors in Gin handlers
func HandleHTTPError(c *gin.Context, code int, err error) {
httpErr := &Error{
Code: code,
Expand Down

0 comments on commit fb65c55

Please sign in to comment.