Skip to content

Commit

Permalink
test and template for stats
Browse files Browse the repository at this point in the history
Signed-off-by: Rohit-PX <rkulkarni@purestorage.com>
  • Loading branch information
Rohit-PX committed Mar 9, 2023
1 parent 6e7426d commit a236b6e
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 61 deletions.
63 changes: 43 additions & 20 deletions pkg/utils/export_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,28 @@ import (
"fmt"
"io/ioutil"
"net/http"
"strconv"
"time"

storkv1 "github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
"github.com/sirupsen/logrus"
)

const (
aetosStatsURL = "http://aetos.pwx.purestorage.com/dashboard/stats?stats_type=migration_stats_new&limit=100"
AetosStatsURL = "http://aetos.pwx.purestorage.com/dashboard/stats?stats_type=migration_stats_mock&limit=100"
)

var StorkVersion string
var PXVersion string

type StatsExportType struct {
id OidType `json:"_id",omitempty`
Name string `json:"name",omitempty`
Product string `json:"product",omitempty`
StatsType string `json:"statsType",omitempty`
Version string `json:"version",omitempty`
Data MigrationStatsType `json:"data",omitempty`
id OidType `json:"_id",omitempty`
Name string `json:"name",omitempty`
Product string `json:"product",omitempty`
StatsType string `json:"statsType",omitempty`
StorkVersion string `json:"storkVersion",omitempty`
PortworxVersion string `json:"portworxVersion",omitempty`
Data MigrationStatsType `json:"data",omitempty`
}

