Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions api/types/load_traffic.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ type WeightedRequest struct {
QuorumGet *RequestGet `json:"quorumGet,omitempty" yaml:"quorumGet,omitempty"`
// Put means this is mutating request.
Put *RequestPut `json:"put,omitempty" yaml:"put,omitempty"`
// Post means this is resource creation request.
Post *RequestPost `json:"post,omitempty" yaml:"post,omitempty"`
// GetPodLog means this is to get log from target pod.
GetPodLog *RequestGetPodLog `json:"getPodLog,omitempty" yaml:"getPodLog,omitempty"`
}
Expand Down Expand Up @@ -146,6 +148,17 @@ type RequestPut struct {
ValueSize int `json:"valueSize" yaml:"valueSize"`
}

// RequestPost defines POST request for resource creation
type RequestPost struct {
// KubeGroupVersionResource identifies the resource URI.
KubeGroupVersionResource `yaml:",inline"`
// Namespace is object's namespace.
Namespace string `json:"namespace" yaml:"namespace"`
// Body is the request body, for resource creation.
// TODO (vittoria): replace with resource template ...e.g workload/deployments/.../deployments.tpl
Body string `json:"body,omitempty" yaml:"body,omitempty"`
}

// RequestGetPodLog defines GetLog request for target pod.
type RequestGetPodLog struct {
// Namespace is pod's namespace.
Expand Down Expand Up @@ -221,6 +234,8 @@ func (r WeightedRequest) Validate() error {
return r.QuorumGet.Validate()
case r.Put != nil:
return r.Put.Validate()
case r.Post != nil:
return r.Post.Validate()
case r.GetPodLog != nil:
return r.GetPodLog.Validate()
default:
Expand Down Expand Up @@ -282,6 +297,17 @@ func (r *RequestPut) Validate() error {
return nil
}

// Validate validates RequestPost type.
func (r *RequestPost) Validate() error {
if err := r.KubeGroupVersionResource.Validate(); err != nil {
return fmt.Errorf("kube metadata: %v", err)
}
if r.Body == "" {
return fmt.Errorf("body is required")
}
return nil
}

// Validate validates RequestGetPodLog type.
func (r *RequestGetPodLog) Validate() error {
if r.Namespace == "" {
Expand Down
61 changes: 61 additions & 0 deletions request/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package request
import (
"context"
"crypto/rand"
"encoding/json"
"fmt"
"math/big"
"strings"
"sync"

"github.com/Azure/kperf/api/types"
Expand Down Expand Up @@ -56,6 +58,8 @@ func NewWeightedRandomRequests(spec *types.LoadProfileSpec) (*WeightedRandomRequ
builder = newRequestGetBuilder(r.QuorumGet, "", spec.MaxRetries)
case r.GetPodLog != nil:
builder = newRequestGetPodLogBuilder(r.GetPodLog, spec.MaxRetries)
case r.Post != nil:
builder = newRequestPOSTBuilder(r.Post, "", spec.MaxRetries)
default:
return nil, fmt.Errorf("not implement for PUT yet")
}
Expand Down Expand Up @@ -354,6 +358,63 @@ func (b *requestGetPodLogBuilder) Build(cli rest.Interface) Requester {
}
}

type requestPOSTBuilder struct {
version schema.GroupVersion
resource string
resourceVersion string
namespace string
body interface{} // TODO (vittoria): replace with resource template
maxRetries int
}

func newRequestPOSTBuilder(src *types.RequestPost, resourceVersion string, maxRetries int) *requestPOSTBuilder {
// TODO (vittoria): load with resource template
var body interface{}

trimmed := strings.TrimSpace(src.Body)
if json.Valid([]byte(trimmed)) {
body = []byte(trimmed) // send raw JSON
} else {
body = trimmed // fallback to raw string
}

return &requestPOSTBuilder{
version: schema.GroupVersion{
Group: src.Group,
Version: src.Version,
},
resource: src.Resource,
resourceVersion: resourceVersion,
namespace: src.Namespace,
body: body,
maxRetries: maxRetries,
}
}

// Build implements RequestBuilder.Build.
func (b *requestPOSTBuilder) Build(cli rest.Interface) Requester {
// https://kubernetes.io/docs/reference/using-api/#api-groups
comps := make([]string, 0, 5)
if b.version.Group == "" {
comps = append(comps, "api", b.version.Version)
} else {
comps = append(comps, "apis", b.version.Group, b.version.Version)
}
if b.namespace != "" {
comps = append(comps, "namespaces", b.namespace)
}
comps = append(comps, b.resource)

return &DiscardRequester{
BaseRequester: BaseRequester{
method: "POST",
req: cli.Post().AbsPath(comps...).
Body(b.body).
MaxRetries(b.maxRetries),
},
}
}

func toPtr[T any](v T) *T {
return &v
}
Loading