зеркало из https://github.com/Azure/ARO-RP.git
move billing functionality into pkg/util/billing and add e2e storage account functionality
Co-authored-by: Julien Stroheker <juliens@microsoft.com> Co-authored-by: Jim Minter <jminter@redhat.com>
This commit is contained in:
Родитель
dd357469f7
Коммит
c87c7c1baa
|
@ -28,5 +28,22 @@ const (
|
|||
type SubscriptionProperties struct {
|
||||
MissingFields
|
||||
|
||||
TenantID string `json:"tenantId,omitempty"`
|
||||
TenantID string `json:"tenantId,omitempty"`
|
||||
AccountOwner *AccountOwnerProfile `json:"accountOwner,omitempty"`
|
||||
RegisteredFeatures []RegisteredFeatureProfile `json:"registeredFeatures,omitempty"`
|
||||
}
|
||||
|
||||
// AccountOwnerProfile represents the subscription account owner information
|
||||
type AccountOwnerProfile struct {
|
||||
MissingFields
|
||||
|
||||
Email string `json:"email,omitempty"`
|
||||
}
|
||||
|
||||
// RegisteredFeatureProfile represents the features registered to the subscription
|
||||
type RegisteredFeatureProfile struct {
|
||||
MissingFields
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
State string `json:"state,omitempty"`
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ func (ocb *openShiftClusterBackend) handle(ctx context.Context, log *logrus.Entr
|
|||
stop := ocb.heartbeat(ctx, cancel, log, doc)
|
||||
defer stop()
|
||||
|
||||
m, err := openshiftcluster.NewManager(log, ocb.env, ocb.db.OpenShiftClusters, ocb.db.Billing, doc)
|
||||
m, err := openshiftcluster.NewManager(log, ocb.env, ocb.db.OpenShiftClusters, ocb.db.Billing, ocb.db.Subscriptions, doc)
|
||||
if err != nil {
|
||||
return ocb.endLease(ctx, log, stop, doc, api.ProvisioningStateFailed, err)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/stringutils"
|
||||
"github.com/Azure/ARO-RP/pkg/util/subnet"
|
||||
|
@ -92,7 +91,6 @@ func (m *Manager) Delete(ctx context.Context) error {
|
|||
(detailedErr.StatusCode == http.StatusForbidden || detailedErr.StatusCode == http.StatusNotFound) {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -107,10 +105,5 @@ func (m *Manager) Delete(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
m.log.Printf("updating billing record with deletion time")
|
||||
_, err = m.billing.MarkForDeletion(ctx, m.doc.ID)
|
||||
if cosmosdb.IsErrorStatusCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
return m.billing.Delete(ctx, m.doc)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/Azure/ARO-RP/pkg/util/acrtoken"
|
||||
pkgacrtoken "github.com/Azure/ARO-RP/pkg/util/acrtoken"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/features"
|
||||
"github.com/Azure/ARO-RP/pkg/util/billing"
|
||||
"github.com/Azure/ARO-RP/pkg/util/dns"
|
||||
"github.com/Azure/ARO-RP/pkg/util/keyvault"
|
||||
"github.com/Azure/ARO-RP/pkg/util/privateendpoint"
|
||||
|
@ -25,7 +26,7 @@ type Manager struct {
|
|||
log *logrus.Entry
|
||||
env env.Interface
|
||||
db database.OpenShiftClusters
|
||||
billing database.Billing
|
||||
billing billing.Manager
|
||||
fpAuthorizer autorest.Authorizer
|
||||
|
||||
ocDynamicValidator validate.OpenShiftClusterDynamicValidator
|
||||
|
@ -41,7 +42,7 @@ type Manager struct {
|
|||
doc *api.OpenShiftClusterDocument
|
||||
}
|
||||
|
||||
func NewManager(log *logrus.Entry, _env env.Interface, db database.OpenShiftClusters, billing database.Billing, doc *api.OpenShiftClusterDocument) (*Manager, error) {
|
||||
func NewManager(log *logrus.Entry, _env env.Interface, db database.OpenShiftClusters, billingDB database.Billing, sub database.Subscriptions, doc *api.OpenShiftClusterDocument) (*Manager, error) {
|
||||
r, err := azure.ParseResourceID(doc.OpenShiftCluster.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -70,11 +71,16 @@ func NewManager(log *logrus.Entry, _env env.Interface, db database.OpenShiftClus
|
|||
}
|
||||
}
|
||||
|
||||
billingManager, err := billing.NewManager(_env, billingDB, sub, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := &Manager{
|
||||
log: log,
|
||||
env: _env,
|
||||
db: db,
|
||||
billing: billing,
|
||||
billing: billingManager,
|
||||
fpAuthorizer: fpAuthorizer,
|
||||
|
||||
ocDynamicValidator: validate.NewOpenShiftClusterDynamicValidator(_env),
|
||||
|
|
|
@ -263,3 +263,15 @@ func (d *dev) CreateARMResourceGroupRoleAssignment(ctx context.Context, fpAuthor
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *dev) E2EStorageAccountName() string {
|
||||
return "arov4e2eint"
|
||||
}
|
||||
|
||||
func (d *dev) E2EStorageAccountRGName() string {
|
||||
return "global-infra"
|
||||
}
|
||||
|
||||
func (d *dev) E2EStorageAccountSubID() string {
|
||||
return "0cc1cafa-578f-4fa5-8d6b-ddfd8d82e6ea"
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ type Interface interface {
|
|||
Zones(vmSize string) ([]string, error)
|
||||
ACRResourceID() string
|
||||
ACRName() string
|
||||
E2EStorageAccountName() string
|
||||
E2EStorageAccountRGName() string
|
||||
E2EStorageAccountSubID() string
|
||||
}
|
||||
|
||||
func NewEnv(ctx context.Context, log *logrus.Entry) (Interface, error) {
|
||||
|
|
|
@ -21,6 +21,9 @@ func newInt(ctx context.Context, log *logrus.Entry, instancemetadata instancemet
|
|||
p.fpServicePrincipalID = "71cfb175-ea3a-444e-8c03-b119b2752ce4"
|
||||
p.clustersGenevaLoggingEnvironment = "Test"
|
||||
p.clustersGenevaLoggingConfigVersion = "2.2"
|
||||
p.e2eStorageAccountName = "arov4e2eint"
|
||||
p.e2eStorageAccountRGName = "global-infra"
|
||||
p.e2eStorageAccountSubID = "0cc1cafa-578f-4fa5-8d6b-ddfd8d82e6ea"
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ type prod struct {
|
|||
clustersGenevaLoggingConfigVersion string
|
||||
clustersGenevaLoggingEnvironment string
|
||||
|
||||
e2eStorageAccountName string
|
||||
e2eStorageAccountRGName string
|
||||
e2eStorageAccountSubID string
|
||||
|
||||
log *logrus.Entry
|
||||
}
|
||||
|
||||
|
@ -117,6 +121,10 @@ func newProd(ctx context.Context, log *logrus.Entry, instancemetadata instanceme
|
|||
p.clustersGenevaLoggingPrivateKey = clustersGenevaLoggingPrivateKey
|
||||
p.clustersGenevaLoggingCertificate = clustersGenevaLoggingCertificates[0]
|
||||
|
||||
p.e2eStorageAccountName = "v4aroe2e"
|
||||
p.e2eStorageAccountRGName = "global"
|
||||
p.e2eStorageAccountSubID = "0923c7de-9fca-4d9e-baf3-131d0c5b2ea4"
|
||||
|
||||
if p.ACRResourceID() != "" { // TODO: ugh!
|
||||
acrResource, err := azure.ParseResourceID(p.ACRResourceID())
|
||||
if err != nil {
|
||||
|
@ -353,3 +361,15 @@ func (p *prod) Zones(vmSize string) ([]string, error) {
|
|||
}
|
||||
return zones, nil
|
||||
}
|
||||
|
||||
func (p *prod) E2EStorageAccountName() string {
|
||||
return p.e2eStorageAccountName
|
||||
}
|
||||
|
||||
func (p *prod) E2EStorageAccountRGName() string {
|
||||
return p.e2eStorageAccountRGName
|
||||
}
|
||||
|
||||
func (p *prod) E2EStorageAccountSubID() string {
|
||||
return p.e2eStorageAccountSubID
|
||||
}
|
||||
|
|
|
@ -5,26 +5,8 @@ package install
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
|
||||
)
|
||||
|
||||
func (i *Installer) createBillingRecord(ctx context.Context) error {
|
||||
_, err := i.billing.Create(ctx, &api.BillingDocument{
|
||||
ID: i.doc.ID,
|
||||
Key: i.doc.Key,
|
||||
ClusterResourceGroupIDKey: i.doc.ClusterResourceGroupIDKey,
|
||||
Billing: &api.Billing{
|
||||
TenantID: i.doc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: i.doc.OpenShiftCluster.Location,
|
||||
},
|
||||
})
|
||||
// If create return a conflict, this means row is already present in database
|
||||
if err, ok := err.(*cosmosdb.Error); ok && err.StatusCode == http.StatusConflict {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
return i.billing.Create(ctx, i.doc)
|
||||
}
|
||||
|
|
|
@ -5,150 +5,57 @@ package install
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
|
||||
mock_database "github.com/Azure/ARO-RP/pkg/util/mocks/database"
|
||||
mock_billing "github.com/Azure/ARO-RP/pkg/util/mocks/billing"
|
||||
)
|
||||
|
||||
func TestCreateBillingEntry(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mockSubID := "11111111-1111-1111-1111-111111111111"
|
||||
mockTenantID := mockSubID
|
||||
location := "eastus"
|
||||
// controller := gomock.NewController(t)
|
||||
// defer controller.Finish()
|
||||
// billing := mock_database.NewMockBilling(controller)
|
||||
|
||||
type test struct {
|
||||
name string
|
||||
openshiftdoc *api.OpenShiftClusterDocument
|
||||
mocks func(*test, *mock_database.MockBilling)
|
||||
wantError error
|
||||
}
|
||||
|
||||
for _, tt := range []*test{
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
mocks func(*mock_billing.MockManager)
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "create a new billing entry",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: "11111111-1111-1111-1111-111111111111",
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
name: "manager create is called and doesn't return an error when create doesn't return an error",
|
||||
mocks: func(billing *mock_billing.MockManager) {
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(billingDoc, nil)
|
||||
Create(gomock.Any(), &api.OpenShiftClusterDocument{}).
|
||||
Return(nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error on create a new billing entry",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: "11111111-1111-1111-1111-111111111111",
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
name: "manager create is called and returns an error on create returning an error",
|
||||
mocks: func(billing *mock_billing.MockManager) {
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(nil, tt.wantError)
|
||||
Create(gomock.Any(), &api.OpenShiftClusterDocument{}).
|
||||
Return(errors.New("random error"))
|
||||
},
|
||||
wantError: fmt.Errorf("Error creating document"),
|
||||
},
|
||||
{
|
||||
name: "billing document already existing on DB on create",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: "11111111-1111-1111-1111-111111111111",
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(nil, &cosmosdb.Error{
|
||||
StatusCode: http.StatusConflict,
|
||||
})
|
||||
},
|
||||
wantError: nil,
|
||||
wantErr: "random error",
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
billing := mock_database.NewMockBilling(controller)
|
||||
|
||||
tt.mocks(tt, billing)
|
||||
billing := mock_billing.NewMockManager(controller)
|
||||
tt.mocks(billing)
|
||||
|
||||
i := &Installer{
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
doc: tt.openshiftdoc,
|
||||
doc: &api.OpenShiftClusterDocument{},
|
||||
billing: billing,
|
||||
}
|
||||
|
||||
err := i.createBillingRecord(ctx)
|
||||
if err != nil {
|
||||
if tt.wantError != err {
|
||||
t.Errorf("Error want (%s), having (%s)", tt.wantError.Error(), err.Error())
|
||||
}
|
||||
if err != nil && err.Error() != tt.wantErr ||
|
||||
err == nil && tt.wantErr != "" {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import (
|
|||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/features"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/network"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/storage"
|
||||
"github.com/Azure/ARO-RP/pkg/util/billing"
|
||||
"github.com/Azure/ARO-RP/pkg/util/dns"
|
||||
"github.com/Azure/ARO-RP/pkg/util/encryption"
|
||||
"github.com/Azure/ARO-RP/pkg/util/keyvault"
|
||||
|
@ -55,7 +56,7 @@ type Installer struct {
|
|||
log *logrus.Entry
|
||||
env env.Interface
|
||||
db database.OpenShiftClusters
|
||||
billing database.Billing
|
||||
billing billing.Manager
|
||||
doc *api.OpenShiftClusterDocument
|
||||
cipher encryption.Cipher
|
||||
fpAuthorizer autorest.Authorizer
|
||||
|
@ -93,7 +94,7 @@ type condition struct {
|
|||
}
|
||||
|
||||
// NewInstaller creates a new Installer
|
||||
func NewInstaller(ctx context.Context, log *logrus.Entry, _env env.Interface, db database.OpenShiftClusters, billing database.Billing, doc *api.OpenShiftClusterDocument) (*Installer, error) {
|
||||
func NewInstaller(ctx context.Context, log *logrus.Entry, _env env.Interface, db database.OpenShiftClusters, billing billing.Manager, doc *api.OpenShiftClusterDocument) (*Installer, error) {
|
||||
r, err := azure.ParseResourceID(doc.OpenShiftCluster.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
package billing
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
azstorage "github.com/Azure/azure-sdk-for-go/storage"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/database"
|
||||
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/storage"
|
||||
"github.com/Azure/ARO-RP/pkg/util/feature"
|
||||
)
|
||||
|
||||
const (
|
||||
tenantIDMSFT = "72f988bf-86f1-41af-91ab-2d7cd011db47"
|
||||
tenantIDAME = "33e01921-4d64-4f8c-a055-5bdaffd5e33d"
|
||||
|
||||
// featureSaveAROTestConfig is the feature in the subscription that is used
|
||||
// to indicate if we need to save ARO cluster config into the E2E
|
||||
// StorageAccount
|
||||
featureSaveAROTestConfig = "Microsoft.RedHatOpenShift/SaveAROTestConfig"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
Create(context.Context, *api.OpenShiftClusterDocument) error
|
||||
Delete(context.Context, *api.OpenShiftClusterDocument) error
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
env env.Interface
|
||||
storageClient *azstorage.Client
|
||||
billingDB database.Billing
|
||||
subDB database.Subscriptions
|
||||
log *logrus.Entry
|
||||
}
|
||||
|
||||
func NewManager(_env env.Interface, billing database.Billing, sub database.Subscriptions, log *logrus.Entry) (Manager, error) {
|
||||
var storageClient *azstorage.Client
|
||||
|
||||
if _, ok := _env.(env.Dev); !ok {
|
||||
localFPAuthorizer, err := _env.FPAuthorizer(_env.TenantID(), azure.PublicCloud.ResourceManagerEndpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e2estorage := storage.NewAccountsClient(_env.E2EStorageAccountSubID(), localFPAuthorizer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys, err := e2estorage.ListKeys(context.Background(), _env.E2EStorageAccountRGName(), _env.E2EStorageAccountName(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := *(*keys.Keys)[0].Value
|
||||
|
||||
client, err := azstorage.NewBasicClient(_env.E2EStorageAccountName(), key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storageClient = &client
|
||||
}
|
||||
|
||||
return &manager{
|
||||
env: _env,
|
||||
storageClient: storageClient,
|
||||
subDB: sub,
|
||||
billingDB: billing,
|
||||
log: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *manager) Create(ctx context.Context, doc *api.OpenShiftClusterDocument) error {
|
||||
billingDoc, err := m.billingDB.Create(ctx, &api.BillingDocument{
|
||||
ID: doc.ID,
|
||||
Key: doc.Key,
|
||||
ClusterResourceGroupIDKey: doc.ClusterResourceGroupIDKey,
|
||||
Billing: &api.Billing{
|
||||
TenantID: doc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: doc.OpenShiftCluster.Location,
|
||||
},
|
||||
})
|
||||
if err, ok := err.(*cosmosdb.Error); ok &&
|
||||
err.StatusCode == http.StatusConflict {
|
||||
m.log.Print("billing record already present in DB")
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e2eErr := m.createOrUpdateE2EBlob(ctx, billingDoc); e2eErr != nil {
|
||||
m.log.Warnf("createOrUpdateE2EBlob failed: %s", e2eErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manager) Delete(ctx context.Context, doc *api.OpenShiftClusterDocument) error {
|
||||
m.log.Printf("updating billing record with deletion time")
|
||||
billingDoc, err := m.billingDB.MarkForDeletion(ctx, doc.ID)
|
||||
if cosmosdb.IsErrorStatusCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e2eErr := m.createOrUpdateE2EBlob(ctx, billingDoc); e2eErr != nil {
|
||||
// We are not failing the operation if we cannot write to e2e storage account, just warning
|
||||
m.log.Warnf("createOrUpdateE2EBlob failed: %s", e2eErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isSubscriptionRegisteredForE2E returns true if the subscription has the
|
||||
// "Microsoft.RedHatOpenShift/SaveAROTestConfig" feature registered
|
||||
func isSubscriptionRegisteredForE2E(sub *api.SubscriptionProperties) bool {
|
||||
if sub.TenantID == tenantIDMSFT || sub.TenantID == tenantIDAME {
|
||||
return feature.IsRegisteredForFeature(sub, featureSaveAROTestConfig)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// createOrUpdateE2Eblob create a copy of the billing document in the e2e
|
||||
// storage account. This is used later on by the billing e2e
|
||||
func (m *manager) createOrUpdateE2EBlob(ctx context.Context, doc *api.BillingDocument) error {
|
||||
//skip updating the storage account if this is a dev scenario
|
||||
if _, ok := m.env.(env.Dev); ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate if E2E Feature is registered
|
||||
resource, err := azure.ParseResourceID(doc.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subDocument, err := m.subDB.Get(ctx, resource.SubscriptionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !isSubscriptionRegisteredForE2E(subDocument.Subscription.Properties) {
|
||||
return nil
|
||||
}
|
||||
|
||||
blobclient := m.storageClient.GetBlobService()
|
||||
|
||||
containerName := strings.ToLower("bill-" + doc.Billing.Location + "-" + resource.ResourceGroup + "-" + resource.ResourceName)
|
||||
if len(containerName) > 63 {
|
||||
containerName = containerName[:63]
|
||||
}
|
||||
|
||||
containerRef := blobclient.GetContainerReference(containerName)
|
||||
_, err = containerRef.CreateIfNotExists(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blobRef := containerRef.GetBlobReference("billingentity")
|
||||
b, err := json.Marshal(doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return blobRef.CreateBlockBlobFromReader(bytes.NewReader(b), nil)
|
||||
}
|
|
@ -0,0 +1,413 @@
|
|||
package billing
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
|
||||
mock_database "github.com/Azure/ARO-RP/pkg/util/mocks/database"
|
||||
)
|
||||
|
||||
func TestIsSubscriptionRegisteredForE2E(t *testing.T) {
|
||||
mockSubID := "11111111-1111-1111-1111-111111111111"
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
sub api.SubscriptionProperties
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
{
|
||||
name: "sub without feature flag registered and not internal tenant",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: mockSubID,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: "RandomFeature",
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sub with feature flag registered and not internal tenant",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: mockSubID,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: featureSaveAROTestConfig,
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AME internal tenant and feature flag not registered",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: tenantIDAME,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: "RandomFeature",
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MSFT internal tenant and feature flag not registered",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: tenantIDMSFT,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: "RandomFeature",
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AME internal tenant and feature flag registered",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: tenantIDAME,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: featureSaveAROTestConfig,
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "MSFT internal tenant and feature flag registered",
|
||||
sub: api.SubscriptionProperties{
|
||||
TenantID: tenantIDMSFT,
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: featureSaveAROTestConfig,
|
||||
State: "Registered",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := isSubscriptionRegisteredForE2E(&tt.sub)
|
||||
if got != tt.want {
|
||||
t.Error(got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mockSubID := "11111111-1111-1111-1111-111111111111"
|
||||
mockTenantID := mockSubID
|
||||
location := "eastus"
|
||||
|
||||
type test struct {
|
||||
name string
|
||||
openshiftdoc *api.OpenShiftClusterDocument
|
||||
mocks func(*test, *mock_database.MockBilling, *mock_database.MockSubscriptions)
|
||||
wantErr string
|
||||
}
|
||||
|
||||
// Can't add tests for billing storage because there isn't an interface on
|
||||
// the azure storage clients.
|
||||
|
||||
for _, tt := range []*test{
|
||||
{
|
||||
name: "successful mark for deletion on billing entity, with a subscription not registered for e2e",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: mockTenantID,
|
||||
Location: location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
MarkForDeletion(gomock.Any(), billingDoc.ID).
|
||||
Return(billingDoc, nil)
|
||||
|
||||
subscription.EXPECT().
|
||||
Get(gomock.Any(), mockSubID).
|
||||
Return(&api.SubscriptionDocument{
|
||||
Subscription: &api.Subscription{
|
||||
Properties: &api.SubscriptionProperties{
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: featureSaveAROTestConfig,
|
||||
State: "NotRegistered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no error on mark for deletion on billing entry that is not found",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billing.EXPECT().
|
||||
MarkForDeletion(gomock.Any(), tt.openshiftdoc.ID).
|
||||
Return(nil, &cosmosdb.Error{
|
||||
StatusCode: 404,
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error on mark for deletion on billing entry",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
MarkForDeletion(gomock.Any(), tt.openshiftdoc.ID).
|
||||
Return(billingDoc, errors.New("random error"))
|
||||
},
|
||||
wantErr: "random error",
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
log := logrus.NewEntry(logrus.StandardLogger())
|
||||
|
||||
billingDB := mock_database.NewMockBilling(controller)
|
||||
subsDB := mock_database.NewMockSubscriptions(controller)
|
||||
|
||||
tt.mocks(tt, billingDB, subsDB)
|
||||
|
||||
m := &manager{
|
||||
log: log,
|
||||
billingDB: billingDB,
|
||||
subDB: subsDB,
|
||||
}
|
||||
|
||||
err := m.Delete(ctx, tt.openshiftdoc)
|
||||
if err != nil && err.Error() != tt.wantErr ||
|
||||
err == nil && tt.wantErr != "" {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
mockSubID := "11111111-1111-1111-1111-111111111111"
|
||||
mockTenantID := mockSubID
|
||||
location := "eastus"
|
||||
|
||||
type test struct {
|
||||
name string
|
||||
openshiftdoc *api.OpenShiftClusterDocument
|
||||
mocks func(*test, *mock_database.MockBilling, *mock_database.MockSubscriptions)
|
||||
wantErr string
|
||||
}
|
||||
|
||||
// Can't add tests for billing storage because there isn't an interface on
|
||||
// the azure storage clients.
|
||||
|
||||
for _, tt := range []*test{
|
||||
{
|
||||
name: "create a new billing entry with a subscription not registered for e2e",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: mockTenantID,
|
||||
Location: location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(billingDoc, nil)
|
||||
|
||||
subscription.EXPECT().
|
||||
Get(gomock.Any(), mockSubID).
|
||||
Return(&api.SubscriptionDocument{
|
||||
Subscription: &api.Subscription{
|
||||
Properties: &api.SubscriptionProperties{
|
||||
RegisteredFeatures: []api.RegisteredFeatureProfile{
|
||||
{
|
||||
Name: featureSaveAROTestConfig,
|
||||
State: "NotRegistered",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error on create a new billing entry",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: tt.openshiftdoc.Key,
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(nil, errors.New("random error"))
|
||||
},
|
||||
wantErr: "random error",
|
||||
},
|
||||
{
|
||||
name: "billing document already existing on DB on create",
|
||||
openshiftdoc: &api.OpenShiftClusterDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName", mockSubID),
|
||||
ID: mockSubID,
|
||||
OpenShiftCluster: &api.OpenShiftCluster{
|
||||
Properties: api.OpenShiftClusterProperties{
|
||||
ServicePrincipalProfile: api.ServicePrincipalProfile{
|
||||
TenantID: mockTenantID,
|
||||
},
|
||||
},
|
||||
Location: location,
|
||||
},
|
||||
},
|
||||
mocks: func(tt *test, billing *mock_database.MockBilling, subscription *mock_database.MockSubscriptions) {
|
||||
billingDoc := &api.BillingDocument{
|
||||
Key: fmt.Sprintf("/subscriptions/%s/resourcegroups/rgName/providers/microsoft.redhatopenshift/openshiftclusters/clusterName", mockSubID),
|
||||
ClusterResourceGroupIDKey: tt.openshiftdoc.ClusterResourceGroupIDKey,
|
||||
ID: mockSubID,
|
||||
Billing: &api.Billing{
|
||||
TenantID: tt.openshiftdoc.OpenShiftCluster.Properties.ServicePrincipalProfile.TenantID,
|
||||
Location: tt.openshiftdoc.OpenShiftCluster.Location,
|
||||
},
|
||||
}
|
||||
|
||||
billing.EXPECT().
|
||||
Create(gomock.Any(), billingDoc).
|
||||
Return(nil, &cosmosdb.Error{
|
||||
StatusCode: http.StatusConflict,
|
||||
})
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
log := logrus.NewEntry(logrus.StandardLogger())
|
||||
|
||||
billingDB := mock_database.NewMockBilling(controller)
|
||||
subsDB := mock_database.NewMockSubscriptions(controller)
|
||||
|
||||
tt.mocks(tt, billingDB, subsDB)
|
||||
|
||||
m := &manager{
|
||||
log: log,
|
||||
billingDB: billingDB,
|
||||
subDB: subsDB,
|
||||
}
|
||||
|
||||
err := m.Create(ctx, tt.openshiftdoc)
|
||||
if err != nil && err.Error() != tt.wantErr ||
|
||||
err == nil && tt.wantErr != "" {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package billing
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
//go:generate go run ../../../vendor/github.com/golang/mock/mockgen -destination=../../util/mocks/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/util/$GOPACKAGE Manager
|
||||
//go:generate go run ../../../vendor/golang.org/x/tools/cmd/goimports -local=github.com/Azure/ARO-RP -e -w ../../util/mocks/$GOPACKAGE/$GOPACKAGE.go
|
|
@ -0,0 +1,17 @@
|
|||
package feature
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
)
|
||||
|
||||
func IsRegisteredForFeature(sub *api.SubscriptionProperties, feature string) bool {
|
||||
for _, f := range sub.RegisteredFeatures {
|
||||
if f.Name == feature && f.State == "Registered" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/Azure/ARO-RP/pkg/util/billing (interfaces: Manager)
|
||||
|
||||
// Package mock_billing is a generated GoMock package.
|
||||
package mock_billing
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
|
||||
api "github.com/Azure/ARO-RP/pkg/api"
|
||||
)
|
||||
|
||||
// MockManager is a mock of Manager interface
|
||||
type MockManager struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockManagerMockRecorder
|
||||
}
|
||||
|
||||
// MockManagerMockRecorder is the mock recorder for MockManager
|
||||
type MockManagerMockRecorder struct {
|
||||
mock *MockManager
|
||||
}
|
||||
|
||||
// NewMockManager creates a new mock instance
|
||||
func NewMockManager(ctrl *gomock.Controller) *MockManager {
|
||||
mock := &MockManager{ctrl: ctrl}
|
||||
mock.recorder = &MockManagerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockManager) EXPECT() *MockManagerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Create mocks base method
|
||||
func (m *MockManager) Create(arg0 context.Context, arg1 *api.OpenShiftClusterDocument) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Create", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create
|
||||
func (mr *MockManagerMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockManager)(nil).Create), arg0, arg1)
|
||||
}
|
||||
|
||||
// Delete mocks base method
|
||||
func (m *MockManager) Delete(arg0 context.Context, arg1 *api.OpenShiftClusterDocument) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete
|
||||
func (mr *MockManagerMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockManager)(nil).Delete), arg0, arg1)
|
||||
}
|
Загрузка…
Ссылка в новой задаче