type MigrationStatsType struct {
Expand All @@ -39,6 +44,8 @@ type OidType struct {
oid string `json:"$oid"`
}

type AllStats []StatsExportType

func GetMigrationStatsFromAetos(url string) ([]StatsExportType, error) {
client := http.Client{Timeout: time.Second * 3}
req, err := http.NewRequest("GET", url, nil)
Expand Down Expand Up @@ -68,7 +75,7 @@ func GetMigrationStatsFromAetos(url string) ([]StatsExportType, error) {
}

//fmt.Printf("\nBody of response: %v\n\n", string(body))
data := []StatsExportType{}
data := AllStats{}
err = json.Unmarshal(body, &data)
if err != nil {
return nil, fmt.Errorf("error parsing Aetos metadata: %v", err)
Expand Down Expand Up @@ -131,10 +138,11 @@ func MockStat() StatsExportType {

func NewStat() StatsExportType {
newStat := StatsExportType{
Name: "stork_integration_test",
Product: "stork",
StatsType: "migration_stats_mock",
Version: "v1alpha1",
Name: "stork_integration_test",
Product: "stork",
StatsType: "migration_stats_mock",
StorkVersion: StorkVersion,
PortworxVersion: PXVersion,
Data: MigrationStatsType{
TotalNumberOfVolumes: "",
NumOfMigratedVolumes: "",
Expand All @@ -150,22 +158,37 @@ func NewStat() StatsExportType {

func GetExportableStatsFromMigrationObject(mig *storkv1.Migration) StatsExportType {
exportStats := NewStat()
exportStats.Data.TotalNumberOfVolumes = json.Number(mig.Status.Summary.TotalNumberOfVolumes)
exportStats.Data.NumOfMigratedVolumes = json.Number(mig.Status.Summary.NumberOfMigratedVolumes)
exportStats.Data.TotalNumberOfResources = json.Number(mig.Status.Summary.TotalNumberOfResources)
exportStats.Data.NumOfMigratedResources = json.Number(mig.Status.Summary.NumberOfMigratedResources)
exportStats.Data.TotalBytesMigrated = json.Number(mig.Status.Summary.TotalBytesMigrated)

exportStats.Data.TotalNumberOfVolumes = json.Number(strconv.FormatUint(mig.Status.Summary.TotalNumberOfVolumes, 10))
fmt.Println("Total vol:", exportStats.Data.TotalNumberOfVolumes)

exportStats.Data.NumOfMigratedVolumes = json.Number(strconv.FormatUint(mig.Status.Summary.NumberOfMigratedVolumes, 10))
fmt.Println("Num mig vol:", exportStats.Data.NumOfMigratedVolumes)

exportStats.Data.TotalNumberOfResources = json.Number(strconv.FormatUint(mig.Status.Summary.TotalNumberOfResources, 10))
fmt.Println("Total num of resources:", mig.Status.Summary.TotalNumberOfResources)

exportStats.Data.NumOfMigratedResources = json.Number(strconv.FormatUint(mig.Status.Summary.NumberOfMigratedResources, 10))
fmt.Println("Number of mig resources:", exportStats.Data.NumOfMigratedResources)

exportStats.Data.TotalBytesMigrated = json.Number(strconv.FormatUint(mig.Status.Summary.TotalBytesMigrated, 10))
fmt.Println("Total bytes mig:", exportStats.Data.TotalBytesMigrated)

exportStats.Data.ElapsedTimeForVolumeMigration = mig.Status.Summary.ElapsedTimeForVolumeMigration
fmt.Println("Elapsed time for vol mi:", exportStats.Data.ElapsedTimeForVolumeMigration)

exportStats.Data.ElapsedTimeForResourceMigration = mig.Status.Summary.ElapsedTimeForResourceMigration
fmt.Println("Elapsed time resource mig:", exportStats.Data.ElapsedTimeForResourceMigration)

PrettyStruct(exportStats)
return exportStats

}

func PrettyStruct(data interface{}) (string, error) {
func PrettyStruct(data interface{}) {
val, err := json.MarshalIndent(data, "", " ")
if err != nil {
return "", err
logrus.Panicf("Failed to prettify data")
}
return string(val), nil
fmt.Printf("Structured data: %v", string(val))
}
7 changes: 7 additions & 0 deletions test/integration_test/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

snapv1 "github.com/kubernetes-incubator/external-storage/snapshot/pkg/apis/crd/v1"
oputils "github.com/libopenstorage/operator/drivers/storage/portworx/util"
storkdriver "github.com/libopenstorage/stork/drivers/volume"
_ "github.com/libopenstorage/stork/drivers/volume/aws"
_ "github.com/libopenstorage/stork/drivers/volume/azure"
Expand All @@ -24,6 +25,7 @@ import (
storkv1 "github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
"github.com/libopenstorage/stork/pkg/schedule"
"github.com/libopenstorage/stork/pkg/storkctl"
"github.com/libopenstorage/stork/pkg/utils"
"github.com/libopenstorage/stork/pkg/version"
"github.com/portworx/sched-ops/k8s/apps"
"github.com/portworx/sched-ops/k8s/core"
Expand Down Expand Up @@ -119,6 +121,8 @@ var backupLocationPath string
var genericCsiConfigMap string
var externalTest bool
var storkVersionCheck bool
var storkVersion string
var pxVersion string
var cloudDeletionValidate bool

func TestSnapshot(t *testing.T) {
Expand Down Expand Up @@ -231,6 +235,9 @@ func setup() error {
if !ok {
return fmt.Errorf("stork version not found in configmap: %s", cmName)
}
utils.StorkVersion = ver
utils.PXVersion = oputils.GetPortworxVersion()
logrus.Infof("RK=> Stork test is running with stork version version: %s", StorkVersion)
if getStorkVersion(ver) != getStorkVersion(version.Version) {
return fmt.Errorf("stork version mismatch, found: %s, expected: %s", getStorkVersion(ver), getStorkVersion(version.Version))
}
Expand Down
96 changes: 96 additions & 0 deletions test/integration_test/migration_stats_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package integrationtest

import (
"html/template"
"os"
"testing"

"github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
"github.com/libopenstorage/stork/pkg/utils"
storkops "github.com/portworx/sched-ops/k8s/stork"
"github.com/portworx/torpedo/drivers/scheduler"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)

func TestMigrationExportStats(t *testing.T) {
t.Run("migrationStatsExportTest", migrationStatsExportTest)
t.Run("migrationStatsDisplayTest", migrationStatsDisplayTest)
}

func migrationStatsExportTest(t *testing.T) {
var err error
// Reset config in case of error
defer func() {
err = setSourceKubeConfig()
require.NoError(t, err, "Error resetting source config")
}()

migrationKey := "mysql-migration"
migrationAppKey := "mysql-1-pvc"
includeResourcesFlag := true
startApplicationsFlag := false

currCtxs, err := schedulerDriver.Schedule(migrationKey,
scheduler.ScheduleOptions{AppKeys: []string{migrationAppKey}})
require.NoError(t, err, "Error scheduling task")
require.Equal(t, 1, len(currCtxs), "Only one task should have started")

err = schedulerDriver.WaitForRunning(currCtxs[0], defaultWaitTimeout, defaultWaitInterval)
require.NoError(t, err, "Error waiting for app to get to running state")

// create, apply and validate cluster pair specs
err = scheduleClusterPair(currCtxs[0], false, true, defaultClusterPairDir, "", false)
require.NoError(t, err, "Error scheduling cluster pair")

currMigNamespace := migrationAppKey + "-" + migrationKey
currMig, err := createMigration(t, migrationKey, currMigNamespace, "remoteclusterpair", currMigNamespace, &includeResourcesFlag, &startApplicationsFlag)
require.NoError(t, err, "failed to create migration: %s in namespace %s", migrationKey, currMigNamespace)

migrationList := []*v1alpha1.Migration{currMig}
err = WaitForMigration(migrationList)
require.NoError(t, err, "error in migrations for exported stats")

finishedMig, err := storkops.Instance().GetMigration(currMig.Name, currMig.Namespace)
require.Nil(t, err, "could not get completed migration")

logrus.Infof("Migration Object Status: %v", finishedMig.Status.Summary)
exportableStat := utils.GetExportableStatsFromMigrationObject(finishedMig)
require.NotNil(t, exportableStat, "could not fetch stats from migration object")

// Export stats to Aetos Mongo DB
err = utils.WriteMigrationStatsToAetos(exportableStat)
require.NoError(t, err, "error while writing stats to mongo DB")

// Get stats from Aetos Mongo DB
stats, err := utils.GetMigrationStatsFromAetos(utils.AetosStatsURL)
require.NoError(t, err, "error while fetching stats from mongo DB")

// Print stats to the console for now
utils.PrettyStruct(stats)
}

func migrationStatsDisplayTest(t *testing.T) {
var err error
// Get stats from Aetos Mongo DB
stats, err := utils.GetMigrationStatsFromAetos(utils.AetosStatsURL)
require.NoError(t, err, "error while fetching stats from mongo DB")

// Print stats to the console for now
utils.PrettyStruct(stats)

paths := []string{
"/specs/stats.tmpl",
}

// create a new file
//err := os.MkdirAll("/reports", 0777)
file, _ := os.Create("/reports/migstats.html")

templ := template.Must(template.ParseFiles(paths...))
err = templ.Execute(file, stats)
if err != nil {
panic(err)
}
file.Close()
}
42 changes: 1 addition & 41 deletions test/integration_test/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"time"

"github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
"github.com/libopenstorage/stork/pkg/utils"
"github.com/portworx/sched-ops/k8s/apps"
"github.com/portworx/sched-ops/k8s/core"
storkops "github.com/portworx/sched-ops/k8s/stork"
Expand Down Expand Up @@ -56,7 +55,6 @@ func testMigration(t *testing.T) {
err = setSourceKubeConfig()
require.NoError(t, err, "failed to set kubeconfig to source cluster: %v", err)

t.Run("migrationStatsExportTest", migrationStatsExportTest)
t.Run("deploymentTest", deploymentMigrationTest)
t.Run("deploymentMigrationReverseTest", deploymentMigrationReverseTest)
t.Run("statefulsetTest", statefulsetMigrationTest)
Expand Down Expand Up @@ -1131,7 +1129,7 @@ func WaitForMigration(migrationList []*v1alpha1.Migration) error {
return "", false, err
}
if mig.Status.Status != v1alpha1.MigrationStatusSuccessful {
logrus.Infof("Migration %s in namespace %s is pending", m.Name, m.Namespace)
logrus.Infof("Migration %s in namespace %s is pending: %v", m.Name, m.Namespace, mig.Status.Status)
isComplete = false
}
}
Expand Down Expand Up @@ -1551,41 +1549,3 @@ func transformResourceTest(t *testing.T) {
require.NoError(t, err, "failed to set kubeconfig to source cluster: %v", err)
validateAndDestroyMigration(t, ctxs, preMigrationCtx, true, false, true, false, true)
}

func migrationStatsExportTest(t *testing.T) {
var err error
// Reset config in case of error
defer func() {
err = setSourceKubeConfig()
require.NoError(t, err, "Error resetting source config")
}()

migrationKey := "mysql-migration"
migrationAppKey := "mysql-1-pvc"
includeResourcesFlag := true
startApplicationsFlag := false

currCtxs, err := schedulerDriver.Schedule(migrationKey,
scheduler.ScheduleOptions{AppKeys: []string{migrationAppKey}})
require.NoError(t, err, "Error scheduling task")
require.Equal(t, 1, len(currCtxs), "Only one task should have started")

err = schedulerDriver.WaitForRunning(currCtxs[0], defaultWaitTimeout, defaultWaitInterval)
require.NoError(t, err, "Error waiting for app to get to running state")

// create, apply and validate cluster pair specs
err = scheduleClusterPair(currCtxs[0], false, true, defaultClusterPairDir, "", false)
require.NoError(t, err, "Error scheduling cluster pair")

currMigNamespace := migrationAppKey + "-" + migrationKey
currMig, err := createMigration(t, migrationKey, currMigNamespace, "remoteclusterpair", currMigNamespace, &includeResourcesFlag, &startApplicationsFlag)
require.NoError(t, err, "failed to create migration: %s in namespace %s", migrationKey, currMigNamespace)

migrationList := []*v1alpha1.Migration{currMig}
err = WaitForMigration(migrationList)
require.NoError(t, err, "Error in scaled migrations")

exportableStat := utils.GetExportableStatsFromMigrationObject(currMig)
// Export stats to Aetos Mongo DB
err = utils.WriteMigrationStatsToAetos(exportableStat)
}
38 changes: 38 additions & 0 deletions test/integration_test/specs/stats.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Go To-Do list</title>
</head>
<body>
<p>
Stats for migration:
</p>
<table border="2">
<tr>
<td>Name</td>
<td>Version</td>
<td>Total Volumes</td>
<td>Migrated Volume</td>
<td>Total Resources</td>
<td>Migrated Resources</td>
<td>Total Bytes Migrated</td>
<td>Elapsed time for Volume Migration</td>
<td>Elapsed time for Resource Migration</td>
</tr>
{{ range $idx, $item := . }}
<tr>
<td>{{ $item.Name }}</td>
<td>{{ $item.StorkVersion }}</td>
<td>{{ $item.PortworxVersion }}</td>
<td>{{ $item.Data.TotalNumberOfVolumes }}</td>
<td>{{ $item.Data.NumOfMigratedVolumes }}</td>
<td>{{ $item.Data.TotalNumberOfResources }}</td>
<td>{{ $item.Data.NumOfMigratedResources }}</td>
<td>{{ $item.Data.TotalBytesMigrated }}</td>
<td>{{ $item.Data.ElapsedTimeForVolumeMigration }}</td>
<td>{{ $item.Data.ElapsedTimeForResourceMigration }}</td>
</tr>
{{ end }}
</table>
</body>
</html>

0 comments on commit a236b6e

Please sign in to comment.