Skip to content

Commit

Permalink
Merge pull request juju#16350 from barrettj12/merge-3.2-3.3-20230929
Browse files Browse the repository at this point in the history
juju#16350

Merges the following patches:
- juju#16349
- juju#16348
- juju#16332
- juju#16325
- juju#16327
- juju#16302
- juju#16309

### Conflicts
None.
  • Loading branch information
jujubot authored Sep 29, 2023
2 parents acee487 + 468f3d2 commit d668d19
Show file tree
Hide file tree
Showing 18 changed files with 368 additions and 89 deletions.
15 changes: 15 additions & 0 deletions api/controller/caasmodeloperator/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"github.com/juju/version/v2"

"github.com/juju/juju/api/base"
apiwatcher "github.com/juju/juju/api/watcher"
"github.com/juju/juju/core/resources"
"github.com/juju/juju/core/watcher"
"github.com/juju/juju/docker"
"github.com/juju/juju/rpc/params"
)
Expand Down Expand Up @@ -87,3 +89,16 @@ func (c *Client) SetPassword(password string) error {
}
return result.OneError()
}

// WatchModelOperatorProvisioningInfo provides a watcher for changes that affect the
// information returned by ModelOperatorProvisioningInfo.
func (c *Client) WatchModelOperatorProvisioningInfo() (watcher.NotifyWatcher, error) {
var result params.NotifyWatchResult
if err := c.facade.FacadeCall("WatchModelOperatorProvisioningInfo", nil, &result); err != nil {
return nil, err
}
if result.Error != nil {
return nil, result.Error
}
return apiwatcher.NewNotifyWatcher(c.facade.RawAPICaller(), result), nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ type mockState struct {
testing.Stub

common.APIAddressAccessor
model *mockModel
applicationWatcher *mockStringsWatcher
app *mockApplication
resource *mockResources
operatorRepo string
controllerConfigWatcher *statetesting.MockNotifyWatcher
isController bool
model *mockModel
applicationWatcher *mockStringsWatcher
app *mockApplication
resource *mockResources
operatorRepo string
controllerConfigWatcher *statetesting.MockNotifyWatcher
apiHostPortsForAgentsWatcher *statetesting.MockNotifyWatcher
isController bool
}

func newMockState() *mockState {
Expand Down Expand Up @@ -126,6 +127,11 @@ func (st *mockState) IsController() bool {
return st.isController
}

func (st *mockState) WatchAPIHostPortsForAgents() state.NotifyWatcher {
st.MethodCall(st, "WatchAPIHostPortsForAgents")
return st.apiHostPortsForAgentsWatcher
}

type mockResources struct {
caasapplicationprovisioner.Resources
resource *resources.DockerImageDetails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,12 @@ func (a *API) watchProvisioningInfo(appName names.ApplicationTag) (params.Notify
return result, errors.Trace(err)
}

modelConfigWatcher := model.WatchForModelConfigChanges()
appWatcher := app.Watch()
controllerConfigWatcher := a.ctrlSt.WatchControllerConfig()
controllerAPIHostPortsWatcher := a.ctrlSt.WatchAPIHostPortsForAgents()
modelConfigWatcher := model.WatchForModelConfigChanges()

multiWatcher := common.NewMultiNotifyWatcher(appWatcher, controllerConfigWatcher, modelConfigWatcher)
multiWatcher := common.NewMultiNotifyWatcher(appWatcher, controllerConfigWatcher, controllerAPIHostPortsWatcher, modelConfigWatcher)

if _, ok := <-multiWatcher.Changes(); ok {
result.NotifyWatcherId = a.resources.Register(multiWatcher)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,40 @@ func (s *CAASApplicationProvisionerSuite) TestProvisioningInfoPendingCharmError(
c.Assert(result.Results[0].Error, gc.ErrorMatches, `charm "ch:gitlab" pending not provisioned`)
}

func (s *CAASApplicationProvisionerSuite) TestWatchProvisioningInfo(c *gc.C) {
appChanged := make(chan struct{}, 1)
portsChanged := make(chan struct{}, 1)
modelConfigChanged := make(chan struct{}, 1)
controllerConfigChanged := make(chan struct{}, 1)
s.st.apiHostPortsForAgentsWatcher = statetesting.NewMockNotifyWatcher(portsChanged)
s.st.model.state.controllerConfigWatcher = statetesting.NewMockNotifyWatcher(controllerConfigChanged)
s.st.model.modelConfigChanges = statetesting.NewMockNotifyWatcher(modelConfigChanged)
s.st.app = &mockApplication{
life: state.Alive,
charm: &mockCharm{
meta: &charm.Meta{},
url: "cs:gitlab",
},
watcher: statetesting.NewMockNotifyWatcher(appChanged),
}
appChanged <- struct{}{}
portsChanged <- struct{}{}
modelConfigChanged <- struct{}{}
controllerConfigChanged <- struct{}{}

results, err := s.api.WatchProvisioningInfo(params.Entities{
Entities: []params.Entity{
{Tag: "application-gitlab"},
},
})

c.Assert(err, jc.ErrorIsNil)
c.Assert(results.Results, gc.HasLen, 1)
c.Assert(results.Results[0].Error, gc.IsNil)
res := s.resources.Get("1")
c.Assert(res, gc.FitsTypeOf, (*common.MultiNotifyWatcher)(nil))
}

func (s *CAASApplicationProvisionerSuite) TestSetOperatorStatus(c *gc.C) {
s.st.app = &mockApplication{
life: state.Alive,
Expand Down
23 changes: 19 additions & 4 deletions apiserver/facades/controller/caasmodeloperator/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ import (
)

type mockModel struct {
password string
tag names.Tag
password string
tag names.Tag
modelConfigChanged state.NotifyWatcher
}

type mockState struct {
common.APIAddressAccessor
operatorRepo string
model *mockModel
operatorRepo string
model *mockModel
controllerConfigWatcher state.NotifyWatcher
apiHostPortsForAgentsWatcher state.NotifyWatcher
}

func newMockState() *mockState {
Expand Down Expand Up @@ -60,6 +63,14 @@ func (st *mockState) Model() (caasmodeloperator.Model, error) {
return st.model, nil
}

func (m *mockState) WatchControllerConfig() state.NotifyWatcher {
return m.controllerConfigWatcher
}

func (m *mockState) WatchAPIHostPortsForAgents() state.NotifyWatcher {
return m.apiHostPortsForAgentsWatcher
}

func (m *mockModel) Tag() names.Tag {
return m.tag
}
Expand All @@ -79,3 +90,7 @@ func (m *mockModel) ModelConfig() (*config.Config, error) {
attrs["agent-version"] = "2.6-beta3"
return config.New(config.UseDefaults, attrs)
}

func (m *mockModel) WatchForModelConfigChanges() state.NotifyWatcher {
return m.modelConfigChanged
}
29 changes: 29 additions & 0 deletions apiserver/facades/controller/caasmodeloperator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/juju/juju/apiserver/facade"
"github.com/juju/juju/cloudconfig/podcfg"
"github.com/juju/juju/rpc/params"
"github.com/juju/juju/state/watcher"
)

var logger = loggo.GetLogger("juju.apiserver.caasmodeloperator")
Expand All @@ -30,6 +31,8 @@ type API struct {
auth facade.Authorizer
ctrlState CAASControllerState
state CAASModelOperatorState

resources facade.Resources
}

// NewAPI is alternative means of constructing a controller model facade.
Expand All @@ -49,9 +52,35 @@ func NewAPI(
PasswordChanger: common.NewPasswordChanger(st, common.AuthFuncForTagKind(names.ModelTagKind)),
ctrlState: ctrlSt,
state: st,
resources: resources,
}, nil
}

// WatchModelOperatorProvisioningInfo provides a watcher for changes that affect the
// information returned by ModelOperatorProvisioningInfo.
func (a *API) WatchModelOperatorProvisioningInfo() (params.NotifyWatchResult, error) {
result := params.NotifyWatchResult{}

model, err := a.state.Model()
if err != nil {
return result, errors.Trace(err)
}

controllerConfigWatcher := a.ctrlState.WatchControllerConfig()
controllerAPIHostPortsWatcher := a.ctrlState.WatchAPIHostPortsForAgents()
modelConfigWatcher := model.WatchForModelConfigChanges()

multiWatcher := common.NewMultiNotifyWatcher(controllerConfigWatcher, controllerAPIHostPortsWatcher, modelConfigWatcher)

if _, ok := <-multiWatcher.Changes(); ok {
result.NotifyWatcherId = a.resources.Register(multiWatcher)
} else {
return result, watcher.EnsureErr(multiWatcher)
}

return result, nil
}

// ModelOperatorProvisioningInfo returns the information needed for provisioning
// a new model operator into a caas cluster.
func (a *API) ModelOperatorProvisioningInfo() (params.ModelOperatorInfo, error) {
Expand Down
20 changes: 20 additions & 0 deletions apiserver/facades/controller/caasmodeloperator/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/juju/juju/apiserver/facades/controller/caasmodeloperator"
apiservertesting "github.com/juju/juju/apiserver/testing"
"github.com/juju/juju/cloudconfig/podcfg"
statetesting "github.com/juju/juju/state/testing"
coretesting "github.com/juju/juju/testing"
)

Expand Down Expand Up @@ -77,3 +78,22 @@ func (m *ModelOperatorSuite) TestProvisioningInfo(c *gc.C) {

c.Assert(vers, jc.DeepEquals, info.Version)
}

func (m *ModelOperatorSuite) TestWatchProvisioningInfo(c *gc.C) {
controllerConfigChanged := make(chan struct{}, 1)
modelConfigChanged := make(chan struct{}, 1)
apiHostPortsForAgentsChanged := make(chan struct{}, 1)
m.state.controllerConfigWatcher = statetesting.NewMockNotifyWatcher(controllerConfigChanged)
m.state.apiHostPortsForAgentsWatcher = statetesting.NewMockNotifyWatcher(apiHostPortsForAgentsChanged)
m.state.model.modelConfigChanged = statetesting.NewMockNotifyWatcher(modelConfigChanged)

controllerConfigChanged <- struct{}{}
apiHostPortsForAgentsChanged <- struct{}{}
modelConfigChanged <- struct{}{}

results, err := m.api.WatchModelOperatorProvisioningInfo()
c.Assert(err, jc.ErrorIsNil)
c.Assert(results.Error, gc.IsNil)
res := m.resources.Get("1")
c.Assert(res, gc.FitsTypeOf, (*common.MultiNotifyWatcher)(nil))
}
2 changes: 2 additions & 0 deletions apiserver/facades/controller/caasmodeloperator/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ type CAASModelOperatorState interface {
type CAASControllerState interface {
common.APIAddressAccessor
ControllerConfig() (controller.Config, error)
WatchControllerConfig() state.NotifyWatcher
}

type Model interface {
ModelConfig() (*config.Config, error)
WatchForModelConfigChanges() state.NotifyWatcher
}

type stateShim struct {
Expand Down
9 changes: 9 additions & 0 deletions apiserver/facades/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10590,6 +10590,15 @@
}
},
"description": "WatchAPIHostPorts watches the API server addresses."
},
"WatchModelOperatorProvisioningInfo": {
"type": "object",
"properties": {
"Result": {
"$ref": "#/definitions/NotifyWatchResult"
}
},
"description": "WatchModelOperatorProvisioningInfo provides a watcher for changes that affect the\ninformation returned by ModelOperatorProvisioningInfo."
}
},
"definitions": {
Expand Down
73 changes: 41 additions & 32 deletions cmd/containeragent/unit/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package unit

import (
"fmt"
"os"
"os/signal"
"path"
Expand Down Expand Up @@ -118,34 +119,6 @@ func (c *containerUnitAgent) CharmModifiedVersion() int {
return c.charmModifiedVersion
}

func (c *containerUnitAgent) ensureAgentConf(dataDir string) error {
templateConfigPath := path.Join(dataDir, k8sconstants.TemplateFileNameAgentConf)
logger.Debugf("template config path %s", templateConfigPath)
config, err := agent.ReadConfig(templateConfigPath)
if err != nil {
return errors.Annotate(err, "reading template agent config file")
}
unitTag := config.Tag()
configPath := agent.ConfigPath(dataDir, unitTag)
logger.Debugf("config path %s", configPath)
configDir := path.Dir(configPath)
if err := os.MkdirAll(configDir, 0755); err != nil {
return errors.Annotatef(err, "making agent directory %q", configDir)
}
configBytes, err := config.Render()
if err != nil {
return errors.Trace(err)
}
if err := os.WriteFile(configPath, configBytes, 0644); err != nil {
return errors.Annotate(err, "writing agent config file")
}

if err := c.ReadConfig(unitTag.String()); err != nil {
return errors.Annotate(err, "reading agent config file")
}
return nil
}

// Init initializes the command for running.
func (c *containerUnitAgent) Init(args []string) error {
if err := c.AgentConf.CheckArgs(args); err != nil {
Expand Down Expand Up @@ -185,9 +158,7 @@ func (c *containerUnitAgent) Init(args []string) error {
Logger: logger,
})

dataDir := c.DataDir()

if err := c.ensureAgentConf(dataDir); err != nil {
if err := ensureAgentConf(c.AgentConf); err != nil {
return errors.Annotate(err, "ensuring agent conf file")
}

Expand All @@ -197,7 +168,7 @@ func (c *containerUnitAgent) Init(args []string) error {
}

srcDir := path.Dir(os.Args[0])
if err := c.ensureToolSymlinks(srcDir, dataDir, unitTag); err != nil {
if err := c.ensureToolSymlinks(srcDir, c.DataDir(), unitTag); err != nil {
return errors.Annotate(err, "ensuring agent tool symlinks")
}
containerNames := c.environment.Getenv(k8sconstants.EnvJujuContainerNames)
Expand Down Expand Up @@ -428,3 +399,41 @@ func AgentDone(logger loggo.Logger, err error) error {
}
return err
}

func ensureAgentConf(ac agentconf.AgentConf) error {
templateConfigPath := path.Join(ac.DataDir(), k8sconstants.TemplateFileNameAgentConf)
logger.Debugf("template config path %s", templateConfigPath)
config, err := agent.ReadConfig(templateConfigPath)
if err != nil {
return errors.Annotate(err, "reading template agent config file")
}

unitTag := config.Tag()
configPath := agent.ConfigPath(ac.DataDir(), unitTag)
logger.Debugf("config path %s", configPath)
// if the rendered configuration already exists, use that copy
// as it likely has updated api addresses or could have a newer password,
// otherwise we need to copy the template.
if _, err := os.Stat(configPath); err == nil {
return ac.ReadConfig(unitTag.String())
} else if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("cannot stat current config %s: %w", configPath, err)
}

configDir := path.Dir(configPath)
if err := os.MkdirAll(configDir, 0755); err != nil {
return errors.Annotatef(err, "making agent directory %q", configDir)
}
configBytes, err := config.Render()
if err != nil {
return errors.Trace(err)
}
if err := os.WriteFile(configPath, configBytes, 0644); err != nil {
return errors.Annotate(err, "writing agent config file")
}

if err := ac.ReadConfig(unitTag.String()); err != nil {
return errors.Annotate(err, "reading agent config file")
}
return nil
}
Loading

0 comments on commit d668d19

Please sign in to comment.