зеркало из https://github.com/Azure/ARO-RP.git
query + tests for maintenancemanifests
This commit is contained in:
Родитель
e9a940316e
Коммит
e4be577423
|
@ -1,5 +1,8 @@
|
|||
package admin
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import "github.com/Azure/ARO-RP/pkg/api"
|
||||
|
||||
type maintenanceManifestConverter struct{}
|
||||
|
|
|
@ -5,14 +5,18 @@ package frontend
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ugorji/go/codec"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/api/admin"
|
||||
"github.com/Azure/ARO-RP/pkg/frontend/middleware"
|
||||
)
|
||||
|
||||
|
@ -20,7 +24,7 @@ func (f *frontend) getAdminMaintManifests(w http.ResponseWriter, r *http.Request
|
|||
ctx := r.Context()
|
||||
log := ctx.Value(middleware.ContextKeyLog).(*logrus.Entry)
|
||||
resourceID := strings.TrimPrefix(filepath.Dir(r.URL.Path), "/admin")
|
||||
b, err := f._getAdminMaintManifests(ctx, resourceID)
|
||||
b, err := f._getAdminMaintManifests(ctx, r, resourceID)
|
||||
|
||||
if cloudErr, ok := err.(*api.CloudError); ok {
|
||||
api.WriteCloudError(w, cloudErr)
|
||||
|
@ -30,28 +34,65 @@ func (f *frontend) getAdminMaintManifests(w http.ResponseWriter, r *http.Request
|
|||
adminReply(log, w, nil, b, err)
|
||||
}
|
||||
|
||||
func (f *frontend) _getAdminMaintManifests(ctx context.Context, resourceID string) ([]byte, error) {
|
||||
doc, err := f.dbOpenShiftClusters.Get(ctx, resourceID)
|
||||
func (f *frontend) _getAdminMaintManifests(ctx context.Context, r *http.Request, resourceID string) ([]byte, error) {
|
||||
limitstr := r.URL.Query().Get("limit")
|
||||
limit, err := strconv.Atoi(limitstr)
|
||||
if err != nil {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
converter := f.apis[admin.APIVersion].MaintenanceManifestConverter
|
||||
|
||||
dbOpenShiftClusters, err := f.dbGroup.OpenShiftClusters()
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", err.Error())
|
||||
}
|
||||
|
||||
dbMaintenanceManifests, err := f.dbGroup.MaintenanceManifests()
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", err.Error())
|
||||
}
|
||||
|
||||
doc, err := dbOpenShiftClusters.Get(ctx, resourceID)
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusNotFound, api.CloudErrorCodeNotFound, "", "cluster not found")
|
||||
}
|
||||
|
||||
f.dbOpenShiftVersions
|
||||
|
||||
if doc.OpenShiftCluster.Properties.HiveProfile.Namespace == "" {
|
||||
return nil, api.NewCloudError(http.StatusNoContent, api.CloudErrorCodeResourceNotFound, "", "cluster is not managed by hive")
|
||||
if doc.OpenShiftCluster.Properties.ProvisioningState == api.ProvisioningStateDeleting {
|
||||
return nil, api.NewCloudError(http.StatusNotFound, api.CloudErrorCodeNotFound, "", "cluster being deleted")
|
||||
}
|
||||
|
||||
cd, err := f.hiveClusterManager.GetClusterDeployment(ctx, doc)
|
||||
skipToken, err := f.parseSkipToken(r.URL.String())
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusNotFound, api.CloudErrorCodeNotFound, "", "cluster deployment not found")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var b []byte
|
||||
err = codec.NewEncoderBytes(&b, &codec.JsonHandle{}).Encode(cd)
|
||||
i, err := dbMaintenanceManifests.GetByClusterResourceID(ctx, resourceID, skipToken)
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "unable to marshal response")
|
||||
return nil, api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", err.Error())
|
||||
}
|
||||
|
||||
return b, nil
|
||||
docList := make([]*api.MaintenanceManifestDocument, 0)
|
||||
for {
|
||||
docs, err := i.Next(ctx, int(math.Min(float64(limit), 10)))
|
||||
if err != nil {
|
||||
return nil, api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", fmt.Errorf("failed reading next manifest document: %w", err).Error())
|
||||
}
|
||||
if docs == nil {
|
||||
break
|
||||
}
|
||||
|
||||
docList = append(docList, docs.MaintenanceManifestDocuments...)
|
||||
|
||||
if len(docList) >= limit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
nextLink, err := f.buildNextLink(r.Header.Get("Referer"), i.Continuation())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.MarshalIndent(converter.ToExternalList(docList, nextLink), "", " ")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
package frontend
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/api/admin"
|
||||
"github.com/Azure/ARO-RP/pkg/metrics/noop"
|
||||
testdatabase "github.com/Azure/ARO-RP/test/database"
|
||||
)
|
||||
|
||||
func TestMIMOList(t *testing.T) {
|
||||
mockSubID := "00000000-0000-0000-0000-000000000000"
|
||||
mockTenantID := "00000000-0000-0000-0000-000000000000"
|
||||
resourceID := fmt.Sprintf("/subscriptions/%s/resourcegroups/resourceGroup/providers/Microsoft.RedHatOpenShift/openShiftClusters/resourceName", mockSubID)
|
||||
ctx := context.Background()
|
||||
|
||||
type test struct {
|
||||
name string
|
||||
fixtures func(f *testdatabase.Fixture)
|
||||
limit int
|
||||
wantStatusCode int
|
||||
wantResponse *admin.MaintenanceManifestList
|
||||
wantError string
|
||||
}
|
||||
|
||||
for _, tt := range []*test{
|
||||
{
|
||||
name: "no entries",
|
||||
fixtures: func(f *testdatabase.Fixture) {
|
||||
f.AddOpenShiftClusterDocuments(&api.OpenShiftClusterDocument{
|
||||
Key: strings.ToLower(resourceID),
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
ID: resourceID,
|
||||
Name: "resourceName",
|
||||
Type: "Microsoft.RedHatOpenShift/openshiftClusters",
|
||||
},
|
||||
})
|
||||
},
|
||||
wantResponse: &admin.MaintenanceManifestList{
|
||||
MaintenanceManifests: []*admin.MaintenanceManifest{},
|
||||
},
|
||||
wantStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "single entry",
|
||||
fixtures: func(f *testdatabase.Fixture) {
|
||||
f.AddOpenShiftClusterDocuments(&api.OpenShiftClusterDocument{
|
||||
Key: strings.ToLower(resourceID),
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
ID: resourceID,
|
||||
Name: "resourceName",
|
||||
Type: "Microsoft.RedHatOpenShift/openshiftClusters",
|
||||
},
|
||||
})
|
||||
f.AddMaintenanceManifestDocuments(&api.MaintenanceManifestDocument{
|
||||
ClusterResourceID: strings.ToLower(resourceID),
|
||||
MaintenanceManifest: &api.MaintenanceManifest{
|
||||
MaintenanceSetID: "exampleset",
|
||||
State: api.MaintenanceManifestStatePending,
|
||||
RunAfter: 1,
|
||||
RunBefore: 1,
|
||||
},
|
||||
})
|
||||
},
|
||||
wantResponse: &admin.MaintenanceManifestList{
|
||||
MaintenanceManifests: []*admin.MaintenanceManifest{
|
||||
{
|
||||
ID: "07070707-0707-0707-0707-070707070001",
|
||||
MaintenanceSetID: "exampleset",
|
||||
State: admin.MaintenanceManifestStatePending,
|
||||
Priority: 0,
|
||||
RunAfter: 1,
|
||||
RunBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "limit over",
|
||||
limit: 1,
|
||||
fixtures: func(f *testdatabase.Fixture) {
|
||||
f.AddOpenShiftClusterDocuments(&api.OpenShiftClusterDocument{
|
||||
Key: strings.ToLower(resourceID),
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
ID: resourceID,
|
||||
Name: "resourceName",
|
||||
Type: "Microsoft.RedHatOpenShift/openshiftClusters",
|
||||
},
|
||||
})
|
||||
f.AddMaintenanceManifestDocuments(&api.MaintenanceManifestDocument{
|
||||
ClusterResourceID: strings.ToLower(resourceID),
|
||||
MaintenanceManifest: &api.MaintenanceManifest{
|
||||
MaintenanceSetID: "exampleset",
|
||||
State: api.MaintenanceManifestStatePending,
|
||||
RunAfter: 1,
|
||||
RunBefore: 1,
|
||||
},
|
||||
})
|
||||
f.AddMaintenanceManifestDocuments(&api.MaintenanceManifestDocument{
|
||||
ClusterResourceID: strings.ToLower(resourceID),
|
||||
MaintenanceManifest: &api.MaintenanceManifest{
|
||||
MaintenanceSetID: "exampleset2",
|
||||
State: api.MaintenanceManifestStatePending,
|
||||
RunAfter: 1,
|
||||
RunBefore: 1,
|
||||
},
|
||||
})
|
||||
},
|
||||
wantResponse: &admin.MaintenanceManifestList{
|
||||
NextLink: "https://mockrefererhost/?%24skipToken=" + url.QueryEscape(base64.StdEncoding.EncodeToString([]byte("FAKE1"))),
|
||||
MaintenanceManifests: []*admin.MaintenanceManifest{
|
||||
{
|
||||
ID: "07070707-0707-0707-0707-070707070001",
|
||||
MaintenanceSetID: "exampleset",
|
||||
State: admin.MaintenanceManifestStatePending,
|
||||
Priority: 0,
|
||||
RunAfter: 1,
|
||||
RunBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "cluster being deleted",
|
||||
fixtures: func(f *testdatabase.Fixture) {
|
||||
f.AddOpenShiftClusterDocuments(&api.OpenShiftClusterDocument{
|
||||
Key: strings.ToLower(resourceID),
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
ID: resourceID,
|
||||
Name: "resourceName",
|
||||
Type: "Microsoft.RedHatOpenShift/openshiftClusters",
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ProvisioningState: api.ProvisioningStateDeleting,
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
wantError: "404: NotFound: : cluster being deleted",
|
||||
wantStatusCode: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
name: "missing cluster",
|
||||
wantError: "404: NotFound: : cluster not found",
|
||||
wantStatusCode: http.StatusNotFound,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
now := func() time.Time { return time.Unix(1000, 0) }
|
||||
|
||||
ti := newTestInfra(t).WithOpenShiftClusters().WithSubscriptions().WithMaintenanceManifests(now)
|
||||
defer ti.done()
|
||||
|
||||
ti.fixture.AddSubscriptionDocuments(&api.SubscriptionDocument{
|
||||
ID: mockSubID,
|
||||
Subscription: &api.Subscription{
|
||||
State: api.SubscriptionStateRegistered,
|
||||
Properties: &api.SubscriptionProperties{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if tt.fixtures != nil {
|
||||
tt.fixtures(ti.fixture)
|
||||
}
|
||||
|
||||
err := ti.buildFixtures(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.dbGroup, api.APIs, &noop.Noop{}, &noop.Noop{}, testdatabase.NewFakeAEAD(), nil, nil, nil, nil, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go f.Run(ctx, nil, nil)
|
||||
|
||||
if tt.limit == 0 {
|
||||
tt.limit = 100
|
||||
}
|
||||
|
||||
fmt.Printf("limit: %d", tt.limit)
|
||||
|
||||
resp, b, err := ti.request(http.MethodGet,
|
||||
fmt.Sprintf("https://server/admin%s/maintenancemanifests?limit=%d", resourceID, tt.limit),
|
||||
http.Header{
|
||||
"Referer": []string{"https://mockrefererhost/"},
|
||||
}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = validateResponse(resp, b, tt.wantStatusCode, tt.wantError, tt.wantResponse)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ type frontendDBs interface {
|
|||
database.DatabaseGroupWithAsyncOperations
|
||||
database.DatabaseGroupWithSubscriptions
|
||||
database.DatabaseGroupWithPlatformWorkloadIdentityRoleSets
|
||||
database.DatabaseGroupWithMaintenanceManifests
|
||||
}
|
||||
|
||||
type kubeActionsFactory func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error)
|
||||
|
@ -326,6 +327,9 @@ func (f *frontend) chiAuthenticatedRoutes(router chi.Router) {
|
|||
|
||||
r.With(f.maintenanceMiddleware.UnplannedMaintenanceSignal).Post("/etcdcertificaterenew", f.postAdminOpenShiftClusterEtcdCertificateRenew)
|
||||
r.With(f.maintenanceMiddleware.UnplannedMaintenanceSignal).Post("/deletemanagedresource", f.postAdminOpenShiftDeleteManagedResource)
|
||||
|
||||
// MIMO
|
||||
r.Get("/maintenancemanifests", f.getAdminMaintManifests)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче