github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/secrets_test.go (about)

     1  // Copyright 2021 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  	"time"
    10  
    11  	"github.com/juju/charm/v12"
    12  	"github.com/juju/collections/set"
    13  	"github.com/juju/errors"
    14  	"github.com/juju/names/v5"
    15  	jc "github.com/juju/testing/checkers"
    16  	"github.com/juju/utils/v3"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/core/secrets"
    20  	"github.com/juju/juju/core/watcher"
    21  	"github.com/juju/juju/provider/dummy"
    22  	"github.com/juju/juju/state"
    23  	"github.com/juju/juju/state/testing"
    24  	"github.com/juju/juju/storage"
    25  	"github.com/juju/juju/storage/provider"
    26  	jujutesting "github.com/juju/juju/testing"
    27  	"github.com/juju/juju/testing/factory"
    28  )
    29  
    30  type SecretsSuite struct {
    31  	testing.StateSuite
    32  	store     state.SecretsStore
    33  	owner     *state.Application
    34  	ownerUnit *state.Unit
    35  	relation  *state.Relation
    36  }
    37  
    38  var _ = gc.Suite(&SecretsSuite{})
    39  
    40  func (s *SecretsSuite) SetUpTest(c *gc.C) {
    41  	s.StateSuite.SetUpTest(c)
    42  	s.store = state.NewSecrets(s.State)
    43  	s.owner = s.Factory.MakeApplication(c, nil)
    44  	s.ownerUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.owner})
    45  	app2 := s.Factory.MakeApplication(c, &factory.ApplicationParams{
    46  		Name:  "wordpress",
    47  		Charm: s.Factory.MakeCharm(c, &factory.CharmParams{Name: "wordpress"}),
    48  	})
    49  	ep1, err := s.owner.Endpoint("server")
    50  	c.Assert(err, jc.ErrorIsNil)
    51  	ep2, err := app2.Endpoint("db")
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	s.relation = s.Factory.MakeRelation(c, &factory.RelationParams{
    54  		Endpoints: []state.Endpoint{ep1, ep2},
    55  	})
    56  }
    57  
    58  func ptr[T any](v T) *T {
    59  	return &v
    60  }
    61  
    62  func (s *SecretsSuite) TestCreate(c *gc.C) {
    63  	uri := secrets.NewURI()
    64  	now := s.Clock.Now().Round(time.Second).UTC()
    65  	next := now.Add(time.Minute).Round(time.Second).UTC()
    66  	expire := now.Add(time.Hour).Round(time.Second).UTC()
    67  	p := state.CreateSecretParams{
    68  		Version: 1,
    69  		Owner:   s.owner.Tag(),
    70  		UpdateSecretParams: state.UpdateSecretParams{
    71  			LeaderToken:    &fakeToken{},
    72  			RotatePolicy:   ptr(secrets.RotateDaily),
    73  			NextRotateTime: ptr(next),
    74  			Description:    ptr("my secret"),
    75  			Label:          ptr("foobar"),
    76  			ExpireTime:     ptr(expire),
    77  			Params:         nil,
    78  			Data:           map[string]string{"foo": "bar"},
    79  		},
    80  	}
    81  	md, err := s.store.CreateSecret(uri, p)
    82  	c.Assert(err, jc.ErrorIsNil)
    83  	mc := jc.NewMultiChecker()
    84  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
    85  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
    86  	c.Assert(md, mc, &secrets.SecretMetadata{
    87  		URI:              uri,
    88  		Version:          1,
    89  		Description:      "my secret",
    90  		Label:            "foobar",
    91  		RotatePolicy:     secrets.RotateDaily,
    92  		NextRotateTime:   ptr(next),
    93  		LatestRevision:   1,
    94  		LatestExpireTime: ptr(expire),
    95  		OwnerTag:         s.owner.Tag().String(),
    96  		CreateTime:       now,
    97  		UpdateTime:       now,
    98  	})
    99  
   100  	p.Label = nil
   101  	_, err = s.store.CreateSecret(uri, p)
   102  	c.Assert(err, jc.Satisfies, errors.IsAlreadyExists)
   103  }
   104  
   105  func (s *SecretsSuite) TestCreateUserSecret(c *gc.C) {
   106  	uri := secrets.NewURI()
   107  	now := s.Clock.Now().Round(time.Second).UTC()
   108  	p := state.CreateSecretParams{
   109  		Version: 1,
   110  		Owner:   s.Model.Tag(),
   111  		UpdateSecretParams: state.UpdateSecretParams{
   112  			LeaderToken: &fakeToken{},
   113  			Description: ptr("my secret"),
   114  			Label:       ptr("label-1"),
   115  			Params:      nil,
   116  			Data:        map[string]string{"foo": "bar"},
   117  		},
   118  	}
   119  	md, err := s.store.CreateSecret(uri, p)
   120  	c.Assert(err, jc.ErrorIsNil)
   121  	mc := jc.NewMultiChecker()
   122  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
   123  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
   124  	c.Assert(md, mc, &secrets.SecretMetadata{
   125  		URI:            uri,
   126  		Version:        1,
   127  		Description:    "my secret",
   128  		Label:          "label-1",
   129  		LatestRevision: 1,
   130  		OwnerTag:       s.Model.Tag().String(),
   131  		CreateTime:     now,
   132  		UpdateTime:     now,
   133  	})
   134  
   135  	uri2 := secrets.NewURI()
   136  	_, err = s.store.CreateSecret(uri2, p)
   137  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf(`user secret label "label-1" already exists`))
   138  }
   139  
   140  func (s *SecretsSuite) TestCreateBackendRef(c *gc.C) {
   141  	backendStore := state.NewSecretBackends(s.State)
   142  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
   143  		ID:          "backend-id",
   144  		Name:        "foo",
   145  		BackendType: "vault",
   146  	})
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	backendRefCount, err := s.State.ReadBackendRefCount("backend-id")
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	c.Assert(backendRefCount, gc.Equals, 0)
   151  
   152  	uri := secrets.NewURI()
   153  	p := state.CreateSecretParams{
   154  		Version: 1,
   155  		Owner:   s.owner.Tag(),
   156  		UpdateSecretParams: state.UpdateSecretParams{
   157  			LeaderToken: &fakeToken{},
   158  			ValueRef: &secrets.ValueRef{
   159  				BackendID:  "backend-id",
   160  				RevisionID: "rev-id",
   161  			},
   162  		},
   163  	}
   164  	_, err = s.store.CreateSecret(uri, p)
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
   167  	c.Assert(err, jc.ErrorIsNil)
   168  	c.Assert(backendRefCount, gc.Equals, 1)
   169  	v, valueRef, err := s.store.GetSecretValue(uri, 1)
   170  	c.Assert(err, jc.ErrorIsNil)
   171  	c.Assert(v.EncodedValues(), gc.HasLen, 0)
   172  	c.Assert(valueRef, gc.NotNil)
   173  	c.Assert(*valueRef, jc.DeepEquals, secrets.ValueRef{
   174  		BackendID:  "backend-id",
   175  		RevisionID: "rev-id",
   176  	})
   177  }
   178  
   179  func (s *SecretsSuite) TestCreateDuplicateLabelApplicationOwned(c *gc.C) {
   180  	uri := secrets.NewURI()
   181  	now := s.Clock.Now().Round(time.Second).UTC()
   182  	next := now.Add(time.Minute).Round(time.Second).UTC()
   183  	expire := now.Add(time.Hour).Round(time.Second).UTC()
   184  	p := state.CreateSecretParams{
   185  		Version: 1,
   186  		Owner:   s.owner.Tag(),
   187  		UpdateSecretParams: state.UpdateSecretParams{
   188  			LeaderToken:    &fakeToken{},
   189  			RotatePolicy:   ptr(secrets.RotateDaily),
   190  			NextRotateTime: ptr(next),
   191  			Description:    ptr("my secret"),
   192  			Label:          ptr("foobar"),
   193  			ExpireTime:     ptr(expire),
   194  			Params:         nil,
   195  			Data:           map[string]string{"foo": "bar"},
   196  		},
   197  	}
   198  	md, err := s.store.CreateSecret(uri, p)
   199  	c.Assert(err, jc.ErrorIsNil)
   200  	uri2 := secrets.NewURI()
   201  	_, err = s.store.CreateSecret(uri2, p)
   202  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   203  
   204  	// Existing application owner label should not be used for owner label for its units.
   205  	uri3 := secrets.NewURI()
   206  	p.Owner = s.ownerUnit.Tag()
   207  	_, err = s.store.CreateSecret(uri3, p)
   208  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   209  
   210  	// Existing application owner label should not be used for consumer label for its units.
   211  	cmd := &secrets.SecretConsumerMetadata{
   212  		Label:           "foobar",
   213  		CurrentRevision: md.LatestRevision,
   214  	}
   215  	err = s.State.SaveSecretConsumer(uri, s.ownerUnit.Tag(), cmd)
   216  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   217  }
   218  
   219  func (s *SecretsSuite) TestCreateDuplicateLabelUnitOwned(c *gc.C) {
   220  	uri := secrets.NewURI()
   221  	now := s.Clock.Now().Round(time.Second).UTC()
   222  	next := now.Add(time.Minute).Round(time.Second).UTC()
   223  	expire := now.Add(time.Hour).Round(time.Second).UTC()
   224  	p := state.CreateSecretParams{
   225  		Version: 1,
   226  		Owner:   s.ownerUnit.Tag(),
   227  		UpdateSecretParams: state.UpdateSecretParams{
   228  			LeaderToken:    &fakeToken{},
   229  			RotatePolicy:   ptr(secrets.RotateDaily),
   230  			NextRotateTime: ptr(next),
   231  			Description:    ptr("my secret"),
   232  			Label:          ptr("foobar"),
   233  			ExpireTime:     ptr(expire),
   234  			Params:         nil,
   235  			Data:           map[string]string{"foo": "bar"},
   236  		},
   237  	}
   238  	md, err := s.store.CreateSecret(uri, p)
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	uri2 := secrets.NewURI()
   241  	_, err = s.store.CreateSecret(uri2, p)
   242  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   243  
   244  	// Existing unit owner label should not be used for owner label for the application.
   245  	uri3 := secrets.NewURI()
   246  	p.Owner = s.owner.Tag()
   247  	_, err = s.store.CreateSecret(uri3, p)
   248  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   249  
   250  	// Existing unit owner label should not be used for consumer label for the application.
   251  	cmd := &secrets.SecretConsumerMetadata{
   252  		Label:           "foobar",
   253  		CurrentRevision: md.LatestRevision,
   254  	}
   255  	err = s.State.SaveSecretConsumer(uri, s.owner.Tag(), cmd)
   256  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   257  }
   258  
   259  func (s *SecretsSuite) TestCreateDuplicateLabelUnitConsumed(c *gc.C) {
   260  	uri := secrets.NewURI()
   261  	p := state.CreateSecretParams{
   262  		Version: 1,
   263  		Owner:   names.NewApplicationTag("wordpress"),
   264  		UpdateSecretParams: state.UpdateSecretParams{
   265  			LeaderToken: &fakeToken{},
   266  			Params:      nil,
   267  			Data:        map[string]string{"foo": "bar"},
   268  		},
   269  	}
   270  	md, err := s.store.CreateSecret(uri, p)
   271  	c.Assert(err, jc.ErrorIsNil)
   272  
   273  	cmd := &secrets.SecretConsumerMetadata{
   274  		Label:           "foobar",
   275  		CurrentRevision: md.LatestRevision,
   276  	}
   277  	err = s.State.SaveSecretConsumer(uri, s.ownerUnit.Tag(), cmd)
   278  	c.Assert(err, jc.ErrorIsNil)
   279  
   280  	// Existing unit consumer label should not be used for owner label.
   281  	uri2 := secrets.NewURI()
   282  	p.Owner = s.ownerUnit.Tag()
   283  	p.Label = ptr("foobar")
   284  	_, err = s.store.CreateSecret(uri2, p)
   285  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   286  
   287  	// Existing unit consumer label should not be used for owner label for the application.
   288  	uri3 := secrets.NewURI()
   289  	p.Owner = s.owner.Tag()
   290  	p.Label = ptr("foobar")
   291  	_, err = s.store.CreateSecret(uri3, p)
   292  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   293  
   294  	// Existing unit consumer label should not be used for consumer label for the application.
   295  	cmd = &secrets.SecretConsumerMetadata{
   296  		Label:           "foobar",
   297  		CurrentRevision: md.LatestRevision,
   298  	}
   299  	err = s.State.SaveSecretConsumer(uri, s.owner.Tag(), cmd)
   300  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   301  }
   302  
   303  func (s *SecretsSuite) TestCreateDyingOwner(c *gc.C) {
   304  	err := s.owner.Destroy()
   305  	c.Assert(err, jc.ErrorIsNil)
   306  
   307  	uri := secrets.NewURI()
   308  	cp := state.CreateSecretParams{
   309  		Version: 1,
   310  		Owner:   s.owner.Tag(),
   311  		UpdateSecretParams: state.UpdateSecretParams{
   312  			LeaderToken: &fakeToken{},
   313  			Data:        map[string]string{"foo": "bar"},
   314  		},
   315  	}
   316  	_, err = s.store.CreateSecret(uri, cp)
   317  	c.Assert(err, gc.ErrorMatches, `cannot create secret for owner "application-mysql" which is not alive`)
   318  }
   319  
   320  func (s *SecretsSuite) TestGetValueNotFound(c *gc.C) {
   321  	uri, _ := secrets.ParseURI("secret:9m4e2mr0ui3e8a215n4g")
   322  	_, _, err := s.store.GetSecretValue(uri, 666)
   323  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   324  }
   325  
   326  func (s *SecretsSuite) TestGetValue(c *gc.C) {
   327  	uri := secrets.NewURI()
   328  	p := state.CreateSecretParams{
   329  		Version: 1,
   330  		Owner:   s.owner.Tag(),
   331  		UpdateSecretParams: state.UpdateSecretParams{
   332  			LeaderToken: &fakeToken{},
   333  			Data:        map[string]string{"foo": "bar"},
   334  		},
   335  	}
   336  	md, err := s.store.CreateSecret(uri, p)
   337  	c.Assert(err, jc.ErrorIsNil)
   338  
   339  	val, backendId, err := s.store.GetSecretValue(md.URI, 1)
   340  	c.Assert(err, jc.ErrorIsNil)
   341  	c.Assert(backendId, gc.IsNil)
   342  	c.Assert(val.EncodedValues(), jc.DeepEquals, map[string]string{
   343  		"foo": "bar",
   344  	})
   345  }
   346  
   347  func (s *SecretsSuite) TestListByOwner(c *gc.C) {
   348  	uri := secrets.NewURI()
   349  	now := s.Clock.Now().Round(time.Second).UTC()
   350  	next := now.Add(time.Minute).Round(time.Second).UTC()
   351  	expire := now.Add(time.Hour).Round(time.Second).UTC()
   352  	p := state.CreateSecretParams{
   353  		Version: 1,
   354  		Owner:   s.owner.Tag(),
   355  		UpdateSecretParams: state.UpdateSecretParams{
   356  			LeaderToken:    &fakeToken{},
   357  			RotatePolicy:   ptr(secrets.RotateDaily),
   358  			NextRotateTime: ptr(next),
   359  			Description:    ptr("my secret"),
   360  			Label:          ptr("foobar"),
   361  			ExpireTime:     ptr(expire),
   362  			Params:         nil,
   363  			Data:           map[string]string{"foo": "bar"},
   364  		},
   365  	}
   366  	_, err := s.store.CreateSecret(uri, p)
   367  	c.Assert(err, jc.ErrorIsNil)
   368  
   369  	another := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   370  		Charm: s.Factory.MakeCharm(c, &factory.CharmParams{Name: "mariadb"}),
   371  	})
   372  	now2 := s.Clock.Now().Round(time.Second).UTC()
   373  	uri2 := secrets.NewURI()
   374  	p2 := state.CreateSecretParams{
   375  		Version: 1,
   376  		Owner:   another.Tag(),
   377  		UpdateSecretParams: state.UpdateSecretParams{
   378  			LeaderToken: &fakeToken{},
   379  			Data:        map[string]string{"foo": "bar"},
   380  		},
   381  	}
   382  	_, err = s.store.CreateSecret(uri2, p2)
   383  	c.Assert(err, jc.ErrorIsNil)
   384  
   385  	// Create another secret to ensure it is excluded.
   386  	uri3 := secrets.NewURI()
   387  	p.Owner = names.NewApplicationTag("wordpress")
   388  	_, err = s.store.CreateSecret(uri3, p)
   389  	c.Assert(err, jc.ErrorIsNil)
   390  
   391  	expectedList := []*secrets.SecretMetadata{{
   392  		URI:              uri,
   393  		RotatePolicy:     secrets.RotateDaily,
   394  		NextRotateTime:   ptr(next),
   395  		LatestRevision:   1,
   396  		LatestExpireTime: ptr(expire),
   397  		Version:          1,
   398  		OwnerTag:         s.owner.Tag().String(),
   399  		Description:      "my secret",
   400  		Label:            "foobar",
   401  		CreateTime:       now,
   402  		UpdateTime:       now,
   403  	}, {
   404  		URI:            uri2,
   405  		LatestRevision: 1,
   406  		Version:        1,
   407  		OwnerTag:       another.Tag().String(),
   408  		CreateTime:     now2,
   409  		UpdateTime:     now2,
   410  	}}
   411  	list, err := s.store.ListSecrets(state.SecretsFilter{
   412  		OwnerTags: []names.Tag{s.owner.Tag(), names.NewApplicationTag("mariadb")},
   413  	})
   414  	c.Assert(err, jc.ErrorIsNil)
   415  
   416  	mc := jc.NewMultiChecker()
   417  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
   418  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
   419  
   420  	sortMD := func(l []*secrets.SecretMetadata) {
   421  		sort.Slice(l, func(i, j int) bool {
   422  			return l[i].URI.String() < l[j].URI.String()
   423  		})
   424  	}
   425  	sortMD(list)
   426  	sortMD(expectedList)
   427  	c.Assert(list, mc, expectedList)
   428  }
   429  
   430  func (s *SecretsSuite) TestListByURI(c *gc.C) {
   431  	uri := secrets.NewURI()
   432  	now := s.Clock.Now().Round(time.Second).UTC()
   433  	next := now.Add(time.Minute).Round(time.Second).UTC()
   434  	expire := now.Add(time.Hour).Round(time.Second).UTC()
   435  	p := state.CreateSecretParams{
   436  		Version: 1,
   437  		Owner:   s.owner.Tag(),
   438  		UpdateSecretParams: state.UpdateSecretParams{
   439  			LeaderToken:    &fakeToken{},
   440  			RotatePolicy:   ptr(secrets.RotateDaily),
   441  			NextRotateTime: ptr(next),
   442  			Description:    ptr("my secret"),
   443  			Label:          ptr("foobar"),
   444  			ExpireTime:     ptr(expire),
   445  			Params:         nil,
   446  			Data:           map[string]string{"foo": "bar"},
   447  		},
   448  	}
   449  	_, err := s.store.CreateSecret(uri, p)
   450  	c.Assert(err, jc.ErrorIsNil)
   451  
   452  	// Create another secret to ensure it is excluded.
   453  	uri2 := secrets.NewURI()
   454  	p.Owner = names.NewApplicationTag("wordpress")
   455  	_, err = s.store.CreateSecret(uri2, p)
   456  	c.Assert(err, jc.ErrorIsNil)
   457  
   458  	list, err := s.store.ListSecrets(state.SecretsFilter{
   459  		URI: uri,
   460  	})
   461  	c.Assert(err, jc.ErrorIsNil)
   462  	mc := jc.NewMultiChecker()
   463  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
   464  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
   465  	c.Assert(list, mc, []*secrets.SecretMetadata{{
   466  		URI:              uri,
   467  		RotatePolicy:     secrets.RotateDaily,
   468  		NextRotateTime:   ptr(next),
   469  		LatestRevision:   1,
   470  		LatestExpireTime: ptr(expire),
   471  		Version:          1,
   472  		OwnerTag:         s.owner.Tag().String(),
   473  		Description:      "my secret",
   474  		Label:            "foobar",
   475  		CreateTime:       now,
   476  		UpdateTime:       now,
   477  	}})
   478  }
   479  
   480  func (s *SecretsSuite) TestListByLabel(c *gc.C) {
   481  	uri := secrets.NewURI()
   482  	now := s.Clock.Now().Round(time.Second).UTC()
   483  	next := now.Add(time.Minute).Round(time.Second).UTC()
   484  	expire := now.Add(time.Hour).Round(time.Second).UTC()
   485  	p := state.CreateSecretParams{
   486  		Version: 1,
   487  		Owner:   s.owner.Tag(),
   488  		UpdateSecretParams: state.UpdateSecretParams{
   489  			LeaderToken:    &fakeToken{},
   490  			RotatePolicy:   ptr(secrets.RotateDaily),
   491  			NextRotateTime: ptr(next),
   492  			Description:    ptr("my secret"),
   493  			Label:          ptr("foobar"),
   494  			ExpireTime:     ptr(expire),
   495  			Params:         nil,
   496  			Data:           map[string]string{"foo": "bar"},
   497  		},
   498  	}
   499  	_, err := s.store.CreateSecret(uri, p)
   500  	c.Assert(err, jc.ErrorIsNil)
   501  
   502  	// Create another secret to ensure it is excluded.
   503  	uri2 := secrets.NewURI()
   504  	p.Label = ptr("another")
   505  	_, err = s.store.CreateSecret(uri2, p)
   506  	c.Assert(err, jc.ErrorIsNil)
   507  
   508  	list, err := s.store.ListSecrets(state.SecretsFilter{
   509  		Label: ptr("foobar"),
   510  	})
   511  	c.Assert(err, jc.ErrorIsNil)
   512  	mc := jc.NewMultiChecker()
   513  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
   514  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
   515  	c.Assert(list, mc, []*secrets.SecretMetadata{{
   516  		URI:              uri,
   517  		RotatePolicy:     secrets.RotateDaily,
   518  		NextRotateTime:   ptr(next),
   519  		LatestRevision:   1,
   520  		LatestExpireTime: ptr(expire),
   521  		Version:          1,
   522  		OwnerTag:         s.owner.Tag().String(),
   523  		Description:      "my secret",
   524  		Label:            "foobar",
   525  		CreateTime:       now,
   526  		UpdateTime:       now,
   527  	}})
   528  }
   529  
   530  func (s *SecretsSuite) TestListByConsumer(c *gc.C) {
   531  	uri := secrets.NewURI()
   532  	now := s.Clock.Now().Round(time.Second).UTC()
   533  	subject := names.NewApplicationTag("wordpress")
   534  
   535  	cp := state.CreateSecretParams{
   536  		Version: 1,
   537  		Owner:   s.owner.Tag(),
   538  		UpdateSecretParams: state.UpdateSecretParams{
   539  			LeaderToken: &fakeToken{},
   540  			Description: ptr("my secret"),
   541  			Data:        map[string]string{"foo": "bar"},
   542  		},
   543  	}
   544  	_, err := s.store.CreateSecret(uri, cp)
   545  	c.Assert(err, jc.ErrorIsNil)
   546  
   547  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
   548  		LeaderToken: &fakeToken{},
   549  		Scope:       s.relation.Tag(),
   550  		Subject:     subject,
   551  		Role:        secrets.RoleView,
   552  	})
   553  	c.Assert(err, jc.ErrorIsNil)
   554  
   555  	// Create another secret to ensure it is excluded.
   556  	uri2 := secrets.NewURI()
   557  	cp.Owner = names.NewApplicationTag("wordpress")
   558  	_, err = s.store.CreateSecret(uri2, cp)
   559  	c.Assert(err, jc.ErrorIsNil)
   560  
   561  	list, err := s.store.ListSecrets(state.SecretsFilter{
   562  		ConsumerTags: []names.Tag{subject},
   563  	})
   564  	c.Assert(err, jc.ErrorIsNil)
   565  	mc := jc.NewMultiChecker()
   566  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
   567  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
   568  	c.Assert(list, mc, []*secrets.SecretMetadata{{
   569  		URI:            uri,
   570  		LatestRevision: 1,
   571  		Version:        1,
   572  		OwnerTag:       s.owner.Tag().String(),
   573  		Description:    "my secret",
   574  		CreateTime:     now,
   575  		UpdateTime:     now,
   576  	}})
   577  }
   578  
   579  func (s *SecretsSuite) TestListModelSecrets(c *gc.C) {
   580  	backendStore := state.NewSecretBackends(s.State)
   581  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
   582  		ID:          "backend-id",
   583  		Name:        "foo",
   584  		BackendType: "vault",
   585  	})
   586  	c.Assert(err, jc.ErrorIsNil)
   587  	backendRefCount, err := s.State.ReadBackendRefCount("backend-id")
   588  	c.Assert(err, jc.ErrorIsNil)
   589  	c.Assert(backendRefCount, gc.Equals, 0)
   590  
   591  	uri := secrets.NewURI()
   592  	p := state.CreateSecretParams{
   593  		Version: 1,
   594  		Owner:   s.owner.Tag(),
   595  		UpdateSecretParams: state.UpdateSecretParams{
   596  			LeaderToken: &fakeToken{},
   597  			Data:        map[string]string{"foo": "bar"},
   598  		},
   599  	}
   600  	_, err = s.store.CreateSecret(uri, p)
   601  	c.Assert(err, jc.ErrorIsNil)
   602  
   603  	uri2 := secrets.NewURI()
   604  	p2 := state.CreateSecretParams{
   605  		Version: 1,
   606  		Owner:   s.owner.Tag(),
   607  		UpdateSecretParams: state.UpdateSecretParams{
   608  			LeaderToken: &fakeToken{},
   609  			ValueRef:    &secrets.ValueRef{BackendID: "backend-id"},
   610  		},
   611  	}
   612  	_, err = s.store.CreateSecret(uri2, p2)
   613  	c.Assert(err, jc.ErrorIsNil)
   614  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
   615  	c.Assert(err, jc.ErrorIsNil)
   616  	c.Assert(backendRefCount, gc.Equals, 1)
   617  
   618  	caasSt := s.newCAASState(c)
   619  	caasSecrets := state.NewSecrets(caasSt)
   620  	uri3 := secrets.NewURI()
   621  	p3 := state.CreateSecretParams{
   622  		Version: 1,
   623  		Owner:   names.NewApplicationTag("wordpress"),
   624  		UpdateSecretParams: state.UpdateSecretParams{
   625  			LeaderToken: &fakeToken{},
   626  			ValueRef:    &secrets.ValueRef{BackendID: caasSt.ModelUUID()},
   627  		},
   628  	}
   629  	_, err = caasSecrets.CreateSecret(uri3, p3)
   630  	c.Assert(err, jc.ErrorIsNil)
   631  
   632  	result, err := s.store.ListModelSecrets(true)
   633  	c.Assert(err, jc.ErrorIsNil)
   634  	c.Assert(result, jc.DeepEquals, map[string]set.Strings{
   635  		s.State.ControllerUUID(): set.NewStrings(uri.ID),
   636  		"backend-id":             set.NewStrings(uri2.ID),
   637  		caasSt.ModelUUID():       set.NewStrings(uri3.ID),
   638  	})
   639  
   640  	result, err = s.store.ListModelSecrets(false)
   641  	c.Assert(err, jc.ErrorIsNil)
   642  	c.Assert(result, jc.DeepEquals, map[string]set.Strings{
   643  		s.State.ControllerUUID(): set.NewStrings(uri.ID),
   644  		"backend-id":             set.NewStrings(uri2.ID),
   645  	})
   646  }
   647  
   648  func (s *SecretsSuite) newCAASState(c *gc.C) *state.State {
   649  	cfg := jujutesting.CustomModelConfig(c, jujutesting.Attrs{
   650  		"name": "caasmodel",
   651  		"uuid": utils.MustNewUUID().String(),
   652  	})
   653  	_, st, err := s.Controller.NewModel(state.ModelArgs{
   654  		Type:        state.ModelTypeCAAS,
   655  		CloudName:   "dummy",
   656  		CloudRegion: "dummy-region",
   657  		Config:      cfg,
   658  		Owner:       s.Owner,
   659  		StorageProviderRegistry: storage.ChainedProviderRegistry{
   660  			dummy.StorageProviders(),
   661  			provider.CommonStorageProviders(),
   662  		},
   663  	})
   664  	c.Assert(err, jc.ErrorIsNil)
   665  	s.AddCleanup(func(*gc.C) { st.Close() })
   666  	s.Factory = factory.NewFactory(st, s.StatePool)
   667  	s.Factory.MakeApplication(c, &factory.ApplicationParams{
   668  		Name:  "wordpress",
   669  		Charm: s.Factory.MakeCharm(c, &factory.CharmParams{Name: "wordpress"}),
   670  	})
   671  	return st
   672  }
   673  
   674  func (s *SecretsSuite) TestUpdateNothing(c *gc.C) {
   675  	up := state.UpdateSecretParams{}
   676  	uri := secrets.NewURI()
   677  	_, err := s.store.UpdateSecret(uri, up)
   678  	c.Assert(err, gc.ErrorMatches, "must specify a new value or metadata to update a secret")
   679  }
   680  
   681  func (s *SecretsSuite) TestUpdateAll(c *gc.C) {
   682  	uri := secrets.NewURI()
   683  	now := s.Clock.Now().Round(time.Second).UTC()
   684  	next := now.Add(time.Minute).Round(time.Second).UTC()
   685  	cp := state.CreateSecretParams{
   686  		Version: 1,
   687  		Owner:   s.owner.Tag(),
   688  		UpdateSecretParams: state.UpdateSecretParams{
   689  			LeaderToken:    &fakeToken{},
   690  			RotatePolicy:   ptr(secrets.RotateDaily),
   691  			NextRotateTime: ptr(next),
   692  			Description:    ptr("my secret"),
   693  			Label:          ptr("foobar"),
   694  			Data:           map[string]string{"foo": "bar"},
   695  		},
   696  	}
   697  	md, err := s.store.CreateSecret(uri, cp)
   698  	c.Assert(err, jc.ErrorIsNil)
   699  	newData := map[string]string{"foo": "bar", "hello": "world"}
   700  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
   701  		LeaderToken:    &fakeToken{},
   702  		Description:    ptr("big secret"),
   703  		Label:          ptr("new label"),
   704  		RotatePolicy:   ptr(secrets.RotateHourly),
   705  		NextRotateTime: ptr(next),
   706  		Data:           newData,
   707  	})
   708  }
   709  
   710  func (s *SecretsSuite) TestUpdateRotateInterval(c *gc.C) {
   711  	uri := secrets.NewURI()
   712  	now := s.Clock.Now().Round(time.Second).UTC()
   713  	next := now.Add(time.Minute).Round(time.Second).UTC()
   714  	cp := state.CreateSecretParams{
   715  		Version: 1,
   716  		Owner:   s.owner.Tag(),
   717  		UpdateSecretParams: state.UpdateSecretParams{
   718  			LeaderToken:    &fakeToken{},
   719  			RotatePolicy:   ptr(secrets.RotateDaily),
   720  			NextRotateTime: ptr(next),
   721  			Data:           map[string]string{"foo": "bar"},
   722  		},
   723  	}
   724  	md, err := s.store.CreateSecret(uri, cp)
   725  	c.Assert(err, jc.ErrorIsNil)
   726  	s.assertUpdatedSecret(c, md, 1, state.UpdateSecretParams{
   727  		LeaderToken:    &fakeToken{},
   728  		RotatePolicy:   ptr(secrets.RotateHourly),
   729  		NextRotateTime: ptr(next),
   730  	})
   731  }
   732  
   733  func (s *SecretsSuite) TestUpdateExpiry(c *gc.C) {
   734  	uri := secrets.NewURI()
   735  	now := s.Clock.Now().Round(time.Second).UTC()
   736  	next := now.Add(time.Minute).Round(time.Second).UTC()
   737  	cp := state.CreateSecretParams{
   738  		Version: 1,
   739  		Owner:   s.owner.Tag(),
   740  		UpdateSecretParams: state.UpdateSecretParams{
   741  			LeaderToken:    &fakeToken{},
   742  			RotatePolicy:   ptr(secrets.RotateDaily),
   743  			NextRotateTime: ptr(next),
   744  			Data:           map[string]string{"foo": "bar"},
   745  		},
   746  	}
   747  	md, err := s.store.CreateSecret(uri, cp)
   748  	c.Assert(err, jc.ErrorIsNil)
   749  	s.assertUpdatedSecret(c, md, 1, state.UpdateSecretParams{
   750  		LeaderToken: &fakeToken{},
   751  		ExpireTime:  ptr(next),
   752  	})
   753  
   754  	s.assertUpdatedSecret(c, md, 1, state.UpdateSecretParams{
   755  		LeaderToken: &fakeToken{},
   756  		ExpireTime:  ptr(time.Time{}),
   757  	})
   758  }
   759  
   760  func (s *SecretsSuite) TestUpdateDuplicateLabel(c *gc.C) {
   761  	uri := secrets.NewURI()
   762  	cp := state.CreateSecretParams{
   763  		Version: 1,
   764  		Owner:   s.owner.Tag(),
   765  		UpdateSecretParams: state.UpdateSecretParams{
   766  			LeaderToken: &fakeToken{},
   767  			Label:       ptr("label"),
   768  			Description: ptr("description"),
   769  			Data:        map[string]string{"foo": "bar"},
   770  		},
   771  	}
   772  	_, err := s.store.CreateSecret(uri, cp)
   773  	c.Assert(err, jc.ErrorIsNil)
   774  	uri2 := secrets.NewURI()
   775  	cp.Label = ptr("label2")
   776  	_, err = s.store.CreateSecret(uri2, cp)
   777  	c.Assert(err, jc.ErrorIsNil)
   778  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
   779  		LeaderToken: &fakeToken{},
   780  		Label:       ptr("label2"),
   781  	})
   782  	c.Assert(errors.Is(err, state.LabelExists), jc.IsTrue)
   783  
   784  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
   785  		LeaderToken: &fakeToken{},
   786  		Label:       ptr("label"),
   787  	})
   788  	c.Assert(err, jc.ErrorIsNil)
   789  }
   790  
   791  func (s *SecretsSuite) TestUpdateData(c *gc.C) {
   792  	uri := secrets.NewURI()
   793  	now := s.Clock.Now().Round(time.Second).UTC()
   794  	next := now.Add(time.Minute).Round(time.Second).UTC()
   795  	cp := state.CreateSecretParams{
   796  		Version: 1,
   797  		Owner:   s.owner.Tag(),
   798  		UpdateSecretParams: state.UpdateSecretParams{
   799  			LeaderToken:    &fakeToken{},
   800  			RotatePolicy:   ptr(secrets.RotateDaily),
   801  			NextRotateTime: ptr(next),
   802  			Data:           map[string]string{"foo": "bar"},
   803  		},
   804  	}
   805  	md, err := s.store.CreateSecret(uri, cp)
   806  	c.Assert(err, jc.ErrorIsNil)
   807  	newData := map[string]string{"foo": "bar", "hello": "world"}
   808  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
   809  		LeaderToken: &fakeToken{},
   810  		Data:        newData,
   811  	})
   812  }
   813  
   814  func (s *SecretsSuite) TestUpdateAutoPrune(c *gc.C) {
   815  	uri := secrets.NewURI()
   816  	now := s.Clock.Now().Round(time.Second).UTC()
   817  	next := now.Add(time.Minute).Round(time.Second).UTC()
   818  	cp := state.CreateSecretParams{
   819  		Version: 1,
   820  		Owner:   s.owner.Tag(),
   821  		UpdateSecretParams: state.UpdateSecretParams{
   822  			LeaderToken:    &fakeToken{},
   823  			RotatePolicy:   ptr(secrets.RotateDaily),
   824  			NextRotateTime: ptr(next),
   825  			Data:           map[string]string{"foo": "bar"},
   826  		},
   827  	}
   828  	md, err := s.store.CreateSecret(uri, cp)
   829  	c.Assert(err, jc.ErrorIsNil)
   830  	c.Assert(md.AutoPrune, jc.IsFalse)
   831  	c.Assert(md.LatestRevision, gc.Equals, 1)
   832  	s.assertUpdatedSecret(
   833  		c, md,
   834  		1, // Update AutoPrune should not increment the revision.
   835  		state.UpdateSecretParams{
   836  			LeaderToken: &fakeToken{},
   837  			AutoPrune:   ptr(true),
   838  		},
   839  	)
   840  }
   841  
   842  func (s *SecretsSuite) TestUpdateDataSetsLatestConsumerRevision(c *gc.C) {
   843  	uri := secrets.NewURI()
   844  	now := s.Clock.Now().Round(time.Second).UTC()
   845  	next := now.Add(time.Minute).Round(time.Second).UTC()
   846  	cp := state.CreateSecretParams{
   847  		Version: 1,
   848  		Owner:   s.owner.Tag(),
   849  		UpdateSecretParams: state.UpdateSecretParams{
   850  			LeaderToken:    &fakeToken{},
   851  			RotatePolicy:   ptr(secrets.RotateDaily),
   852  			NextRotateTime: ptr(next),
   853  			Data:           map[string]string{"foo": "bar"},
   854  		},
   855  	}
   856  	md, err := s.store.CreateSecret(uri, cp)
   857  	c.Assert(err, jc.ErrorIsNil)
   858  	cmd := &secrets.SecretConsumerMetadata{
   859  		Label:           "foobar",
   860  		CurrentRevision: 1,
   861  	}
   862  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
   863  	c.Assert(err, jc.ErrorIsNil)
   864  	newData := map[string]string{"foo": "bar", "hello": "world"}
   865  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
   866  		LeaderToken: &fakeToken{},
   867  		Data:        newData,
   868  	})
   869  	cmd, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
   870  	c.Assert(err, jc.ErrorIsNil)
   871  	c.Assert(cmd, jc.DeepEquals, &secrets.SecretConsumerMetadata{
   872  		Label:           "foobar",
   873  		CurrentRevision: 1,
   874  		LatestRevision:  2,
   875  	})
   876  }
   877  
   878  func (s *SecretsSuite) TestUpdateOwnerLabel(c *gc.C) {
   879  	uri := secrets.NewURI()
   880  	now := s.Clock.Now().Round(time.Second).UTC()
   881  	next := now.Add(time.Minute).Round(time.Second).UTC()
   882  	cp := state.CreateSecretParams{
   883  		Version: 1,
   884  		Owner:   s.owner.Tag(),
   885  		UpdateSecretParams: state.UpdateSecretParams{
   886  			LeaderToken:    &fakeToken{},
   887  			RotatePolicy:   ptr(secrets.RotateDaily),
   888  			NextRotateTime: ptr(next),
   889  			Data:           map[string]string{"foo": "bar"},
   890  		},
   891  	}
   892  	md, err := s.store.CreateSecret(uri, cp)
   893  	c.Assert(err, jc.ErrorIsNil)
   894  	s.assertUpdatedSecret(c, md, 1, state.UpdateSecretParams{
   895  		LeaderToken: &fakeToken{},
   896  		Label:       ptr("foobar2"),
   897  	})
   898  	// Ensure it can be reset back to an older value.
   899  	s.assertUpdatedSecret(c, md, 1, state.UpdateSecretParams{
   900  		LeaderToken: &fakeToken{},
   901  		Label:       ptr("foobar"),
   902  	})
   903  }
   904  
   905  func (s *SecretsSuite) TestUpdateDataSetsLatestConsumerRevisionConcurrentAdd(c *gc.C) {
   906  	uri := secrets.NewURI()
   907  	now := s.Clock.Now().Round(time.Second).UTC()
   908  	cp := state.CreateSecretParams{
   909  		Version: 1,
   910  		Owner:   s.owner.Tag(),
   911  		UpdateSecretParams: state.UpdateSecretParams{
   912  			LeaderToken:    &fakeToken{},
   913  			RotatePolicy:   ptr(secrets.RotateDaily),
   914  			NextRotateTime: ptr(now.Add(time.Minute)),
   915  			Data:           map[string]string{"foo": "bar"},
   916  		},
   917  	}
   918  	md, err := s.store.CreateSecret(uri, cp)
   919  	c.Assert(err, jc.ErrorIsNil)
   920  	cmd := &secrets.SecretConsumerMetadata{
   921  		Label:           "foobar",
   922  		CurrentRevision: 1,
   923  	}
   924  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
   925  	c.Assert(err, jc.ErrorIsNil)
   926  
   927  	state.SetBeforeHooks(c, s.State, func() {
   928  		err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
   929  		c.Assert(err, jc.ErrorIsNil)
   930  	})
   931  
   932  	newData := map[string]string{"foo": "bar", "hello": "world"}
   933  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
   934  		LeaderToken: &fakeToken{},
   935  		Data:        newData,
   936  	})
   937  	cmd, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
   938  	c.Assert(err, jc.ErrorIsNil)
   939  	c.Assert(cmd.LatestRevision, gc.Equals, 2)
   940  	cmd, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
   941  	c.Assert(err, jc.ErrorIsNil)
   942  	c.Assert(cmd.LatestRevision, gc.Equals, 2)
   943  }
   944  
   945  func (s *SecretsSuite) TestUpdateDataSetsLatestConsumerRevisionConcurrentRemove(c *gc.C) {
   946  	uri := secrets.NewURI()
   947  	now := s.Clock.Now().Round(time.Second).UTC()
   948  	next := now.Add(time.Minute).Round(time.Second).UTC()
   949  	cp := state.CreateSecretParams{
   950  		Version: 1,
   951  		Owner:   s.owner.Tag(),
   952  		UpdateSecretParams: state.UpdateSecretParams{
   953  			LeaderToken:    &fakeToken{},
   954  			RotatePolicy:   ptr(secrets.RotateDaily),
   955  			NextRotateTime: ptr(next),
   956  			Data:           map[string]string{"foo": "bar"},
   957  		},
   958  	}
   959  	md, err := s.store.CreateSecret(uri, cp)
   960  	c.Assert(err, jc.ErrorIsNil)
   961  	cmd := &secrets.SecretConsumerMetadata{
   962  		Label:           "foobar",
   963  		CurrentRevision: 1,
   964  	}
   965  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
   966  	c.Assert(err, jc.ErrorIsNil)
   967  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mysql/0"), cmd)
   968  	c.Assert(err, jc.ErrorIsNil)
   969  
   970  	state.SetBeforeHooks(c, s.State, func() {
   971  		consColl, closer := state.GetCollection(s.State, "secretConsumers")
   972  		defer closer()
   973  		err := consColl.Writeable().RemoveId(state.DocID(s.State, fmt.Sprintf("%s#unit-mysql-0", uri.ID)))
   974  		c.Assert(err, jc.ErrorIsNil)
   975  
   976  		err = state.IncSecretConsumerRefCount(s.State, uri, 1)
   977  		c.Assert(err, jc.ErrorIsNil)
   978  	})
   979  
   980  	newData := map[string]string{"foo": "bar", "hello": "world"}
   981  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
   982  		LeaderToken: &fakeToken{},
   983  		Data:        newData,
   984  	})
   985  	cmd, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
   986  	c.Assert(err, jc.ErrorIsNil)
   987  	c.Assert(cmd.LatestRevision, gc.Equals, 2)
   988  	_, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mysql/0"))
   989  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   990  }
   991  
   992  func (s *SecretsSuite) assertUpdatedSecret(c *gc.C, original *secrets.SecretMetadata, expectedRevision int, update state.UpdateSecretParams) {
   993  	expected := *original
   994  	expected.LatestRevision = expectedRevision
   995  	if update.RotatePolicy != nil {
   996  		expected.RotatePolicy = *update.RotatePolicy
   997  		expected.NextRotateTime = update.NextRotateTime
   998  	}
   999  	if update.Description != nil {
  1000  		expected.Description = *update.Description
  1001  	}
  1002  	if update.AutoPrune != nil {
  1003  		expected.AutoPrune = *update.AutoPrune
  1004  	}
  1005  	if update.Label != nil {
  1006  		expected.Label = *update.Label
  1007  	}
  1008  	if update.ExpireTime != nil && !update.ExpireTime.IsZero() {
  1009  		expected.LatestExpireTime = update.ExpireTime
  1010  	}
  1011  
  1012  	s.Clock.Advance(time.Hour)
  1013  	updated := s.Clock.Now().Round(time.Second).UTC()
  1014  	expected.UpdateTime = updated
  1015  	md, err := s.store.UpdateSecret(original.URI, update)
  1016  	c.Assert(err, jc.ErrorIsNil)
  1017  
  1018  	list, err := s.store.ListSecrets(state.SecretsFilter{})
  1019  	c.Assert(err, jc.ErrorIsNil)
  1020  	mc := jc.NewMultiChecker()
  1021  	mc.AddExpr(`(*_[_]).CreateTime`, jc.Almost, jc.ExpectedValue)
  1022  	mc.AddExpr(`(*_[_]).UpdateTime`, jc.Almost, jc.ExpectedValue)
  1023  	c.Assert(list, mc, []*secrets.SecretMetadata{&expected})
  1024  	expectedData := map[string]string{"foo": "bar"}
  1025  	if update.Data != nil {
  1026  		expectedData = update.Data
  1027  	}
  1028  	val, valueRef, err := s.store.GetSecretValue(md.URI, expectedRevision)
  1029  	c.Assert(err, jc.ErrorIsNil)
  1030  	if update.ValueRef != nil {
  1031  		c.Assert(valueRef, gc.NotNil)
  1032  		c.Assert(*update.ValueRef, jc.DeepEquals, *valueRef)
  1033  	} else {
  1034  		c.Assert(valueRef, gc.IsNil)
  1035  		c.Assert(val.EncodedValues(), jc.DeepEquals, expectedData)
  1036  	}
  1037  	if update.ExpireTime != nil {
  1038  		revs, err := s.store.ListSecretRevisions(md.URI)
  1039  		c.Assert(err, jc.ErrorIsNil)
  1040  		for _, r := range revs {
  1041  			if r.ExpireTime == nil && update.ExpireTime.IsZero() {
  1042  				return
  1043  			}
  1044  			if r.ExpireTime != nil && r.ExpireTime.Equal(update.ExpireTime.Round(time.Second).UTC()) {
  1045  				return
  1046  			}
  1047  		}
  1048  		c.Fatalf("expire time not set for secret revision %d", expectedRevision)
  1049  		md, err := s.store.GetSecret(original.URI)
  1050  		c.Assert(err, jc.ErrorIsNil)
  1051  		if update.ExpireTime.IsZero() {
  1052  			c.Assert(md.LatestExpireTime, gc.IsNil)
  1053  		} else {
  1054  			c.Assert(md.LatestExpireTime, gc.Equals, update.ExpireTime.Round(time.Second).UTC())
  1055  		}
  1056  	}
  1057  	if update.NextRotateTime != nil {
  1058  		nextTime := state.GetSecretNextRotateTime(c, s.State, md.URI.ID)
  1059  		c.Assert(nextTime, gc.Equals, *update.NextRotateTime)
  1060  	}
  1061  }
  1062  
  1063  func (s *SecretsSuite) TestUpdateConcurrent(c *gc.C) {
  1064  	uri := secrets.NewURI()
  1065  
  1066  	now := s.Clock.Now().Round(time.Second).UTC()
  1067  	next := now.Add(time.Minute).Round(time.Second).UTC()
  1068  	cp := state.CreateSecretParams{
  1069  		Version: 1,
  1070  		Owner:   s.owner.Tag(),
  1071  		UpdateSecretParams: state.UpdateSecretParams{
  1072  			LeaderToken:    &fakeToken{},
  1073  			RotatePolicy:   ptr(secrets.RotateDaily),
  1074  			NextRotateTime: ptr(next),
  1075  			Data:           map[string]string{"foo": "bar"},
  1076  		},
  1077  	}
  1078  	md, err := s.store.CreateSecret(uri, cp)
  1079  
  1080  	state.SetBeforeHooks(c, s.State, func() {
  1081  		up := state.UpdateSecretParams{
  1082  			LeaderToken:    &fakeToken{},
  1083  			RotatePolicy:   ptr(secrets.RotateYearly),
  1084  			NextRotateTime: ptr(next),
  1085  			Params:         nil,
  1086  			Data:           map[string]string{"foo": "baz", "goodbye": "world"},
  1087  		}
  1088  		md, err = s.store.UpdateSecret(md.URI, up)
  1089  		c.Assert(err, jc.ErrorIsNil)
  1090  	})
  1091  	newData := map[string]string{"foo": "bar", "hello": "world"}
  1092  	s.assertUpdatedSecret(c, md, 3, state.UpdateSecretParams{
  1093  		LeaderToken:    &fakeToken{},
  1094  		RotatePolicy:   ptr(secrets.RotateHourly),
  1095  		NextRotateTime: ptr(next),
  1096  		Data:           newData,
  1097  	})
  1098  }
  1099  
  1100  func (s *SecretsSuite) TestChangeSecretBackendExternalToExternal(c *gc.C) {
  1101  	backendStore := state.NewSecretBackends(s.State)
  1102  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1103  		ID:          "old-backend-id",
  1104  		Name:        "foo",
  1105  		BackendType: "vault",
  1106  	})
  1107  	c.Assert(err, jc.ErrorIsNil)
  1108  	backendRefCount, err := s.State.ReadBackendRefCount("old-backend-id")
  1109  	c.Assert(err, jc.ErrorIsNil)
  1110  	c.Assert(backendRefCount, gc.Equals, 0)
  1111  
  1112  	_, err = backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1113  		ID:          "new-backend-id",
  1114  		Name:        "bar",
  1115  		BackendType: "vault",
  1116  	})
  1117  	c.Assert(err, jc.ErrorIsNil)
  1118  	backendRefCount, err = s.State.ReadBackendRefCount("new-backend-id")
  1119  	c.Assert(err, jc.ErrorIsNil)
  1120  	c.Assert(backendRefCount, gc.Equals, 0)
  1121  
  1122  	uri := secrets.NewURI()
  1123  	p := state.CreateSecretParams{
  1124  		Version: 1,
  1125  		Owner:   s.owner.Tag(),
  1126  		UpdateSecretParams: state.UpdateSecretParams{
  1127  			LeaderToken: &fakeToken{},
  1128  			ValueRef: &secrets.ValueRef{
  1129  				BackendID:  "old-backend-id",
  1130  				RevisionID: "rev-id",
  1131  			},
  1132  		},
  1133  	}
  1134  	_, err = s.store.CreateSecret(uri, p)
  1135  	c.Assert(err, jc.ErrorIsNil)
  1136  
  1137  	backendRefCount, err = s.State.ReadBackendRefCount("old-backend-id")
  1138  	c.Assert(err, jc.ErrorIsNil)
  1139  	c.Assert(backendRefCount, gc.Equals, 1)
  1140  
  1141  	val, valRef, err := s.store.GetSecretValue(uri, 1)
  1142  	c.Assert(err, jc.ErrorIsNil)
  1143  	c.Assert(val.IsEmpty(), jc.IsTrue)
  1144  	c.Assert(valRef, gc.DeepEquals, &secrets.ValueRef{
  1145  		BackendID:  "old-backend-id",
  1146  		RevisionID: "rev-id",
  1147  	})
  1148  
  1149  	err = s.store.ChangeSecretBackend(state.ChangeSecretBackendParams{
  1150  		URI:      uri,
  1151  		Token:    &fakeToken{},
  1152  		Revision: 1,
  1153  		ValueRef: &secrets.ValueRef{
  1154  			BackendID:  "new-backend-id",
  1155  			RevisionID: "rev-id",
  1156  		},
  1157  	})
  1158  	c.Assert(err, jc.ErrorIsNil)
  1159  
  1160  	backendRefCount, err = s.State.ReadBackendRefCount("old-backend-id")
  1161  	c.Assert(err, jc.ErrorIsNil)
  1162  	c.Assert(backendRefCount, gc.Equals, 0)
  1163  
  1164  	backendRefCount, err = s.State.ReadBackendRefCount("new-backend-id")
  1165  	c.Assert(err, jc.ErrorIsNil)
  1166  	c.Assert(backendRefCount, gc.Equals, 1)
  1167  
  1168  	val, valRef, err = s.store.GetSecretValue(uri, 1)
  1169  	c.Assert(err, jc.ErrorIsNil)
  1170  	c.Assert(val.IsEmpty(), jc.IsTrue)
  1171  	c.Assert(valRef, jc.DeepEquals, &secrets.ValueRef{
  1172  		BackendID:  "new-backend-id",
  1173  		RevisionID: "rev-id",
  1174  	})
  1175  }
  1176  
  1177  func (s *SecretsSuite) TestChangeSecretBackendInternalToExternal(c *gc.C) {
  1178  	backendStore := state.NewSecretBackends(s.State)
  1179  
  1180  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1181  		ID:          "new-backend-id",
  1182  		Name:        "bar",
  1183  		BackendType: "vault",
  1184  	})
  1185  	c.Assert(err, jc.ErrorIsNil)
  1186  
  1187  	uri := secrets.NewURI()
  1188  	p := state.CreateSecretParams{
  1189  		Version: 1,
  1190  		Owner:   s.owner.Tag(),
  1191  		UpdateSecretParams: state.UpdateSecretParams{
  1192  			LeaderToken: &fakeToken{},
  1193  			Data:        map[string]string{"foo": "bar"},
  1194  		},
  1195  	}
  1196  	_, err = s.store.CreateSecret(uri, p)
  1197  	c.Assert(err, jc.ErrorIsNil)
  1198  
  1199  	_, err = s.State.ReadBackendRefCount(s.Model.UUID())
  1200  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1201  	_, err = s.State.ReadBackendRefCount(s.State.ControllerUUID())
  1202  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1203  
  1204  	backendRefCount, err := s.State.ReadBackendRefCount("new-backend-id")
  1205  	c.Assert(err, jc.ErrorIsNil)
  1206  	c.Assert(backendRefCount, gc.Equals, 0)
  1207  
  1208  	val, valRef, err := s.store.GetSecretValue(uri, 1)
  1209  	c.Assert(err, jc.ErrorIsNil)
  1210  	c.Assert(val, jc.DeepEquals, secrets.NewSecretValue(map[string]string{"foo": "bar"}))
  1211  	c.Assert(valRef, gc.IsNil)
  1212  
  1213  	err = s.store.ChangeSecretBackend(state.ChangeSecretBackendParams{
  1214  		URI:      uri,
  1215  		Token:    &fakeToken{},
  1216  		Revision: 1,
  1217  		ValueRef: &secrets.ValueRef{
  1218  			BackendID:  "new-backend-id",
  1219  			RevisionID: "rev-id",
  1220  		},
  1221  	})
  1222  	c.Assert(err, jc.ErrorIsNil)
  1223  
  1224  	_, err = s.State.ReadBackendRefCount(s.Model.UUID())
  1225  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1226  	_, err = s.State.ReadBackendRefCount(s.State.ControllerUUID())
  1227  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1228  
  1229  	backendRefCount, err = s.State.ReadBackendRefCount("new-backend-id")
  1230  	c.Assert(err, jc.ErrorIsNil)
  1231  	c.Assert(backendRefCount, gc.Equals, 1)
  1232  
  1233  	val, valRef, err = s.store.GetSecretValue(uri, 1)
  1234  	c.Assert(err, jc.ErrorIsNil)
  1235  	c.Assert(val.IsEmpty(), jc.IsTrue)
  1236  	c.Assert(valRef, jc.DeepEquals, &secrets.ValueRef{
  1237  		BackendID:  "new-backend-id",
  1238  		RevisionID: "rev-id",
  1239  	})
  1240  }
  1241  
  1242  func (s *SecretsSuite) TestChangeSecretBackendExternalToInternal(c *gc.C) {
  1243  	backendStore := state.NewSecretBackends(s.State)
  1244  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1245  		ID:          "backend-id",
  1246  		Name:        "foo",
  1247  		BackendType: "vault",
  1248  	})
  1249  	c.Assert(err, jc.ErrorIsNil)
  1250  	backendRefCount, err := s.State.ReadBackendRefCount("backend-id")
  1251  	c.Assert(err, jc.ErrorIsNil)
  1252  	c.Assert(backendRefCount, gc.Equals, 0)
  1253  
  1254  	uri := secrets.NewURI()
  1255  	p := state.CreateSecretParams{
  1256  		Version: 1,
  1257  		Owner:   s.owner.Tag(),
  1258  		UpdateSecretParams: state.UpdateSecretParams{
  1259  			LeaderToken: &fakeToken{},
  1260  			ValueRef: &secrets.ValueRef{
  1261  				BackendID:  "backend-id",
  1262  				RevisionID: "rev-id",
  1263  			},
  1264  		},
  1265  	}
  1266  	_, err = s.store.CreateSecret(uri, p)
  1267  	c.Assert(err, jc.ErrorIsNil)
  1268  
  1269  	_, err = s.State.ReadBackendRefCount(s.Model.UUID())
  1270  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1271  	_, err = s.State.ReadBackendRefCount(s.State.ControllerUUID())
  1272  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1273  
  1274  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  1275  	c.Assert(err, jc.ErrorIsNil)
  1276  	c.Assert(backendRefCount, gc.Equals, 1)
  1277  
  1278  	val, valRef, err := s.store.GetSecretValue(uri, 1)
  1279  	c.Assert(err, jc.ErrorIsNil)
  1280  	c.Assert(val.IsEmpty(), jc.IsTrue)
  1281  	c.Assert(valRef, gc.DeepEquals, &secrets.ValueRef{
  1282  		BackendID:  "backend-id",
  1283  		RevisionID: "rev-id",
  1284  	})
  1285  
  1286  	err = s.store.ChangeSecretBackend(state.ChangeSecretBackendParams{
  1287  		URI:      uri,
  1288  		Token:    &fakeToken{},
  1289  		Data:     map[string]string{"foo": "bar"},
  1290  		Revision: 1,
  1291  	})
  1292  	c.Assert(err, jc.ErrorIsNil)
  1293  
  1294  	_, err = s.State.ReadBackendRefCount(s.Model.UUID())
  1295  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1296  	_, err = s.State.ReadBackendRefCount(s.State.ControllerUUID())
  1297  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1298  
  1299  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  1300  	c.Assert(err, jc.ErrorIsNil)
  1301  	c.Assert(backendRefCount, gc.Equals, 0)
  1302  
  1303  	val, valRef, err = s.store.GetSecretValue(uri, 1)
  1304  	c.Assert(err, jc.ErrorIsNil)
  1305  	c.Assert(val, jc.DeepEquals, secrets.NewSecretValue(map[string]string{"foo": "bar"}))
  1306  	c.Assert(valRef, gc.IsNil)
  1307  }
  1308  
  1309  func (s *SecretsSuite) TestSecretGrants(c *gc.C) {
  1310  	uri := secrets.NewURI()
  1311  
  1312  	now := s.Clock.Now().Round(time.Second).UTC()
  1313  	next := now.Add(time.Minute).Round(time.Second).UTC()
  1314  	cp := state.CreateSecretParams{
  1315  		Version: 1,
  1316  		Owner:   s.owner.Tag(),
  1317  		UpdateSecretParams: state.UpdateSecretParams{
  1318  			Label:          strPtr("label-1"),
  1319  			LeaderToken:    &fakeToken{},
  1320  			RotatePolicy:   ptr(secrets.RotateDaily),
  1321  			NextRotateTime: ptr(next),
  1322  			Data:           map[string]string{"foo": "bar"},
  1323  		},
  1324  	}
  1325  	md, err := s.store.CreateSecret(uri, cp)
  1326  	c.Check(err, jc.ErrorIsNil)
  1327  	c.Check(md.URI, jc.DeepEquals, uri)
  1328  
  1329  	subject := names.NewApplicationTag("wordpress")
  1330  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1331  		LeaderToken: &fakeToken{},
  1332  		Scope:       s.relation.Tag(),
  1333  		Subject:     subject,
  1334  		Role:        secrets.RoleView,
  1335  	})
  1336  	c.Assert(err, jc.ErrorIsNil)
  1337  
  1338  	access, err := s.store.SecretGrants(uri, secrets.RoleView)
  1339  	c.Assert(err, jc.ErrorIsNil)
  1340  	c.Assert(access, jc.DeepEquals, []secrets.AccessInfo{
  1341  		{
  1342  			Target: subject.String(),
  1343  			Scope:  "relation-wordpress.db#mysql.server",
  1344  			Role:   secrets.RoleView,
  1345  		},
  1346  	})
  1347  }
  1348  
  1349  func (s *SecretsSuite) TestGetSecret(c *gc.C) {
  1350  	uri := secrets.NewURI()
  1351  
  1352  	now := s.Clock.Now().Round(time.Second).UTC()
  1353  	next := now.Add(time.Minute).Round(time.Second).UTC()
  1354  	cp := state.CreateSecretParams{
  1355  		Version: 1,
  1356  		Owner:   s.owner.Tag(),
  1357  		UpdateSecretParams: state.UpdateSecretParams{
  1358  			Label:          strPtr("label-1"),
  1359  			LeaderToken:    &fakeToken{},
  1360  			RotatePolicy:   ptr(secrets.RotateDaily),
  1361  			NextRotateTime: ptr(next),
  1362  			Data:           map[string]string{"foo": "bar"},
  1363  		},
  1364  	}
  1365  	md, err := s.store.CreateSecret(uri, cp)
  1366  	c.Check(err, jc.ErrorIsNil)
  1367  	c.Check(md.URI, jc.DeepEquals, uri)
  1368  
  1369  	md, err = s.store.GetSecret(uri)
  1370  	c.Check(err, jc.ErrorIsNil)
  1371  	c.Check(md.URI, jc.DeepEquals, uri)
  1372  }
  1373  
  1374  func (s *SecretsSuite) TestListSecretRevisions(c *gc.C) {
  1375  	uri := secrets.NewURI()
  1376  	now := s.Clock.Now().Round(time.Second).UTC()
  1377  	next := now.Add(time.Minute).Round(time.Second).UTC()
  1378  	cp := state.CreateSecretParams{
  1379  		Version: 1,
  1380  		Owner:   s.owner.Tag(),
  1381  		UpdateSecretParams: state.UpdateSecretParams{
  1382  			LeaderToken:    &fakeToken{},
  1383  			RotatePolicy:   ptr(secrets.RotateDaily),
  1384  			NextRotateTime: ptr(next),
  1385  			Data:           map[string]string{"foo": "bar"},
  1386  		},
  1387  	}
  1388  	md, err := s.store.CreateSecret(uri, cp)
  1389  	c.Assert(err, jc.ErrorIsNil)
  1390  	newData := map[string]string{"foo": "bar", "hello": "world"}
  1391  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
  1392  		LeaderToken: &fakeToken{},
  1393  		Data:        newData,
  1394  	})
  1395  
  1396  	backendStore := state.NewSecretBackends(s.State)
  1397  	backendID, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1398  		Name:        "myvault",
  1399  		BackendType: "vault",
  1400  	})
  1401  	c.Assert(err, jc.ErrorIsNil)
  1402  	updateTime := s.Clock.Now().Round(time.Second).UTC()
  1403  	s.assertUpdatedSecret(c, md, 3, state.UpdateSecretParams{
  1404  		LeaderToken: &fakeToken{},
  1405  		ValueRef: &secrets.ValueRef{
  1406  			BackendID:  backendID,
  1407  			RevisionID: "rev-id",
  1408  		},
  1409  	})
  1410  	updateTime2 := s.Clock.Now().Round(time.Second).UTC()
  1411  	r, err := s.store.ListSecretRevisions(uri)
  1412  	c.Assert(err, jc.ErrorIsNil)
  1413  
  1414  	mc := jc.NewMultiChecker()
  1415  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
  1416  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
  1417  	c.Assert(r, mc, []*secrets.SecretRevisionMetadata{{
  1418  		Revision:   1,
  1419  		CreateTime: now,
  1420  		UpdateTime: now,
  1421  	}, {
  1422  		Revision:   2,
  1423  		CreateTime: updateTime,
  1424  		UpdateTime: updateTime,
  1425  	}, {
  1426  		Revision: 3,
  1427  		ValueRef: &secrets.ValueRef{
  1428  			BackendID:  backendID,
  1429  			RevisionID: "rev-id",
  1430  		},
  1431  		BackendName: ptr("myvault"),
  1432  		CreateTime:  updateTime2,
  1433  		UpdateTime:  updateTime2,
  1434  	}})
  1435  }
  1436  
  1437  func (s *SecretsSuite) TestListUnusedSecretRevisions(c *gc.C) {
  1438  	uri := secrets.NewURI()
  1439  	now := s.Clock.Now().Round(time.Second).UTC()
  1440  	next := now.Add(time.Minute).Round(time.Second).UTC()
  1441  	cp := state.CreateSecretParams{
  1442  		Version: 1,
  1443  		Owner:   s.owner.Tag(),
  1444  		UpdateSecretParams: state.UpdateSecretParams{
  1445  			LeaderToken:    &fakeToken{},
  1446  			RotatePolicy:   ptr(secrets.RotateDaily),
  1447  			NextRotateTime: ptr(next),
  1448  			Data:           map[string]string{"foo": "bar"},
  1449  		},
  1450  	}
  1451  	md, err := s.store.CreateSecret(uri, cp)
  1452  	c.Assert(err, jc.ErrorIsNil)
  1453  	newData := map[string]string{"foo": "bar", "hello": "world"}
  1454  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
  1455  		LeaderToken: &fakeToken{},
  1456  		Data:        newData,
  1457  	})
  1458  
  1459  	backendStore := state.NewSecretBackends(s.State)
  1460  	backendID, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1461  		Name:        "myvault",
  1462  		BackendType: "vault",
  1463  	})
  1464  	c.Assert(err, jc.ErrorIsNil)
  1465  	s.assertUpdatedSecret(c, md, 3, state.UpdateSecretParams{
  1466  		LeaderToken: &fakeToken{},
  1467  		ValueRef: &secrets.ValueRef{
  1468  			BackendID:  backendID,
  1469  			RevisionID: "rev-id",
  1470  		},
  1471  	})
  1472  	r, err := s.store.ListUnusedSecretRevisions(uri)
  1473  	c.Assert(err, jc.ErrorIsNil)
  1474  
  1475  	mc := jc.NewMultiChecker()
  1476  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
  1477  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
  1478  	c.Assert(r, mc, []int{
  1479  		1, 2,
  1480  		// The latest revision `3` is still in use, so it's not returned.
  1481  	})
  1482  }
  1483  
  1484  func (s *SecretsSuite) TestGetSecretRevision(c *gc.C) {
  1485  	uri := secrets.NewURI()
  1486  	cp := state.CreateSecretParams{
  1487  		Version: 1,
  1488  		Owner:   s.owner.Tag(),
  1489  		UpdateSecretParams: state.UpdateSecretParams{
  1490  			LeaderToken: &fakeToken{},
  1491  			Data:        map[string]string{"foo": "bar"},
  1492  		},
  1493  	}
  1494  	md, err := s.store.CreateSecret(uri, cp)
  1495  	c.Assert(err, jc.ErrorIsNil)
  1496  	newData := map[string]string{"foo": "bar", "hello": "world"}
  1497  	s.assertUpdatedSecret(c, md, 2, state.UpdateSecretParams{
  1498  		LeaderToken: &fakeToken{},
  1499  		Data:        newData,
  1500  	})
  1501  	r, err := s.store.GetSecretRevision(uri, 2)
  1502  	c.Assert(err, jc.ErrorIsNil)
  1503  	updateTime := s.Clock.Now().Round(time.Second).UTC()
  1504  	mc := jc.NewMultiChecker()
  1505  	mc.AddExpr(`_.CreateTime`, jc.Almost, jc.ExpectedValue)
  1506  	mc.AddExpr(`_.UpdateTime`, jc.Almost, jc.ExpectedValue)
  1507  	c.Assert(r, mc, &secrets.SecretRevisionMetadata{
  1508  		Revision:   2,
  1509  		CreateTime: updateTime,
  1510  		UpdateTime: updateTime,
  1511  	})
  1512  }
  1513  
  1514  func (s *SecretsSuite) TestGetSecretConsumerAndGetSecretConsumerURI(c *gc.C) {
  1515  	cp := state.CreateSecretParams{
  1516  		Version: 1,
  1517  		Owner:   s.owner.Tag(),
  1518  		UpdateSecretParams: state.UpdateSecretParams{
  1519  			LeaderToken: &fakeToken{},
  1520  			Data:        map[string]string{"foo": "bar"},
  1521  			Label:       strPtr("owner-label"),
  1522  		},
  1523  	}
  1524  	uri := secrets.NewURI()
  1525  	_, err := s.store.CreateSecret(uri, cp)
  1526  	c.Assert(err, jc.ErrorIsNil)
  1527  
  1528  	_, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1529  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1530  	md := &secrets.SecretConsumerMetadata{
  1531  		Label:           "consumer-label",
  1532  		CurrentRevision: 666,
  1533  	}
  1534  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), md)
  1535  	c.Assert(err, jc.ErrorIsNil)
  1536  
  1537  	_, err = s.State.GetSecretConsumer(nil, names.NewUnitTag("mariadb/0"))
  1538  	c.Check(err, gc.ErrorMatches, `empty URI`)
  1539  
  1540  	md2, err := s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1541  	c.Check(err, jc.ErrorIsNil)
  1542  	c.Check(md2, jc.DeepEquals, md)
  1543  
  1544  	uri3, err := s.State.GetURIByConsumerLabel("consumer-label", names.NewUnitTag("mariadb/0"))
  1545  	c.Check(err, jc.ErrorIsNil)
  1546  	c.Check(uri3, jc.DeepEquals, uri)
  1547  
  1548  	_, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mysql/0"))
  1549  	c.Check(err, jc.Satisfies, errors.IsNotFound)
  1550  }
  1551  
  1552  func (s *SecretsSuite) TestGetSecretConsumerCrossModelURI(c *gc.C) {
  1553  	cp := state.CreateSecretParams{
  1554  		Version: 1,
  1555  		Owner:   s.owner.Tag(),
  1556  		UpdateSecretParams: state.UpdateSecretParams{
  1557  			LeaderToken: &fakeToken{},
  1558  			Data:        map[string]string{"foo": "bar"},
  1559  			Label:       strPtr("owner-label"),
  1560  		},
  1561  	}
  1562  	uri := secrets.NewURI().WithSource("deadbeef-1bad-500d-9000-4b1d0d06f00d")
  1563  	_, err := s.store.CreateSecret(uri, cp)
  1564  	c.Assert(err, jc.ErrorIsNil)
  1565  
  1566  	_, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1567  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1568  	md := &secrets.SecretConsumerMetadata{
  1569  		Label:           "consumer-label",
  1570  		CurrentRevision: 666,
  1571  	}
  1572  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), md)
  1573  	c.Assert(err, jc.ErrorIsNil)
  1574  
  1575  	_, err = s.State.GetSecretConsumer(nil, names.NewUnitTag("mariadb/0"))
  1576  	c.Check(err, gc.ErrorMatches, `empty URI`)
  1577  
  1578  	md2, err := s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1579  	c.Check(err, jc.ErrorIsNil)
  1580  	c.Check(md2, jc.DeepEquals, md)
  1581  
  1582  	uri3, err := s.State.GetURIByConsumerLabel("consumer-label", names.NewUnitTag("mariadb/0"))
  1583  	c.Check(err, jc.ErrorIsNil)
  1584  	c.Check(uri3, jc.DeepEquals, uri)
  1585  }
  1586  
  1587  func (s *SecretsSuite) TestSaveSecretConsumer(c *gc.C) {
  1588  	cp := state.CreateSecretParams{
  1589  		Version: 1,
  1590  		Owner:   s.owner.Tag(),
  1591  		UpdateSecretParams: state.UpdateSecretParams{
  1592  			LeaderToken: &fakeToken{},
  1593  			Data:        map[string]string{"foo": "bar"},
  1594  		},
  1595  	}
  1596  	uri := secrets.NewURI()
  1597  	md, err := s.store.CreateSecret(uri, cp)
  1598  	c.Assert(err, jc.ErrorIsNil)
  1599  	c.Assert(md.LatestRevision, gc.Equals, 1)
  1600  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 1), jc.IsFalse)
  1601  
  1602  	cmd := &secrets.SecretConsumerMetadata{
  1603  		Label:           "foobar",
  1604  		CurrentRevision: md.LatestRevision,
  1605  		LatestRevision:  md.LatestRevision,
  1606  	}
  1607  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
  1608  	c.Assert(err, jc.ErrorIsNil)
  1609  	md2, err := s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1610  	c.Assert(err, jc.ErrorIsNil)
  1611  	c.Assert(md2, jc.DeepEquals, cmd)
  1612  	c.Assert(md2.LatestRevision, gc.Equals, 1)
  1613  	c.Assert(md2.CurrentRevision, gc.Equals, 1)
  1614  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 1), jc.IsFalse)
  1615  
  1616  	// secret revison ++, but not obsolete.
  1617  	md, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
  1618  		LeaderToken: &fakeToken{},
  1619  		Data:        map[string]string{"foo": "bar", "baz": "qux"},
  1620  	})
  1621  	c.Assert(err, jc.ErrorIsNil)
  1622  	c.Assert(md.LatestRevision, gc.Equals, 2)
  1623  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 1), jc.IsFalse)
  1624  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 2), jc.IsFalse)
  1625  
  1626  	// consumer latest revison ++, but not obsolete.
  1627  	cmd.LatestRevision = md.LatestRevision
  1628  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
  1629  	c.Assert(err, jc.ErrorIsNil)
  1630  	md2, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1631  	c.Assert(err, jc.ErrorIsNil)
  1632  	c.Assert(md2, jc.DeepEquals, cmd)
  1633  	c.Assert(md2.LatestRevision, gc.Equals, 2)
  1634  	c.Assert(md2.CurrentRevision, gc.Equals, 1)
  1635  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 1), jc.IsFalse)
  1636  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 2), jc.IsFalse)
  1637  
  1638  	// consumer current revison ++, then obsolete.
  1639  	cmd.CurrentRevision = md.LatestRevision
  1640  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
  1641  	c.Assert(err, jc.ErrorIsNil)
  1642  	md2, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1643  	c.Assert(err, jc.ErrorIsNil)
  1644  	c.Assert(md2, jc.DeepEquals, cmd)
  1645  	c.Assert(md2.LatestRevision, gc.Equals, 2)
  1646  	c.Assert(md2.CurrentRevision, gc.Equals, 2)
  1647  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 1), jc.IsTrue)
  1648  	c.Assert(s.State.IsSecretRevisionObsolete(c, uri, 2), jc.IsFalse)
  1649  }
  1650  
  1651  func (s *SecretsSuite) TestSaveSecretConsumerConcurrent(c *gc.C) {
  1652  	cp := state.CreateSecretParams{
  1653  		Version: 1,
  1654  		Owner:   s.owner.Tag(),
  1655  		UpdateSecretParams: state.UpdateSecretParams{
  1656  			LeaderToken: &fakeToken{},
  1657  			Data:        map[string]string{"foo": "bar"},
  1658  		},
  1659  	}
  1660  	uri := secrets.NewURI()
  1661  	_, err := s.store.CreateSecret(uri, cp)
  1662  	c.Assert(err, jc.ErrorIsNil)
  1663  	md := &secrets.SecretConsumerMetadata{
  1664  		Label:           "foobar",
  1665  		CurrentRevision: 666,
  1666  	}
  1667  	state.SetBeforeHooks(c, s.State, func() {
  1668  		err := s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), &secrets.SecretConsumerMetadata{CurrentRevision: 668})
  1669  		c.Assert(err, jc.ErrorIsNil)
  1670  	})
  1671  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), md)
  1672  	c.Assert(err, jc.ErrorIsNil)
  1673  	md2, err := s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1674  	c.Assert(err, jc.ErrorIsNil)
  1675  	c.Assert(md2, jc.DeepEquals, md)
  1676  }
  1677  
  1678  func (s *SecretsSuite) TestSaveSecretConsumerDifferentModel(c *gc.C) {
  1679  	uri := secrets.NewURI().WithSource("some-uuid")
  1680  	md := &secrets.SecretConsumerMetadata{
  1681  		Label:           "foobar",
  1682  		CurrentRevision: 666,
  1683  	}
  1684  	err := s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), md)
  1685  	c.Assert(err, jc.ErrorIsNil)
  1686  	md2, err := s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1687  	c.Assert(err, jc.ErrorIsNil)
  1688  	c.Assert(md2, jc.DeepEquals, md)
  1689  	md.CurrentRevision = 668
  1690  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), md)
  1691  	c.Assert(err, jc.ErrorIsNil)
  1692  	md2, err = s.State.GetSecretConsumer(uri, names.NewUnitTag("mariadb/0"))
  1693  	c.Assert(err, jc.ErrorIsNil)
  1694  	c.Assert(md2, jc.DeepEquals, md)
  1695  }
  1696  
  1697  func (s *SecretsSuite) TestSecretGrantAccess(c *gc.C) {
  1698  	uri := secrets.NewURI()
  1699  	subject := names.NewApplicationTag("wordpress")
  1700  	err := s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1701  		LeaderToken: &fakeToken{},
  1702  		Scope:       s.relation.Tag(),
  1703  		Subject:     subject,
  1704  		Role:        secrets.RoleView,
  1705  	})
  1706  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1707  
  1708  	cp := state.CreateSecretParams{
  1709  		Version: 1,
  1710  		Owner:   s.owner.Tag(),
  1711  		UpdateSecretParams: state.UpdateSecretParams{
  1712  			LeaderToken: &fakeToken{},
  1713  			Data:        map[string]string{"foo": "bar"},
  1714  		},
  1715  	}
  1716  	_, err = s.store.CreateSecret(uri, cp)
  1717  	c.Assert(err, jc.ErrorIsNil)
  1718  
  1719  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1720  		LeaderToken: &fakeToken{},
  1721  		Scope:       s.relation.Tag(),
  1722  		Subject:     subject,
  1723  		Role:        secrets.RoleView,
  1724  	})
  1725  	c.Assert(err, jc.ErrorIsNil)
  1726  	access, err := s.State.SecretAccess(uri, subject)
  1727  	c.Assert(err, jc.ErrorIsNil)
  1728  	c.Assert(access, gc.Equals, secrets.RoleView)
  1729  }
  1730  
  1731  func (s *SecretsSuite) TestSecretGrantCrossModelOffer(c *gc.C) {
  1732  	s.assertSecretGrantCrossModelOffer(c, true, false)
  1733  }
  1734  
  1735  func (s *SecretsSuite) TestSecretGrantCrossModelConsumer(c *gc.C) {
  1736  	s.assertSecretGrantCrossModelOffer(c, false, false)
  1737  }
  1738  
  1739  func (s *SecretsSuite) TestSecretGrantCrossModelConsumerUnit(c *gc.C) {
  1740  	s.assertSecretGrantCrossModelOffer(c, false, true)
  1741  }
  1742  
  1743  func (s *SecretsSuite) TestSecretGrantCrossModelUnit(c *gc.C) {
  1744  	s.assertSecretGrantCrossModelOffer(c, true, true)
  1745  }
  1746  
  1747  func (s *SecretsSuite) assertSecretGrantCrossModelOffer(c *gc.C, offer, unit bool) {
  1748  	rwordpress, err := s.State.AddRemoteApplication(state.AddRemoteApplicationParams{
  1749  		Name:            "remote-wordpress",
  1750  		SourceModel:     names.NewModelTag("source-model"),
  1751  		IsConsumerProxy: offer,
  1752  		OfferUUID:       "offer-uuid",
  1753  		Endpoints: []charm.Relation{{
  1754  			Interface: "mysql",
  1755  			Limit:     1,
  1756  			Name:      "db",
  1757  			Role:      charm.RoleRequirer,
  1758  			Scope:     charm.ScopeGlobal,
  1759  		}},
  1760  	})
  1761  	c.Assert(err, jc.ErrorIsNil)
  1762  	wordpressEP, err := rwordpress.Endpoint("db")
  1763  	c.Assert(err, jc.ErrorIsNil)
  1764  	mysqlEP, err := s.owner.Endpoint("server")
  1765  	c.Assert(err, jc.ErrorIsNil)
  1766  	relation, err := s.State.AddRelation(wordpressEP, mysqlEP)
  1767  	c.Assert(err, jc.ErrorIsNil)
  1768  
  1769  	uri := secrets.NewURI()
  1770  	cp := state.CreateSecretParams{
  1771  		Version: 1,
  1772  		Owner:   s.owner.Tag(),
  1773  		UpdateSecretParams: state.UpdateSecretParams{
  1774  			LeaderToken: &fakeToken{},
  1775  			Data:        map[string]string{"foo": "bar"},
  1776  		},
  1777  	}
  1778  	_, err = s.store.CreateSecret(uri, cp)
  1779  	c.Assert(err, jc.ErrorIsNil)
  1780  
  1781  	subject := rwordpress.Tag()
  1782  	if unit {
  1783  		subject = names.NewUnitTag(rwordpress.Name() + "/0")
  1784  	}
  1785  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1786  		LeaderToken: &fakeToken{},
  1787  		Scope:       relation.Tag(),
  1788  		Subject:     subject,
  1789  		Role:        secrets.RoleView,
  1790  	})
  1791  	if offer && !unit {
  1792  		c.Assert(err, jc.ErrorIsNil)
  1793  		access, err := s.State.SecretAccess(uri, rwordpress.Tag())
  1794  		c.Assert(err, jc.ErrorIsNil)
  1795  		c.Assert(access, gc.Equals, secrets.RoleView)
  1796  	} else {
  1797  		c.Assert(err, jc.Satisfies, errors.IsNotSupported)
  1798  	}
  1799  }
  1800  
  1801  func (s *SecretsSuite) TestSecretGrantAccessDyingScope(c *gc.C) {
  1802  	uri := secrets.NewURI()
  1803  	cp := state.CreateSecretParams{
  1804  		Version: 1,
  1805  		Owner:   s.owner.Tag(),
  1806  		UpdateSecretParams: state.UpdateSecretParams{
  1807  			LeaderToken: &fakeToken{},
  1808  			Data:        map[string]string{"foo": "bar"},
  1809  		},
  1810  	}
  1811  	_, err := s.store.CreateSecret(uri, cp)
  1812  	c.Assert(err, jc.ErrorIsNil)
  1813  
  1814  	// Ensure destroy only sets relation to dying.
  1815  	wordpress, err := s.State.Application("wordpress")
  1816  	c.Assert(err, jc.ErrorIsNil)
  1817  	unit, err := wordpress.AddUnit(state.AddUnitParams{})
  1818  	c.Assert(err, jc.ErrorIsNil)
  1819  	ru, err := s.relation.Unit(unit)
  1820  	c.Assert(err, jc.ErrorIsNil)
  1821  	err = ru.EnterScope(nil)
  1822  	c.Assert(err, jc.ErrorIsNil)
  1823  
  1824  	_, err = s.relation.DestroyWithForce(true, time.Second)
  1825  	c.Assert(err, jc.ErrorIsNil)
  1826  
  1827  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1828  		LeaderToken: &fakeToken{},
  1829  		Scope:       s.relation.Tag(),
  1830  		Subject:     wordpress.Tag(),
  1831  		Role:        secrets.RoleView,
  1832  	})
  1833  	c.Assert(err, gc.ErrorMatches, `cannot grant access to secret in scope of "relation-wordpress.db#mysql.server" which is not alive`)
  1834  }
  1835  
  1836  func (s *SecretsSuite) TestSecretGrantAccessDyingSubject(c *gc.C) {
  1837  	uri := secrets.NewURI()
  1838  	cp := state.CreateSecretParams{
  1839  		Version: 1,
  1840  		Owner:   s.owner.Tag(),
  1841  		UpdateSecretParams: state.UpdateSecretParams{
  1842  			LeaderToken: &fakeToken{},
  1843  			Data:        map[string]string{"foo": "bar"},
  1844  		},
  1845  	}
  1846  	_, err := s.store.CreateSecret(uri, cp)
  1847  	c.Assert(err, jc.ErrorIsNil)
  1848  
  1849  	// Ensure destroy only sets app to dying.
  1850  	wordpress, err := s.State.Application("wordpress")
  1851  	c.Assert(err, jc.ErrorIsNil)
  1852  	unit, err := wordpress.AddUnit(state.AddUnitParams{})
  1853  	c.Assert(err, jc.ErrorIsNil)
  1854  	ru, err := s.relation.Unit(unit)
  1855  	c.Assert(err, jc.ErrorIsNil)
  1856  	err = ru.EnterScope(nil)
  1857  	c.Assert(err, jc.ErrorIsNil)
  1858  
  1859  	err = wordpress.Destroy()
  1860  	c.Assert(err, jc.ErrorIsNil)
  1861  
  1862  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1863  		LeaderToken: &fakeToken{},
  1864  		Scope:       s.relation.Tag(),
  1865  		Subject:     wordpress.Tag(),
  1866  		Role:        secrets.RoleView,
  1867  	})
  1868  	c.Assert(err, gc.ErrorMatches, `cannot grant access to secret in scope of "relation-wordpress.db#mysql.server" which is not alive`)
  1869  }
  1870  
  1871  func (s *SecretsSuite) TestSecretRevokeAccess(c *gc.C) {
  1872  	uri := secrets.NewURI()
  1873  	cp := state.CreateSecretParams{
  1874  		Version: 1,
  1875  		Owner:   s.owner.Tag(),
  1876  		UpdateSecretParams: state.UpdateSecretParams{
  1877  			LeaderToken: &fakeToken{},
  1878  			Data:        map[string]string{"foo": "bar"},
  1879  		},
  1880  	}
  1881  	_, err := s.store.CreateSecret(uri, cp)
  1882  	c.Assert(err, jc.ErrorIsNil)
  1883  
  1884  	subject := names.NewApplicationTag("wordpress")
  1885  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1886  		LeaderToken: &fakeToken{},
  1887  		Scope:       s.relation.Tag(),
  1888  		Subject:     subject,
  1889  		Role:        secrets.RoleView,
  1890  	})
  1891  	c.Assert(err, jc.ErrorIsNil)
  1892  	access, err := s.State.SecretAccess(uri, subject)
  1893  	c.Assert(err, jc.ErrorIsNil)
  1894  	c.Assert(access, gc.Equals, secrets.RoleView)
  1895  
  1896  	err = s.State.RevokeSecretAccess(uri, state.SecretAccessParams{
  1897  		LeaderToken: &fakeToken{},
  1898  		Subject:     subject,
  1899  	})
  1900  	c.Assert(err, jc.ErrorIsNil)
  1901  	access, err = s.State.SecretAccess(uri, subject)
  1902  	c.Assert(err, jc.ErrorIsNil)
  1903  	c.Assert(access, gc.Equals, secrets.RoleNone)
  1904  
  1905  	err = s.State.RevokeSecretAccess(uri, state.SecretAccessParams{
  1906  		LeaderToken: &fakeToken{},
  1907  		Subject:     subject,
  1908  	})
  1909  	c.Assert(err, jc.ErrorIsNil)
  1910  }
  1911  
  1912  func (s *SecretsSuite) TestSecretAccessScope(c *gc.C) {
  1913  	uri := secrets.NewURI()
  1914  	subject := names.NewApplicationTag("wordpress")
  1915  
  1916  	cp := state.CreateSecretParams{
  1917  		Version: 1,
  1918  		Owner:   s.owner.Tag(),
  1919  		UpdateSecretParams: state.UpdateSecretParams{
  1920  			LeaderToken: &fakeToken{},
  1921  			Data:        map[string]string{"foo": "bar"},
  1922  		},
  1923  	}
  1924  	_, err := s.store.CreateSecret(uri, cp)
  1925  	c.Assert(err, jc.ErrorIsNil)
  1926  
  1927  	err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1928  		LeaderToken: &fakeToken{},
  1929  		Scope:       s.relation.Tag(),
  1930  		Subject:     subject,
  1931  		Role:        secrets.RoleView,
  1932  	})
  1933  	c.Assert(err, jc.ErrorIsNil)
  1934  	scope, err := s.State.SecretAccessScope(uri, subject)
  1935  	c.Assert(err, jc.ErrorIsNil)
  1936  	c.Assert(scope, jc.DeepEquals, s.relation.Tag())
  1937  }
  1938  
  1939  func (s *SecretsSuite) TestDelete(c *gc.C) {
  1940  	subject := names.NewApplicationTag("wordpress")
  1941  	create := func(label string) *secrets.URI {
  1942  		uri := secrets.NewURI()
  1943  		now := s.Clock.Now().Round(time.Second).UTC()
  1944  		next := now.Add(time.Minute).Round(time.Second).UTC()
  1945  		cp := state.CreateSecretParams{
  1946  			Version: 1,
  1947  			Owner:   s.owner.Tag(),
  1948  			UpdateSecretParams: state.UpdateSecretParams{
  1949  				LeaderToken:    &fakeToken{},
  1950  				RotatePolicy:   ptr(secrets.RotateDaily),
  1951  				NextRotateTime: ptr(next),
  1952  				Label:          ptr(label),
  1953  				Data:           map[string]string{"foo": "bar"},
  1954  			},
  1955  		}
  1956  		_, err := s.store.CreateSecret(uri, cp)
  1957  		c.Assert(err, jc.ErrorIsNil)
  1958  		cmd := &secrets.SecretConsumerMetadata{
  1959  			Label:           "consumer-" + label,
  1960  			CurrentRevision: 1,
  1961  		}
  1962  		err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), cmd)
  1963  		c.Assert(err, jc.ErrorIsNil)
  1964  		err = s.State.GrantSecretAccess(uri, state.SecretAccessParams{
  1965  			LeaderToken: &fakeToken{},
  1966  			Scope:       s.relation.Tag(),
  1967  			Subject:     subject,
  1968  			Role:        secrets.RoleView,
  1969  		})
  1970  		c.Assert(err, jc.ErrorIsNil)
  1971  		return uri
  1972  	}
  1973  	backendStore := state.NewSecretBackends(s.State)
  1974  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  1975  		ID:          "backend-id",
  1976  		Name:        "foo",
  1977  		BackendType: "vault",
  1978  	})
  1979  	c.Assert(err, jc.ErrorIsNil)
  1980  	backendRefCount, err := s.State.ReadBackendRefCount("backend-id")
  1981  	c.Assert(err, jc.ErrorIsNil)
  1982  	c.Assert(backendRefCount, gc.Equals, 0)
  1983  
  1984  	uri1 := create("label1")
  1985  	up := state.UpdateSecretParams{
  1986  		LeaderToken: &fakeToken{},
  1987  		ValueRef: &secrets.ValueRef{
  1988  			BackendID:  "backend-id",
  1989  			RevisionID: "rev-id",
  1990  		},
  1991  	}
  1992  	_, err = s.store.UpdateSecret(uri1, up)
  1993  	c.Assert(err, jc.ErrorIsNil)
  1994  
  1995  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  1996  	c.Assert(err, jc.ErrorIsNil)
  1997  	c.Assert(backendRefCount, gc.Equals, 1)
  1998  
  1999  	uri2 := create("label2")
  2000  
  2001  	external, err := s.store.DeleteSecret(uri1)
  2002  	c.Assert(err, jc.ErrorIsNil)
  2003  	c.Assert(external, jc.DeepEquals, []secrets.ValueRef{{
  2004  		BackendID:  "backend-id",
  2005  		RevisionID: "rev-id",
  2006  	}})
  2007  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  2008  	c.Assert(err, jc.ErrorIsNil)
  2009  	c.Assert(backendRefCount, gc.Equals, 0)
  2010  
  2011  	_, _, err = s.store.GetSecretValue(uri1, 1)
  2012  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  2013  	external, err = s.store.DeleteSecret(uri1)
  2014  	c.Assert(err, jc.ErrorIsNil)
  2015  	c.Assert(external, gc.HasLen, 0)
  2016  
  2017  	// Check that other secret info remains intact.
  2018  	secretRevisionsCollection, closer := state.GetCollection(s.State, "secretRevisions")
  2019  	defer closer()
  2020  	n, err := secretRevisionsCollection.FindId(uri2.ID + "/1").Count()
  2021  	c.Assert(err, jc.ErrorIsNil)
  2022  	c.Assert(n, gc.Equals, 1)
  2023  	n, err = secretRevisionsCollection.Find(nil).Count()
  2024  	c.Assert(err, jc.ErrorIsNil)
  2025  	c.Assert(n, gc.Equals, 1)
  2026  
  2027  	secretRotateCollection, closer := state.GetCollection(s.State, "secretRotate")
  2028  	defer closer()
  2029  	n, err = secretRotateCollection.FindId(uri2.ID).Count()
  2030  	c.Assert(err, jc.ErrorIsNil)
  2031  	c.Assert(n, gc.Equals, 1)
  2032  	n, err = secretRotateCollection.Find(nil).Count()
  2033  	c.Assert(err, jc.ErrorIsNil)
  2034  	c.Assert(n, gc.Equals, 1)
  2035  
  2036  	secretConsumersCollection, closer := state.GetCollection(s.State, "secretConsumers")
  2037  	defer closer()
  2038  	n, err = secretConsumersCollection.FindId(uri2.ID + "#unit-mariadb-0").Count()
  2039  	c.Assert(err, jc.ErrorIsNil)
  2040  	c.Assert(n, gc.Equals, 1)
  2041  	n, err = secretConsumersCollection.Find(nil).Count()
  2042  	c.Assert(err, jc.ErrorIsNil)
  2043  	c.Assert(n, gc.Equals, 1)
  2044  
  2045  	secretPermissionsCollection, closer := state.GetCollection(s.State, "secretPermissions")
  2046  	defer closer()
  2047  	n, err = secretPermissionsCollection.FindId(uri2.ID + "#application-wordpress").Count()
  2048  	c.Assert(err, jc.ErrorIsNil)
  2049  	c.Assert(n, gc.Equals, 1)
  2050  	n, err = secretPermissionsCollection.Find(nil).Count()
  2051  	c.Assert(err, jc.ErrorIsNil)
  2052  	c.Assert(n, gc.Equals, 1)
  2053  
  2054  	refCountsCollection, closer := state.GetCollection(s.State, "refcounts")
  2055  	defer closer()
  2056  	n, err = refCountsCollection.FindId(uri2.ID + "#consumer").Count()
  2057  	c.Assert(err, jc.ErrorIsNil)
  2058  	c.Assert(n, gc.Equals, 1)
  2059  	n, err = refCountsCollection.FindId(uri1.ID + "#consumer").Count()
  2060  	c.Assert(err, jc.ErrorIsNil)
  2061  	c.Assert(n, gc.Equals, 0)
  2062  
  2063  	// Check we can now reuse the label.
  2064  	create("label1")
  2065  }
  2066  
  2067  func (s *SecretsSuite) TestDeleteRevisions(c *gc.C) {
  2068  	backendStore := state.NewSecretBackends(s.State)
  2069  	_, err := backendStore.CreateSecretBackend(state.CreateSecretBackendParams{
  2070  		ID:          "backend-id",
  2071  		Name:        "foo",
  2072  		BackendType: "vault",
  2073  	})
  2074  	c.Assert(err, jc.ErrorIsNil)
  2075  	backendRefCount, err := s.State.ReadBackendRefCount("backend-id")
  2076  	c.Assert(err, jc.ErrorIsNil)
  2077  	c.Assert(backendRefCount, gc.Equals, 0)
  2078  
  2079  	uri := secrets.NewURI()
  2080  	cp := state.CreateSecretParams{
  2081  		Version: 1,
  2082  		Owner:   s.owner.Tag(),
  2083  		UpdateSecretParams: state.UpdateSecretParams{
  2084  			LeaderToken: &fakeToken{},
  2085  			Data:        map[string]string{"foo": "bar"},
  2086  		},
  2087  	}
  2088  	_, err = s.store.CreateSecret(uri, cp)
  2089  	c.Assert(err, jc.ErrorIsNil)
  2090  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2091  		LeaderToken: &fakeToken{},
  2092  		Data:        map[string]string{"foo": "bar2"},
  2093  	})
  2094  	c.Assert(err, jc.ErrorIsNil)
  2095  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2096  		LeaderToken: &fakeToken{},
  2097  		ValueRef: &secrets.ValueRef{
  2098  			BackendID:  "backend-id",
  2099  			RevisionID: "rev-id",
  2100  		},
  2101  	})
  2102  	c.Assert(err, jc.ErrorIsNil)
  2103  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  2104  	c.Assert(err, jc.ErrorIsNil)
  2105  	c.Assert(backendRefCount, gc.Equals, 1)
  2106  
  2107  	external, err := s.store.DeleteSecret(uri, 1)
  2108  	c.Assert(err, jc.ErrorIsNil)
  2109  	c.Assert(external, gc.HasLen, 0)
  2110  	_, _, err = s.store.GetSecretValue(uri, 1)
  2111  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  2112  	val, _, err := s.store.GetSecretValue(uri, 2)
  2113  	c.Assert(err, jc.ErrorIsNil)
  2114  	c.Assert(val.EncodedValues(), jc.DeepEquals, map[string]string{"foo": "bar2"})
  2115  	_, ref, err := s.store.GetSecretValue(uri, 3)
  2116  	c.Assert(err, jc.ErrorIsNil)
  2117  	c.Assert(ref, gc.NotNil)
  2118  	c.Assert(ref, jc.DeepEquals, &secrets.ValueRef{
  2119  		BackendID:  "backend-id",
  2120  		RevisionID: "rev-id",
  2121  	})
  2122  
  2123  	external, err = s.store.DeleteSecret(uri, 1, 2, 3)
  2124  	c.Assert(err, jc.ErrorIsNil)
  2125  	c.Assert(external, jc.DeepEquals, []secrets.ValueRef{{
  2126  		BackendID:  "backend-id",
  2127  		RevisionID: "rev-id",
  2128  	}})
  2129  	_, _, err = s.store.GetSecretValue(uri, 3)
  2130  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  2131  	_, err = s.store.GetSecret(uri)
  2132  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  2133  
  2134  	backendRefCount, err = s.State.ReadBackendRefCount("backend-id")
  2135  	c.Assert(err, jc.ErrorIsNil)
  2136  	c.Assert(backendRefCount, gc.Equals, 0)
  2137  }
  2138  
  2139  func (s *SecretsSuite) TestSecretRotated(c *gc.C) {
  2140  	uri := secrets.NewURI()
  2141  
  2142  	now := s.Clock.Now().Round(time.Second).UTC()
  2143  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2144  	cp := state.CreateSecretParams{
  2145  		Version: 1,
  2146  		Owner:   s.owner.Tag(),
  2147  		UpdateSecretParams: state.UpdateSecretParams{
  2148  			LeaderToken:    &fakeToken{},
  2149  			RotatePolicy:   ptr(secrets.RotateDaily),
  2150  			NextRotateTime: ptr(next),
  2151  			Data:           map[string]string{"foo": "bar"},
  2152  		},
  2153  	}
  2154  	md, err := s.store.CreateSecret(uri, cp)
  2155  	c.Assert(err, jc.ErrorIsNil)
  2156  	next2 := now.Add(time.Hour).Round(time.Second).UTC()
  2157  	err = s.State.SecretRotated(uri, next2)
  2158  	c.Assert(err, jc.ErrorIsNil)
  2159  
  2160  	nextTime := state.GetSecretNextRotateTime(c, s.State, md.URI.ID)
  2161  	c.Assert(nextTime, gc.Equals, next2)
  2162  }
  2163  
  2164  func (s *SecretsSuite) TestSecretRotatedConcurrent(c *gc.C) {
  2165  	uri := secrets.NewURI()
  2166  
  2167  	now := s.Clock.Now().Round(time.Second).UTC()
  2168  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2169  	cp := state.CreateSecretParams{
  2170  		Version: 1,
  2171  		Owner:   s.owner.Tag(),
  2172  		UpdateSecretParams: state.UpdateSecretParams{
  2173  			LeaderToken:    &fakeToken{},
  2174  			RotatePolicy:   ptr(secrets.RotateDaily),
  2175  			NextRotateTime: ptr(next),
  2176  			Data:           map[string]string{"foo": "bar"},
  2177  		},
  2178  	}
  2179  	md, err := s.store.CreateSecret(uri, cp)
  2180  	c.Assert(err, jc.ErrorIsNil)
  2181  
  2182  	later := now.Add(time.Hour).Round(time.Second).UTC()
  2183  	later2 := now.Add(2 * time.Hour).Round(time.Second).UTC()
  2184  	state.SetBeforeHooks(c, s.State, func() {
  2185  		err := s.State.SecretRotated(uri, later)
  2186  		c.Assert(err, jc.ErrorIsNil)
  2187  	})
  2188  
  2189  	err = s.State.SecretRotated(uri, later2)
  2190  	c.Assert(err, jc.ErrorIsNil)
  2191  
  2192  	nextTime := state.GetSecretNextRotateTime(c, s.State, md.URI.ID)
  2193  	c.Assert(nextTime, gc.Equals, later)
  2194  }
  2195  
  2196  type SecretsRotationWatcherSuite struct {
  2197  	testing.StateSuite
  2198  	store state.SecretsStore
  2199  
  2200  	ownerApp  *state.Application
  2201  	ownerUnit *state.Unit
  2202  }
  2203  
  2204  var _ = gc.Suite(&SecretsRotationWatcherSuite{})
  2205  
  2206  func (s *SecretsRotationWatcherSuite) SetUpTest(c *gc.C) {
  2207  	s.StateSuite.SetUpTest(c)
  2208  	s.store = state.NewSecrets(s.State)
  2209  	s.ownerApp = s.Factory.MakeApplication(c, nil)
  2210  	s.ownerUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.ownerApp})
  2211  }
  2212  
  2213  func (s *SecretsRotationWatcherSuite) setupWatcher(c *gc.C) (state.SecretsTriggerWatcher, *secrets.URI) {
  2214  	uri := secrets.NewURI()
  2215  	now := s.Clock.Now().Round(time.Second).UTC()
  2216  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2217  	cp := state.CreateSecretParams{
  2218  		Version: 1,
  2219  		Owner:   s.ownerApp.Tag(),
  2220  		UpdateSecretParams: state.UpdateSecretParams{
  2221  			LeaderToken:    &fakeToken{},
  2222  			RotatePolicy:   ptr(secrets.RotateDaily),
  2223  			NextRotateTime: ptr(next),
  2224  			Data:           map[string]string{"foo": "bar"},
  2225  		},
  2226  	}
  2227  	md, err := s.store.CreateSecret(uri, cp)
  2228  	c.Assert(err, jc.ErrorIsNil)
  2229  	w, err := s.State.WatchSecretsRotationChanges(
  2230  		[]names.Tag{s.ownerApp.Tag(), s.ownerUnit.Tag()})
  2231  	c.Assert(err, jc.ErrorIsNil)
  2232  
  2233  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2234  	wc.AssertChange(watcher.SecretTriggerChange{
  2235  		URI:             md.URI,
  2236  		NextTriggerTime: next,
  2237  	})
  2238  	wc.AssertNoChange()
  2239  	return w, uri
  2240  }
  2241  
  2242  func (s *SecretsRotationWatcherSuite) TestWatchInitialEvent(c *gc.C) {
  2243  	w, _ := s.setupWatcher(c)
  2244  	testing.AssertStop(c, w)
  2245  }
  2246  
  2247  func (s *SecretsRotationWatcherSuite) TestWatchSingleUpdate(c *gc.C) {
  2248  	w, uri := s.setupWatcher(c)
  2249  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2250  	defer testing.AssertStop(c, w)
  2251  
  2252  	now := s.Clock.Now().Round(time.Second).UTC()
  2253  	next := now.Add(2 * time.Hour).Round(time.Second).UTC()
  2254  	err := s.State.SecretRotated(uri, next)
  2255  	c.Assert(err, jc.ErrorIsNil)
  2256  
  2257  	wc.AssertChange(watcher.SecretTriggerChange{
  2258  		URI:             uri,
  2259  		NextTriggerTime: next,
  2260  	})
  2261  	wc.AssertNoChange()
  2262  }
  2263  
  2264  func (s *SecretsRotationWatcherSuite) TestWatchDelete(c *gc.C) {
  2265  	w, uri := s.setupWatcher(c)
  2266  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2267  	defer testing.AssertStop(c, w)
  2268  
  2269  	md, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2270  		LeaderToken:  &fakeToken{},
  2271  		RotatePolicy: ptr(secrets.RotateNever),
  2272  	})
  2273  	c.Assert(err, jc.ErrorIsNil)
  2274  
  2275  	wc.AssertChange(watcher.SecretTriggerChange{
  2276  		URI: md.URI,
  2277  	})
  2278  	wc.AssertNoChange()
  2279  }
  2280  
  2281  func (s *SecretsRotationWatcherSuite) TestWatchMultipleUpdatesSameSecret(c *gc.C) {
  2282  	w, uri := s.setupWatcher(c)
  2283  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2284  	defer testing.AssertStop(c, w)
  2285  
  2286  	// TODO(quiescence): these two changes should be one event.
  2287  	now := s.Clock.Now().Round(time.Second).UTC()
  2288  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2289  	err := s.State.SecretRotated(uri, next)
  2290  	c.Assert(err, jc.ErrorIsNil)
  2291  	wc.AssertChange(watcher.SecretTriggerChange{
  2292  		URI:             uri,
  2293  		NextTriggerTime: next,
  2294  	})
  2295  	next2 := now.Add(time.Hour).Round(time.Second).UTC()
  2296  	err = s.State.SecretRotated(uri, next2)
  2297  	c.Assert(err, jc.ErrorIsNil)
  2298  
  2299  	wc.AssertChange(watcher.SecretTriggerChange{
  2300  		URI:             uri,
  2301  		NextTriggerTime: next2,
  2302  	})
  2303  	wc.AssertNoChange()
  2304  }
  2305  
  2306  func (s *SecretsRotationWatcherSuite) TestWatchMultipleUpdatesSameSecretDeleted(c *gc.C) {
  2307  	w, uri := s.setupWatcher(c)
  2308  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2309  	defer testing.AssertStop(c, w)
  2310  
  2311  	// TODO(quiescence): these two changes should be one event.
  2312  	now := s.Clock.Now().Round(time.Second).UTC()
  2313  	next := now.Add(time.Hour).Round(time.Second).UTC()
  2314  	err := s.State.SecretRotated(uri, next)
  2315  	c.Assert(err, jc.ErrorIsNil)
  2316  	wc.AssertChange(watcher.SecretTriggerChange{
  2317  		URI:             uri,
  2318  		NextTriggerTime: next,
  2319  	})
  2320  	md, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2321  		LeaderToken:  &fakeToken{},
  2322  		RotatePolicy: ptr(secrets.RotateNever),
  2323  	})
  2324  	c.Assert(err, jc.ErrorIsNil)
  2325  
  2326  	wc.AssertChange(watcher.SecretTriggerChange{
  2327  		URI: md.URI,
  2328  	})
  2329  	wc.AssertNoChange()
  2330  }
  2331  
  2332  func (s *SecretsRotationWatcherSuite) TestWatchMultipleUpdates(c *gc.C) {
  2333  	w, uri := s.setupWatcher(c)
  2334  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2335  	defer testing.AssertStop(c, w)
  2336  
  2337  	// TODO(quiescence): these two changes should be one event.
  2338  	now := s.Clock.Now().Round(time.Second).UTC()
  2339  	next := now.Add(time.Hour).Round(time.Second).UTC()
  2340  	err := s.State.SecretRotated(uri, next)
  2341  	c.Assert(err, jc.ErrorIsNil)
  2342  	wc.AssertChange(watcher.SecretTriggerChange{
  2343  		URI:             uri,
  2344  		NextTriggerTime: next,
  2345  	})
  2346  
  2347  	uri2 := secrets.NewURI()
  2348  	next2 := now.Add(time.Minute).Round(time.Second).UTC()
  2349  	md2, err := s.store.CreateSecret(uri2, state.CreateSecretParams{
  2350  		Version: 1,
  2351  		Owner:   s.ownerApp.Tag(),
  2352  		UpdateSecretParams: state.UpdateSecretParams{
  2353  			LeaderToken:    &fakeToken{},
  2354  			RotatePolicy:   ptr(secrets.RotateHourly),
  2355  			NextRotateTime: ptr(next2),
  2356  			Data:           map[string]string{"foo": "bar"},
  2357  		},
  2358  	})
  2359  	c.Assert(err, jc.ErrorIsNil)
  2360  	wc.AssertChange(watcher.SecretTriggerChange{
  2361  		URI:             md2.URI,
  2362  		NextTriggerTime: next2,
  2363  	})
  2364  
  2365  	md, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2366  		LeaderToken:  &fakeToken{},
  2367  		RotatePolicy: ptr(secrets.RotateNever),
  2368  	})
  2369  	c.Assert(err, jc.ErrorIsNil)
  2370  
  2371  	wc.AssertChange(watcher.SecretTriggerChange{
  2372  		URI: md.URI,
  2373  	})
  2374  	wc.AssertNoChange()
  2375  }
  2376  
  2377  func (s *SecretsRotationWatcherSuite) TestWatchRestartChangeOwners(c *gc.C) {
  2378  	w, uri := s.setupWatcher(c)
  2379  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2380  	defer testing.AssertStop(c, w)
  2381  
  2382  	now := s.Clock.Now().Round(time.Second).UTC()
  2383  	next1 := now.Add(time.Minute).Round(time.Second).UTC()
  2384  	next2 := now.Add(time.Minute).Round(time.Second).UTC()
  2385  
  2386  	uri2 := secrets.NewURI()
  2387  	cp := state.CreateSecretParams{
  2388  		Version: 1,
  2389  		Owner:   s.ownerUnit.Tag(),
  2390  		UpdateSecretParams: state.UpdateSecretParams{
  2391  			LeaderToken:    &fakeToken{},
  2392  			RotatePolicy:   ptr(secrets.RotateHourly),
  2393  			NextRotateTime: ptr(next2),
  2394  			Data:           map[string]string{"foo": "bar"},
  2395  		},
  2396  	}
  2397  	_, err := s.store.CreateSecret(uri2, cp)
  2398  	c.Assert(err, jc.ErrorIsNil)
  2399  
  2400  	next3 := now.Add(time.Minute).Round(time.Second).UTC()
  2401  	anotherUnit := s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.ownerApp})
  2402  
  2403  	uri3 := secrets.NewURI()
  2404  	cp = state.CreateSecretParams{
  2405  		Version: 1,
  2406  		Owner:   anotherUnit.Tag(),
  2407  		UpdateSecretParams: state.UpdateSecretParams{
  2408  			LeaderToken:    &fakeToken{},
  2409  			RotatePolicy:   ptr(secrets.RotateHourly),
  2410  			NextRotateTime: ptr(next3),
  2411  			Data:           map[string]string{"foo": "bar"},
  2412  		},
  2413  	}
  2414  	_, err = s.store.CreateSecret(uri3, cp)
  2415  	c.Assert(err, jc.ErrorIsNil)
  2416  
  2417  	wc.AssertChange(watcher.SecretTriggerChange{
  2418  		URI:             uri2,
  2419  		NextTriggerTime: next2,
  2420  	})
  2421  
  2422  	wc.AssertNoChange()
  2423  	testing.AssertStop(c, w)
  2424  
  2425  	w, err = s.State.WatchSecretsRotationChanges(
  2426  		[]names.Tag{s.ownerApp.Tag(), anotherUnit.Tag()})
  2427  	c.Assert(err, jc.ErrorIsNil)
  2428  
  2429  	wc = testing.NewSecretsTriggerWatcherC(c, w)
  2430  	defer testing.AssertStop(c, w)
  2431  
  2432  	wc.AssertChange(watcher.SecretTriggerChange{
  2433  		URI:             uri,
  2434  		NextTriggerTime: next1,
  2435  	}, watcher.SecretTriggerChange{
  2436  		URI:             uri3,
  2437  		NextTriggerTime: next3,
  2438  	})
  2439  	wc.AssertNoChange()
  2440  }
  2441  
  2442  type SecretsExpiryWatcherSuite struct {
  2443  	testing.StateSuite
  2444  	store state.SecretsStore
  2445  
  2446  	ownerApp  *state.Application
  2447  	ownerUnit *state.Unit
  2448  }
  2449  
  2450  var _ = gc.Suite(&SecretsExpiryWatcherSuite{})
  2451  
  2452  func (s *SecretsExpiryWatcherSuite) SetUpTest(c *gc.C) {
  2453  	s.StateSuite.SetUpTest(c)
  2454  	s.store = state.NewSecrets(s.State)
  2455  	s.ownerApp = s.Factory.MakeApplication(c, nil)
  2456  	s.ownerUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.ownerApp})
  2457  }
  2458  
  2459  func (s *SecretsExpiryWatcherSuite) setupWatcher(c *gc.C) (state.SecretsTriggerWatcher, *secrets.URI) {
  2460  	uri := secrets.NewURI()
  2461  	now := s.Clock.Now().Round(time.Second).UTC()
  2462  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2463  	cp := state.CreateSecretParams{
  2464  		Version: 1,
  2465  		Owner:   s.ownerApp.Tag(),
  2466  		UpdateSecretParams: state.UpdateSecretParams{
  2467  			LeaderToken: &fakeToken{},
  2468  			ExpireTime:  ptr(next),
  2469  			Data:        map[string]string{"foo": "bar"},
  2470  		},
  2471  	}
  2472  	md, err := s.store.CreateSecret(uri, cp)
  2473  	c.Assert(err, jc.ErrorIsNil)
  2474  	w, err := s.State.WatchSecretRevisionsExpiryChanges(
  2475  		[]names.Tag{s.ownerApp.Tag(), s.ownerUnit.Tag()})
  2476  	c.Assert(err, jc.ErrorIsNil)
  2477  
  2478  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2479  	wc.AssertChange(watcher.SecretTriggerChange{
  2480  		URI:             md.URI,
  2481  		Revision:        1,
  2482  		NextTriggerTime: next,
  2483  	})
  2484  	wc.AssertNoChange()
  2485  	return w, uri
  2486  }
  2487  
  2488  func (s *SecretsExpiryWatcherSuite) TestWatchInitialEvent(c *gc.C) {
  2489  	w, _ := s.setupWatcher(c)
  2490  	testing.AssertStop(c, w)
  2491  }
  2492  
  2493  func (s *SecretsExpiryWatcherSuite) TestWatchSingleUpdate(c *gc.C) {
  2494  	w, uri := s.setupWatcher(c)
  2495  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2496  	defer testing.AssertStop(c, w)
  2497  
  2498  	now := s.Clock.Now().Round(time.Second).UTC()
  2499  	next := now.Add(2 * time.Hour).Round(time.Second).UTC()
  2500  
  2501  	s.Clock.Advance(time.Hour)
  2502  	updated := s.Clock.Now().Round(time.Second).UTC()
  2503  	update := state.UpdateSecretParams{
  2504  		LeaderToken: &fakeToken{},
  2505  		ExpireTime:  ptr(next),
  2506  	}
  2507  	md, err := s.store.UpdateSecret(uri, update)
  2508  	c.Assert(err, jc.ErrorIsNil)
  2509  	c.Assert(md.LatestExpireTime, gc.NotNil)
  2510  	c.Assert(*md.LatestExpireTime, gc.Equals, next)
  2511  
  2512  	revs, err := s.store.ListSecretRevisions(md.URI)
  2513  	c.Assert(err, jc.ErrorIsNil)
  2514  	for _, r := range revs {
  2515  		if r.ExpireTime != nil && r.ExpireTime.Equal(update.ExpireTime.Round(time.Second).UTC()) {
  2516  			c.Assert(r.UpdateTime, jc.Almost, updated)
  2517  			return
  2518  		}
  2519  	}
  2520  	c.Fatalf("expire time not set for secret revision %d", 2)
  2521  
  2522  	wc.AssertChange(watcher.SecretTriggerChange{
  2523  		URI:             uri,
  2524  		Revision:        3,
  2525  		NextTriggerTime: next,
  2526  	})
  2527  	wc.AssertNoChange()
  2528  }
  2529  
  2530  func (s *SecretsExpiryWatcherSuite) TestWatchSetExpiryToNil(c *gc.C) {
  2531  	w, uri := s.setupWatcher(c)
  2532  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2533  	defer testing.AssertStop(c, w)
  2534  
  2535  	md, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2536  		LeaderToken: &fakeToken{},
  2537  		ExpireTime:  ptr(time.Time{}),
  2538  	})
  2539  	c.Assert(err, jc.ErrorIsNil)
  2540  
  2541  	wc.AssertChange(watcher.SecretTriggerChange{
  2542  		URI:      md.URI,
  2543  		Revision: 1,
  2544  	})
  2545  	wc.AssertNoChange()
  2546  }
  2547  
  2548  func (s *SecretsExpiryWatcherSuite) TestWatchMultipleUpdates(c *gc.C) {
  2549  	w, uri := s.setupWatcher(c)
  2550  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2551  	defer testing.AssertStop(c, w)
  2552  
  2553  	now := s.Clock.Now().Round(time.Second).UTC()
  2554  	md, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2555  		LeaderToken: &fakeToken{},
  2556  		ExpireTime:  ptr(time.Time{}),
  2557  	})
  2558  	c.Assert(err, jc.ErrorIsNil)
  2559  
  2560  	next := now.Add(2 * time.Hour).Round(time.Second).UTC()
  2561  	update := state.UpdateSecretParams{
  2562  		LeaderToken: &fakeToken{},
  2563  		ExpireTime:  ptr(next),
  2564  	}
  2565  	_, err = s.store.UpdateSecret(uri, update)
  2566  	c.Assert(err, jc.ErrorIsNil)
  2567  
  2568  	wc.AssertChange(watcher.SecretTriggerChange{
  2569  		URI:      md.URI,
  2570  		Revision: 1,
  2571  	}, watcher.SecretTriggerChange{
  2572  		URI:             md.URI,
  2573  		Revision:        1,
  2574  		NextTriggerTime: next,
  2575  	})
  2576  	wc.AssertNoChange()
  2577  }
  2578  
  2579  func (s *SecretsExpiryWatcherSuite) TestWatchRemoveSecret(c *gc.C) {
  2580  	w, uri := s.setupWatcher(c)
  2581  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2582  	defer testing.AssertStop(c, w)
  2583  
  2584  	_, err := s.store.DeleteSecret(uri)
  2585  	c.Assert(err, jc.ErrorIsNil)
  2586  
  2587  	wc.AssertChange(watcher.SecretTriggerChange{
  2588  		URI:      uri,
  2589  		Revision: 1,
  2590  	})
  2591  	wc.AssertNoChange()
  2592  
  2593  	uri2 := secrets.NewURI()
  2594  	now := s.Clock.Now().Round(time.Second).UTC()
  2595  	next := now.Add(time.Minute).Round(time.Second).UTC()
  2596  	cp := state.CreateSecretParams{
  2597  		Version: 1,
  2598  		Owner:   s.ownerUnit.Tag(),
  2599  		UpdateSecretParams: state.UpdateSecretParams{
  2600  			LeaderToken: &fakeToken{},
  2601  			ExpireTime:  ptr(next),
  2602  			Data:        map[string]string{"foo": "bar"},
  2603  		},
  2604  	}
  2605  	_, err = s.store.CreateSecret(uri2, cp)
  2606  	c.Assert(err, jc.ErrorIsNil)
  2607  	wc.AssertChange(watcher.SecretTriggerChange{
  2608  		URI:             uri2,
  2609  		Revision:        1,
  2610  		NextTriggerTime: next,
  2611  	})
  2612  	wc.AssertNoChange()
  2613  
  2614  	_, err = s.store.DeleteSecret(uri2)
  2615  	c.Assert(err, jc.ErrorIsNil)
  2616  
  2617  	wc.AssertChange(watcher.SecretTriggerChange{
  2618  		URI:      uri2,
  2619  		Revision: 1,
  2620  	})
  2621  	wc.AssertNoChange()
  2622  }
  2623  
  2624  func (s *SecretsExpiryWatcherSuite) TestWatchRemoveRevision(c *gc.C) {
  2625  	w, uri := s.setupWatcher(c)
  2626  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2627  	defer testing.AssertStop(c, w)
  2628  
  2629  	now := s.Clock.Now().Round(time.Second).UTC()
  2630  	triggerTime := now.Add(time.Minute).Round(time.Second).UTC()
  2631  	_, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2632  		LeaderToken: &fakeToken{},
  2633  		Data:        map[string]string{"foo": "bar2"},
  2634  	})
  2635  	c.Assert(err, jc.ErrorIsNil)
  2636  	wc.AssertChange(watcher.SecretTriggerChange{
  2637  		URI:             uri,
  2638  		Revision:        1,
  2639  		NextTriggerTime: triggerTime,
  2640  	})
  2641  	wc.AssertNoChange()
  2642  
  2643  	_, err = s.store.DeleteSecret(uri, 1)
  2644  	c.Assert(err, jc.ErrorIsNil)
  2645  
  2646  	wc.AssertChange(watcher.SecretTriggerChange{
  2647  		URI:      uri,
  2648  		Revision: 1,
  2649  	})
  2650  	wc.AssertNoChange()
  2651  }
  2652  
  2653  func (s *SecretsExpiryWatcherSuite) TestWatchRestartChangeOwners(c *gc.C) {
  2654  	w, uri := s.setupWatcher(c)
  2655  	wc := testing.NewSecretsTriggerWatcherC(c, w)
  2656  	defer testing.AssertStop(c, w)
  2657  
  2658  	now := s.Clock.Now().Round(time.Second).UTC()
  2659  	next1 := now.Add(time.Minute).Round(time.Second).UTC()
  2660  	next2 := now.Add(time.Minute).Round(time.Second).UTC()
  2661  
  2662  	uri2 := secrets.NewURI()
  2663  	cp := state.CreateSecretParams{
  2664  		Version: 1,
  2665  		Owner:   s.ownerUnit.Tag(),
  2666  		UpdateSecretParams: state.UpdateSecretParams{
  2667  			LeaderToken: &fakeToken{},
  2668  			ExpireTime:  ptr(next2),
  2669  			Data:        map[string]string{"foo": "bar"},
  2670  		},
  2671  	}
  2672  	_, err := s.store.CreateSecret(uri2, cp)
  2673  	c.Assert(err, jc.ErrorIsNil)
  2674  
  2675  	next3 := now.Add(time.Minute).Round(time.Second).UTC()
  2676  
  2677  	anotherUnit := s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.ownerApp})
  2678  	uri3 := secrets.NewURI()
  2679  	cp = state.CreateSecretParams{
  2680  		Version: 1,
  2681  		Owner:   anotherUnit.Tag(),
  2682  		UpdateSecretParams: state.UpdateSecretParams{
  2683  			LeaderToken: &fakeToken{},
  2684  			ExpireTime:  ptr(next3),
  2685  			Data:        map[string]string{"foo": "bar"},
  2686  		},
  2687  	}
  2688  	_, err = s.store.CreateSecret(uri3, cp)
  2689  	c.Assert(err, jc.ErrorIsNil)
  2690  
  2691  	wc.AssertChange(watcher.SecretTriggerChange{
  2692  		URI:             uri2,
  2693  		Revision:        1,
  2694  		NextTriggerTime: next2,
  2695  	})
  2696  
  2697  	wc.AssertNoChange()
  2698  	testing.AssertStop(c, w)
  2699  
  2700  	w, err = s.State.WatchSecretRevisionsExpiryChanges(
  2701  		[]names.Tag{s.ownerApp.Tag(), anotherUnit.Tag()})
  2702  	c.Assert(err, jc.ErrorIsNil)
  2703  
  2704  	wc = testing.NewSecretsTriggerWatcherC(c, w)
  2705  	defer testing.AssertStop(c, w)
  2706  
  2707  	wc.AssertChange(watcher.SecretTriggerChange{
  2708  		URI:             uri,
  2709  		Revision:        1,
  2710  		NextTriggerTime: next1,
  2711  	}, watcher.SecretTriggerChange{
  2712  		URI:             uri3,
  2713  		Revision:        1,
  2714  		NextTriggerTime: next3,
  2715  	})
  2716  	wc.AssertNoChange()
  2717  }
  2718  
  2719  type SecretsConsumedWatcherSuite struct {
  2720  	testing.StateSuite
  2721  	store state.SecretsStore
  2722  
  2723  	owner *state.Application
  2724  }
  2725  
  2726  var _ = gc.Suite(&SecretsConsumedWatcherSuite{})
  2727  
  2728  func (s *SecretsConsumedWatcherSuite) SetUpTest(c *gc.C) {
  2729  	s.StateSuite.SetUpTest(c)
  2730  	s.store = state.NewSecrets(s.State)
  2731  	s.owner = s.Factory.MakeApplication(c, nil)
  2732  }
  2733  
  2734  func (s *SecretsConsumedWatcherSuite) TestWatcherInitialEvent(c *gc.C) {
  2735  	w, err := s.State.WatchConsumedSecretsChanges(names.NewUnitTag("mariadb/0"))
  2736  	c.Assert(err, jc.ErrorIsNil)
  2737  	wc := testing.NewStringsWatcherC(c, w)
  2738  	wc.AssertChange()
  2739  
  2740  	testing.AssertStop(c, w)
  2741  }
  2742  
  2743  func (s *SecretsConsumedWatcherSuite) setupWatcher(c *gc.C) (state.StringsWatcher, *secrets.URI) {
  2744  	uri := secrets.NewURI()
  2745  	cp := state.CreateSecretParams{
  2746  		Version: 1,
  2747  		Owner:   s.owner.Tag(),
  2748  		UpdateSecretParams: state.UpdateSecretParams{
  2749  			LeaderToken: &fakeToken{},
  2750  			Data:        map[string]string{"foo": "bar"},
  2751  		},
  2752  	}
  2753  	_, err := s.store.CreateSecret(uri, cp)
  2754  	c.Assert(err, jc.ErrorIsNil)
  2755  
  2756  	uri2 := secrets.NewURI()
  2757  	cp = state.CreateSecretParams{
  2758  		Version: 1,
  2759  		Owner:   s.owner.Tag(),
  2760  		UpdateSecretParams: state.UpdateSecretParams{
  2761  			LeaderToken: &fakeToken{},
  2762  			Data:        map[string]string{"foo": "bar"},
  2763  		},
  2764  	}
  2765  	_, err = s.store.CreateSecret(uri2, cp)
  2766  	c.Assert(err, jc.ErrorIsNil)
  2767  	_, err = s.store.UpdateSecret(uri2, state.UpdateSecretParams{
  2768  		LeaderToken: &fakeToken{},
  2769  		Data:        secrets.SecretData{"foo": "bar2"},
  2770  	})
  2771  	c.Assert(err, jc.ErrorIsNil)
  2772  
  2773  	err = s.State.SaveSecretConsumer(uri, names.NewUnitTag("mariadb/0"), &secrets.SecretConsumerMetadata{
  2774  		CurrentRevision: 1,
  2775  		LatestRevision:  1,
  2776  	})
  2777  	c.Assert(err, jc.ErrorIsNil)
  2778  	err = s.State.SaveSecretConsumer(uri2, names.NewUnitTag("mariadb/0"), &secrets.SecretConsumerMetadata{
  2779  		CurrentRevision: 1,
  2780  		LatestRevision:  2,
  2781  	})
  2782  	c.Assert(err, jc.ErrorIsNil)
  2783  
  2784  	w, err := s.State.WatchConsumedSecretsChanges(names.NewUnitTag("mariadb/0"))
  2785  	c.Assert(err, jc.ErrorIsNil)
  2786  	wc := testing.NewStringsWatcherC(c, w)
  2787  
  2788  	// No event until rev > 1, so just the one change.
  2789  	wc.AssertChange(uri2.String())
  2790  	return w, uri
  2791  }
  2792  
  2793  func (s *SecretsConsumedWatcherSuite) TestWatcherStartStop(c *gc.C) {
  2794  	w, _ := s.setupWatcher(c)
  2795  	testing.AssertStop(c, w)
  2796  }
  2797  
  2798  func (s *SecretsConsumedWatcherSuite) TestWatchSingleUpdate(c *gc.C) {
  2799  	w, uri := s.setupWatcher(c)
  2800  	wc := testing.NewStringsWatcherC(c, w)
  2801  	defer testing.AssertStop(c, w)
  2802  
  2803  	_, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2804  		LeaderToken: &fakeToken{},
  2805  		Data:        secrets.SecretData{"foo": "bar2"},
  2806  	})
  2807  	c.Assert(err, jc.ErrorIsNil)
  2808  
  2809  	wc.AssertChange(uri.String())
  2810  	wc.AssertNoChange()
  2811  }
  2812  
  2813  func (s *SecretsConsumedWatcherSuite) TestWatchMultipleSecrets(c *gc.C) {
  2814  	w, uri := s.setupWatcher(c)
  2815  	wc := testing.NewStringsWatcherC(c, w)
  2816  	defer testing.AssertStop(c, w)
  2817  
  2818  	uri2 := secrets.NewURI()
  2819  	cp := state.CreateSecretParams{
  2820  		Version: 1,
  2821  		Owner:   s.owner.Tag(),
  2822  		UpdateSecretParams: state.UpdateSecretParams{
  2823  			LeaderToken: &fakeToken{},
  2824  			Data:        map[string]string{"foo2": "bar"},
  2825  		},
  2826  	}
  2827  	_, err := s.store.CreateSecret(uri2, cp)
  2828  	c.Assert(err, jc.ErrorIsNil)
  2829  
  2830  	err = s.State.SaveSecretConsumer(uri2, names.NewUnitTag("mariadb/0"), &secrets.SecretConsumerMetadata{CurrentRevision: 1})
  2831  	c.Assert(err, jc.ErrorIsNil)
  2832  	// No event until rev > 1.
  2833  	wc.AssertNoChange()
  2834  
  2835  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2836  		LeaderToken: &fakeToken{},
  2837  		Data:        secrets.SecretData{"foo": "bar2"},
  2838  	})
  2839  	c.Assert(err, jc.ErrorIsNil)
  2840  
  2841  	wc.AssertChange(uri.String())
  2842  	wc.AssertNoChange()
  2843  
  2844  	_, err = s.store.UpdateSecret(uri2, state.UpdateSecretParams{
  2845  		LeaderToken: &fakeToken{},
  2846  		Data:        secrets.SecretData{"foo2": "bar2"},
  2847  	})
  2848  	c.Assert(err, jc.ErrorIsNil)
  2849  
  2850  	wc.AssertChange(uri2.String())
  2851  	wc.AssertNoChange()
  2852  }
  2853  
  2854  func (s *SecretsConsumedWatcherSuite) TestWatchConsumedDeleted(c *gc.C) {
  2855  	w, uri := s.setupWatcher(c)
  2856  	wc := testing.NewStringsWatcherC(c, w)
  2857  	defer testing.AssertStop(c, w)
  2858  
  2859  	err := s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  2860  		CurrentRevision: 1,
  2861  	})
  2862  	c.Assert(err, jc.ErrorIsNil)
  2863  	wc.AssertNoChange()
  2864  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("baz"), &secrets.SecretConsumerMetadata{
  2865  		CurrentRevision: 1,
  2866  	})
  2867  	c.Assert(err, jc.ErrorIsNil)
  2868  	wc.AssertNoChange()
  2869  
  2870  	_, err = s.store.DeleteSecret(uri)
  2871  	c.Assert(err, jc.ErrorIsNil)
  2872  	wc.AssertChange(uri.String())
  2873  	wc.AssertNoChange()
  2874  }
  2875  
  2876  type SecretsRemoteConsumerWatcherSuite struct {
  2877  	testing.StateSuite
  2878  	store state.SecretsStore
  2879  
  2880  	owner *state.Application
  2881  }
  2882  
  2883  var _ = gc.Suite(&SecretsRemoteConsumerWatcherSuite{})
  2884  
  2885  func (s *SecretsRemoteConsumerWatcherSuite) SetUpTest(c *gc.C) {
  2886  	s.StateSuite.SetUpTest(c)
  2887  	s.store = state.NewSecrets(s.State)
  2888  	s.owner = s.Factory.MakeApplication(c, nil)
  2889  }
  2890  
  2891  func (s *SecretsRemoteConsumerWatcherSuite) TestWatcherInitialEvent(c *gc.C) {
  2892  	w, err := s.State.WatchRemoteConsumedSecretsChanges("remote-app")
  2893  	c.Assert(err, jc.ErrorIsNil)
  2894  	wc := testing.NewStringsWatcherC(c, w)
  2895  	wc.AssertChange()
  2896  
  2897  	testing.AssertStop(c, w)
  2898  }
  2899  
  2900  func (s *SecretsRemoteConsumerWatcherSuite) setupWatcher(c *gc.C) (state.StringsWatcher, *secrets.URI) {
  2901  	uri := secrets.NewURI()
  2902  	cp := state.CreateSecretParams{
  2903  		Version: 1,
  2904  		Owner:   s.owner.Tag(),
  2905  		UpdateSecretParams: state.UpdateSecretParams{
  2906  			LeaderToken: &fakeToken{},
  2907  			Data:        map[string]string{"foo": "bar"},
  2908  		},
  2909  	}
  2910  	_, err := s.store.CreateSecret(uri, cp)
  2911  	c.Assert(err, jc.ErrorIsNil)
  2912  
  2913  	uri2 := secrets.NewURI()
  2914  	cp = state.CreateSecretParams{
  2915  		Version: 1,
  2916  		Owner:   s.owner.Tag(),
  2917  		UpdateSecretParams: state.UpdateSecretParams{
  2918  			LeaderToken: &fakeToken{},
  2919  			Data:        map[string]string{"foo": "bar"},
  2920  		},
  2921  	}
  2922  	_, err = s.store.CreateSecret(uri2, cp)
  2923  	c.Assert(err, jc.ErrorIsNil)
  2924  	_, err = s.store.UpdateSecret(uri2, state.UpdateSecretParams{
  2925  		LeaderToken: &fakeToken{},
  2926  		Data:        secrets.SecretData{"foo": "bar2"},
  2927  	})
  2928  	c.Assert(err, jc.ErrorIsNil)
  2929  
  2930  	err = s.State.SaveSecretRemoteConsumer(uri, names.NewUnitTag("remote-app/0"), &secrets.SecretConsumerMetadata{
  2931  		CurrentRevision: 1,
  2932  		LatestRevision:  1,
  2933  	})
  2934  	c.Assert(err, jc.ErrorIsNil)
  2935  	err = s.State.SaveSecretRemoteConsumer(uri2, names.NewUnitTag("remote-app/0"), &secrets.SecretConsumerMetadata{
  2936  		CurrentRevision: 1,
  2937  		LatestRevision:  2,
  2938  	})
  2939  	c.Assert(err, jc.ErrorIsNil)
  2940  
  2941  	w, err := s.State.WatchRemoteConsumedSecretsChanges("remote-app")
  2942  	c.Assert(err, jc.ErrorIsNil)
  2943  	wc := testing.NewStringsWatcherC(c, w)
  2944  
  2945  	// No event until rev > 1, so just the one change.
  2946  	wc.AssertChange(uri2.String())
  2947  	return w, uri
  2948  }
  2949  
  2950  func (s *SecretsRemoteConsumerWatcherSuite) TestWatcherStartStop(c *gc.C) {
  2951  	w, _ := s.setupWatcher(c)
  2952  	testing.AssertStop(c, w)
  2953  }
  2954  
  2955  func (s *SecretsRemoteConsumerWatcherSuite) TestWatchSingleUpdate(c *gc.C) {
  2956  	w, uri := s.setupWatcher(c)
  2957  	wc := testing.NewStringsWatcherC(c, w)
  2958  	defer testing.AssertStop(c, w)
  2959  
  2960  	_, err := s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2961  		LeaderToken: &fakeToken{},
  2962  		Data:        secrets.SecretData{"foo": "bar2"},
  2963  	})
  2964  	c.Assert(err, jc.ErrorIsNil)
  2965  
  2966  	wc.AssertChange(uri.String())
  2967  	wc.AssertNoChange()
  2968  }
  2969  
  2970  func (s *SecretsRemoteConsumerWatcherSuite) TestWatchMultipleSecrets(c *gc.C) {
  2971  	w, uri := s.setupWatcher(c)
  2972  	wc := testing.NewStringsWatcherC(c, w)
  2973  	defer testing.AssertStop(c, w)
  2974  
  2975  	uri2 := secrets.NewURI()
  2976  	cp := state.CreateSecretParams{
  2977  		Version: 1,
  2978  		Owner:   s.owner.Tag(),
  2979  		UpdateSecretParams: state.UpdateSecretParams{
  2980  			LeaderToken: &fakeToken{},
  2981  			Data:        map[string]string{"foo2": "bar"},
  2982  		},
  2983  	}
  2984  	_, err := s.store.CreateSecret(uri2, cp)
  2985  	c.Assert(err, jc.ErrorIsNil)
  2986  
  2987  	err = s.State.SaveSecretRemoteConsumer(uri2, names.NewUnitTag("remote-app/0"), &secrets.SecretConsumerMetadata{CurrentRevision: 1})
  2988  	c.Assert(err, jc.ErrorIsNil)
  2989  	// No event until rev > 1.
  2990  	wc.AssertNoChange()
  2991  
  2992  	_, err = s.store.UpdateSecret(uri, state.UpdateSecretParams{
  2993  		LeaderToken: &fakeToken{},
  2994  		Data:        secrets.SecretData{"foo": "bar2"},
  2995  	})
  2996  	c.Assert(err, jc.ErrorIsNil)
  2997  
  2998  	wc.AssertChange(uri.String())
  2999  	wc.AssertNoChange()
  3000  
  3001  	_, err = s.store.UpdateSecret(uri2, state.UpdateSecretParams{
  3002  		LeaderToken: &fakeToken{},
  3003  		Data:        secrets.SecretData{"foo2": "bar2"},
  3004  	})
  3005  	c.Assert(err, jc.ErrorIsNil)
  3006  
  3007  	wc.AssertChange(uri2.String())
  3008  	wc.AssertNoChange()
  3009  }
  3010  
  3011  func (s *SecretsRemoteConsumerWatcherSuite) TestWatchConsumedDeleted(c *gc.C) {
  3012  	w, uri := s.setupWatcher(c)
  3013  	wc := testing.NewStringsWatcherC(c, w)
  3014  	defer testing.AssertStop(c, w)
  3015  
  3016  	err := s.State.SaveSecretRemoteConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3017  		CurrentRevision: 1,
  3018  	})
  3019  	c.Assert(err, jc.ErrorIsNil)
  3020  	wc.AssertNoChange()
  3021  	err = s.State.SaveSecretRemoteConsumer(uri, names.NewApplicationTag("baz"), &secrets.SecretConsumerMetadata{
  3022  		CurrentRevision: 1,
  3023  	})
  3024  	c.Assert(err, jc.ErrorIsNil)
  3025  	wc.AssertNoChange()
  3026  
  3027  	_, err = s.store.DeleteSecret(uri)
  3028  	c.Assert(err, jc.ErrorIsNil)
  3029  	wc.AssertChange(uri.String())
  3030  	wc.AssertNoChange()
  3031  }
  3032  
  3033  type SecretsObsoleteWatcherSuite struct {
  3034  	testing.StateSuite
  3035  	store state.SecretsStore
  3036  
  3037  	ownerApp  *state.Application
  3038  	ownerUnit *state.Unit
  3039  }
  3040  
  3041  var _ = gc.Suite(&SecretsObsoleteWatcherSuite{})
  3042  
  3043  func (s *SecretsObsoleteWatcherSuite) SetUpTest(c *gc.C) {
  3044  	s.StateSuite.SetUpTest(c)
  3045  	s.store = state.NewSecrets(s.State)
  3046  	s.ownerApp = s.Factory.MakeApplication(c, nil)
  3047  	s.ownerUnit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: s.ownerApp})
  3048  }
  3049  
  3050  func (s *SecretsObsoleteWatcherSuite) setupWatcher(c *gc.C, forAutoPrune bool) (state.StringsWatcher, *secrets.URI) {
  3051  	uri := secrets.NewURI()
  3052  	cp := state.CreateSecretParams{
  3053  		Version: 1,
  3054  		Owner:   s.ownerApp.Tag(),
  3055  		UpdateSecretParams: state.UpdateSecretParams{
  3056  			LeaderToken: &fakeToken{},
  3057  			Data:        map[string]string{"foo": "bar"},
  3058  		},
  3059  	}
  3060  	if forAutoPrune {
  3061  		cp.Owner = names.NewModelTag(s.State.ModelUUID())
  3062  	}
  3063  	_, err := s.store.CreateSecret(uri, cp)
  3064  	c.Assert(err, jc.ErrorIsNil)
  3065  	var w state.StringsWatcher
  3066  	if forAutoPrune {
  3067  		w, err = s.store.WatchRevisionsToPrune(
  3068  			[]names.Tag{names.NewModelTag(s.State.ModelUUID())},
  3069  		)
  3070  	} else {
  3071  		w, err = s.store.WatchObsolete(
  3072  			[]names.Tag{s.ownerApp.Tag(), s.ownerUnit.Tag()},
  3073  		)
  3074  	}
  3075  	c.Assert(err, jc.ErrorIsNil)
  3076  
  3077  	wc := testing.NewStringsWatcherC(c, w)
  3078  	wc.AssertChange()
  3079  	wc.AssertNoChange()
  3080  	return w, uri
  3081  }
  3082  
  3083  func (s *SecretsObsoleteWatcherSuite) TestWatcherStartStop(c *gc.C) {
  3084  	w, _ := s.setupWatcher(c, false)
  3085  	testing.AssertStop(c, w)
  3086  }
  3087  
  3088  func (s *SecretsObsoleteWatcherSuite) TestWatchObsoleteRevisions(c *gc.C) {
  3089  	w, uri := s.setupWatcher(c, false)
  3090  	wc := testing.NewStringsWatcherC(c, w)
  3091  	defer testing.AssertStop(c, w)
  3092  
  3093  	err := s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3094  		CurrentRevision: 1,
  3095  	})
  3096  	c.Assert(err, jc.ErrorIsNil)
  3097  	wc.AssertNoChange()
  3098  
  3099  	p := state.UpdateSecretParams{
  3100  		LeaderToken: &fakeToken{},
  3101  		Data:        map[string]string{"foo": "bar2"},
  3102  	}
  3103  	_, err = s.store.UpdateSecret(uri, p)
  3104  	c.Assert(err, jc.ErrorIsNil)
  3105  	wc.AssertNoChange()
  3106  
  3107  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo2"), &secrets.SecretConsumerMetadata{
  3108  		CurrentRevision: 2,
  3109  	})
  3110  	c.Assert(err, jc.ErrorIsNil)
  3111  	wc.AssertNoChange()
  3112  
  3113  	// The previous consumer of rev 1 now uses rev 2; rev 1 is orphaned.
  3114  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3115  		CurrentRevision: 2,
  3116  	})
  3117  	c.Assert(err, jc.ErrorIsNil)
  3118  	wc.AssertChange(uri.String() + "/1")
  3119  	wc.AssertNoChange()
  3120  
  3121  	// The latest added revision is never obsolete.
  3122  	p = state.UpdateSecretParams{
  3123  		LeaderToken: &fakeToken{},
  3124  		Data:        map[string]string{"foo": "bar3"},
  3125  	}
  3126  	_, err = s.store.UpdateSecret(uri, p)
  3127  	c.Assert(err, jc.ErrorIsNil)
  3128  	wc.AssertChange(uri.String() + "/1")
  3129  	wc.AssertNoChange()
  3130  
  3131  	// New revision 4 added, so rev 3 is now also obsolete.
  3132  	p = state.UpdateSecretParams{
  3133  		LeaderToken: &fakeToken{},
  3134  		Data:        map[string]string{"foo": "bar4"},
  3135  	}
  3136  	_, err = s.store.UpdateSecret(uri, p)
  3137  	c.Assert(err, jc.ErrorIsNil)
  3138  	wc.AssertChange(uri.String()+"/1", uri.String()+"/3")
  3139  	wc.AssertNoChange()
  3140  }
  3141  
  3142  func (s *SecretsObsoleteWatcherSuite) TestWatchObsoleteRevisionsToPrune(c *gc.C) {
  3143  	w, uri := s.setupWatcher(c, true)
  3144  	wc := testing.NewStringsWatcherC(c, w)
  3145  	defer testing.AssertStop(c, w)
  3146  
  3147  	err := s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3148  		CurrentRevision: 1,
  3149  	})
  3150  	c.Assert(err, jc.ErrorIsNil)
  3151  	wc.AssertNoChange()
  3152  
  3153  	p := state.UpdateSecretParams{
  3154  		LeaderToken: &fakeToken{},
  3155  		Data:        map[string]string{"foo": "bar2"},
  3156  	}
  3157  	_, err = s.store.UpdateSecret(uri, p)
  3158  	c.Assert(err, jc.ErrorIsNil)
  3159  	// No change because AutoPrune is not turned on.
  3160  	wc.AssertNoChange()
  3161  
  3162  	// The previous consumer of rev 1 now uses rev 2; rev 1 is orphaned.
  3163  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3164  		CurrentRevision: 2,
  3165  	})
  3166  	c.Assert(err, jc.ErrorIsNil)
  3167  	// No change because AutoPrune is not turned on.
  3168  	wc.AssertNoChange()
  3169  
  3170  	// turn on AutoPrune.
  3171  	p = state.UpdateSecretParams{
  3172  		AutoPrune:   ptr(true),
  3173  		LeaderToken: &fakeToken{},
  3174  		Data:        map[string]string{"foo": "bar3"},
  3175  	}
  3176  	_, err = s.store.UpdateSecret(uri, p)
  3177  	c.Assert(err, jc.ErrorIsNil)
  3178  	wc.AssertChange(uri.String() + "/1")
  3179  	wc.AssertNoChange()
  3180  
  3181  	// New revision 4 added, so rev 3 is now also obsolete.
  3182  	p = state.UpdateSecretParams{
  3183  		LeaderToken: &fakeToken{},
  3184  		Data:        map[string]string{"foo": "bar4"},
  3185  	}
  3186  	_, err = s.store.UpdateSecret(uri, p)
  3187  	c.Assert(err, jc.ErrorIsNil)
  3188  	wc.AssertChange(uri.String()+"/1", uri.String()+"/3")
  3189  	wc.AssertNoChange()
  3190  
  3191  	// The previous consumer of rev 1 now uses rev 2; rev 1 is orphaned.
  3192  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3193  		CurrentRevision: 4,
  3194  	})
  3195  	c.Assert(err, jc.ErrorIsNil)
  3196  	wc.AssertChange(uri.String()+"/1", uri.String()+"/2", uri.String()+"/3")
  3197  	wc.AssertNoChange()
  3198  }
  3199  
  3200  func (s *SecretsObsoleteWatcherSuite) TestWatchOwnedDeleted(c *gc.C) {
  3201  	w, uri := s.setupWatcher(c, false)
  3202  	wc := testing.NewStringsWatcherC(c, w)
  3203  	defer testing.AssertStop(c, w)
  3204  
  3205  	owner2 := s.Factory.MakeApplication(c, &factory.ApplicationParams{
  3206  		Charm: s.Factory.MakeCharm(c, &factory.CharmParams{
  3207  			Name: "wordpress",
  3208  		}),
  3209  	})
  3210  	uri2 := secrets.NewURI()
  3211  	cp := state.CreateSecretParams{
  3212  		Version: 1,
  3213  		Owner:   owner2.Tag(),
  3214  		UpdateSecretParams: state.UpdateSecretParams{
  3215  			LeaderToken: &fakeToken{},
  3216  			Data:        map[string]string{"foo": "bar"},
  3217  		},
  3218  	}
  3219  	_, err := s.store.CreateSecret(uri2, cp)
  3220  	c.Assert(err, jc.ErrorIsNil)
  3221  
  3222  	uri3 := secrets.NewURI()
  3223  	cp = state.CreateSecretParams{
  3224  		Version: 1,
  3225  		Owner:   s.ownerUnit.Tag(),
  3226  		UpdateSecretParams: state.UpdateSecretParams{
  3227  			LeaderToken: &fakeToken{},
  3228  			Data:        map[string]string{"foo": "bar"},
  3229  		},
  3230  	}
  3231  	_, err = s.store.CreateSecret(uri3, cp)
  3232  	c.Assert(err, jc.ErrorIsNil)
  3233  
  3234  	_, err = s.store.DeleteSecret(uri)
  3235  	c.Assert(err, jc.ErrorIsNil)
  3236  	wc.AssertChange(uri.String())
  3237  	wc.AssertNoChange()
  3238  
  3239  	_, err = s.store.DeleteSecret(uri2)
  3240  	c.Assert(err, jc.ErrorIsNil)
  3241  	wc.AssertNoChange()
  3242  
  3243  	_, err = s.store.DeleteSecret(uri3)
  3244  	c.Assert(err, jc.ErrorIsNil)
  3245  	wc.AssertChange(uri3.String())
  3246  	wc.AssertNoChange()
  3247  }
  3248  
  3249  func (s *SecretsObsoleteWatcherSuite) TestWatchDeletedSupercedesObsolete(c *gc.C) {
  3250  	w, uri := s.setupWatcher(c, false)
  3251  	wc := testing.NewStringsWatcherC(c, w)
  3252  	defer testing.AssertStop(c, w)
  3253  
  3254  	err := s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3255  		CurrentRevision: 1,
  3256  	})
  3257  	c.Assert(err, jc.ErrorIsNil)
  3258  	wc.AssertNoChange()
  3259  
  3260  	p := state.UpdateSecretParams{
  3261  		LeaderToken: &fakeToken{},
  3262  		Data:        map[string]string{"foo": "bar2"},
  3263  	}
  3264  	_, err = s.store.UpdateSecret(uri, p)
  3265  	c.Assert(err, jc.ErrorIsNil)
  3266  	wc.AssertNoChange()
  3267  
  3268  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo2"), &secrets.SecretConsumerMetadata{
  3269  		CurrentRevision: 2,
  3270  	})
  3271  	c.Assert(err, jc.ErrorIsNil)
  3272  	wc.AssertNoChange()
  3273  
  3274  	// The previous consumer of rev 1 now uses rev 2; rev 1 is orphaned.
  3275  	err = s.State.SaveSecretConsumer(uri, names.NewApplicationTag("foo"), &secrets.SecretConsumerMetadata{
  3276  		CurrentRevision: 2,
  3277  	})
  3278  	c.Assert(err, jc.ErrorIsNil)
  3279  
  3280  	// Deleting the secret removes any pending orphaned changes.
  3281  	_, err = s.store.DeleteSecret(uri)
  3282  	c.Assert(err, jc.ErrorIsNil)
  3283  	wc.AssertChange(uri.String())
  3284  	wc.AssertNoChange()
  3285  }