Skip to content

Commit

Permalink
*** WIP. ROLL BACK. ***
Browse files Browse the repository at this point in the history
  • Loading branch information
manadart committed Nov 27, 2024
1 parent 89d2088 commit 3d792b1
Show file tree
Hide file tree
Showing 31 changed files with 261 additions and 259 deletions.
34 changes: 23 additions & 11 deletions agent/agentbootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ package agentbootstrap
import (
stdcontext "context"
"fmt"
jujuversion "github.com/juju/juju/core/version"
modelerrors "github.com/juju/juju/domain/model/errors"
"github.com/juju/version/v2"

"github.com/juju/clock"
"github.com/juju/errors"
Expand Down Expand Up @@ -225,15 +228,14 @@ func (b *AgentBootstrap) Initialize(ctx stdcontext.Context) (_ *state.Controller
},
)

controllerModelArgs := modeldomain.ModelCreationArgs{
AgentVersion: stateParams.AgentVersion,
Name: stateParams.ControllerModelConfig.Name(),
Owner: adminUserUUID,
Cloud: stateParams.ControllerCloud.Name,
CloudRegion: stateParams.ControllerCloudRegion,
Credential: credential.KeyFromTag(cloudCredTag),
controllerModelArgs := modeldomain.ControllerDBModelCreationArgs{
Name: stateParams.ControllerModelConfig.Name(),
Owner: adminUserUUID,
Cloud: stateParams.ControllerCloud.Name,
CloudRegion: stateParams.ControllerCloudRegion,
Credential: credential.KeyFromTag(cloudCredTag),
}
controllerModelCreateFunc := modelbootstrap.CreateModel(controllerModelUUID, controllerModelArgs)
controllerModelCreateFunc := modelbootstrap.CreateControllerDBModelRecord(controllerModelUUID, controllerModelArgs)

controllerModelDefaults := modeldefaultsbootstrap.ModelDefaultsProvider(
stateParams.ControllerInheritedConfig,
Expand All @@ -247,6 +249,14 @@ func (b *AgentBootstrap) Initialize(ctx stdcontext.Context) (_ *state.Controller
modelType = state.ModelTypeCAAS
}

agentVersion := stateParams.AgentVersion
if agentVersion == version.Zero {
agentVersion = jujuversion.Current
}
if agentVersion.Major != jujuversion.Current.Major || agentVersion.Minor != jujuversion.Current.Minor {
return nil, fmt.Errorf("%w %q during bootstrap", modelerrors.AgentVersionNotSupported, agentVersion)
}

databaseBootstrapOptions := []database.BootstrapOpt{
// The controller config needs to be inserted before the admin users
// because the admin users permissions require the controller UUID.
Expand All @@ -259,15 +269,17 @@ func (b *AgentBootstrap) Initialize(ctx stdcontext.Context) (_ *state.Controller
modeldefaultsbootstrap.SetCloudDefaults(stateParams.ControllerCloud.Name, stateParams.ControllerInheritedConfig),
secretbackendbootstrap.CreateDefaultBackends(model.ModelType(modelType)),
controllerModelCreateFunc,
modelbootstrap.CreateReadOnlyModel(controllerModelUUID, controllerUUID),
modelconfigbootstrap.SetModelConfig(controllerModelUUID, stateParams.ControllerModelConfig.AllAttrs(), controllerModelDefaults),
modelbootstrap.CreateModelDBModelRecord(controllerModelUUID, controllerUUID, agentVersion),
modelconfigbootstrap.SetModelConfig(
controllerModelUUID, stateParams.ControllerModelConfig.AllAttrs(), controllerModelDefaults),
}
if !isCAAS {
databaseBootstrapOptions = append(databaseBootstrapOptions,
// TODO(wallyworld) - this is just a placeholder for now
machinebootstrap.InsertMachine(agent.BootstrapControllerId),

cloudimagemetadatabootstrap.AddCustomImageMetadata(clock.WallClock, stateParams.ControllerModelConfig.ImageStream(), stateParams.CustomImageMetadata),
cloudimagemetadatabootstrap.AddCustomImageMetadata(
clock.WallClock, stateParams.ControllerModelConfig.ImageStream(), stateParams.CustomImageMetadata),
)
}

Expand Down
2 changes: 1 addition & 1 deletion apiserver/facades/client/client/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ func (s *statusUnitTestSuite) TestMigrationInProgress(c *gc.C) {
// Double-write model information to dqlite.
// Add the model to the model database.
err = s.ModelTxnRunner(c, model2.UUID()).Txn(context.Background(), func(ctx context.Context, tx *sqlair.TX) error {
return modelstate.CreateReadOnlyModel(ctx, domainmodel.ReadOnlyModelCreationArgs{
return modelstate.CreateReadOnlyModel(ctx, domainmodel.ReadOnlyModelRecordArgs{
UUID: coremodel.UUID(model2.UUID()),
Name: model2.Name(),
Cloud: "dummy",
Expand Down
6 changes: 3 additions & 3 deletions apiserver/facades/client/modelmanager/mocks/service_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions apiserver/facades/client/modelmanager/modelmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (m *ModelManagerAPI) createModelNew(
// if there was an error. If a failure to rollback occurs, then the endpoint
// should at least be somewhat idempotent.

creationArgs := model.ModelCreationArgs{
creationArgs := model.ControllerDBModelCreationArgs{
CloudRegion: args.CloudRegion,
Name: args.Name,
}
Expand All @@ -216,15 +216,15 @@ func (m *ModelManagerAPI) createModelNew(
// we will try and apply the defaults where authorisation allows us to.
defaultCloudName, _, err := m.modelService.DefaultModelCloudNameAndCredential(ctx)
if errors.Is(err, modelerrors.NotFound) {
return coremodel.UUID(""), errors.New("failed to find default model cloud and credential for controller")
return "", errors.New("failed to find default model cloud and credential for controller")
}

var cloudTag names.CloudTag
if args.CloudTag != "" {
var err error
cloudTag, err = names.ParseCloudTag(args.CloudTag)
if err != nil {
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}
} else {
cloudTag = names.NewCloudTag(defaultCloudName)
Expand All @@ -233,33 +233,33 @@ func (m *ModelManagerAPI) createModelNew(

err = m.authorizer.HasPermission(ctx, permission.SuperuserAccess, m.state.ControllerTag())
if err != nil && !errors.Is(err, authentication.ErrorEntityMissingPermission) {
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}
if err != nil {
canAddModel, err := m.checkAddModelPermission(ctx, cloudTag.Id(), m.apiUser)
if err != nil {
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}
if !canAddModel {
return coremodel.UUID(""), apiservererrors.ErrPerm
return "", apiservererrors.ErrPerm
}
}

ownerTag, err := names.ParseUserTag(args.OwnerTag)
if err != nil {
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}

// a special case of ErrPerm will happen if the user has add-model permission but is trying to
// create a model for another person, which is not yet supported.
if !m.isAdmin && ownerTag != m.apiUser {
return coremodel.UUID(""), errors.Annotatef(apiservererrors.ErrPerm, "%q permission does not permit creation of models for different owners", permission.AddModelAccess)
return "", errors.Annotatef(apiservererrors.ErrPerm, "%q permission does not permit creation of models for different owners", permission.AddModelAccess)
}

user, err := m.accessService.GetUserByName(ctx, user.NameFromTag(ownerTag))
if err != nil {
// TODO handle error properly
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}
creationArgs.Owner = user.UUID

Expand All @@ -268,7 +268,7 @@ func (m *ModelManagerAPI) createModelNew(
var err error
cloudCredentialTag, err = names.ParseCloudCredentialTag(args.CloudCredentialTag)
if err != nil {
return coremodel.UUID(""), errors.Trace(err)
return "", errors.Trace(err)
}

creationArgs.Credential = credential.KeyFromTag(cloudCredentialTag)
Expand All @@ -277,7 +277,7 @@ func (m *ModelManagerAPI) createModelNew(
// Create the model in the controller database.
modelID, activator, err := m.modelService.CreateModel(ctx, creationArgs)
if err != nil {
return coremodel.UUID(""), errors.Annotatef(err, "failed to create model %q", modelID)
return "", errors.Annotatef(err, "failed to create model %q", modelID)
}

// We need to get the model domain services from the newly created model
Expand Down
6 changes: 3 additions & 3 deletions apiserver/facades/client/modelmanager/modelmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (s *modelManagerSuite) expectCreateModel(
).Return(user.User{UUID: ownerUUID}, nil)

// Create model in controller database.
s.modelService.EXPECT().CreateModel(gomock.Any(), model.ModelCreationArgs{
s.modelService.EXPECT().CreateModel(gomock.Any(), model.ControllerDBModelCreationArgs{
Name: modelCreateArgs.Name,
Owner: ownerUUID,
Cloud: expectedCloudName,
Expand Down Expand Up @@ -564,7 +564,7 @@ func (s *modelManagerSuite) TestCreateModelNoDefaultCredentialNonAdmin(c *gc.C)
// //s.accessService.EXPECT().GetUserByName(
// // gomock.Any(), ownerName,
// //).Return(user.User{UUID: ownerUUID}, nil)
// //s.modelService.EXPECT().CreateModel(gomock.Any(), model.ModelCreationArgs{
// //s.modelService.EXPECT().CreateModel(gomock.Any(), model.ControllerDBModelCreationArgs{
// // Name: "existing-ns",
// // Owner: ownerUUID,
// // Cloud: "k8s-cloud",
Expand Down Expand Up @@ -1097,7 +1097,7 @@ func (s *modelManagerStateSuite) expectCreateModelStateSuite(
).Return(user.User{UUID: ownerUUID}, nil)

// Create model in controller database.
s.modelService.EXPECT().CreateModel(gomock.Any(), model.ModelCreationArgs{
s.modelService.EXPECT().CreateModel(gomock.Any(), model.ControllerDBModelCreationArgs{
Name: modelCreateArgs.Name,
Owner: ownerUUID,
Cloud: "dummy",
Expand Down
2 changes: 1 addition & 1 deletion apiserver/facades/client/modelmanager/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type ModelConfigService interface {
// ModelService defines an interface for interacting with the model service.
type ModelService interface {
// CreateModel creates a model returning the resultant model's new id.
CreateModel(context.Context, model.ModelCreationArgs) (coremodel.UUID, func(context.Context) error, error)
CreateModel(context.Context, model.ControllerDBModelCreationArgs) (coremodel.UUID, func(context.Context) error, error)

// DefaultModelCloudNameAndCredential returns the default cloud name and
// credential that should be used for newly created models that haven't had
Expand Down
2 changes: 1 addition & 1 deletion domain/agentprovisioner/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (s *suite) TestModelID(c *gc.C) {
// Create a read-only model
modelID := modeltesting.GenModelUUID(c)
modelSt := modelstate.NewModelState(s.TxnRunnerFactory(), loggertesting.WrapCheckLog(c))
err := modelSt.Create(context.Background(), model.ReadOnlyModelCreationArgs{
err := modelSt.Create(context.Background(), model.ReadOnlyModelRecordArgs{
UUID: modelID,
AgentVersion: version.Number{Major: 4, Minor: 21, Patch: 67},
ControllerUUID: uuid.MustNewUUID(),
Expand Down
2 changes: 1 addition & 1 deletion domain/cloud/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func (s *stateSuite) TestCloudIsControllerCloud(c *gc.C) {
context.Background(),
modelUUID,
coremodel.IAAS,
model.ModelCreationArgs{
model.ControllerDBModelCreationArgs{
Cloud: testCloud.Name,
Name: coremodel.ControllerModelName,
Owner: user.UUID(s.adminUUID.String()),
Expand Down
4 changes: 2 additions & 2 deletions domain/keyupdater/keyupdater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (s *keyUpdaterSuite) SetUpTest(c *gc.C) {
testing.CreateInternalSecretBackend(c, s.ControllerTxnRunner())

modelUUID := modeltesting.GenModelUUID(c)
modelFn := modelbootstrap.CreateModel(modelUUID, domainmodel.ModelCreationArgs{
modelFn := modelbootstrap.CreateControllerDBModelRecord(modelUUID, domainmodel.ControllerDBModelCreationArgs{
AgentVersion: jujuversion.Current,
Cloud: cloudName,
Credential: credential.Key{
Expand All @@ -106,7 +106,7 @@ func (s *keyUpdaterSuite) SetUpTest(c *gc.C) {
err = modelFn(context.Background(), s.ControllerTxnRunner(), s.ControllerSuite.NoopTxnRunner())
c.Assert(err, jc.ErrorIsNil)

err = modelbootstrap.CreateReadOnlyModel(modelUUID, uuid.MustNewUUID())(context.Background(), s.ControllerTxnRunner(), s.ModelTxnRunner())
err = modelbootstrap.CreateModelDBModelRecord(modelUUID, uuid.MustNewUUID())(context.Background(), s.ControllerTxnRunner(), s.ModelTxnRunner())
c.Assert(err, jc.ErrorIsNil)

err = machinebootstrap.InsertMachine("0")(
Expand Down
2 changes: 1 addition & 1 deletion domain/keyupdater/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (s *stateSuite) TestGetModelId(c *gc.C) {
mst := modelstate.NewModelState(s.TxnRunnerFactory(), loggertesting.WrapCheckLog(c))

modelUUID := modeltesting.GenModelUUID(c)
args := model.ReadOnlyModelCreationArgs{
args := model.ReadOnlyModelRecordArgs{
UUID: modelUUID,
AgentVersion: jujuversion.Current,
ControllerUUID: uuid.MustNewUUID(),
Expand Down
67 changes: 28 additions & 39 deletions domain/model/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,10 @@ func (m modelTypeStateFunc) CloudType(c context.Context, n string) (string, erro
return m(c, n)
}

// CreateModel is responsible for making a new model with all of its associated
// metadata during the bootstrap process.
// If the ModelCreationArgs does not have a credential name set then no cloud
// credential will be associated with the model.
//
// The only supported agent version during bootstrap is that of the current
// controller. This will be the default if no agent version is supplied.
// CreateControllerDBModelRecord is responsible for making a new model with all
// of its associated metadata during the bootstrap process.
// If the ControllerDBModelCreationArgs does not have a credential name set then
// no cloud credential will be associated with the model.
//
// The following error types can be expected to be returned:
// - modelerrors.AlreadyExists: When the model uuid is already in use or a model
Expand All @@ -48,14 +45,14 @@ func (m modelTypeStateFunc) CloudType(c context.Context, n string) (string, erro
// - [secretbackenderrors.NotFound] When the secret backend for the model
// cannot be found.
//
// CreateModel expects the caller to generate their own model id and pass it to
// this function. In an ideal world we want to have this stopped and make this
// function generate a new id and return the value. This can only be achieved
// once we have the Juju client stop generating id's for controller models in
// the bootstrap process.
func CreateModel(
// CreateControllerDBModelRecord expects the caller to generate their own model
// ID and pass it to this function. In an ideal world we want to have this
// stopped and make this function generate a new id and return the value.
// This can only be achieved once we have the Juju client stop generating ID's
// for controller models in the bootstrap process.
func CreateControllerDBModelRecord(
modelID coremodel.UUID,
args model.ModelCreationArgs,
args model.ControllerDBModelCreationArgs,
) internaldatabase.BootstrapOpt {
return func(ctx context.Context, controller, model database.TxnRunner) error {
if err := args.Validate(); err != nil {
Expand All @@ -68,16 +65,6 @@ func CreateModel(
)
}

agentVersion := args.AgentVersion
if args.AgentVersion == version.Zero {
agentVersion = jujuversion.Current
}

if agentVersion.Major != jujuversion.Current.Major || agentVersion.Minor != jujuversion.Current.Minor {
return fmt.Errorf("%w %q during bootstrap", modelerrors.AgentVersionNotSupported, agentVersion)
}
args.AgentVersion = agentVersion

activator := state.GetActivator()
return controller.Txn(ctx, func(ctx context.Context, tx *sqlair.TX) error {
modelTypeState := modelTypeStateFunc(
Expand Down Expand Up @@ -114,12 +101,12 @@ func CreateModel(
}
}

// CreateReadOnlyModel creates a new model within the model database with all of
// its associated metadata. The data will be read-only and cannot be modified
// once created.
func CreateReadOnlyModel(
// CreateModelDBModelRecord creates a new model within the model database with
// all of its associated metadata.
func CreateModelDBModelRecord(
id coremodel.UUID,
controllerUUID uuid.UUID,
agentVersion version.Number,
) internaldatabase.BootstrapOpt {
return func(ctx context.Context, controllerDB, modelDB database.TxnRunner) error {
if err := id.Validate(); err != nil {
Expand All @@ -136,17 +123,19 @@ func CreateReadOnlyModel(
return fmt.Errorf("getting model for id %q: %w", id, err)
}

args := model.ReadOnlyModelCreationArgs{
UUID: m.UUID,
AgentVersion: m.AgentVersion,
ControllerUUID: controllerUUID,
Name: m.Name,
Type: m.ModelType,
Cloud: m.Cloud,
CloudRegion: m.CloudRegion,
CredentialOwner: m.Credential.Owner,
CredentialName: m.Credential.Name,
IsControllerModel: true,
args := model.ModelDBModelCreationArgs{
ReadOnlyModelRecordArgs: model.ReadOnlyModelRecordArgs{
UUID: m.UUID,
ControllerUUID: controllerUUID,
Name: m.Name,
Type: m.ModelType,
Cloud: m.Cloud,
CloudRegion: m.CloudRegion,
CredentialOwner: m.Credential.Owner,
CredentialName: m.Credential.Name,
IsControllerModel: true,
},
AgentVersion: agentVersion,
}

return modelDB.Txn(ctx, func(ctx context.Context, tx *sqlair.TX) error {
Expand Down
Loading

0 comments on commit 3d792b1

Please sign in to comment.