From 70869ebce8e8f914a5ff68c410d7a2f5434a61ce Mon Sep 17 00:00:00 2001 From: nam Date: Fri, 22 Nov 2019 11:21:19 +0100 Subject: [PATCH 1/3] add firewallrule export step and new description version --- Gopkg.lock | 4 +- Gopkg.toml | 2 +- apiserver/common/crossmodel/crossmodel.go | 2 +- .../client/firewallrules/firewallrules.go | 10 ++-- .../firewallrules/firewallrules_test.go | 5 +- .../facades/client/firewallrules/mock_test.go | 12 ++-- .../crossmodelrelations_test.go | 3 +- .../controller/firewaller/firewaller.go | 2 +- .../firewaller/firewaller_unit_test.go | 6 +- state/firewallrules.go | 50 ++++++++++++---- state/firewallrules_test.go | 59 +++++-------------- state/migration_export.go | 38 ++++++++++++ state/migration_export_test.go | 20 +++++++ state/migrations/firewallRules.go | 52 ++++++++++++++++ state/migrations/remoteapplications.go | 10 ++-- worker/firewaller/firewaller_test.go | 5 +- 16 files changed, 188 insertions(+), 92 deletions(-) create mode 100644 state/migrations/firewallRules.go diff --git a/Gopkg.lock b/Gopkg.lock index 49f73a39dbc..6df02bc154a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -492,11 +492,11 @@ revision = "9be91dc79b7c185fa8b08e7ceceee40562055c83" [[projects]] - digest = "1:12e9d8a3a8f87f24295b14721ae5a222b06db2c3215d0015b7766a3ddb559095" + digest = "1:ef77a561f2a4b11670d81ae04ccb2257b908af008b140929051d5841593f08bf" name = "github.com/juju/description" packages = ["."] pruneopts = "" - revision = "4a2d8e1a91c9355889febe294accbbcfb3a1a656" + revision = "61283e074b8b886a5f4a1c5d29d063de33a7faf3" [[projects]] digest = "1:594030c0f0ed3842773b68708d4f9716d809556b9c631460051f99b15057512d" diff --git a/Gopkg.toml b/Gopkg.toml index 06fd71c09f8..7c5be5161cf 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -62,7 +62,7 @@ name = "github.com/juju/bundlechanges" [[constraint]] - revision = "4a2d8e1a91c9355889febe294accbbcfb3a1a656" + revision = "61283e074b8b886a5f4a1c5d29d063de33a7faf3" name = "github.com/juju/description" [[constraint]] diff --git a/apiserver/common/crossmodel/crossmodel.go b/apiserver/common/crossmodel/crossmodel.go index 4843ef6d459..da746843df5 100644 --- a/apiserver/common/crossmodel/crossmodel.go +++ b/apiserver/common/crossmodel/crossmodel.go @@ -257,7 +257,7 @@ func validateIngressNetworks(backend Backend, networks []string) error { return nil } var whitelistCIDRs, requestedCIDRs []*net.IPNet - if err := parseCIDRs(&whitelistCIDRs, rule.WhitelistCIDRs); err != nil { + if err := parseCIDRs(&whitelistCIDRs, rule.WhitelistCIDRs()); err != nil { return errors.Trace(err) } if err := parseCIDRs(&requestedCIDRs, networks); err != nil { diff --git a/apiserver/facades/client/firewallrules/firewallrules.go b/apiserver/facades/client/firewallrules/firewallrules.go index 46d433162b3..84838c77d70 100644 --- a/apiserver/facades/client/firewallrules/firewallrules.go +++ b/apiserver/facades/client/firewallrules/firewallrules.go @@ -86,10 +86,8 @@ func (api *API) SetFirewallRules(args params.FirewallRuleArgs) (params.ErrorResu results := make([]params.ErrorResult, len(args.Args)) for i, arg := range args.Args { logger.Debugf("saving firewall rule %+v", arg) - err := api.backend.SaveFirewallRule(state.FirewallRule{ - WellKnownService: state.WellKnownServiceType(arg.KnownService), - WhitelistCIDRs: arg.WhitelistCIDRS, - }) + err := api.backend.SaveFirewallRule(state.NewFirewallRule( + state.WellKnownServiceType(arg.KnownService), arg.WhitelistCIDRS)) results[i].Error = common.ServerError(err) } errResults.Results = results @@ -109,8 +107,8 @@ func (api *API) ListFirewallRules() (params.ListFirewallRulesResults, error) { listResults.Rules = make([]params.FirewallRule, len(rules)) for i, r := range rules { listResults.Rules[i] = params.FirewallRule{ - KnownService: params.KnownServiceValue(r.WellKnownService), - WhitelistCIDRS: r.WhitelistCIDRs, + KnownService: params.KnownServiceValue(r.WellKnownServiceType()), + WhitelistCIDRS: r.WhitelistCIDRs(), } } return listResults, nil diff --git a/apiserver/facades/client/firewallrules/firewallrules_test.go b/apiserver/facades/client/firewallrules/firewallrules_test.go index f4e620a0fc6..510299eb0e9 100644 --- a/apiserver/facades/client/firewallrules/firewallrules_test.go +++ b/apiserver/facades/client/firewallrules/firewallrules_test.go @@ -74,10 +74,7 @@ func (s *FirewallRulesSuite) TestSetFirewallRules(c *gc.C) { }) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.ErrorResults{[]params.ErrorResult{{Error: nil}}}) - c.Assert(s.backend.rules["juju-controller"], jc.DeepEquals, state.FirewallRule{ - WellKnownService: state.JujuControllerRule, - WhitelistCIDRs: []string{"1.2.3.4/8"}, - }) + c.Assert(s.backend.rules["juju-controller"], jc.DeepEquals, state.NewFirewallRule(state.JujuControllerRule, []string{"1.2.3.4/8"})) } func (s *FirewallRulesSuite) TestSetFirewallRulesPermission(c *gc.C) { diff --git a/apiserver/facades/client/firewallrules/mock_test.go b/apiserver/facades/client/firewallrules/mock_test.go index 412b4621d89..f111c77a69f 100644 --- a/apiserver/facades/client/firewallrules/mock_test.go +++ b/apiserver/facades/client/firewallrules/mock_test.go @@ -32,19 +32,17 @@ func (m *mockBackend) ModelTag() names.ModelTag { func (m *mockBackend) SaveFirewallRule(rule state.FirewallRule) error { m.MethodCall(m, "SaveFirewallRule") m.PopNoErr() - m.rules[string(rule.WellKnownService)] = rule + m.rules[string(rule.WellKnownServiceType())] = rule return nil } func (m *mockBackend) ListFirewallRules() ([]*state.FirewallRule, error) { m.MethodCall(m, "ListFirewallRules") m.PopNoErr() - return []*state.FirewallRule{ - { - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"1.2.3.4/8"}, - }, - }, nil + frls := make([]*state.FirewallRule, 1) + firewareRule := state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"1.2.3.4/8"}) + frls[0] = &firewareRule + return frls, nil } type mockBlockChecker struct { diff --git a/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go b/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go index 214e6d639c4..8fa68bfff0a 100644 --- a/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go +++ b/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go @@ -369,7 +369,8 @@ func (s *crossmodelRelationsSuite) TestPublishIngressNetworkChangesRejected(c *g }) c.Assert(err, jc.ErrorIsNil) - s.st.firewallRules[state.JujuApplicationOfferRule] = &state.FirewallRule{WhitelistCIDRs: []string{"10.1.1.1/8"}} + rule := state.NewFirewallRule("", []string{"10.1.1.1/8"}) + s.st.firewallRules[state.JujuApplicationOfferRule] = &rule results, err := s.api.PublishIngressNetworkChanges(params.IngressNetworksChanges{ Changes: []params.IngressNetworksChangeEvent{ { diff --git a/apiserver/facades/controller/firewaller/firewaller.go b/apiserver/facades/controller/firewaller/firewaller.go index 2a8a3b3d2c7..d17e920856a 100644 --- a/apiserver/facades/controller/firewaller/firewaller.go +++ b/apiserver/facades/controller/firewaller/firewaller.go @@ -497,7 +497,7 @@ func (f *FirewallerAPIV4) FirewallRules(args params.KnownServiceArgs) (params.Li } result.Rules = append(result.Rules, params.FirewallRule{ KnownService: knownService, - WhitelistCIDRS: rule.WhitelistCIDRs, + WhitelistCIDRS: rule.WhitelistCIDRs(), }) } return result, nil diff --git a/apiserver/facades/controller/firewaller/firewaller_unit_test.go b/apiserver/facades/controller/firewaller/firewaller_unit_test.go index 1b4432e2c03..0b3b72dd542 100644 --- a/apiserver/facades/controller/firewaller/firewaller_unit_test.go +++ b/apiserver/facades/controller/firewaller/firewaller_unit_test.go @@ -123,10 +123,8 @@ func (s *RemoteFirewallerSuite) TestSetRelationStatus(c *gc.C) { } func (s *RemoteFirewallerSuite) TestFirewallRules(c *gc.C) { - s.st.firewallRules[state.JujuApplicationOfferRule] = &state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.0.0/16"}, - } + rule := state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.0.0/16"}) + s.st.firewallRules[state.JujuApplicationOfferRule] = &rule result, err := s.api.FirewallRules(params.KnownServiceArgs{ KnownServices: []params.KnownServiceValue{params.JujuApplicationOfferRule, params.SSHRule}}) c.Assert(err, jc.ErrorIsNil) diff --git a/state/firewallrules.go b/state/firewallrules.go index c2eb79675e7..81fa12ab8c5 100644 --- a/state/firewallrules.go +++ b/state/firewallrules.go @@ -26,11 +26,34 @@ import ( // - juju-controller // - juju-application-offer type FirewallRule struct { - // WellKnownService is the known service for the firewall rules entity. - WellKnownService WellKnownServiceType + id string - // WhitelistCIDRS is the whitelist CIDRs for the rule. - WhitelistCIDRs []string + wellKnownService string + + whitelistCIDRs []string +} + +func NewFirewallRule(serviceType WellKnownServiceType, cidrs []string) FirewallRule { + return FirewallRule{whitelistCIDRs: cidrs, wellKnownService: string(serviceType)} +} + +func (f FirewallRule) ID() string { + return f.id +} + +// WellKnownServiceType is the known service for the firewall rules entity. +func (f FirewallRule) WellKnownServiceType() WellKnownServiceType { + return WellKnownServiceType(f.wellKnownService) +} + +// WellKnownService is the known service for the firewall rules entity as a string. +func (f FirewallRule) WellKnownService() string { + return f.wellKnownService +} + +// WhitelistCIDRS is the whitelist CIDRs for the rule. +func (f FirewallRule) WhitelistCIDRs() []string { + return f.whitelistCIDRs } type firewallRulesDoc struct { @@ -41,8 +64,9 @@ type firewallRulesDoc struct { func (r *firewallRulesDoc) toRule() *FirewallRule { return &FirewallRule{ - WellKnownService: WellKnownServiceType(r.WellKnownService), - WhitelistCIDRs: r.WhitelistCIDRS, + id: r.Id, + wellKnownService: r.WellKnownService, + whitelistCIDRs: r.WhitelistCIDRS, } } @@ -86,19 +110,19 @@ func NewFirewallRules(st *State) *firewallRulesState { // Save stores the specified firewall rule. func (fw *firewallRulesState) Save(rule FirewallRule) error { - if err := rule.WellKnownService.validate(); err != nil { + if err := rule.WellKnownServiceType().validate(); err != nil { return errors.Trace(err) } - for _, cidr := range rule.WhitelistCIDRs { + for _, cidr := range rule.WhitelistCIDRs() { if _, _, err := net.ParseCIDR(cidr); err != nil { return errors.NotValidf("CIDR %q", cidr) } } - serviceStr := string(rule.WellKnownService) + serviceStr := string(rule.WellKnownServiceType()) doc := firewallRulesDoc{ Id: serviceStr, WellKnownService: serviceStr, - WhitelistCIDRS: rule.WhitelistCIDRs, + WhitelistCIDRS: rule.WhitelistCIDRs(), } buildTxn := func(int) ([]txn.Op, error) { model, err := fw.st.Model() @@ -109,7 +133,7 @@ func (fw *firewallRulesState) Save(rule FirewallRule) error { return nil, errors.Trace(err) } - _, err = fw.Rule(rule.WellKnownService) + _, err = fw.Rule(rule.WellKnownServiceType()) if err != nil && !errors.IsNotFound(err) { return nil, errors.Trace(err) } @@ -120,11 +144,11 @@ func (fw *firewallRulesState) Save(rule FirewallRule) error { Id: serviceStr, Assert: txn.DocExists, Update: bson.D{ - {"$set", bson.D{{"whitelist-cidrs", rule.WhitelistCIDRs}}}, + {"$set", bson.D{{"whitelist-cidrs", rule.WhitelistCIDRs()}}}, }, }, model.assertActiveOp()} } else { - doc.WhitelistCIDRS = rule.WhitelistCIDRs + doc.WhitelistCIDRS = rule.WhitelistCIDRs() ops = []txn.Op{{ C: firewallRulesC, Id: doc.Id, diff --git a/state/firewallrules_test.go b/state/firewallrules_test.go index 2b97066ea8b..b5a21fd8530 100644 --- a/state/firewallrules_test.go +++ b/state/firewallrules_test.go @@ -4,9 +4,9 @@ package state_test import ( + "github.com/juju/errors" "regexp" - "github.com/juju/errors" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" "gopkg.in/mgo.v2/bson" @@ -22,10 +22,7 @@ var _ = gc.Suite(&FirewallRulesSuite{}) func (s *FirewallRulesSuite) TestSaveInvalidWhitelistCIDR(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: state.JujuControllerRule, - WhitelistCIDRs: []string{"192.168.1"}, - }) + err := rules.Save(state.NewFirewallRule(state.JujuControllerRule, []string{"192.168.1"})) c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`CIDR "192.168.1" not valid`)) } @@ -46,30 +43,21 @@ func (s *FirewallRulesSuite) assertSavedRules(c *gc.C, service state.WellKnownSe func (s *FirewallRulesSuite) TestSaveInvalid(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: "foo", - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := rules.Save(state.NewFirewallRule("foo", []string{"192.168.1.0/16"})) c.Assert(err, jc.Satisfies, errors.IsNotValid) c.Assert(err, gc.ErrorMatches, `well known service type "foo" not valid`) } func (s *FirewallRulesSuite) TestSave(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: state.SSHRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := rules.Save(state.NewFirewallRule(state.SSHRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) s.assertSavedRules(c, state.SSHRule, []string{"192.168.1.0/16"}) } func (s *FirewallRulesSuite) TestSaveIdempotent(c *gc.C) { rules := state.NewFirewallRules(s.State) - rule := state.FirewallRule{ - WellKnownService: state.SSHRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - } + rule := state.NewFirewallRule(state.SSHRule, []string{"192.168.1.0/16"}) err := rules.Save(rule) c.Assert(err, jc.ErrorIsNil) err = rules.Save(rule) @@ -79,56 +67,41 @@ func (s *FirewallRulesSuite) TestSaveIdempotent(c *gc.C) { func (s *FirewallRulesSuite) TestRule(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) result, err := rules.Rule(state.JujuApplicationOfferRule) c.Assert(err, jc.ErrorIsNil) - c.Assert(result.WhitelistCIDRs, jc.DeepEquals, []string{"192.168.1.0/16"}) + c.Assert(result.WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.1.0/16"}) _, err = rules.Rule(state.JujuControllerRule) c.Assert(err, jc.Satisfies, errors.IsNotFound) } func (s *FirewallRulesSuite) TestAllRules(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - err = rules.Save(state.FirewallRule{ - WellKnownService: state.JujuControllerRule, - WhitelistCIDRs: []string{"192.168.2.0/16"}, - }) + err = rules.Save(state.NewFirewallRule(state.JujuControllerRule, []string{"192.168.2.0/16"})) c.Assert(err, jc.ErrorIsNil) result, err := rules.AllRules() c.Assert(err, jc.ErrorIsNil) c.Assert(result, gc.HasLen, 2) appRuleIndex := 0 ctrlRuleIndex := 1 - if result[0].WellKnownService == state.JujuControllerRule { + if result[0].WellKnownServiceType() == state.JujuControllerRule { appRuleIndex = 1 ctrlRuleIndex = 0 } - c.Assert(result[appRuleIndex].WellKnownService, gc.Equals, state.JujuApplicationOfferRule) - c.Assert(result[appRuleIndex].WhitelistCIDRs, jc.DeepEquals, []string{"192.168.1.0/16"}) - c.Assert(result[ctrlRuleIndex].WellKnownService, gc.Equals, state.JujuControllerRule) - c.Assert(result[ctrlRuleIndex].WhitelistCIDRs, jc.DeepEquals, []string{"192.168.2.0/16"}) + c.Assert(result[appRuleIndex].WellKnownServiceType(), gc.Equals, state.JujuApplicationOfferRule) + c.Assert(result[appRuleIndex].WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.1.0/16"}) + c.Assert(result[ctrlRuleIndex].WellKnownServiceType(), gc.Equals, state.JujuControllerRule) + c.Assert(result[ctrlRuleIndex].WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.2.0/16"}) } func (s *FirewallRulesSuite) TestUpdate(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - err = rules.Save(state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.2.0/16"}, - }) + err = rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.2.0/16"})) c.Assert(err, jc.ErrorIsNil) s.assertSavedRules(c, state.JujuApplicationOfferRule, []string{"192.168.2.0/16"}) } diff --git a/state/migration_export.go b/state/migration_export.go index e5de233433e..8507af60053 100644 --- a/state/migration_export.go +++ b/state/migration_export.go @@ -176,6 +176,9 @@ func (st *State) exportImpl(cfg ExportConfig) (description.Model, error) { if err := export.remoteEntities(); err != nil { return nil, errors.Trace(err) } + if err := export.firewallRules(); err != nil { + return nil, errors.Trace(err) + } if err := export.relationNetworks(); err != nil { return nil, errors.Trace(err) } @@ -1172,6 +1175,41 @@ func (e *exporter) relations() error { } return nil } +func (e *exporter) firewallRules() error { + e.logger.Debugf("reading firewall rules") + migration := &ExportStateMigration{ + src: e.st, + dst: e.model, + } + migration.Add(func() error { + m := migrations.ExportFirewallRule{} + return m.Execute(firewallRulesShim{ + st: migration.src, + }, migration.dst) + }) + return migration.Run() +} + +// firewallRulesShim is to handle the fact that go doesn't handle covariance +// and the tight abstraction around the new migration export work ensures that +// we handle our dependencies up front. +type firewallRulesShim struct { + st *State +} + +func (s firewallRulesShim) AllFirewallRules() ([]migrations.MigrationFirewallRule, error) { + fRs := firewallRulesState{st: s.st} + firewallRules, err := fRs.AllRules() + if err != nil { + return nil, errors.Trace(err) + } + result := make([]migrations.MigrationFirewallRule, len(firewallRules)) + for k, v := range firewallRules { + result[k] = v + + } + return result, nil +} func (e *exporter) remoteEntities() error { e.logger.Debugf("reading remote entities") diff --git a/state/migration_export_test.go b/state/migration_export_test.go index b2c77e8f0b9..0fc474961c1 100644 --- a/state/migration_export_test.go +++ b/state/migration_export_test.go @@ -847,6 +847,26 @@ func (s *MigrationExportSuite) TestEndpointBindings(c *gc.C) { c.Assert(bindings["db"], gc.Equals, oneSpace.Id()) } +func (s *MigrationExportSuite) TestFirewallRules(c *gc.C) { + service := "ssh" + cidrs := []string{"192.168.1.0/16"} + + frst := state.NewFirewallRules(s.State) + rule := state.NewFirewallRule(state.WellKnownServiceType(service), cidrs) + err := frst.Save(rule) + c.Assert(err, jc.ErrorIsNil) + + model, err := s.State.Export() + c.Assert(err, jc.ErrorIsNil) + + firewallRules := model.FirewallRules() + c.Assert(firewallRules, gc.HasLen, 1) + + entity := firewallRules[0] + c.Assert(entity.WellKnownService(), gc.Equals, service) + c.Assert(entity.WhitelistCIDRs(), gc.DeepEquals, cidrs) +} + func (s *MigrationExportSuite) TestRemoteEntities(c *gc.C) { remotes := s.State.RemoteEntities() remoteCtrl := names.NewControllerTag("uuid-223412") diff --git a/state/migrations/firewallRules.go b/state/migrations/firewallRules.go new file mode 100644 index 00000000000..e7e179dc1ab --- /dev/null +++ b/state/migrations/firewallRules.go @@ -0,0 +1,52 @@ +// Copyright 2019 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package migrations + +import ( + "github.com/juju/description" + "github.com/juju/errors" +) + +// MigrationFirewallRule represents a state.FirewallRule +// Point of use interface to enable better encapsulation. +type MigrationFirewallRule interface { + ID() string + WellKnownService() string + WhitelistCIDRs() []string +} + +// FirewallRuleSource defines an inplace usage for reading all the remote +// entities. +type FirewallRuleSource interface { + AllFirewallRules() ([]MigrationFirewallRule, error) +} + +// FirewallRulesModel defines an inplace usage for adding a remote entity +// to a model. +type FirewallRulesModel interface { + AddFirewallRule(args description.FirewallRuleArgs) description.FirewallRule +} + +// ExportRemoteEntities describes a way to execute a migration for exporting +// remote entities. +type ExportFirewallRule struct{} + +// Execute the migration of the remote entities using typed interfaces, to +// ensure we don't loose any type safety. +// This doesn't conform to an interface because go doesn't have generics, but +// when this does arrive this would be an execellent place to use them. +func (ExportFirewallRule) Execute(src FirewallRuleSource, dst FirewallRulesModel) error { + firewallRules, err := src.AllFirewallRules() + if err != nil { + return errors.Trace(err) + } + for _, firewallRule := range firewallRules { + dst.AddFirewallRule(description.FirewallRuleArgs{ + ID: firewallRule.ID(), + WellKnownService: firewallRule.WellKnownService(), + WhitelistCIDRs: firewallRule.WhitelistCIDRs(), + }) + } + return nil +} diff --git a/state/migrations/remoteapplications.go b/state/migrations/remoteapplications.go index 00440f8cfb1..1d605a9fb08 100644 --- a/state/migrations/remoteapplications.go +++ b/state/migrations/remoteapplications.go @@ -10,7 +10,7 @@ import ( "gopkg.in/juju/names.v3" ) -// MigrationRemoteApplication is an implace representation of the state.RemoteApplication +// MigrationRemoteApplication is an in-place representation of the state.RemoteApplication type MigrationRemoteApplication interface { Tag() names.Tag OfferUUID() string @@ -23,7 +23,7 @@ type MigrationRemoteApplication interface { GlobalKey() string } -// MigrationRemoteEndpoint is an implace representation of the state.Endpoint +// MigrationRemoteEndpoint is an in-place representation of the state.Endpoint type MigrationRemoteEndpoint struct { Name string Role charm.RelationRole @@ -49,13 +49,13 @@ type MigrationRemoteSubnet struct { ProviderNetworkId string } -// AllRemoteApplicationSource defines an inplace usage for reading all the +// AllRemoteApplicationSource defines an in-place usage for reading all the // remote application. type AllRemoteApplicationSource interface { AllRemoteApplications() ([]MigrationRemoteApplication, error) } -// StatusSource defines an inplace usage for reading in the status for a given +// StatusSource defines an in-place usage for reading in the status for a given // entity. type StatusSource interface { StatusArgs(string) (description.StatusArgs, error) @@ -68,7 +68,7 @@ type RemoteApplicationSource interface { StatusSource } -// RemoteApplicationModel defines an inplace usage for adding a remote entity +// RemoteApplicationModel defines an in-place usage for adding a remote entity // to a model. type RemoteApplicationModel interface { AddRemoteApplication(description.RemoteApplicationArgs) description.RemoteApplication diff --git a/worker/firewaller/firewaller_test.go b/worker/firewaller/firewaller_test.go index 8c1d606454a..4d21600b754 100644 --- a/worker/firewaller/firewaller_test.go +++ b/worker/firewaller/firewaller_test.go @@ -1214,10 +1214,7 @@ func (s *InstanceModeSuite) TestRemoteRelationIngressFallbackToPublic(c *gc.C) { func (s *InstanceModeSuite) TestRemoteRelationIngressFallbackToWhitelist(c *gc.C) { fwRules := state.NewFirewallRules(s.State) - err := fwRules.Save(state.FirewallRule{ - WellKnownService: state.JujuApplicationOfferRule, - WhitelistCIDRs: []string{"192.168.1.0/16"}, - }) + err := fwRules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) var ingress []string for i := 1; i < 30; i++ { From e76ca4998439f99bc6c3fa364c2f9f4c79341fbc Mon Sep 17 00:00:00 2001 From: nam Date: Tue, 26 Nov 2019 10:47:54 +0100 Subject: [PATCH 2/3] add region check --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 6df02bc154a..f9022f3e2d6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -492,11 +492,11 @@ revision = "9be91dc79b7c185fa8b08e7ceceee40562055c83" [[projects]] - digest = "1:ef77a561f2a4b11670d81ae04ccb2257b908af008b140929051d5841593f08bf" + digest = "1:94b9e76ec21e8feb0ac758073b6ca34a1774087204a76217add133cdd807ab85" name = "github.com/juju/description" packages = ["."] pruneopts = "" - revision = "61283e074b8b886a5f4a1c5d29d063de33a7faf3" + revision = "17bd24b997e3e0f8e9f0b287978d1177edaab306" [[projects]] digest = "1:594030c0f0ed3842773b68708d4f9716d809556b9c631460051f99b15057512d" diff --git a/Gopkg.toml b/Gopkg.toml index 7c5be5161cf..bbebd156ec2 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -62,7 +62,7 @@ name = "github.com/juju/bundlechanges" [[constraint]] - revision = "61283e074b8b886a5f4a1c5d29d063de33a7faf3" + revision = "17bd24b997e3e0f8e9f0b287978d1177edaab306" name = "github.com/juju/description" [[constraint]] From 674c879ff33a9a14b89e379d0d7542008bdec432 Mon Sep 17 00:00:00 2001 From: nam Date: Tue, 26 Nov 2019 14:08:50 +0100 Subject: [PATCH 3/3] add firewall import step refactor firewall transaction handling --- apiserver/common/crossmodel/crossmodel.go | 3 +- apiserver/common/crossmodel/interface.go | 3 +- apiserver/common/crossmodel/state.go | 3 +- .../client/firewallrules/firewallrules.go | 5 +- .../firewallrules/firewallrules_test.go | 3 +- .../facades/client/firewallrules/mock_test.go | 5 +- .../crossmodelrelations_test.go | 3 +- .../crossmodelrelations/mock_test.go | 7 +- .../controller/firewaller/firewaller.go | 3 +- .../firewaller/firewaller_unit_test.go | 5 +- .../controller/firewaller/mock_test.go | 7 +- .../facades/controller/firewaller/state.go | 5 +- core/firewall/firewall.go | 28 ++++ state/firewallrules.go | 132 ++++++++---------- state/firewallrules_test.go | 41 +++--- state/migration_description_mock_test.go | 60 ++++++++ state/migration_export_test.go | 6 +- state/migration_import.go | 73 +++++++++- state/migration_import_mock_test.go | 60 ++++++++ state/migration_import_test.go | 30 ++++ .../{firewallRules.go => firewallrules.go} | 8 +- worker/firewaller/firewaller_test.go | 3 +- 22 files changed, 366 insertions(+), 127 deletions(-) create mode 100644 core/firewall/firewall.go rename state/migrations/{firewallRules.go => firewallrules.go} (86%) diff --git a/apiserver/common/crossmodel/crossmodel.go b/apiserver/common/crossmodel/crossmodel.go index da746843df5..216536290f0 100644 --- a/apiserver/common/crossmodel/crossmodel.go +++ b/apiserver/common/crossmodel/crossmodel.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/apiserver/params" "github.com/juju/juju/core/crossmodel" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/life" "github.com/juju/juju/core/status" "github.com/juju/juju/network" @@ -249,7 +250,7 @@ func validateIngressNetworks(backend Backend, networks []string) error { } // Check that the required ingress is allowed. - rule, err := backend.FirewallRule(state.JujuApplicationOfferRule) + rule, err := backend.FirewallRule(firewall.JujuApplicationOfferRule) if err != nil && !errors.IsNotFound(err) { return errors.Trace(err) } diff --git a/apiserver/common/crossmodel/interface.go b/apiserver/common/crossmodel/interface.go index 9d9e7017bb9..4dcbd31396c 100644 --- a/apiserver/common/crossmodel/interface.go +++ b/apiserver/common/crossmodel/interface.go @@ -9,6 +9,7 @@ import ( "gopkg.in/macaroon.v2-unstable" "github.com/juju/juju/core/crossmodel" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/status" "github.com/juju/juju/permission" "github.com/juju/juju/state" @@ -83,7 +84,7 @@ type Backend interface { WatchOfferStatus(offerUUID string) (state.NotifyWatcher, error) // FirewallRule returns the firewall rule for the specified service. - FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) + FirewallRule(service firewall.WellKnownServiceType) (*state.FirewallRule, error) // ApplyOperation applies a model operation to the state. ApplyOperation(op state.ModelOperation) error diff --git a/apiserver/common/crossmodel/state.go b/apiserver/common/crossmodel/state.go index 1f17850d66d..2efd7168219 100644 --- a/apiserver/common/crossmodel/state.go +++ b/apiserver/common/crossmodel/state.go @@ -8,6 +8,7 @@ import ( "gopkg.in/juju/names.v3" "github.com/juju/juju/core/crossmodel" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/state" ) @@ -169,7 +170,7 @@ func (s stateShim) IngressNetworks(relationKey string) (state.RelationNetworks, return api.Networks(relationKey) } -func (s stateShim) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) { +func (s stateShim) FirewallRule(service firewall.WellKnownServiceType) (*state.FirewallRule, error) { api := state.NewFirewallRules(s.State) return api.Rule(service) } diff --git a/apiserver/facades/client/firewallrules/firewallrules.go b/apiserver/facades/client/firewallrules/firewallrules.go index 84838c77d70..20d1bcde3bb 100644 --- a/apiserver/facades/client/firewallrules/firewallrules.go +++ b/apiserver/facades/client/firewallrules/firewallrules.go @@ -11,6 +11,7 @@ import ( "github.com/juju/juju/apiserver/common" "github.com/juju/juju/apiserver/facade" "github.com/juju/juju/apiserver/params" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/permission" "github.com/juju/juju/state" ) @@ -87,7 +88,7 @@ func (api *API) SetFirewallRules(args params.FirewallRuleArgs) (params.ErrorResu for i, arg := range args.Args { logger.Debugf("saving firewall rule %+v", arg) err := api.backend.SaveFirewallRule(state.NewFirewallRule( - state.WellKnownServiceType(arg.KnownService), arg.WhitelistCIDRS)) + firewall.WellKnownServiceType(arg.KnownService), arg.WhitelistCIDRS)) results[i].Error = common.ServerError(err) } errResults.Results = results @@ -107,7 +108,7 @@ func (api *API) ListFirewallRules() (params.ListFirewallRulesResults, error) { listResults.Rules = make([]params.FirewallRule, len(rules)) for i, r := range rules { listResults.Rules[i] = params.FirewallRule{ - KnownService: params.KnownServiceValue(r.WellKnownServiceType()), + KnownService: params.KnownServiceValue(r.WellKnownService()), WhitelistCIDRS: r.WhitelistCIDRs(), } } diff --git a/apiserver/facades/client/firewallrules/firewallrules_test.go b/apiserver/facades/client/firewallrules/firewallrules_test.go index 510299eb0e9..c363b3b8442 100644 --- a/apiserver/facades/client/firewallrules/firewallrules_test.go +++ b/apiserver/facades/client/firewallrules/firewallrules_test.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/apiserver/facades/client/firewallrules" "github.com/juju/juju/apiserver/params" apiservertesting "github.com/juju/juju/apiserver/testing" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/state" coretesting "github.com/juju/juju/testing" ) @@ -74,7 +75,7 @@ func (s *FirewallRulesSuite) TestSetFirewallRules(c *gc.C) { }) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.ErrorResults{[]params.ErrorResult{{Error: nil}}}) - c.Assert(s.backend.rules["juju-controller"], jc.DeepEquals, state.NewFirewallRule(state.JujuControllerRule, []string{"1.2.3.4/8"})) + c.Assert(s.backend.rules["juju-controller"], jc.DeepEquals, state.NewFirewallRule(firewall.JujuControllerRule, []string{"1.2.3.4/8"})) } func (s *FirewallRulesSuite) TestSetFirewallRulesPermission(c *gc.C) { diff --git a/apiserver/facades/client/firewallrules/mock_test.go b/apiserver/facades/client/firewallrules/mock_test.go index f111c77a69f..c59152dc7fa 100644 --- a/apiserver/facades/client/firewallrules/mock_test.go +++ b/apiserver/facades/client/firewallrules/mock_test.go @@ -8,6 +8,7 @@ import ( "gopkg.in/juju/names.v3" "github.com/juju/juju/apiserver/facades/client/firewallrules" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/state" ) @@ -32,7 +33,7 @@ func (m *mockBackend) ModelTag() names.ModelTag { func (m *mockBackend) SaveFirewallRule(rule state.FirewallRule) error { m.MethodCall(m, "SaveFirewallRule") m.PopNoErr() - m.rules[string(rule.WellKnownServiceType())] = rule + m.rules[string(rule.WellKnownService())] = rule return nil } @@ -40,7 +41,7 @@ func (m *mockBackend) ListFirewallRules() ([]*state.FirewallRule, error) { m.MethodCall(m, "ListFirewallRules") m.PopNoErr() frls := make([]*state.FirewallRule, 1) - firewareRule := state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"1.2.3.4/8"}) + firewareRule := state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"1.2.3.4/8"}) frls[0] = &firewareRule return frls, nil } diff --git a/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go b/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go index 8fa68bfff0a..7f2c47a91bd 100644 --- a/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go +++ b/apiserver/facades/controller/crossmodelrelations/crossmodelrelations_test.go @@ -23,6 +23,7 @@ import ( "github.com/juju/juju/apiserver/params" apiservertesting "github.com/juju/juju/apiserver/testing" "github.com/juju/juju/core/crossmodel" + corefirewall "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/life" "github.com/juju/juju/core/status" "github.com/juju/juju/state" @@ -370,7 +371,7 @@ func (s *crossmodelRelationsSuite) TestPublishIngressNetworkChangesRejected(c *g c.Assert(err, jc.ErrorIsNil) rule := state.NewFirewallRule("", []string{"10.1.1.1/8"}) - s.st.firewallRules[state.JujuApplicationOfferRule] = &rule + s.st.firewallRules[corefirewall.JujuApplicationOfferRule] = &rule results, err := s.api.PublishIngressNetworkChanges(params.IngressNetworksChanges{ Changes: []params.IngressNetworksChangeEvent{ { diff --git a/apiserver/facades/controller/crossmodelrelations/mock_test.go b/apiserver/facades/controller/crossmodelrelations/mock_test.go index ac11924c84e..436e3bf60d3 100644 --- a/apiserver/facades/controller/crossmodelrelations/mock_test.go +++ b/apiserver/facades/controller/crossmodelrelations/mock_test.go @@ -21,6 +21,7 @@ import ( "github.com/juju/juju/apiserver/common/firewall" "github.com/juju/juju/apiserver/facades/controller/crossmodelrelations" "github.com/juju/juju/core/crossmodel" + corefirewall "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/status" "github.com/juju/juju/state" coretesting "github.com/juju/juju/testing" @@ -48,7 +49,7 @@ type mockState struct { offerConnections map[int]*mockOfferConnection offerConnectionsByKey map[string]*mockOfferConnection remoteEntities map[names.Tag]string - firewallRules map[state.WellKnownServiceType]*state.FirewallRule + firewallRules map[corefirewall.WellKnownServiceType]*state.FirewallRule ingressNetworks map[string][]string } @@ -61,7 +62,7 @@ func newMockState() *mockState { offers: make(map[string]*crossmodel.ApplicationOffer), offerConnections: make(map[int]*mockOfferConnection), offerConnectionsByKey: make(map[string]*mockOfferConnection), - firewallRules: make(map[state.WellKnownServiceType]*state.FirewallRule), + firewallRules: make(map[corefirewall.WellKnownServiceType]*state.FirewallRule), ingressNetworks: make(map[string][]string), } } @@ -119,7 +120,7 @@ func (st *mockState) AddOfferConnection(arg state.AddOfferConnectionParams) (cro return oc, nil } -func (st *mockState) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) { +func (st *mockState) FirewallRule(service corefirewall.WellKnownServiceType) (*state.FirewallRule, error) { if r, ok := st.firewallRules[service]; ok { return r, nil } diff --git a/apiserver/facades/controller/firewaller/firewaller.go b/apiserver/facades/controller/firewaller/firewaller.go index d17e920856a..62468a90f3d 100644 --- a/apiserver/facades/controller/firewaller/firewaller.go +++ b/apiserver/facades/controller/firewaller/firewaller.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/apiserver/common/firewall" "github.com/juju/juju/apiserver/facade" "github.com/juju/juju/apiserver/params" + corefirewall "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/network" "github.com/juju/juju/core/status" "github.com/juju/juju/state" @@ -488,7 +489,7 @@ func (f *FirewallerAPIV4) SetRelationsStatus(args params.SetStatus) (params.Erro func (f *FirewallerAPIV4) FirewallRules(args params.KnownServiceArgs) (params.ListFirewallRulesResults, error) { var result params.ListFirewallRulesResults for _, knownService := range args.KnownServices { - rule, err := f.st.FirewallRule(state.WellKnownServiceType(knownService)) + rule, err := f.st.FirewallRule(corefirewall.WellKnownServiceType(knownService)) if err != nil && !errors.IsNotFound(err) { return result, common.ServerError(err) } diff --git a/apiserver/facades/controller/firewaller/firewaller_unit_test.go b/apiserver/facades/controller/firewaller/firewaller_unit_test.go index 0b3b72dd542..b7023b214b9 100644 --- a/apiserver/facades/controller/firewaller/firewaller_unit_test.go +++ b/apiserver/facades/controller/firewaller/firewaller_unit_test.go @@ -15,6 +15,7 @@ import ( "github.com/juju/juju/apiserver/params" apiservertesting "github.com/juju/juju/apiserver/testing" "github.com/juju/juju/core/crossmodel" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/status" "github.com/juju/juju/state" coretesting "github.com/juju/juju/testing" @@ -123,8 +124,8 @@ func (s *RemoteFirewallerSuite) TestSetRelationStatus(c *gc.C) { } func (s *RemoteFirewallerSuite) TestFirewallRules(c *gc.C) { - rule := state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.0.0/16"}) - s.st.firewallRules[state.JujuApplicationOfferRule] = &rule + rule := state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.0.0/16"}) + s.st.firewallRules[firewall.JujuApplicationOfferRule] = &rule result, err := s.api.FirewallRules(params.KnownServiceArgs{ KnownServices: []params.KnownServiceValue{params.JujuApplicationOfferRule, params.SSHRule}}) c.Assert(err, jc.ErrorIsNil) diff --git a/apiserver/facades/controller/firewaller/mock_test.go b/apiserver/facades/controller/firewaller/mock_test.go index 50bd300f37a..d0eb0d6ab02 100644 --- a/apiserver/facades/controller/firewaller/mock_test.go +++ b/apiserver/facades/controller/firewaller/mock_test.go @@ -17,6 +17,7 @@ import ( "github.com/juju/juju/apiserver/params" "github.com/juju/juju/controller" "github.com/juju/juju/core/crossmodel" + corefirewall "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/status" "github.com/juju/juju/environs/config" "github.com/juju/juju/state" @@ -37,7 +38,7 @@ type mockState struct { macaroons map[names.Tag]*macaroon.Macaroon relations map[string]*mockRelation controllerInfo map[string]*mockControllerInfo - firewallRules map[state.WellKnownServiceType]*state.FirewallRule + firewallRules map[corefirewall.WellKnownServiceType]*state.FirewallRule subnetsWatcher *mockStringsWatcher modelWatcher *mockNotifyWatcher configAttrs map[string]interface{} @@ -50,7 +51,7 @@ func newMockState(modelUUID string) *mockState { remoteEntities: make(map[names.Tag]string), macaroons: make(map[names.Tag]*macaroon.Macaroon), controllerInfo: make(map[string]*mockControllerInfo), - firewallRules: make(map[state.WellKnownServiceType]*state.FirewallRule), + firewallRules: make(map[corefirewall.WellKnownServiceType]*state.FirewallRule), subnetsWatcher: newMockStringsWatcher(), modelWatcher: newMockNotifyWatcher(), configAttrs: coretesting.FakeConfig(), @@ -110,7 +111,7 @@ func (st *mockState) FindEntity(tag names.Tag) (state.Entity, error) { return nil, errors.NotImplementedf("FindEntity") } -func (st *mockState) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) { +func (st *mockState) FirewallRule(service corefirewall.WellKnownServiceType) (*state.FirewallRule, error) { r, ok := st.firewallRules[service] if !ok { return nil, errors.NotFoundf("firewall rule for %q", service) diff --git a/apiserver/facades/controller/firewaller/state.go b/apiserver/facades/controller/firewaller/state.go index 9d44ed2c279..f235a7e1433 100644 --- a/apiserver/facades/controller/firewaller/state.go +++ b/apiserver/facades/controller/firewaller/state.go @@ -8,6 +8,7 @@ import ( "gopkg.in/macaroon.v2-unstable" "github.com/juju/juju/apiserver/common/firewall" + corefirewall "github.com/juju/juju/core/firewall" "github.com/juju/juju/state" ) @@ -24,7 +25,7 @@ type State interface { FindEntity(tag names.Tag) (state.Entity, error) - FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) + FirewallRule(service corefirewall.WellKnownServiceType) (*state.FirewallRule, error) Subnet(id string) (Subnet, error) @@ -58,7 +59,7 @@ func (st stateShim) WatchOpenedPorts() state.StringsWatcher { return st.st.WatchOpenedPorts() } -func (st stateShim) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) { +func (st stateShim) FirewallRule(service corefirewall.WellKnownServiceType) (*state.FirewallRule, error) { api := state.NewFirewallRules(st.st) return api.Rule(service) } diff --git a/core/firewall/firewall.go b/core/firewall/firewall.go new file mode 100644 index 00000000000..753a2ab0bb7 --- /dev/null +++ b/core/firewall/firewall.go @@ -0,0 +1,28 @@ +// Copyright 2019 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package firewall + +import "github.com/juju/errors" + +const ( + // SSHRule is a rule for SSH connections. + SSHRule = WellKnownServiceType("ssh") + + // JujuControllerRule is a rule for connections to the Juju controller. + JujuControllerRule = WellKnownServiceType("juju-controller") + + // JujuApplicationOfferRule is a rule for connections to a Juju offer. + JujuApplicationOfferRule = WellKnownServiceType("juju-application-offer") +) + +// WellKnownService defines a service for which firewall rules may be applied. +type WellKnownServiceType string + +func (v WellKnownServiceType) Validate() error { + switch v { + case SSHRule, JujuControllerRule, JujuApplicationOfferRule: + return nil + } + return errors.NotValidf("well known service type %q", v) +} diff --git a/state/firewallrules.go b/state/firewallrules.go index 81fa12ab8c5..b177c0337ec 100644 --- a/state/firewallrules.go +++ b/state/firewallrules.go @@ -10,6 +10,8 @@ import ( "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/txn" + + "github.com/juju/juju/core/firewall" ) // FirewallRule instances describe the ingress networks @@ -28,26 +30,21 @@ import ( type FirewallRule struct { id string - wellKnownService string + wellKnownService firewall.WellKnownServiceType whitelistCIDRs []string } -func NewFirewallRule(serviceType WellKnownServiceType, cidrs []string) FirewallRule { - return FirewallRule{whitelistCIDRs: cidrs, wellKnownService: string(serviceType)} +func NewFirewallRule(serviceType firewall.WellKnownServiceType, cidrs []string) FirewallRule { + return FirewallRule{whitelistCIDRs: cidrs, wellKnownService: serviceType} } func (f FirewallRule) ID() string { return f.id } -// WellKnownServiceType is the known service for the firewall rules entity. -func (f FirewallRule) WellKnownServiceType() WellKnownServiceType { - return WellKnownServiceType(f.wellKnownService) -} - -// WellKnownService is the known service for the firewall rules entity as a string. -func (f FirewallRule) WellKnownService() string { +// WellKnownService is the known service for the firewall rules entity. +func (f FirewallRule) WellKnownService() firewall.WellKnownServiceType { return f.wellKnownService } @@ -65,40 +62,18 @@ type firewallRulesDoc struct { func (r *firewallRulesDoc) toRule() *FirewallRule { return &FirewallRule{ id: r.Id, - wellKnownService: r.WellKnownService, + wellKnownService: firewall.WellKnownServiceType(r.WellKnownService), whitelistCIDRs: r.WhitelistCIDRS, } } // FirewallRuler instances provide access to firewall rules in state. type FirewallRuler interface { - Save(service WellKnownServiceType, whiteListCidrs []string) (FirewallRule, error) - Rule(service WellKnownServiceType) (FirewallRule, error) + Save(service firewall.WellKnownServiceType, whiteListCidrs []string) (FirewallRule, error) + Rule(service firewall.WellKnownServiceType) (FirewallRule, error) AllRules() ([]FirewallRule, error) } -const ( - // SSHRule is a rule for SSH connections. - SSHRule = WellKnownServiceType("ssh") - - // JujuControllerRule is a rule for connections to the Juju controller. - JujuControllerRule = WellKnownServiceType("juju-controller") - - // JujuApplicationOfferRule is a rule for connections to a Juju offer. - JujuApplicationOfferRule = WellKnownServiceType("juju-application-offer") -) - -// WellKnownServiceType defines a service for which firewall rules may be applied. -type WellKnownServiceType string - -func (v WellKnownServiceType) validate() error { - switch v { - case SSHRule, JujuControllerRule, JujuApplicationOfferRule: - return nil - } - return errors.NotValidf("well known service type %q", v) -} - type firewallRulesState struct { st *State } @@ -110,63 +85,70 @@ func NewFirewallRules(st *State) *firewallRulesState { // Save stores the specified firewall rule. func (fw *firewallRulesState) Save(rule FirewallRule) error { - if err := rule.WellKnownServiceType().validate(); err != nil { + if err := checkModelActive(fw.st); err != nil { return errors.Trace(err) } + buildTxn := func(int) ([]txn.Op, error) { + return fw.GetSaveTransactionOps(rule, false) + } + if err := fw.st.db().Run(buildTxn); err != nil { + return errors.Annotate(err, "failed to create firewall rules") + } + + return nil +} + +func (fw *firewallRulesState) GetSaveTransactionOps(rule FirewallRule, isMigrating bool) ([]txn.Op, error) { + if err := rule.WellKnownService().Validate(); err != nil { + return nil, errors.Trace(err) + } for _, cidr := range rule.WhitelistCIDRs() { if _, _, err := net.ParseCIDR(cidr); err != nil { - return errors.NotValidf("CIDR %q", cidr) + return nil, errors.NotValidf("CIDR %q", cidr) } } - serviceStr := string(rule.WellKnownServiceType()) + serviceStr := string(rule.WellKnownService()) doc := firewallRulesDoc{ Id: serviceStr, WellKnownService: serviceStr, WhitelistCIDRS: rule.WhitelistCIDRs(), } - buildTxn := func(int) ([]txn.Op, error) { - model, err := fw.st.Model() - if err != nil { - return nil, errors.Annotate(err, "failed to load model") - } - if err := checkModelActive(fw.st); err != nil { - return nil, errors.Trace(err) - } - _, err = fw.Rule(rule.WellKnownServiceType()) - if err != nil && !errors.IsNotFound(err) { - return nil, errors.Trace(err) - } - var ops []txn.Op - if err == nil { - ops = []txn.Op{{ - C: firewallRulesC, - Id: serviceStr, - Assert: txn.DocExists, - Update: bson.D{ - {"$set", bson.D{{"whitelist-cidrs", rule.WhitelistCIDRs()}}}, - }, - }, model.assertActiveOp()} - } else { - doc.WhitelistCIDRS = rule.WhitelistCIDRs() - ops = []txn.Op{{ - C: firewallRulesC, - Id: doc.Id, - Assert: txn.DocMissing, - Insert: doc, - }, model.assertActiveOp()} - } - return ops, nil + model, err := fw.st.Model() + if err != nil { + return nil, errors.Annotate(err, "failed to load model") } - if err := fw.st.db().Run(buildTxn); err != nil { - return errors.Annotate(err, "failed to create firewall rules") + _, err = fw.Rule(rule.WellKnownService()) + if err != nil && !errors.IsNotFound(err) { + return nil, errors.Trace(err) } - - return nil + var ops []txn.Op + if err == nil { + ops = []txn.Op{{ + C: firewallRulesC, + Id: serviceStr, + Assert: txn.DocExists, + Update: bson.D{ + {"$set", bson.D{{"whitelist-cidrs", rule.WhitelistCIDRs()}}}, + }, + }} + } else { + doc.WhitelistCIDRS = rule.WhitelistCIDRs() + ops = []txn.Op{{ + C: firewallRulesC, + Id: doc.Id, + Assert: txn.DocMissing, + Insert: doc, + }} + } + if !isMigrating { + ops = append(ops, model.assertActiveOp()) + } + return ops, nil } // Rule returns the firewall rule for the specified service. -func (fw *firewallRulesState) Rule(service WellKnownServiceType) (*FirewallRule, error) { +func (fw *firewallRulesState) Rule(service firewall.WellKnownServiceType) (*FirewallRule, error) { coll, closer := fw.st.db().GetCollection(firewallRulesC) defer closer() diff --git a/state/firewallrules_test.go b/state/firewallrules_test.go index b5a21fd8530..665cbaf9405 100644 --- a/state/firewallrules_test.go +++ b/state/firewallrules_test.go @@ -4,13 +4,14 @@ package state_test import ( - "github.com/juju/errors" "regexp" + "github.com/juju/errors" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" "gopkg.in/mgo.v2/bson" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/state" ) @@ -22,11 +23,11 @@ var _ = gc.Suite(&FirewallRulesSuite{}) func (s *FirewallRulesSuite) TestSaveInvalidWhitelistCIDR(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.NewFirewallRule(state.JujuControllerRule, []string{"192.168.1"})) - c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`CIDR "192.168.1" not valid`)) + err := rules.Save(state.NewFirewallRule(firewall.JujuControllerRule, []string{"192.168.1"})) + c.Assert(errors.Cause(err), gc.ErrorMatches, regexp.QuoteMeta(`CIDR "192.168.1" not valid`)) } -func (s *FirewallRulesSuite) assertSavedRules(c *gc.C, service state.WellKnownServiceType, expectedWhitelist []string) { +func (s *FirewallRulesSuite) assertSavedRules(c *gc.C, service firewall.WellKnownServiceType, expectedWhitelist []string) { coll, closer := state.GetCollection(s.State, "firewallRules") defer closer() @@ -45,63 +46,63 @@ func (s *FirewallRulesSuite) TestSaveInvalid(c *gc.C) { rules := state.NewFirewallRules(s.State) err := rules.Save(state.NewFirewallRule("foo", []string{"192.168.1.0/16"})) c.Assert(err, jc.Satisfies, errors.IsNotValid) - c.Assert(err, gc.ErrorMatches, `well known service type "foo" not valid`) + c.Assert(errors.Cause(err), gc.ErrorMatches, `well known service type "foo" not valid`) } func (s *FirewallRulesSuite) TestSave(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.NewFirewallRule(state.SSHRule, []string{"192.168.1.0/16"})) + err := rules.Save(state.NewFirewallRule(firewall.SSHRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - s.assertSavedRules(c, state.SSHRule, []string{"192.168.1.0/16"}) + s.assertSavedRules(c, firewall.SSHRule, []string{"192.168.1.0/16"}) } func (s *FirewallRulesSuite) TestSaveIdempotent(c *gc.C) { rules := state.NewFirewallRules(s.State) - rule := state.NewFirewallRule(state.SSHRule, []string{"192.168.1.0/16"}) + rule := state.NewFirewallRule(firewall.SSHRule, []string{"192.168.1.0/16"}) err := rules.Save(rule) c.Assert(err, jc.ErrorIsNil) err = rules.Save(rule) c.Assert(err, jc.ErrorIsNil) - s.assertSavedRules(c, state.SSHRule, []string{"192.168.1.0/16"}) + s.assertSavedRules(c, firewall.SSHRule, []string{"192.168.1.0/16"}) } func (s *FirewallRulesSuite) TestRule(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) + err := rules.Save(state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - result, err := rules.Rule(state.JujuApplicationOfferRule) + result, err := rules.Rule(firewall.JujuApplicationOfferRule) c.Assert(err, jc.ErrorIsNil) c.Assert(result.WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.1.0/16"}) - _, err = rules.Rule(state.JujuControllerRule) + _, err = rules.Rule(firewall.JujuControllerRule) c.Assert(err, jc.Satisfies, errors.IsNotFound) } func (s *FirewallRulesSuite) TestAllRules(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) + err := rules.Save(state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - err = rules.Save(state.NewFirewallRule(state.JujuControllerRule, []string{"192.168.2.0/16"})) + err = rules.Save(state.NewFirewallRule(firewall.JujuControllerRule, []string{"192.168.2.0/16"})) c.Assert(err, jc.ErrorIsNil) result, err := rules.AllRules() c.Assert(err, jc.ErrorIsNil) c.Assert(result, gc.HasLen, 2) appRuleIndex := 0 ctrlRuleIndex := 1 - if result[0].WellKnownServiceType() == state.JujuControllerRule { + if result[0].WellKnownService() == firewall.JujuControllerRule { appRuleIndex = 1 ctrlRuleIndex = 0 } - c.Assert(result[appRuleIndex].WellKnownServiceType(), gc.Equals, state.JujuApplicationOfferRule) + c.Assert(result[appRuleIndex].WellKnownService(), gc.Equals, firewall.JujuApplicationOfferRule) c.Assert(result[appRuleIndex].WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.1.0/16"}) - c.Assert(result[ctrlRuleIndex].WellKnownServiceType(), gc.Equals, state.JujuControllerRule) + c.Assert(result[ctrlRuleIndex].WellKnownService(), gc.Equals, firewall.JujuControllerRule) c.Assert(result[ctrlRuleIndex].WhitelistCIDRs(), jc.DeepEquals, []string{"192.168.2.0/16"}) } func (s *FirewallRulesSuite) TestUpdate(c *gc.C) { rules := state.NewFirewallRules(s.State) - err := rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) + err := rules.Save(state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) - err = rules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.2.0/16"})) + err = rules.Save(state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.2.0/16"})) c.Assert(err, jc.ErrorIsNil) - s.assertSavedRules(c, state.JujuApplicationOfferRule, []string{"192.168.2.0/16"}) + s.assertSavedRules(c, firewall.JujuApplicationOfferRule, []string{"192.168.2.0/16"}) } diff --git a/state/migration_description_mock_test.go b/state/migration_description_mock_test.go index fedf71b1de5..9f811613847 100644 --- a/state/migration_description_mock_test.go +++ b/state/migration_description_mock_test.go @@ -37,6 +37,7 @@ func (m *MockRemoteEntity) EXPECT() *MockRemoteEntityMockRecorder { // ID mocks base method func (m *MockRemoteEntity) ID() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ID") ret0, _ := ret[0].(string) return ret0 @@ -44,11 +45,13 @@ func (m *MockRemoteEntity) ID() string { // ID indicates an expected call of ID func (mr *MockRemoteEntityMockRecorder) ID() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockRemoteEntity)(nil).ID)) } // Macaroon mocks base method func (m *MockRemoteEntity) Macaroon() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Macaroon") ret0, _ := ret[0].(string) return ret0 @@ -56,11 +59,13 @@ func (m *MockRemoteEntity) Macaroon() string { // Macaroon indicates an expected call of Macaroon func (mr *MockRemoteEntityMockRecorder) Macaroon() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Macaroon", reflect.TypeOf((*MockRemoteEntity)(nil).Macaroon)) } // Token mocks base method func (m *MockRemoteEntity) Token() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Token") ret0, _ := ret[0].(string) return ret0 @@ -68,6 +73,7 @@ func (m *MockRemoteEntity) Token() string { // Token indicates an expected call of Token func (mr *MockRemoteEntityMockRecorder) Token() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockRemoteEntity)(nil).Token)) } @@ -96,6 +102,7 @@ func (m *MockRelationNetwork) EXPECT() *MockRelationNetworkMockRecorder { // CIDRS mocks base method func (m *MockRelationNetwork) CIDRS() []string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CIDRS") ret0, _ := ret[0].([]string) return ret0 @@ -103,11 +110,13 @@ func (m *MockRelationNetwork) CIDRS() []string { // CIDRS indicates an expected call of CIDRS func (mr *MockRelationNetworkMockRecorder) CIDRS() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CIDRS", reflect.TypeOf((*MockRelationNetwork)(nil).CIDRS)) } // ID mocks base method func (m *MockRelationNetwork) ID() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ID") ret0, _ := ret[0].(string) return ret0 @@ -115,11 +124,13 @@ func (m *MockRelationNetwork) ID() string { // ID indicates an expected call of ID func (mr *MockRelationNetworkMockRecorder) ID() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockRelationNetwork)(nil).ID)) } // RelationKey mocks base method func (m *MockRelationNetwork) RelationKey() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RelationKey") ret0, _ := ret[0].(string) return ret0 @@ -127,6 +138,7 @@ func (m *MockRelationNetwork) RelationKey() string { // RelationKey indicates an expected call of RelationKey func (mr *MockRelationNetworkMockRecorder) RelationKey() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RelationKey", reflect.TypeOf((*MockRelationNetwork)(nil).RelationKey)) } @@ -155,6 +167,7 @@ func (m *MockRemoteApplication) EXPECT() *MockRemoteApplicationMockRecorder { // AddEndpoint mocks base method func (m *MockRemoteApplication) AddEndpoint(arg0 description.RemoteEndpointArgs) description.RemoteEndpoint { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddEndpoint", arg0) ret0, _ := ret[0].(description.RemoteEndpoint) return ret0 @@ -162,11 +175,13 @@ func (m *MockRemoteApplication) AddEndpoint(arg0 description.RemoteEndpointArgs) // AddEndpoint indicates an expected call of AddEndpoint func (mr *MockRemoteApplicationMockRecorder) AddEndpoint(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddEndpoint", reflect.TypeOf((*MockRemoteApplication)(nil).AddEndpoint), arg0) } // AddSpace mocks base method func (m *MockRemoteApplication) AddSpace(arg0 description.RemoteSpaceArgs) description.RemoteSpace { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddSpace", arg0) ret0, _ := ret[0].(description.RemoteSpace) return ret0 @@ -174,11 +189,13 @@ func (m *MockRemoteApplication) AddSpace(arg0 description.RemoteSpaceArgs) descr // AddSpace indicates an expected call of AddSpace func (mr *MockRemoteApplicationMockRecorder) AddSpace(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSpace", reflect.TypeOf((*MockRemoteApplication)(nil).AddSpace), arg0) } // Bindings mocks base method func (m *MockRemoteApplication) Bindings() map[string]string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Bindings") ret0, _ := ret[0].(map[string]string) return ret0 @@ -186,11 +203,13 @@ func (m *MockRemoteApplication) Bindings() map[string]string { // Bindings indicates an expected call of Bindings func (mr *MockRemoteApplicationMockRecorder) Bindings() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bindings", reflect.TypeOf((*MockRemoteApplication)(nil).Bindings)) } // Endpoints mocks base method func (m *MockRemoteApplication) Endpoints() []description.RemoteEndpoint { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Endpoints") ret0, _ := ret[0].([]description.RemoteEndpoint) return ret0 @@ -198,11 +217,13 @@ func (m *MockRemoteApplication) Endpoints() []description.RemoteEndpoint { // Endpoints indicates an expected call of Endpoints func (mr *MockRemoteApplicationMockRecorder) Endpoints() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Endpoints", reflect.TypeOf((*MockRemoteApplication)(nil).Endpoints)) } // IsConsumerProxy mocks base method func (m *MockRemoteApplication) IsConsumerProxy() bool { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsConsumerProxy") ret0, _ := ret[0].(bool) return ret0 @@ -210,11 +231,13 @@ func (m *MockRemoteApplication) IsConsumerProxy() bool { // IsConsumerProxy indicates an expected call of IsConsumerProxy func (mr *MockRemoteApplicationMockRecorder) IsConsumerProxy() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsConsumerProxy", reflect.TypeOf((*MockRemoteApplication)(nil).IsConsumerProxy)) } // Name mocks base method func (m *MockRemoteApplication) Name() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Name") ret0, _ := ret[0].(string) return ret0 @@ -222,11 +245,13 @@ func (m *MockRemoteApplication) Name() string { // Name indicates an expected call of Name func (mr *MockRemoteApplicationMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockRemoteApplication)(nil).Name)) } // OfferUUID mocks base method func (m *MockRemoteApplication) OfferUUID() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OfferUUID") ret0, _ := ret[0].(string) return ret0 @@ -234,21 +259,25 @@ func (m *MockRemoteApplication) OfferUUID() string { // OfferUUID indicates an expected call of OfferUUID func (mr *MockRemoteApplicationMockRecorder) OfferUUID() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OfferUUID", reflect.TypeOf((*MockRemoteApplication)(nil).OfferUUID)) } // SetStatus mocks base method func (m *MockRemoteApplication) SetStatus(arg0 description.StatusArgs) { + m.ctrl.T.Helper() m.ctrl.Call(m, "SetStatus", arg0) } // SetStatus indicates an expected call of SetStatus func (mr *MockRemoteApplicationMockRecorder) SetStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetStatus", reflect.TypeOf((*MockRemoteApplication)(nil).SetStatus), arg0) } // SourceModelTag mocks base method func (m *MockRemoteApplication) SourceModelTag() names_v3.ModelTag { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SourceModelTag") ret0, _ := ret[0].(names_v3.ModelTag) return ret0 @@ -256,11 +285,13 @@ func (m *MockRemoteApplication) SourceModelTag() names_v3.ModelTag { // SourceModelTag indicates an expected call of SourceModelTag func (mr *MockRemoteApplicationMockRecorder) SourceModelTag() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SourceModelTag", reflect.TypeOf((*MockRemoteApplication)(nil).SourceModelTag)) } // Spaces mocks base method func (m *MockRemoteApplication) Spaces() []description.RemoteSpace { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Spaces") ret0, _ := ret[0].([]description.RemoteSpace) return ret0 @@ -268,11 +299,13 @@ func (m *MockRemoteApplication) Spaces() []description.RemoteSpace { // Spaces indicates an expected call of Spaces func (mr *MockRemoteApplicationMockRecorder) Spaces() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Spaces", reflect.TypeOf((*MockRemoteApplication)(nil).Spaces)) } // Status mocks base method func (m *MockRemoteApplication) Status() description.Status { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Status") ret0, _ := ret[0].(description.Status) return ret0 @@ -280,11 +313,13 @@ func (m *MockRemoteApplication) Status() description.Status { // Status indicates an expected call of Status func (mr *MockRemoteApplicationMockRecorder) Status() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockRemoteApplication)(nil).Status)) } // Tag mocks base method func (m *MockRemoteApplication) Tag() names_v3.ApplicationTag { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Tag") ret0, _ := ret[0].(names_v3.ApplicationTag) return ret0 @@ -292,11 +327,13 @@ func (m *MockRemoteApplication) Tag() names_v3.ApplicationTag { // Tag indicates an expected call of Tag func (mr *MockRemoteApplicationMockRecorder) Tag() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Tag", reflect.TypeOf((*MockRemoteApplication)(nil).Tag)) } // URL mocks base method func (m *MockRemoteApplication) URL() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "URL") ret0, _ := ret[0].(string) return ret0 @@ -304,6 +341,7 @@ func (m *MockRemoteApplication) URL() string { // URL indicates an expected call of URL func (mr *MockRemoteApplicationMockRecorder) URL() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "URL", reflect.TypeOf((*MockRemoteApplication)(nil).URL)) } @@ -332,6 +370,7 @@ func (m *MockRemoteSpace) EXPECT() *MockRemoteSpaceMockRecorder { // AddSubnet mocks base method func (m *MockRemoteSpace) AddSubnet(arg0 description.SubnetArgs) description.Subnet { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddSubnet", arg0) ret0, _ := ret[0].(description.Subnet) return ret0 @@ -339,11 +378,13 @@ func (m *MockRemoteSpace) AddSubnet(arg0 description.SubnetArgs) description.Sub // AddSubnet indicates an expected call of AddSubnet func (mr *MockRemoteSpaceMockRecorder) AddSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockRemoteSpace)(nil).AddSubnet), arg0) } // CloudType mocks base method func (m *MockRemoteSpace) CloudType() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CloudType") ret0, _ := ret[0].(string) return ret0 @@ -351,11 +392,13 @@ func (m *MockRemoteSpace) CloudType() string { // CloudType indicates an expected call of CloudType func (mr *MockRemoteSpaceMockRecorder) CloudType() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloudType", reflect.TypeOf((*MockRemoteSpace)(nil).CloudType)) } // Name mocks base method func (m *MockRemoteSpace) Name() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Name") ret0, _ := ret[0].(string) return ret0 @@ -363,11 +406,13 @@ func (m *MockRemoteSpace) Name() string { // Name indicates an expected call of Name func (mr *MockRemoteSpaceMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockRemoteSpace)(nil).Name)) } // ProviderAttributes mocks base method func (m *MockRemoteSpace) ProviderAttributes() map[string]interface{} { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProviderAttributes") ret0, _ := ret[0].(map[string]interface{}) return ret0 @@ -375,11 +420,13 @@ func (m *MockRemoteSpace) ProviderAttributes() map[string]interface{} { // ProviderAttributes indicates an expected call of ProviderAttributes func (mr *MockRemoteSpaceMockRecorder) ProviderAttributes() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProviderAttributes", reflect.TypeOf((*MockRemoteSpace)(nil).ProviderAttributes)) } // ProviderId mocks base method func (m *MockRemoteSpace) ProviderId() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProviderId") ret0, _ := ret[0].(string) return ret0 @@ -387,11 +434,13 @@ func (m *MockRemoteSpace) ProviderId() string { // ProviderId indicates an expected call of ProviderId func (mr *MockRemoteSpaceMockRecorder) ProviderId() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProviderId", reflect.TypeOf((*MockRemoteSpace)(nil).ProviderId)) } // Subnets mocks base method func (m *MockRemoteSpace) Subnets() []description.Subnet { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Subnets") ret0, _ := ret[0].([]description.Subnet) return ret0 @@ -399,6 +448,7 @@ func (m *MockRemoteSpace) Subnets() []description.Subnet { // Subnets indicates an expected call of Subnets func (mr *MockRemoteSpaceMockRecorder) Subnets() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subnets", reflect.TypeOf((*MockRemoteSpace)(nil).Subnets)) } @@ -427,6 +477,7 @@ func (m *MockStatus) EXPECT() *MockStatusMockRecorder { // Data mocks base method func (m *MockStatus) Data() map[string]interface{} { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Data") ret0, _ := ret[0].(map[string]interface{}) return ret0 @@ -434,11 +485,13 @@ func (m *MockStatus) Data() map[string]interface{} { // Data indicates an expected call of Data func (mr *MockStatusMockRecorder) Data() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Data", reflect.TypeOf((*MockStatus)(nil).Data)) } // Message mocks base method func (m *MockStatus) Message() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Message") ret0, _ := ret[0].(string) return ret0 @@ -446,11 +499,13 @@ func (m *MockStatus) Message() string { // Message indicates an expected call of Message func (mr *MockStatusMockRecorder) Message() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Message", reflect.TypeOf((*MockStatus)(nil).Message)) } // NeverSet mocks base method func (m *MockStatus) NeverSet() bool { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NeverSet") ret0, _ := ret[0].(bool) return ret0 @@ -458,11 +513,13 @@ func (m *MockStatus) NeverSet() bool { // NeverSet indicates an expected call of NeverSet func (mr *MockStatusMockRecorder) NeverSet() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NeverSet", reflect.TypeOf((*MockStatus)(nil).NeverSet)) } // Updated mocks base method func (m *MockStatus) Updated() time.Time { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Updated") ret0, _ := ret[0].(time.Time) return ret0 @@ -470,11 +527,13 @@ func (m *MockStatus) Updated() time.Time { // Updated indicates an expected call of Updated func (mr *MockStatusMockRecorder) Updated() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Updated", reflect.TypeOf((*MockStatus)(nil).Updated)) } // Value mocks base method func (m *MockStatus) Value() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Value") ret0, _ := ret[0].(string) return ret0 @@ -482,5 +541,6 @@ func (m *MockStatus) Value() string { // Value indicates an expected call of Value func (mr *MockStatusMockRecorder) Value() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Value", reflect.TypeOf((*MockStatus)(nil).Value)) } diff --git a/state/migration_export_test.go b/state/migration_export_test.go index 0fc474961c1..14617fb822c 100644 --- a/state/migration_export_test.go +++ b/state/migration_export_test.go @@ -5,6 +5,7 @@ package state_test import ( "bytes" + "github.com/juju/juju/core/firewall" "io/ioutil" "math/rand" "sort" @@ -848,11 +849,10 @@ func (s *MigrationExportSuite) TestEndpointBindings(c *gc.C) { } func (s *MigrationExportSuite) TestFirewallRules(c *gc.C) { - service := "ssh" cidrs := []string{"192.168.1.0/16"} frst := state.NewFirewallRules(s.State) - rule := state.NewFirewallRule(state.WellKnownServiceType(service), cidrs) + rule := state.NewFirewallRule(firewall.SSHRule, cidrs) err := frst.Save(rule) c.Assert(err, jc.ErrorIsNil) @@ -863,7 +863,7 @@ func (s *MigrationExportSuite) TestFirewallRules(c *gc.C) { c.Assert(firewallRules, gc.HasLen, 1) entity := firewallRules[0] - c.Assert(entity.WellKnownService(), gc.Equals, service) + c.Assert(entity.WellKnownService(), gc.Equals, string(firewall.SSHRule)) c.Assert(entity.WhitelistCIDRs(), gc.DeepEquals, cidrs) } diff --git a/state/migration_import.go b/state/migration_import.go index 21a2183f15b..c30352bcb97 100644 --- a/state/migration_import.go +++ b/state/migration_import.go @@ -191,6 +191,9 @@ func (ctrl *Controller) Import(model description.Model) (_ *Model, _ *State, err if err := restore.remoteApplications(); err != nil { return nil, nil, errors.Annotate(err, "remoteapplications") } + if err := restore.firewallRules(); err != nil { + return nil, nil, errors.Annotate(err, "firewallrules") + } if err := restore.relations(); err != nil { return nil, nil, errors.Annotate(err, "relations") } @@ -1249,6 +1252,38 @@ func (i *importer) remoteApplications() error { return nil } +func (i *importer) firewallRules() error { + i.logger.Debugf("importing firewall rules") + migration := &ImportStateMigration{ + src: i.model, + dst: i.st.db(), + } + migration.Add(func() error { + m := ImportFirewallRules{} + return m.Execute(stateDocumentFactoryShim{ + stateModelNamspaceShim{ + Model: migration.src, + st: i.st, + }, + i, + }, migration.dst) + }) + if err := migration.Run(); err != nil { + return errors.Trace(err) + } + i.logger.Debugf("importing remote applications succeeded") + return nil +} + +// makeStatusDoc assumes status is non-nil. +func (i *importer) makeFirewallRuleDoc(firewallRule description.FirewallRule) *firewallRulesDoc { + return &firewallRulesDoc{ + Id: firewallRule.ID(), + WellKnownService: firewallRule.WellKnownService(), + WhitelistCIDRS: firewallRule.WhitelistCIDRs(), + } +} + // StateDocumentFactory creates documents that are useful with in the state // package. In essence this just allows us to model our dependencies correctly // without having to construct dependencies everywhere. @@ -1258,6 +1293,7 @@ type StateDocumentFactory interface { MakeRemoteApplicationDoc(description.RemoteApplication) *remoteApplicationDoc MakeStatusDoc(description.Status) statusDoc MakeStatusOp(string, statusDoc) txn.Op + MakeFirewallRuleDoc(description.FirewallRule) *firewallRulesDoc } // RemoteApplicationsDescription defines an inplace usage for reading remote @@ -1269,7 +1305,7 @@ type RemoteApplicationsDescription interface { } // stateDocumentFactoryShim is required to allow the new vertical boundary -// around importing a remoteApplication, from being accessed by the existing +// around importing a remoteApplication and firewallRules, from being accessed by the existing // state package code. // That way we can keep the importing code clean from the proliferation of state // code in the juju code base. @@ -1294,15 +1330,42 @@ func (s stateDocumentFactoryShim) MakeStatusOp(globalKey string, doc statusDoc) return createStatusOp(s.importer.st, globalKey, doc) } +func (s stateDocumentFactoryShim) MakeFirewallRuleDoc(rule description.FirewallRule) *firewallRulesDoc { + return s.importer.makeFirewallRuleDoc(rule) +} + +// ImportFirewallRules describes a way to import firewallRules from a +// description. +type ImportFirewallRules struct{} + +func (rules ImportFirewallRules) Execute(src stateDocumentFactoryShim, runner TransactionRunner) error { + firewallRules := src.FirewallRules() + if len(firewallRules) == 0 { + return nil + } + firewallState := NewFirewallRules(src.st) + ops := make([]txn.Op, 0) + for _, rule := range firewallRules { + firewallRule := src.MakeFirewallRuleDoc(rule).toRule() + op, err := firewallState.GetSaveTransactionOps(*firewallRule, true) + if err != nil { + return err + } + ops = append(ops, op...) + } + if err := runner.RunTransaction(ops); err != nil { + return errors.Trace(err) + } + return nil +} + // ImportRemoteApplications describes a way to import remote applications from a // description. type ImportRemoteApplications struct{} // Execute the import on the remote entities description, carefully modelling // the dependencies we have. -func (i ImportRemoteApplications) Execute(src RemoteApplicationsDescription, - runner TransactionRunner, -) error { +func (i ImportRemoteApplications) Execute(src RemoteApplicationsDescription, runner TransactionRunner) error { remoteApplications := src.RemoteApplications() if len(remoteApplications) == 0 { return nil @@ -1312,7 +1375,7 @@ func (i ImportRemoteApplications) Execute(src RemoteApplicationsDescription, appDoc := src.MakeRemoteApplicationDoc(app) // Status maybe empty for some remoteApplications. Ensure we handle - // that correctly by checking if we get one before mkaing a new + // that correctly by checking if we get one before making a new // StatusDoc var appStatusDoc *statusDoc if status := app.Status(); status != nil { diff --git a/state/migration_import_mock_test.go b/state/migration_import_mock_test.go index 8ab66e118f1..41134d895f3 100644 --- a/state/migration_import_mock_test.go +++ b/state/migration_import_mock_test.go @@ -36,6 +36,7 @@ func (m *MockTransactionRunner) EXPECT() *MockTransactionRunnerMockRecorder { // RunTransaction mocks base method func (m *MockTransactionRunner) RunTransaction(arg0 []txn.Op) error { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RunTransaction", arg0) ret0, _ := ret[0].(error) return ret0 @@ -43,6 +44,7 @@ func (m *MockTransactionRunner) RunTransaction(arg0 []txn.Op) error { // RunTransaction indicates an expected call of RunTransaction func (mr *MockTransactionRunnerMockRecorder) RunTransaction(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunTransaction", reflect.TypeOf((*MockTransactionRunner)(nil).RunTransaction), arg0) } @@ -69,8 +71,23 @@ func (m *MockStateDocumentFactory) EXPECT() *MockStateDocumentFactoryMockRecorde return m.recorder } +// MakeFirewallRuleDoc mocks base method +func (m *MockStateDocumentFactory) MakeFirewallRuleDoc(arg0 description.FirewallRule) *firewallRulesDoc { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MakeFirewallRuleDoc", arg0) + ret0, _ := ret[0].(*firewallRulesDoc) + return ret0 +} + +// MakeFirewallRuleDoc indicates an expected call of MakeFirewallRuleDoc +func (mr *MockStateDocumentFactoryMockRecorder) MakeFirewallRuleDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeFirewallRuleDoc", reflect.TypeOf((*MockStateDocumentFactory)(nil).MakeFirewallRuleDoc), arg0) +} + // MakeRemoteApplicationDoc mocks base method func (m *MockStateDocumentFactory) MakeRemoteApplicationDoc(arg0 description.RemoteApplication) *remoteApplicationDoc { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeRemoteApplicationDoc", arg0) ret0, _ := ret[0].(*remoteApplicationDoc) return ret0 @@ -78,11 +95,13 @@ func (m *MockStateDocumentFactory) MakeRemoteApplicationDoc(arg0 description.Rem // MakeRemoteApplicationDoc indicates an expected call of MakeRemoteApplicationDoc func (mr *MockStateDocumentFactoryMockRecorder) MakeRemoteApplicationDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeRemoteApplicationDoc", reflect.TypeOf((*MockStateDocumentFactory)(nil).MakeRemoteApplicationDoc), arg0) } // MakeStatusDoc mocks base method func (m *MockStateDocumentFactory) MakeStatusDoc(arg0 description.Status) statusDoc { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeStatusDoc", arg0) ret0, _ := ret[0].(statusDoc) return ret0 @@ -90,11 +109,13 @@ func (m *MockStateDocumentFactory) MakeStatusDoc(arg0 description.Status) status // MakeStatusDoc indicates an expected call of MakeStatusDoc func (mr *MockStateDocumentFactoryMockRecorder) MakeStatusDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeStatusDoc", reflect.TypeOf((*MockStateDocumentFactory)(nil).MakeStatusDoc), arg0) } // MakeStatusOp mocks base method func (m *MockStateDocumentFactory) MakeStatusOp(arg0 string, arg1 statusDoc) txn.Op { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeStatusOp", arg0, arg1) ret0, _ := ret[0].(txn.Op) return ret0 @@ -102,11 +123,13 @@ func (m *MockStateDocumentFactory) MakeStatusOp(arg0 string, arg1 statusDoc) txn // MakeStatusOp indicates an expected call of MakeStatusOp func (mr *MockStateDocumentFactoryMockRecorder) MakeStatusOp(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeStatusOp", reflect.TypeOf((*MockStateDocumentFactory)(nil).MakeStatusOp), arg0, arg1) } // NewRemoteApplication mocks base method func (m *MockStateDocumentFactory) NewRemoteApplication(arg0 *remoteApplicationDoc) *RemoteApplication { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NewRemoteApplication", arg0) ret0, _ := ret[0].(*RemoteApplication) return ret0 @@ -114,6 +137,7 @@ func (m *MockStateDocumentFactory) NewRemoteApplication(arg0 *remoteApplicationD // NewRemoteApplication indicates an expected call of NewRemoteApplication func (mr *MockStateDocumentFactoryMockRecorder) NewRemoteApplication(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRemoteApplication", reflect.TypeOf((*MockStateDocumentFactory)(nil).NewRemoteApplication), arg0) } @@ -142,6 +166,7 @@ func (m *MockDocModelNamespace) EXPECT() *MockDocModelNamespaceMockRecorder { // DocID mocks base method func (m *MockDocModelNamespace) DocID(arg0 string) string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DocID", arg0) ret0, _ := ret[0].(string) return ret0 @@ -149,6 +174,7 @@ func (m *MockDocModelNamespace) DocID(arg0 string) string { // DocID indicates an expected call of DocID func (mr *MockDocModelNamespaceMockRecorder) DocID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DocID", reflect.TypeOf((*MockDocModelNamespace)(nil).DocID), arg0) } @@ -177,6 +203,7 @@ func (m *MockRemoteEntitiesDescription) EXPECT() *MockRemoteEntitiesDescriptionM // DocID mocks base method func (m *MockRemoteEntitiesDescription) DocID(arg0 string) string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DocID", arg0) ret0, _ := ret[0].(string) return ret0 @@ -184,11 +211,13 @@ func (m *MockRemoteEntitiesDescription) DocID(arg0 string) string { // DocID indicates an expected call of DocID func (mr *MockRemoteEntitiesDescriptionMockRecorder) DocID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DocID", reflect.TypeOf((*MockRemoteEntitiesDescription)(nil).DocID), arg0) } // RemoteEntities mocks base method func (m *MockRemoteEntitiesDescription) RemoteEntities() []description.RemoteEntity { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoteEntities") ret0, _ := ret[0].([]description.RemoteEntity) return ret0 @@ -196,6 +225,7 @@ func (m *MockRemoteEntitiesDescription) RemoteEntities() []description.RemoteEnt // RemoteEntities indicates an expected call of RemoteEntities func (mr *MockRemoteEntitiesDescriptionMockRecorder) RemoteEntities() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteEntities", reflect.TypeOf((*MockRemoteEntitiesDescription)(nil).RemoteEntities)) } @@ -224,6 +254,7 @@ func (m *MockRelationNetworksDescription) EXPECT() *MockRelationNetworksDescript // DocID mocks base method func (m *MockRelationNetworksDescription) DocID(arg0 string) string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DocID", arg0) ret0, _ := ret[0].(string) return ret0 @@ -231,11 +262,13 @@ func (m *MockRelationNetworksDescription) DocID(arg0 string) string { // DocID indicates an expected call of DocID func (mr *MockRelationNetworksDescriptionMockRecorder) DocID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DocID", reflect.TypeOf((*MockRelationNetworksDescription)(nil).DocID), arg0) } // RelationNetworks mocks base method func (m *MockRelationNetworksDescription) RelationNetworks() []description.RelationNetwork { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RelationNetworks") ret0, _ := ret[0].([]description.RelationNetwork) return ret0 @@ -243,6 +276,7 @@ func (m *MockRelationNetworksDescription) RelationNetworks() []description.Relat // RelationNetworks indicates an expected call of RelationNetworks func (mr *MockRelationNetworksDescriptionMockRecorder) RelationNetworks() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RelationNetworks", reflect.TypeOf((*MockRelationNetworksDescription)(nil).RelationNetworks)) } @@ -271,6 +305,7 @@ func (m *MockRemoteApplicationsDescription) EXPECT() *MockRemoteApplicationsDesc // DocID mocks base method func (m *MockRemoteApplicationsDescription) DocID(arg0 string) string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DocID", arg0) ret0, _ := ret[0].(string) return ret0 @@ -278,11 +313,27 @@ func (m *MockRemoteApplicationsDescription) DocID(arg0 string) string { // DocID indicates an expected call of DocID func (mr *MockRemoteApplicationsDescriptionMockRecorder) DocID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DocID", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).DocID), arg0) } +// MakeFirewallRuleDoc mocks base method +func (m *MockRemoteApplicationsDescription) MakeFirewallRuleDoc(arg0 description.FirewallRule) *firewallRulesDoc { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MakeFirewallRuleDoc", arg0) + ret0, _ := ret[0].(*firewallRulesDoc) + return ret0 +} + +// MakeFirewallRuleDoc indicates an expected call of MakeFirewallRuleDoc +func (mr *MockRemoteApplicationsDescriptionMockRecorder) MakeFirewallRuleDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeFirewallRuleDoc", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).MakeFirewallRuleDoc), arg0) +} + // MakeRemoteApplicationDoc mocks base method func (m *MockRemoteApplicationsDescription) MakeRemoteApplicationDoc(arg0 description.RemoteApplication) *remoteApplicationDoc { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeRemoteApplicationDoc", arg0) ret0, _ := ret[0].(*remoteApplicationDoc) return ret0 @@ -290,11 +341,13 @@ func (m *MockRemoteApplicationsDescription) MakeRemoteApplicationDoc(arg0 descri // MakeRemoteApplicationDoc indicates an expected call of MakeRemoteApplicationDoc func (mr *MockRemoteApplicationsDescriptionMockRecorder) MakeRemoteApplicationDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeRemoteApplicationDoc", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).MakeRemoteApplicationDoc), arg0) } // MakeStatusDoc mocks base method func (m *MockRemoteApplicationsDescription) MakeStatusDoc(arg0 description.Status) statusDoc { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeStatusDoc", arg0) ret0, _ := ret[0].(statusDoc) return ret0 @@ -302,11 +355,13 @@ func (m *MockRemoteApplicationsDescription) MakeStatusDoc(arg0 description.Statu // MakeStatusDoc indicates an expected call of MakeStatusDoc func (mr *MockRemoteApplicationsDescriptionMockRecorder) MakeStatusDoc(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeStatusDoc", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).MakeStatusDoc), arg0) } // MakeStatusOp mocks base method func (m *MockRemoteApplicationsDescription) MakeStatusOp(arg0 string, arg1 statusDoc) txn.Op { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MakeStatusOp", arg0, arg1) ret0, _ := ret[0].(txn.Op) return ret0 @@ -314,11 +369,13 @@ func (m *MockRemoteApplicationsDescription) MakeStatusOp(arg0 string, arg1 statu // MakeStatusOp indicates an expected call of MakeStatusOp func (mr *MockRemoteApplicationsDescriptionMockRecorder) MakeStatusOp(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeStatusOp", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).MakeStatusOp), arg0, arg1) } // NewRemoteApplication mocks base method func (m *MockRemoteApplicationsDescription) NewRemoteApplication(arg0 *remoteApplicationDoc) *RemoteApplication { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NewRemoteApplication", arg0) ret0, _ := ret[0].(*RemoteApplication) return ret0 @@ -326,11 +383,13 @@ func (m *MockRemoteApplicationsDescription) NewRemoteApplication(arg0 *remoteApp // NewRemoteApplication indicates an expected call of NewRemoteApplication func (mr *MockRemoteApplicationsDescriptionMockRecorder) NewRemoteApplication(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRemoteApplication", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).NewRemoteApplication), arg0) } // RemoteApplications mocks base method func (m *MockRemoteApplicationsDescription) RemoteApplications() []description.RemoteApplication { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoteApplications") ret0, _ := ret[0].([]description.RemoteApplication) return ret0 @@ -338,5 +397,6 @@ func (m *MockRemoteApplicationsDescription) RemoteApplications() []description.R // RemoteApplications indicates an expected call of RemoteApplications func (mr *MockRemoteApplicationsDescriptionMockRecorder) RemoteApplications() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteApplications", reflect.TypeOf((*MockRemoteApplicationsDescription)(nil).RemoteApplications)) } diff --git a/state/migration_import_test.go b/state/migration_import_test.go index aad89d663c6..024bb627ffe 100644 --- a/state/migration_import_test.go +++ b/state/migration_import_test.go @@ -22,6 +22,7 @@ import ( "gopkg.in/yaml.v2" "github.com/juju/juju/core/constraints" + "github.com/juju/juju/core/firewall" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/model" "github.com/juju/juju/core/network" @@ -1185,6 +1186,35 @@ func (s *MigrationImportSuite) TestSpaces(c *gc.C) { c.Check(imported.Id(), gc.Not(gc.Equals), "") } +func (s *MigrationImportSuite) TestFirewallRules(c *gc.C) { + serviceType := firewall.WellKnownServiceType("ssh") + cidr := []string{"192.0.2.1/24"} + + fwRule := state.NewFirewallRule(serviceType, cidr) + + fst := state.NewFirewallRules(s.State) + err := fst.Save(fwRule) + c.Assert(err, jc.ErrorIsNil) + + out, err := s.State.Export() + c.Assert(err, jc.ErrorIsNil) + + uuid := utils.MustNewUUID().String() + in := newModel(out, uuid, "new") + + _, newSt, err := s.Controller.Import(in) + c.Assert(err, jc.ErrorIsNil) + + fst = state.NewFirewallRules(newSt) + if err == nil { + defer newSt.Close() + } + rule, err := fst.Rule(serviceType) + c.Assert(err, jc.ErrorIsNil) + c.Assert(rule.WhitelistCIDRs(), gc.DeepEquals, fwRule.WhitelistCIDRs()) + c.Assert(rule.WellKnownService(), gc.Equals, fwRule.WellKnownService()) +} + func (s *MigrationImportSuite) TestDestroyEmptyModel(c *gc.C) { newModel, _ := s.importModel(c, s.State) s.assertDestroyModelAdvancesLife(c, newModel, state.Dying) diff --git a/state/migrations/firewallRules.go b/state/migrations/firewallrules.go similarity index 86% rename from state/migrations/firewallRules.go rename to state/migrations/firewallrules.go index e7e179dc1ab..928b78c8a17 100644 --- a/state/migrations/firewallRules.go +++ b/state/migrations/firewallrules.go @@ -6,13 +6,15 @@ package migrations import ( "github.com/juju/description" "github.com/juju/errors" + + "github.com/juju/juju/core/firewall" ) // MigrationFirewallRule represents a state.FirewallRule // Point of use interface to enable better encapsulation. type MigrationFirewallRule interface { ID() string - WellKnownService() string + WellKnownService() firewall.WellKnownServiceType WhitelistCIDRs() []string } @@ -28,7 +30,7 @@ type FirewallRulesModel interface { AddFirewallRule(args description.FirewallRuleArgs) description.FirewallRule } -// ExportRemoteEntities describes a way to execute a migration for exporting +// ExportFirewallRule describes a way to execute a migration for exporting // remote entities. type ExportFirewallRule struct{} @@ -44,7 +46,7 @@ func (ExportFirewallRule) Execute(src FirewallRuleSource, dst FirewallRulesModel for _, firewallRule := range firewallRules { dst.AddFirewallRule(description.FirewallRuleArgs{ ID: firewallRule.ID(), - WellKnownService: firewallRule.WellKnownService(), + WellKnownService: string(firewallRule.WellKnownService()), WhitelistCIDRs: firewallRule.WhitelistCIDRs(), }) } diff --git a/worker/firewaller/firewaller_test.go b/worker/firewaller/firewaller_test.go index 4d21600b754..f6c2ee97873 100644 --- a/worker/firewaller/firewaller_test.go +++ b/worker/firewaller/firewaller_test.go @@ -29,6 +29,7 @@ import ( apitesting "github.com/juju/juju/api/testing" "github.com/juju/juju/apiserver/params" "github.com/juju/juju/core/crossmodel" + "github.com/juju/juju/core/firewall" corenetwork "github.com/juju/juju/core/network" "github.com/juju/juju/core/status" "github.com/juju/juju/environs" @@ -1214,7 +1215,7 @@ func (s *InstanceModeSuite) TestRemoteRelationIngressFallbackToPublic(c *gc.C) { func (s *InstanceModeSuite) TestRemoteRelationIngressFallbackToWhitelist(c *gc.C) { fwRules := state.NewFirewallRules(s.State) - err := fwRules.Save(state.NewFirewallRule(state.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) + err := fwRules.Save(state.NewFirewallRule(firewall.JujuApplicationOfferRule, []string{"192.168.1.0/16"})) c.Assert(err, jc.ErrorIsNil) var ingress []string for i := 1; i < 30; i++ {