Skip to content

Commit

Permalink
Merge pull request #11604 from wallyworld/merge-2.8-20200519
Browse files Browse the repository at this point in the history
#11604

## Description

Merge 2.8 branch with these commits:

#11585 don't write errors when pubsub socket disconnects
#11583 k8s pod initialisaton races
#11582 increase max wait time for WaitAdance
#11573 finish legacy lease removal
#11591 increase timeout in machine agent tests
#11592 expose engine worker restart time as package variable
#11507 add k8s model agent pod
#11595 fix caas uniter restart on error
#11593 add revoke leases so dead units lose their lease immediately
#11594 fix deferreturn and bolt
#11599 update deployment name used for model op

## QA

Se individual PRs
  • Loading branch information
jujubot committed May 19, 2020
2 parents 59e21a8 + 9d260f8 commit 50f03eb
Show file tree
Hide file tree
Showing 148 changed files with 3,735 additions and 5,238 deletions.
12 changes: 9 additions & 3 deletions Makefile
Expand Up @@ -14,14 +14,14 @@ define MAIN_PACKAGES
endef

# Allow the tests to take longer on restricted platforms.
ifeq ($(shell uname -p | sed -E 's/.*(armel|armhf|aarch64|ppc64le|ppc64|s390x).*/golang/'), golang)
ifeq ($(shell go env GOARCH | sed -E 's/.*(arm|arm64|ppc64le|ppc64|s390x).*/golang/'), golang)
TEST_TIMEOUT := 5400s
else
TEST_TIMEOUT := 1800s
endif

# Limit concurrency on s390x.
ifeq ($(shell uname -p | sed -E 's/.*(s390x).*/golang/'), golang)
ifeq ($(shell go env GOARCH | sed -E 's/.*(s390x).*/golang/'), golang)
TEST_ARGS := -p 4
else
TEST_ARGS :=
Expand Down Expand Up @@ -56,7 +56,13 @@ ifeq ($(DEBUG_JUJU), 1)
COMPILE_FLAGS = -gcflags "all=-N -l"
LINK_FLAGS = -ldflags "-X $(PROJECT)/version.GitCommit=$(GIT_COMMIT) -X $(PROJECT)/version.GitTreeState=$(GIT_TREE_STATE) -X $(PROJECT)/version.build=$(JUJU_BUILD_NUMBER)"
else
COMPILE_FLAGS =
ifeq ($(shell go env GOARCH | sed -E 's/.*(ppc64le|ppc64).*/golang/'), golang)
# disable optimizations on ppc64le due to https://golang.org/issue/39049
# go 1.15 should include the fix for this issue.
COMPILE_FLAGS = -gcflags "all=-N"
else
COMPILE_FLAGS =
endif
LINK_FLAGS = -ldflags "-s -w -X $(PROJECT)/version.GitCommit=$(GIT_COMMIT) -X $(PROJECT)/version.GitTreeState=$(GIT_TREE_STATE) -X $(PROJECT)/version.build=$(JUJU_BUILD_NUMBER)"
endif

Expand Down
10 changes: 7 additions & 3 deletions agent/agent.go
Expand Up @@ -444,10 +444,14 @@ func NewAgentConfig(configParams AgentConfigParams) (ConfigSetterWriter, error)
return nil, errors.Trace(requiredError("entity tag"))
}
switch configParams.Tag.(type) {
case names.MachineTag, names.UnitTag, names.ApplicationTag, names.ControllerAgentTag:
// These are the only three type of tags that can represent an agent
case names.MachineTag,
names.ModelTag,
names.UnitTag,
names.ApplicationTag,
names.ControllerAgentTag:
// These are the only five type of tags that can represent an agent
// IAAS - machine and unit
// CAAS - application, controller agent
// CAAS - application, controller agent, model
default:
return nil, errors.Errorf("entity tag must be MachineTag, UnitTag, ApplicationTag or ControllerAgentTag, got %T", configParams.Tag)
}
Expand Down
15 changes: 15 additions & 0 deletions agent/agent_test.go
Expand Up @@ -262,6 +262,21 @@ var agentConfigTests = []struct {
inspectConfig: func(c *gc.C, cfg agent.Config) {
c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/application-ubuntu")
},
}, {
about: "agentConfig accepts an Model tag",
params: agent.AgentConfigParams{
Paths: agent.Paths{DataDir: "/data/dir"},
Tag: testing.ModelTag,
Password: "sekrit",
UpgradedToVersion: jujuversion.Current,
Controller: testing.ControllerTag,
Model: testing.ModelTag,
CACert: "ca cert",
APIAddresses: []string{"localhost:1235"},
},
inspectConfig: func(c *gc.C, cfg agent.Config) {
c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/model-deadbeef-0bad-400d-8000-4b1d0d06f00d")
},
}}

