Skip to content

Commit

Permalink
plz: add specifics of API
Browse files Browse the repository at this point in the history
  • Loading branch information
yorugac committed Jun 13, 2023
1 parent 0d1416c commit 9983f58
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 29 deletions.
30 changes: 27 additions & 3 deletions api/v1alpha1/privateloadzone_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
"fmt"

"github.com/go-logr/logr"
"github.com/grafana/k6-operator/pkg/cloud"
"k8s.io/apimachinery/pkg/api/resource"

"go.k6.io/k6/cloudapi"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -69,16 +72,37 @@ func init() {
func (plz *PrivateLoadZone) Register(ctx context.Context, logger logr.Logger, client *cloudapi.Client) {
plz.UpdateCondition(PLZRegistered, metav1.ConditionFalse)

// TODO add register call and error processing
cpu, err := resource.ParseQuantity(plz.Spec.Resources.Cpu().String())
if err != nil {
logger.Error(err, fmt.Sprintf("CPU resource of PLZ %s cannot be parsed", plz.Name))
return
}

data := cloud.PLZRegistrationData{
LoadZoneID: plz.Name,
Resources: cloud.PLZResources{
CPU: cpu.AsApproximateFloat64(),
Memory: plz.Spec.Resources.Memory().String(),
},
}

if err := cloud.RegisterPLZ(client, data); err != nil {
logger.Error(err, fmt.Sprintf("Failed to register PLZ %s.", plz.Name))
}

logger.Info(fmt.Sprintf("Registered PLZ %s.", plz.Name))

plz.UpdateCondition(PLZRegistered, metav1.ConditionTrue)
}

// Deregister attempts to deregister PLZ with the k6 Cloud.
// It is meant to be used as a finalizer.
func (plz *PrivateLoadZone) Deregister(ctx context.Context, logger logr.Logger, client *cloudapi.Client) {
// TODO add deregister call and error processing
if err := cloud.DeRegisterPLZ(client, plz.Name); err != nil {
logger.Error(err, fmt.Sprintf("Failed to de-register PLZ %s.", plz.Name))
}

logger.Info(fmt.Sprintf("De-registered PLZ %s.", plz.Name))

fmt.Println("calling deregister for", *plz)
plz.UpdateCondition(PLZRegistered, metav1.ConditionFalse)
}
40 changes: 40 additions & 0 deletions pkg/cloud/plz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cloud

import (
"fmt"

"go.k6.io/k6/cloudapi"
)

func RegisterPLZ(client *cloudapi.Client, data PLZRegistrationData) error {
// url := fmt.Sprintf("https://%s/v1/load-zones", client.GetURL())
url := fmt.Sprintf("http://%s/v1/load-zones", "mock-cloud.k6-operator-system.svc.cluster.local:8080")

req, err := client.NewRequest("POST", url, data)
if err != nil {
return err
}

var resp struct {
Error struct {
Message string `json:"message"`
} `json:"error"`
}
if err = client.Do(req, &resp); err != nil {
return fmt.Errorf("Received error `%s`. Message from server `%s`", err.Error(), resp.Error.Message)
}

return nil
}

func DeRegisterPLZ(client *cloudapi.Client, name string) error {
// url := fmt.Sprintf("https://%s/v1/load-zones/%s", client.GetURL(), name)
url := fmt.Sprintf("http://%s/v1/load-zones/%s", "mock-cloud.k6-operator-system.svc.cluster.local:8080", name)

req, err := client.NewRequest("DELETE", url, nil)
if err != nil {
return err
}

return client.Do(req, nil)
}
92 changes: 92 additions & 0 deletions pkg/cloud/resources_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package cloud

import (
"testing"

"k8s.io/apimachinery/pkg/api/resource"

"github.com/stretchr/testify/assert"
)

// 1 CPU in Kubernetes = 1 AWS vCPU = 1 GCP Core = 1 Azure vCore
// Docs: https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/#cpu-units

func TestConversion(t *testing.T) {
testCases := []struct {
k8sResource string
expected float64
}{
// CPU
{
"512m",
0.512,
},
{
"1000m",
1,
},
{
"1",
1,
},
{
"100",
100,
},
// Memory
{
"104857600",
104857600,
},
{
"100M",
100000000,
},
{
"100Mi",
104857600,
},
{
"150Mi",
157286400,
},
{
"1050Mi",
1101004800,
},
{
"4000M",
4000000000,
},
{
"4000Mi",
4194304000,
},
{
"4Gi",
4294967296,
},
{
"10000Mi",
10485760000,
},
{
"16G",
16000000000,
},
{
"32G",
32000000000,
},
{
"64G",
64000000000,
},
}

for _, testCase := range testCases {
q := resource.MustParse(testCase.k8sResource)
got := q.AsApproximateFloat64()
assert.Equal(t, testCase.expected, got, "testCase", testCase)
}
}
34 changes: 15 additions & 19 deletions pkg/cloud/test_runs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cloud

import (
"fmt"
"math/rand"
"os"
"time"

Expand Down Expand Up @@ -71,7 +70,7 @@ func (poller *TestRunPoller) GetTestRuns() chan string {
}

func (poller *TestRunPoller) getTestRuns() ([]string, error) {
url := poller.host + "/get-tests" // TODO
url := poller.host + "/v4/plz-test-runs"
req, err := poller.Client.NewRequest("GET", url, nil)
if err != nil {
return nil, err
Expand All @@ -82,7 +81,12 @@ func (poller *TestRunPoller) getTestRuns() ([]string, error) {
return nil, err
}

return list.List, nil
simplifiedList := make([]string, len(list.List))
for i, item := range list.List {
simplifiedList[i] = fmt.Sprintf("%d", item.ID)
}

return simplifiedList, nil
}

func getTestRun(client *cloudapi.Client, url string) (*TestRunData, error) {
Expand All @@ -100,24 +104,16 @@ func getTestRun(client *cloudapi.Client, url string) (*TestRunData, error) {
}

func GetTestRunData(client *cloudapi.Client, refID string) (*TestRunData, error) {
// url := fmt.Sprintf("https://%s/loadtests/v4/test_runs(%s)?select=id,run_status,k8s_load_zones_config", client.Host, refID)
// return getTestRun(client, url)
return &TestRunData{
TestRunId: refID,
LZConfig: LZConfig{
RunnerImage: "grafana/k6:latest",
InstanceCount: 1,
},
}, nil
url := fmt.Sprintf("http://%s/loadtests/v4/test_runs(%s)?select=id,run_status,k8s_load_zones_config",
"mock-cloud.k6-operator-system.svc.cluster.local:8080", refID)
// url := fmt.Sprintf("https://%s/loadtests/v4/test_runs(%s)?select=id,run_status,k8s_load_zones_config", client.GetURL(), refID)
return getTestRun(client, url)
}

func GetTestRunState(client *cloudapi.Client, refID string, log logr.Logger) (TestRunStatus, error) {
url := fmt.Sprintf("http://%s/loadtests/v4/test_runs(%s)?select=id,run_status,k8s_load_zones_config",
"mock-cloud.k6-operator-system.svc.cluster.local:8080", refID)
// url := fmt.Sprintf("https://%s/loadtests/v4/test_runs(%s)?select=id,run_status", client.Host, refID)
// trData, err := getTestRun(client, url)
// return TestRunStatus(trData.RunStatus), err

if rand.Intn(2) > 0 {
return TestRunStatus(5), nil // mimic aborted
}
return TestRunStatus(2), nil
trData, err := getTestRun(client, url)
return TestRunStatus(trData.RunStatus), err
}
29 changes: 24 additions & 5 deletions pkg/cloud/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cloud

import (
"fmt"

"go.k6.io/k6/cloudapi"
"go.k6.io/k6/lib/types"
"go.k6.io/k6/metrics"
Expand All @@ -19,15 +21,17 @@ type InspectOutput struct {
Thresholds map[string]*metrics.Thresholds `json:"thresholds,omitempty"`
}

// testRunList holds the output from /get-tests call
// testRunList holds the output from /v4/plz-test-runs call
type testRunList struct {
List []string `json:"list"`
List []struct {
ID uint64 `json:"id"`
} `json:"object"`
}

// TestRunData holds the output from /get-test-data call
// TestRunData holds the output from /loadtests/v4/test_runs(%s)
type TestRunData struct {
TestRunId string `json:"id"`
Instances int `json:"instances"`
TestRunId int `json:"id"`
Instances int `json:"instances"`
LZConfig `json:"k8s_load_zones_config"`
RunStatus cloudapi.RunStatus `json:"run_status"`
}
Expand All @@ -38,6 +42,10 @@ type LZConfig struct {
ArchiveURL string `json:"k6_archive_temp_public_url"`
}

func (trd *TestRunData) TestRunID() string {
return fmt.Sprintf("%d", trd.TestRunId)
}

type TestRunStatus cloudapi.RunStatus

func (trs TestRunStatus) Aborted() bool {
Expand All @@ -47,3 +55,14 @@ func (trs TestRunStatus) Aborted() bool {
// func (trs TestRunStatus) String() string {
// TODO
// }

// PLZRegistrationData holds info that needs to be sent to /v1/load-zones
type PLZRegistrationData struct {
LoadZoneID string `json:"k6_load_zone_id"`
Resources PLZResources `json:"pod_tiers"`
}

type PLZResources struct {
CPU float64 `json:"cpu"`
Memory string `json:"memory"`
}
5 changes: 5 additions & 0 deletions pkg/resources/jobs/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func NewRunnerJob(k6 *v1alpha1.K6, index int, token string) (*batchv1.Job, error

// this is a cloud output run
if len(k6.Status.TestRunID) > 0 {
// temporary hack
if k6.IsTrue(v1alpha1.CloudPLZTestRun) {
k6.Status.AggregationVars = "50|3s|8s|6s|10000|10"
}

aggregationVars, err := cloud.DecodeAggregationConfig(k6.Status.AggregationVars)
if err != nil {
return nil, err
Expand Down
5 changes: 3 additions & 2 deletions pkg/testrun/plz.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestName(testRunId string) string {
func NewPLZTestRun(plz *v1alpha1.PrivateLoadZone, trData *cloud.TestRunData) *v1alpha1.K6 {
return &v1alpha1.K6{
ObjectMeta: metav1.ObjectMeta{
Name: TestName(trData.TestRunId),
Name: TestName(trData.TestRunID()),
Namespace: plz.Namespace,
},
Spec: v1alpha1.K6Spec{
Expand All @@ -35,7 +35,8 @@ func NewPLZTestRun(plz *v1alpha1.PrivateLoadZone, trData *cloud.TestRunData) *v1
NodeSelector: plz.Spec.NodeSelector,
},
Parallelism: int32(trData.InstanceCount),
Separate: true,
// temporary
// Separate: true,
// Arguments: "--out cloud",
Cleanup: v1alpha1.Cleanup("post"),

Expand Down

0 comments on commit 9983f58

Please sign in to comment.