...

Source file src/edge-infra.dev/pkg/edge/controllers/util/edgedb/embedded_sql_test.go

Documentation: edge-infra.dev/pkg/edge/controllers/util/edgedb

     1  package edgedb
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/google/uuid"
    10  
    11  	"edge-infra.dev/pkg/edge/api/testutils/seededpostgres"
    12  	bannerApi "edge-infra.dev/pkg/edge/apis/banner/v1alpha1"
    13  	clusterApi "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1"
    14  	gkeclusterApi "edge-infra.dev/pkg/edge/apis/gkecluster/v1alpha1"
    15  	"edge-infra.dev/pkg/edge/controllers/dbmetrics"
    16  	"edge-infra.dev/pkg/k8s/runtime/conditions"
    17  	"edge-infra.dev/pkg/lib/build/bazel"
    18  
    19  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    20  )
    21  
    22  var edb *EdgeDB
    23  
    24  func TestRecordInfraStatus(t *testing.T) {
    25  	if !bazel.IsBazelTest() && !bazel.IsBazelRun() {
    26  		t.Skip()
    27  		return
    28  	}
    29  
    30  	sp, err := seededpostgres.New()
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	db, err := sp.DB()
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  
    39  	edb = &EdgeDB{DB: db}
    40  
    41  	defer func() {
    42  		_ = db.Close()
    43  		_ = sp.Close()
    44  	}()
    45  
    46  	t.Run("banner", testStatusForBannerAPI)
    47  	t.Run("cluster", testStatusForClusterAPI)
    48  	t.Run("gkecluster", testStatusForGKEClusterAPI)
    49  	t.Run("store", testStoreClusterArtifacts)
    50  }
    51  
    52  // nolint: dupl
    53  func testStatusForBannerAPI(t *testing.T) {
    54  	// Get a banner_edge_id
    55  	var bannerEdgeID string
    56  
    57  	row := edb.DB.QueryRow("SELECT banner_edge_id FROM banners LIMIT 1")
    58  	if err := row.Err(); err != nil {
    59  		t.Fatal(err)
    60  	} else if err = row.Scan(&bannerEdgeID); err != nil {
    61  		t.Fatal(err)
    62  	}
    63  
    64  	var now = time.Now().UTC().Round(time.Second)
    65  	var banner = &bannerApi.Banner{
    66  		TypeMeta: metav1.TypeMeta{
    67  			Kind: bannerApi.BannerKind,
    68  		},
    69  		ObjectMeta: metav1.ObjectMeta{
    70  			Name: bannerEdgeID,
    71  		},
    72  		Status: bannerApi.BannerStatus{
    73  			Conditions: make([]metav1.Condition, 1),
    74  		},
    75  	}
    76  
    77  	// Test InfraStatusReady
    78  	banner.Status.Conditions[0] = metav1.Condition{
    79  		Type:               "Ready",
    80  		Status:             metav1.ConditionTrue,
    81  		Message:            "banner reconciled successfully",
    82  		Reason:             bannerApi.ProvisionSucceededReason,
    83  		ObservedGeneration: 1,
    84  		LastTransitionTime: metav1.Time{Time: now},
    85  	}
    86  
    87  	edb.RecordInfraStatus(context.Background(), banner, dbmetrics.DBMetrics{})
    88  	validateExpectedInfraStatus(t, banner)
    89  
    90  	// Test InfraStatusError
    91  	banner.Status.Conditions[0] = metav1.Condition{
    92  		Type:               "Ready",
    93  		Status:             metav1.ConditionFalse,
    94  		Message:            "oof",
    95  		Reason:             "OofReason",
    96  		ObservedGeneration: 1,
    97  		LastTransitionTime: metav1.Time{Time: now},
    98  	}
    99  
   100  	edb.RecordInfraStatus(context.Background(), banner, dbmetrics.DBMetrics{})
   101  	validateExpectedInfraStatus(t, banner)
   102  }
   103  
   104  // nolint: dupl
   105  func testStatusForGKEClusterAPI(t *testing.T) {
   106  	var (
   107  		clusterEdgeID = uuid.NewString()
   108  		clusterName   = "gkeclusterFooName"
   109  	)
   110  
   111  	// Setup cluster in database.
   112  	result, err := edb.DB.Exec("INSERT INTO clusters (cluster_edge_id, cluster_name) VALUES ($1, $2)", clusterEdgeID, clusterName)
   113  	if err != nil {
   114  		t.Logf("Got result: %v", result)
   115  		t.Fatal(err)
   116  	} else if ra, err := result.RowsAffected(); err != nil {
   117  		t.Fatal(err)
   118  	} else if ra != 1 {
   119  		t.Fatalf("Got %d rows affected by insert", ra)
   120  	}
   121  
   122  	var now = time.Now().UTC().Round(time.Second)
   123  	var cluster = &gkeclusterApi.GKECluster{
   124  		TypeMeta: metav1.TypeMeta{
   125  			Kind: gkeclusterApi.Kind,
   126  		},
   127  		ObjectMeta: metav1.ObjectMeta{
   128  			Name: clusterEdgeID,
   129  		},
   130  		Status: gkeclusterApi.GKEClusterStatus{
   131  			Conditions: make([]metav1.Condition, 1),
   132  		},
   133  	}
   134  
   135  	// Test InfraStatusReady
   136  	cluster.Status.Conditions[0] = metav1.Condition{
   137  		Type:               "Ready",
   138  		Status:             metav1.ConditionTrue,
   139  		Message:            "gkecluster reconciled successfully",
   140  		Reason:             gkeclusterApi.GKEClusterReadyReason,
   141  		ObservedGeneration: 1,
   142  		LastTransitionTime: metav1.Time{Time: now},
   143  	}
   144  
   145  	edb.RecordInfraStatus(context.Background(), cluster, dbmetrics.DBMetrics{})
   146  	validateExpectedInfraStatus(t, cluster)
   147  
   148  	// Test InfraStatusError
   149  	cluster.Status.Conditions[0] = metav1.Condition{
   150  		Type:               "Ready",
   151  		Status:             metav1.ConditionFalse,
   152  		Message:            "oof",
   153  		Reason:             "OofReason",
   154  		ObservedGeneration: 1,
   155  		LastTransitionTime: metav1.Time{Time: now},
   156  	}
   157  
   158  	edb.RecordInfraStatus(context.Background(), cluster, dbmetrics.DBMetrics{})
   159  	validateExpectedInfraStatus(t, cluster)
   160  }
   161  
   162  // nolint: dupl
   163  func testStatusForClusterAPI(t *testing.T) {
   164  	var (
   165  		clusterEdgeID = uuid.NewString()
   166  		clusterName   = "clusterNameFoo"
   167  	)
   168  
   169  	// Setup cluster in database.
   170  	result, err := edb.DB.Exec("INSERT INTO clusters (cluster_edge_id, cluster_name) VALUES ($1, $2)", clusterEdgeID, clusterName)
   171  	if err != nil {
   172  		t.Logf("Got result: %v", result)
   173  		t.Fatal(err)
   174  	} else if ra, err := result.RowsAffected(); err != nil {
   175  		t.Fatal(err)
   176  	} else if ra != 1 {
   177  		t.Fatalf("Got %d rows affected by insert", ra)
   178  	}
   179  
   180  	var now = time.Now().UTC().Round(time.Second)
   181  	var cluster = &clusterApi.Cluster{
   182  		TypeMeta: metav1.TypeMeta{
   183  			Kind: clusterApi.Kind,
   184  		},
   185  		ObjectMeta: metav1.ObjectMeta{
   186  			Name: clusterEdgeID,
   187  		},
   188  		Status: clusterApi.ClusterStatus{
   189  			Conditions: make([]metav1.Condition, 1),
   190  		},
   191  	}
   192  
   193  	// Test InfraStatusReady
   194  	cluster.Status.Conditions[0] = metav1.Condition{
   195  		Type:               "Ready",
   196  		Status:             metav1.ConditionTrue,
   197  		Message:            "cluster reconciled successfully",
   198  		Reason:             clusterApi.ClusterReadyReason,
   199  		ObservedGeneration: 1,
   200  		LastTransitionTime: metav1.Time{Time: now},
   201  	}
   202  
   203  	edb.RecordInfraStatus(context.Background(), cluster, dbmetrics.DBMetrics{})
   204  	validateExpectedInfraStatus(t, cluster)
   205  
   206  	// Test InfraStatusError
   207  	cluster.Status.Conditions[0] = metav1.Condition{
   208  		Type:               "Ready",
   209  		Status:             metav1.ConditionFalse,
   210  		Message:            "oof",
   211  		Reason:             "OofReason",
   212  		ObservedGeneration: 1,
   213  		LastTransitionTime: metav1.Time{Time: now},
   214  	}
   215  
   216  	edb.RecordInfraStatus(context.Background(), cluster, dbmetrics.DBMetrics{})
   217  	validateExpectedInfraStatus(t, cluster)
   218  }
   219  
   220  const (
   221  	sqlSelectClusterInfraStatus = "SELECT infra_status, infra_status_details, infra_status_updated_at FROM clusters WHERE cluster_edge_id=$1"
   222  	sqlSelectBannerInfraStatus  = "SELECT infra_status, infra_status_details, infra_status_updated_at FROM banners WHERE banner_edge_id=$1"
   223  )
   224  
   225  func validateExpectedInfraStatus(t *testing.T, obj conditions.Getter) {
   226  	var stmt string
   227  	switch obj.GetObjectKind().GroupVersionKind().Kind {
   228  	case clusterApi.Kind, gkeclusterApi.Kind:
   229  		stmt = sqlSelectClusterInfraStatus
   230  	case bannerApi.BannerKind:
   231  		stmt = sqlSelectBannerInfraStatus
   232  	default:
   233  		t.Fatalf("Unknown object %v", obj)
   234  	}
   235  
   236  	var edgeID = obj.GetName()
   237  	row := edb.DB.QueryRow(stmt, edgeID)
   238  	if err := row.Err(); err != nil {
   239  		t.Fatal(err)
   240  	}
   241  
   242  	var got struct {
   243  		Status    string
   244  		Details   string
   245  		UpdatedAt time.Time
   246  	}
   247  	err := row.Scan(&got.Status, &got.Details, &got.UpdatedAt)
   248  	if err != nil {
   249  		t.Fatal(err)
   250  	}
   251  
   252  	// Expected details (formatted using the same code as the controller)
   253  	cond := obj.GetConditions()[0]
   254  	var enum InfraStatus
   255  	if cond.Status == metav1.ConditionTrue {
   256  		enum = InfraStatusReady
   257  	} else {
   258  		enum = InfraStatusError
   259  	}
   260  	var details = fmt.Sprintf("%s: %s", cond.Reason, cond.Message)
   261  	var when = cond.LastTransitionTime.Time
   262  
   263  	if got.Status != string(enum) {
   264  		t.Fatalf("Got infra_status %q and expected %q", got.Status, enum)
   265  	} else if got.Details != details {
   266  		t.Fatalf("Got infra_status_details %q and expected %q", got.Details, details)
   267  	} else if !got.UpdatedAt.Equal(when) {
   268  		t.Fatalf("Got infra_status_updated_at %q and expeceted %q", got.UpdatedAt, when)
   269  	}
   270  	t.Logf("successfully set InfraStatus=%q for %s", enum, obj.GetObjectKind().GroupVersionKind().Kind)
   271  }
   272  
   273  func testStoreClusterArtifacts(t *testing.T) {
   274  	storeID := "dc8e59c3-6338-4c28-a776-f54e93a19ff4"
   275  	artifacts, err := edb.GetClusterArtifactVersions(context.Background(), storeID)
   276  	if err != nil {
   277  		t.Fatal(err)
   278  	}
   279  	if len(artifacts) != 1 {
   280  		t.Fatalf("got %d artifact for store and expected 1", len(artifacts))
   281  	}
   282  	name := artifacts[0].Name
   283  	version := artifacts[0].Version
   284  	if name != "store" || version != "0.14.0-seed" {
   285  		t.Fatalf("got %s:%s artifact for store and expected store:0.14.0-seed", name, version)
   286  	}
   287  }
   288  

View as plain text