func (*suite) TestNewAgentConfig(c *gc.C) {
Expand Down
69 changes: 69 additions & 0 deletions api/caasmodeloperator/client.go
@@ -0,0 +1,69 @@
// Copyright 2020 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasmodeloperator

import (
"github.com/juju/errors"
"github.com/juju/version"

"github.com/juju/juju/api/base"
"github.com/juju/juju/apiserver/params"
)

// Client is a caas model operator facade client
type Client struct {
facade base.FacadeCaller
}

// NewClient returns a client used to access the CAAS Operator Provisioner API.
func NewClient(caller base.APICaller) *Client {
facadeCaller := base.NewFacadeCaller(caller, "CAASModelOperator")
return &Client{
facade: facadeCaller,
}
}

// ModelOperatorProvisioningInfo represents return api information for
// provisioning a caas model operator
type ModelOperatorProvisioningInfo struct {
APIAddresses []string
ImagePath string
Version version.Number
}

// ModelOperatorProvisioningInfo returns the information needed for a given model
// when provisioning into a caas env
func (c *Client) ModelOperatorProvisioningInfo() (ModelOperatorProvisioningInfo, error) {
var result params.ModelOperatorInfo
if err := c.facade.FacadeCall("ModelOperatorProvisioningInfo", nil, &result); err != nil {
return ModelOperatorProvisioningInfo{}, err
}

return ModelOperatorProvisioningInfo{
APIAddresses: result.APIAddresses,
ImagePath: result.ImagePath,
Version: result.Version,
}, nil
}

// SetPasswords sets the supplied passwords on their corresponding models
func (c *Client) SetPassword(password string) error {
var result params.ErrorResults
modelTag, modelCon := c.facade.RawAPICaller().ModelTag()
if !modelCon {
return errors.New("not a model connection")
}

args := params.EntityPasswords{
Changes: []params.EntityPassword{{
Tag: modelTag.String(),
Password: password,
}},
}
err := c.facade.FacadeCall("SetPasswords", args, &result)
if err != nil {
return errors.Trace(err)
}
return result.OneError()
}
1 change: 1 addition & 0 deletions api/facadeversions.go
Expand Up @@ -27,6 +27,7 @@ var facadeVersions = map[string]int{
"CAASAgent": 1,
"CAASAdmission": 1,
"CAASFirewaller": 1,
"CAASModelOperator": 1,
"CAASOperator": 1,
"CAASOperatorProvisioner": 1,
"CAASOperatorUpgrader": 1,
Expand Down
2 changes: 2 additions & 0 deletions apiserver/allfacades.go
Expand Up @@ -75,6 +75,7 @@ import (
"github.com/juju/juju/apiserver/facades/controller/agenttools"
"github.com/juju/juju/apiserver/facades/controller/applicationscaler"
"github.com/juju/juju/apiserver/facades/controller/caasfirewaller"
"github.com/juju/juju/apiserver/facades/controller/caasmodeloperator"
"github.com/juju/juju/apiserver/facades/controller/caasoperatorprovisioner"
"github.com/juju/juju/apiserver/facades/controller/caasoperatorupgrader"
"github.com/juju/juju/apiserver/facades/controller/caasunitprovisioner"
Expand Down Expand Up @@ -183,6 +184,7 @@ func AllFacades() *facade.Registry {
reg("CAASOperator", 1, caasoperator.NewStateFacade)
reg("CAASAdmission", 1, caasadmission.NewStateFacade)
reg("CAASAgent", 1, caasagent.NewStateFacade)
reg("CAASModelOperator", 1, caasmodeloperator.NewAPIFromContext)
reg("CAASOperatorProvisioner", 1, caasoperatorprovisioner.NewStateCAASOperatorProvisionerAPI)
reg("CAASOperatorUpgrader", 1, caasoperatorupgrader.NewStateCAASOperatorUpgraderAPI)
reg("CAASUnitProvisioner", 1, caasunitprovisioner.NewStateFacade)
Expand Down
12 changes: 10 additions & 2 deletions apiserver/common/ensuredead.go
Expand Up @@ -15,15 +15,17 @@ import (
// various facades.
type DeadEnsurer struct {
st state.EntityFinder
afterDead func(names.Tag)
getCanModify GetAuthFunc
}

// NewDeadEnsurer returns a new DeadEnsurer. The GetAuthFunc will be
// used on each invocation of EnsureDead to determine current
// permissions.
func NewDeadEnsurer(st state.EntityFinder, getCanModify GetAuthFunc) *DeadEnsurer {
func NewDeadEnsurer(st state.EntityFinder, afterDead func(names.Tag), getCanModify GetAuthFunc) *DeadEnsurer {
return &DeadEnsurer{
st: st,
afterDead: afterDead,
getCanModify: getCanModify,
}
}
Expand All @@ -37,7 +39,13 @@ func (d *DeadEnsurer) ensureEntityDead(tag names.Tag) error {
if !ok {
return NotSupportedError(tag, "ensuring death")
}
return entity.EnsureDead()
if err := entity.EnsureDead(); err != nil {
return errors.Trace(err)
}
if d.afterDead != nil {
d.afterDead(tag)
}
return nil
}

// EnsureDead calls EnsureDead on each given entity from state. It
Expand Down
14 changes: 11 additions & 3 deletions apiserver/common/ensuredead_test.go
Expand Up @@ -54,13 +54,21 @@ func (*deadEnsurerSuite) TestEnsureDead(c *gc.C) {
return tag == x0 || tag == x1 || tag == x2 || tag == x4
}, nil
}
afterDeadCalled := false
afterDead := func(tag names.Tag) {
if tag != u("x/1") && tag != u("x/2") {
c.Fail()
}
afterDeadCalled = true
}

d := common.NewDeadEnsurer(st, getCanModify)
d := common.NewDeadEnsurer(st, afterDead, getCanModify)
entities := params.Entities{[]params.Entity{
{"unit-x-0"}, {"unit-x-1"}, {"unit-x-2"}, {"unit-x-3"}, {"unit-x-4"}, {"unit-x-5"},
}}
result, err := d.EnsureDead(entities)
c.Assert(err, jc.ErrorIsNil)
c.Assert(afterDeadCalled, jc.IsTrue)
c.Assert(result, gc.DeepEquals, params.ErrorResults{
Results: []params.ErrorResult{
{&params.Error{Message: "x0 fails"}},
Expand All @@ -77,7 +85,7 @@ func (*deadEnsurerSuite) TestEnsureDeadError(c *gc.C) {
getCanModify := func() (common.AuthFunc, error) {
return nil, fmt.Errorf("pow")
}
d := common.NewDeadEnsurer(&fakeState{}, getCanModify)
d := common.NewDeadEnsurer(&fakeState{}, nil, getCanModify)
_, err := d.EnsureDead(params.Entities{[]params.Entity{{"x0"}}})
c.Assert(err, gc.ErrorMatches, "pow")
}
Expand All @@ -86,7 +94,7 @@ func (*removeSuite) TestEnsureDeadNoArgsNoError(c *gc.C) {
getCanModify := func() (common.AuthFunc, error) {
return nil, fmt.Errorf("pow")
}
d := common.NewDeadEnsurer(&fakeState{}, getCanModify)
d := common.NewDeadEnsurer(&fakeState{}, nil, getCanModify)
result, err := d.EnsureDead(params.Entities{})
c.Assert(err, jc.ErrorIsNil)
c.Assert(result.Results, gc.HasLen, 0)
Expand Down
11 changes: 2 additions & 9 deletions apiserver/common/getstatus_test.go
Expand Up @@ -4,8 +4,6 @@
package common_test

import (
"time"

"github.com/juju/errors"
"github.com/juju/names/v4"
jc "github.com/juju/testing/checkers"
Expand Down Expand Up @@ -213,13 +211,8 @@ func (s *applicationStatusGetterSuite) TestGetUnitStatusIsLeader(c *gc.C) {
unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &status.StatusInfo{
Status: status.Maintenance,
}})
app, err := unit.Application()
c.Assert(err, jc.ErrorIsNil)
err = s.State.LeadershipClaimer().ClaimLeadership(
app.Name(),
unit.Name(),
time.Minute)
c.Assert(err, jc.ErrorIsNil)
// No need to claim leadership - the checker passed in in setup
// always returns true.
result, err := s.getter.Status(params.Entities{[]params.Entity{{
unit.Tag().String(),
}}})
Expand Down
7 changes: 6 additions & 1 deletion apiserver/common/remove.go
Expand Up @@ -17,6 +17,7 @@ import (
// Remover implements a common Remove method for use by various facades.
type Remover struct {
st state.EntityFinder
afterDead func(tag names.Tag)
callEnsureDead bool
getCanModify GetAuthFunc
}
Expand All @@ -25,9 +26,10 @@ type Remover struct {
// whether EnsureDead should be called on an entity before
// removing. The GetAuthFunc will be used on each invocation of Remove
// to determine current permissions.
func NewRemover(st state.EntityFinder, callEnsureDead bool, getCanModify GetAuthFunc) *Remover {
func NewRemover(st state.EntityFinder, afterDead func(tag names.Tag), callEnsureDead bool, getCanModify GetAuthFunc) *Remover {
return &Remover{
st: st,
afterDead: afterDead,
callEnsureDead: callEnsureDead,
getCanModify: getCanModify,
}
Expand All @@ -54,6 +56,9 @@ func (r *Remover) removeEntity(tag names.Tag) error {
if err := remover.EnsureDead(); err != nil {
return err
}
if r.afterDead != nil {
r.afterDead(tag)
}
}
// TODO (anastasiamac) this needs to work with force if needed
return remover.Remove()
Expand Down
18 changes: 14 additions & 4 deletions apiserver/common/remove_test.go
Expand Up @@ -61,13 +61,21 @@ func (*removeSuite) TestRemove(c *gc.C) {
return tag == u0 || tag == u1 || tag == u2 || tag == u3 || tag == u5
}, nil
}
afterDeadCalled := false
afterDead := func(tag names.Tag) {
if tag != u("x/1") && tag != u("x/3") {
c.Fail()
}
afterDeadCalled = true
}

r := common.NewRemover(st, true, getCanModify)
r := common.NewRemover(st, afterDead, true, getCanModify)
entities := params.Entities{[]params.Entity{
{"unit-x-0"}, {"unit-x-1"}, {"unit-x-2"}, {"unit-x-3"}, {"unit-x-4"}, {"unit-x-5"}, {"unit-x-6"},
}}
result, err := r.Remove(entities)
c.Assert(err, jc.ErrorIsNil)
c.Assert(afterDeadCalled, jc.IsTrue)
c.Assert(result, gc.DeepEquals, params.ErrorResults{
Results: []params.ErrorResult{
{&params.Error{Message: "x0 EnsureDead fails"}},
Expand All @@ -82,10 +90,12 @@ func (*removeSuite) TestRemove(c *gc.C) {

// Make sure when callEnsureDead is false EnsureDead() doesn't
// get called.
r = common.NewRemover(st, false, getCanModify)
afterDeadCalled = false
r = common.NewRemover(st, afterDead, false, getCanModify)
entities = params.Entities{[]params.Entity{{"unit-x-0"}, {"unit-x-1"}}}
result, err = r.Remove(entities)
c.Assert(err, jc.ErrorIsNil)
c.Assert(afterDeadCalled, jc.IsFalse)
c.Assert(result, gc.DeepEquals, params.ErrorResults{
Results: []params.ErrorResult{
{nil},
Expand All @@ -98,7 +108,7 @@ func (*removeSuite) TestRemoveError(c *gc.C) {
getCanModify := func() (common.AuthFunc, error) {
return nil, fmt.Errorf("pow")
}
r := common.NewRemover(&fakeState{}, true, getCanModify)
r := common.NewRemover(&fakeState{}, nil, true, getCanModify)
_, err := r.Remove(params.Entities{[]params.Entity{{"x0"}}})
c.Assert(err, gc.ErrorMatches, "pow")
}
Expand All @@ -107,7 +117,7 @@ func (*removeSuite) TestRemoveNoArgsNoError(c *gc.C) {
getCanModify := func() (common.AuthFunc, error) {
return nil, fmt.Errorf("pow")
}
r := common.NewRemover(&fakeState{}, true, getCanModify)
r := common.NewRemover(&fakeState{}, nil, true, getCanModify)
result, err := r.Remove(params.Entities{})
c.Assert(err, jc.ErrorIsNil)
c.Assert(result.Results, gc.HasLen, 0)
Expand Down
9 changes: 2 additions & 7 deletions apiserver/common/setstatus_test.go
Expand Up @@ -4,8 +4,6 @@
package common_test

import (
"time"

"github.com/juju/errors"
"github.com/juju/names/v4"
jc "github.com/juju/testing/checkers"
Expand Down Expand Up @@ -244,11 +242,8 @@ func (s *serviceStatusSetterSuite) TestSetUnitStatusIsLeader(c *gc.C) {
Status: &status.StatusInfo{
Status: status.Maintenance,
}})
err := s.State.LeadershipClaimer().ClaimLeadership(
service.Name(),
unit.Name(),
time.Minute)
c.Assert(err, jc.ErrorIsNil)
// No need to claim leadership - the checker passed in in setup
// always returns true.
result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{
Tag: unit.Tag().String(),
Status: status.Active.String(),
Expand Down
23 changes: 23 additions & 0 deletions apiserver/common/unit.go
@@ -0,0 +1,23 @@
// Copyright 2020 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package common

import (
"github.com/juju/names/v4"

"github.com/juju/juju/core/leadership"
)

// RevokeLeadershipFunc returns a function that revokes leadership for dead units.
func RevokeLeadershipFunc(leadershipRevoker leadership.Revoker) func(names.Tag) {
return func(tag names.Tag) {
if tag.Kind() != names.UnitTagKind {
return
}
appName, _ := names.UnitApplication(tag.Id())
if err := leadershipRevoker.RevokeLeadership(appName, tag.Id()); err != nil && err != leadership.ErrClaimNotHeld {
logger.Warningf("cannot revoke lease for dead unit %q", tag.Id())
}
}
}

0 comments on commit 50f03eb

Please sign in to comment.