Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal- Porch Performance Testing Framework - Operation Flow with Prometheus #174

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
49 changes: 49 additions & 0 deletions test/performance/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

package metrics

import (
"fmt"
"log"
"os"
"path/filepath"
"testing"
"time"
)

type TestLogger struct {
t *testing.T
file *os.File
logger *log.Logger
}

func NewTestLogger(t *testing.T) (*TestLogger, error) {
// Create logs directory if it doesn't exist
logsDir := "logs"
if err := os.MkdirAll(logsDir, 0755); err != nil {
return nil, fmt.Errorf("failed to create logs directory: %v", err)
}

// Create log file with timestamp
timestamp := time.Now().Format("2006-01-02-15-04-05")
filename := filepath.Join(logsDir, fmt.Sprintf("porch-metrics-%s.log", timestamp))
file, err := os.Create(filename)
if err != nil {
return nil, fmt.Errorf("failed to create log file: %v", err)
}

logger := log.New(file, "", 0) // Remove timestamp from log entries
return &TestLogger{
t: t,
file: file,
logger: logger,
}, nil
}

func (l *TestLogger) Close() error {
return l.file.Close()
}

func (l *TestLogger) LogResult(format string, args ...interface{}) {
// Log only to file
l.logger.Printf(format, args...)
}
162 changes: 162 additions & 0 deletions test/performance/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package metrics

import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"testing"
"time"

porchapi "github.com/nephio-project/porch/api/porch/v1alpha1"
configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1"
"github.com/nephio-project/porch/api/generated/clientset/versioned"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var (
scheme = runtime.NewScheme()
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(porchapi.AddToScheme(scheme))
utilruntime.Must(configapi.AddToScheme(scheme))
}

// Helper functions for metrics collection and operations
func getPorchClientset(cfg *rest.Config) (*versioned.Clientset, error) {
return versioned.NewForConfig(cfg)
}

func createGiteaRepo(repoName string) error {
giteaURL := "http://172.18.255.200:3000/api/v1/user/repos"
payload := map[string]interface{}{
"name": repoName,
"description": "Test repository for Porch metrics",
"private": false,
"auto_init": true,
}

jsonPayload, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("failed to marshal payload: %v", err)
}

req, err := http.NewRequest("POST", giteaURL, bytes.NewBuffer(jsonPayload))
if err != nil {
return fmt.Errorf("failed to create request: %v", err)
}

req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("nephio", "secret")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to create repo: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusCreated {
return fmt.Errorf("failed to create repo, status: %d", resp.StatusCode)
}

return nil
}

func debugPackageStatus(t *testing.T, c client.Client, ctx context.Context, namespace, name string) {
var pkg porchapi.PackageRevision
err := c.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &pkg)
if err != nil {
t.Logf("Error getting package: %v", err)
return
}

t.Logf("\nPackage Status Details:")
t.Logf(" Name: %s", pkg.Name)
t.Logf(" LifecycleState: %s", pkg.Spec.Lifecycle)
t.Logf(" WorkspaceName: %s", pkg.Spec.WorkspaceName)
t.Logf(" Revision: %s", pkg.Spec.Revision)
t.Logf(" Published: %v", pkg.Status.PublishedAt)
t.Logf(" Tasks:")
for i, task := range pkg.Spec.Tasks {
t.Logf(" %d. Type: %s", i+1, task.Type)
if task.Type == porchapi.TaskTypeInit && task.Init != nil {
t.Logf(" Description: %s", task.Init.Description)
t.Logf(" Keywords: %v", task.Init.Keywords)
}
}
t.Logf(" Conditions:")
for _, cond := range pkg.Status.Conditions {
t.Logf(" - Type: %s", cond.Type)
t.Logf(" Status: %s", cond.Status)
t.Logf(" Message: %s", cond.Message)
t.Logf(" Reason: %s", cond.Reason)
}
}

// ... existing imports and code ...

func deleteGiteaRepo(repoName string) error {
giteaURL := fmt.Sprintf("http://172.18.255.200:3000/api/v1/repos/nephio/%s", repoName)

req, err := http.NewRequest("DELETE", giteaURL, nil)
if err != nil {
return fmt.Errorf("failed to create delete request: %v", err)
}

req.SetBasicAuth("nephio", "secret")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to delete repo: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusNotFound {
return fmt.Errorf("failed to delete repo, status: %d", resp.StatusCode)
}

return nil
}
func waitForRepository(ctx context.Context, c client.Client, t *testing.T, namespace, name string, timeout time.Duration) error {
start := time.Now()
for {
if time.Since(start) > timeout {
return fmt.Errorf("timeout waiting for repository to be ready")
}

var repo configapi.Repository
err := c.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &repo)
if err != nil {
return err
}

t.Logf("\nRepository conditions at %v:", time.Since(start))
t.Logf("Spec: %+v", repo.Spec)
t.Logf("Status: %+v", repo.Status)

ready := false
for _, cond := range repo.Status.Conditions {
t.Logf(" - Type: %s, Status: %s, Message: %s",
cond.Type, cond.Status, cond.Message)
if cond.Type == "Ready" && cond.Status == "True" {
ready = true
break
}
}

if ready {
return nil
}

time.Sleep(2 * time.Second)
}
}
Loading
Loading