Skip to content

Commit

Permalink
706 update e2e process stats tests (#707)
Browse files Browse the repository at this point in the history
#706

- Adds metrics-server to kind deployment script
- Pins kpack ClusterStore node buildpack version to previous working one
- Adds an e2e test for the GET process_stats endpoint when metrics server is present

Co-authored-by: Ashwin Krishna <krishnaas@vmware.com>
  • Loading branch information
gnovv and akrishna90 authored Feb 24, 2022
1 parent d66af05 commit a31dedb
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 36 deletions.
21 changes: 11 additions & 10 deletions api/repositories/pod_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,29 +120,31 @@ func (r *PodRepo) ListPodStats(ctx context.Context, authInfo authorization.Info,

podMetrics, err := r.metricsFetcher(ctx, p.Namespace, p.Name)
if err != nil {
if !strings.Contains(err.Error(), "the server could not find the requested resource") {
return nil, err
errorMsg := err.Error()
if strings.Contains(errorMsg, "not found") ||
strings.Contains(errorMsg, "the server could not find the requested resource") {
continue
}
continue
return nil, err
}
metricsMap := aggregateContainerMetrics(podMetrics.Containers)
if len(metricsMap) == 0 {
continue
}

if quantity, ok := metricsMap["cpu"]; ok {
value := float64(quantity.ScaledValue(resource.Nano))
if CPUquantity, ok := metricsMap["cpu"]; ok {
value := float64(CPUquantity.ScaledValue(resource.Nano))
percentage := value / 1e7
records[index].Usage.CPU = &percentage
}

if r2, ok := metricsMap["memory"]; ok {
value := r2.Value()
if memQuantity, ok := metricsMap["memory"]; ok {
value := memQuantity.Value()
records[index].Usage.Mem = &value
}

if r3, ok := metricsMap["storage"]; ok {
value := r3.Value()
if storageQuantity, ok := metricsMap["storage"]; ok {
value := storageQuantity.Value()
records[index].Usage.Disk = &value
}
time := podMetrics.Timestamp.UTC().Format(TimestampFormat)
Expand Down Expand Up @@ -297,7 +299,6 @@ func containersRunning(statuses []corev1.ContainerStatus) bool {
return true
}

// Untested
func CreateMetricsFetcher() (MetricsFetcherFn, error) {
restConfig, err := rest.InClusterConfig()
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions api/repositories/pod_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,22 @@ var _ = Describe("PodRepository", func() {
})
})

When("MetricsFetcherFunction returns a not found error for the PodMetrics", func() {
BeforeEach(func() {
message.Instances = 2
metricFetcherFn.Returns(nil, errors.New("podmetrics.metrics.k8s.io \\\"Blah\\\" not found"))
})
It("fetches all the pods and sets the usage stats with empty values", func() {
Expect(listStatsErr).NotTo(HaveOccurred())
Expect(records).To(ConsistOf(
[]PodStatsRecord{
{Type: "web", Index: 0, State: "RUNNING"},
{Type: "web", Index: 1, State: "DOWN"},
},
))
})
})

When("MetricFetcherFunction return some other error", func() {
BeforeEach(func() {
message.Instances = 2
Expand Down
8 changes: 2 additions & 6 deletions api/tests/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"code.cloudfoundry.org/cf-k8s-controllers/api/apis"
"code.cloudfoundry.org/cf-k8s-controllers/api/presenter"
"code.cloudfoundry.org/cf-k8s-controllers/api/tests/e2e/helpers"

"github.com/go-resty/resty/v2"
Expand Down Expand Up @@ -93,12 +94,7 @@ type dropletResource struct {
}

type statsResourceList struct {
Resources []statsResource `json:"resources"`
}

type statsResource struct {
Type string `json:"type"`
State string `json:"state"`
Resources []presenter.ProcessStatsResource `json:"resources"`
}

type manifestResource struct {
Expand Down
60 changes: 41 additions & 19 deletions api/tests/e2e/processes_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package e2e_test

import (
"fmt"
"net/http"
"time"

"code.cloudfoundry.org/cf-k8s-controllers/api/presenter"

"github.com/go-resty/resty/v2"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

. "github.com/onsi/gomega/gstruct"
rbacv1 "k8s.io/api/rbac/v1"
)

Expand All @@ -16,13 +20,13 @@ var _ = Describe("Processes", func() {
spaceGUID string
appGUID string
processGUID string
client *resty.Client
restyClient *resty.Client
resp *resty.Response
errResp cfErrs
)

BeforeEach(func() {
client = certClient
restyClient = certClient
errResp = cfErrs{}
orgGUID = createOrg(generateGUID("org"))
createOrgRole("organization_user", rbacv1.UserKind, certUserName, orgGUID)
Expand All @@ -37,11 +41,6 @@ var _ = Describe("Processes", func() {
deleteOrg(orgGUID)
})

BeforeEach(func() {
appGUID = pushNodeApp(spaceGUID)
processGUID = getProcess(appGUID, "web")
})

Describe("listing sidecars", Ordered, func() {
var list resourceList

Expand All @@ -51,7 +50,7 @@ var _ = Describe("Processes", func() {

JustBeforeEach(func() {
var err error
resp, err = client.R().
resp, err = restyClient.R().
SetResult(&list).
SetError(&errResp).
Get("/v3/processes/" + processGUID + "/sidecars")
Expand All @@ -66,7 +65,7 @@ var _ = Describe("Processes", func() {

When("the user is not authorized in the space", func() {
BeforeEach(func() {
client = tokenClient
restyClient = tokenClient
})

It("returns a not found error", func() {
Expand All @@ -85,15 +84,9 @@ var _ = Describe("Processes", func() {
Describe("getting process stats", func() {
var processStats statsResourceList

BeforeEach(func() {
appGUID = pushNodeApp(spaceGUID)
processGUID = getProcess(appGUID, "web")
processStats = statsResourceList{}
})

JustBeforeEach(func() {
var err error
resp, err = client.R().
resp, err = restyClient.R().
SetResult(&processStats).
SetError(&errResp).
Get("/v3/processes/" + processGUID + "/stats")
Expand All @@ -109,9 +102,38 @@ var _ = Describe("Processes", func() {
Expect(processStats.Resources[0].Type).To(Equal("web"))
})

When("we wait for the metrics to be ready", func() {
BeforeEach(func() {
// use an eventually to check when the pod metrics become available
Eventually(func() presenter.ProcessUsage {
var err error
resp, err = restyClient.R().
SetResult(&processStats).
SetError(&errResp).
Get("/v3/processes/" + processGUID + "/stats")
Expect(err).NotTo(HaveOccurred())

return processStats.Resources[0].Usage
}, 60*time.Second).ShouldNot(Equal(presenter.ProcessUsage{}))
})
It("succeeds", func() {
Expect(resp).To(HaveRestyStatusCode(http.StatusOK))

fmt.Printf("\nWAIT RESPONSE\n\n%#v\n\n\n", resp)
fmt.Printf("\nWAIT PROCESS STATS\n\n%#v\n\n\n", processStats)
Expect(processStats.Resources).To(HaveLen(1))
Expect(processStats.Resources[0].Usage).To(MatchFields(IgnoreExtras, Fields{
"Mem": Not(BeNil()),
"CPU": Not(BeNil()),
"Time": Not(BeNil()),
//"Disk": Not(BeNil()), // Disk is currently empty
}))
})
})

When("the user is not authorized in the space", func() {
BeforeEach(func() {
client = tokenClient
restyClient = tokenClient
})

It("returns a not found error", func() {
Expand All @@ -132,7 +154,7 @@ var _ = Describe("Processes", func() {

JustBeforeEach(func() {
var err error
resp, err = client.R().
resp, err = restyClient.R().
SetResult(&result).
Get("/v3/processes/" + processGUID)
Expect(err).NotTo(HaveOccurred())
Expand Down
2 changes: 1 addition & 1 deletion dependencies/kpack/cluster_store.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
spec:
sources:
- image: gcr.io/paketo-buildpacks/java
- image: gcr.io/paketo-buildpacks/nodejs
- image: gcr.io/paketo-buildpacks/nodejs:0.13
- image: gcr.io/paketo-buildpacks/ruby
- image: gcr.io/paketo-buildpacks/procfile
- image: gcr.io/paketo-buildpacks/go
Loading

0 comments on commit a31dedb

Please sign in to comment.