github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/certupdater/certupdater_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package certupdater_test 5 6 import ( 7 "crypto/x509" 8 stdtesting "testing" 9 "time" 10 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/cert" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/network" 18 "github.com/juju/juju/state" 19 coretesting "github.com/juju/juju/testing" 20 "github.com/juju/juju/worker/certupdater" 21 ) 22 23 func TestPackage(t *stdtesting.T) { 24 gc.TestingT(t) 25 } 26 27 type CertUpdaterSuite struct { 28 coretesting.BaseSuite 29 } 30 31 var _ = gc.Suite(&CertUpdaterSuite{}) 32 33 type mockNotifyWatcher struct { 34 changes <-chan struct{} 35 } 36 37 func (w *mockNotifyWatcher) Changes() <-chan struct{} { 38 return w.changes 39 } 40 41 func (*mockNotifyWatcher) Stop() error { 42 return nil 43 } 44 45 func (*mockNotifyWatcher) Kill() {} 46 47 func (*mockNotifyWatcher) Wait() error { 48 return nil 49 } 50 51 func (*mockNotifyWatcher) Err() error { 52 return nil 53 } 54 55 func newMockNotifyWatcher(changes <-chan struct{}) state.NotifyWatcher { 56 return &mockNotifyWatcher{changes} 57 } 58 59 type mockMachine struct { 60 changes chan struct{} 61 } 62 63 func (m *mockMachine) WatchAddresses() state.NotifyWatcher { 64 return newMockNotifyWatcher(m.changes) 65 } 66 67 func (m *mockMachine) Addresses() (addresses []network.Address) { 68 return []network.Address{{ 69 Value: "0.1.2.3", 70 }} 71 } 72 73 type mockStateServingGetter struct{} 74 75 func (g *mockStateServingGetter) StateServingInfo() (params.StateServingInfo, bool) { 76 return params.StateServingInfo{ 77 Cert: coretesting.ServerCert, 78 PrivateKey: coretesting.ServerKey, 79 CAPrivateKey: coretesting.CAKey, 80 StatePort: 123, 81 APIPort: 456, 82 }, true 83 } 84 85 type mockConfigGetter struct{} 86 87 func (g *mockConfigGetter) EnvironConfig() (*config.Config, error) { 88 return config.New(config.NoDefaults, coretesting.FakeConfig()) 89 90 } 91 92 func (s *CertUpdaterSuite) TestStartStop(c *gc.C) { 93 setter := func(info params.StateServingInfo, dying <-chan struct{}) error { 94 return nil 95 } 96 changes := make(chan struct{}) 97 certChangedChan := make(chan params.StateServingInfo) 98 worker := certupdater.NewCertificateUpdater( 99 &mockMachine{changes}, &mockStateServingGetter{}, &mockConfigGetter{}, setter, certChangedChan, 100 ) 101 worker.Kill() 102 c.Assert(worker.Wait(), gc.IsNil) 103 } 104 105 func (s *CertUpdaterSuite) TestAddressChange(c *gc.C) { 106 var srvCert *x509.Certificate 107 updated := make(chan struct{}) 108 setter := func(info params.StateServingInfo, dying <-chan struct{}) error { 109 var err error 110 srvCert, err = cert.ParseCert(info.Cert) 111 c.Assert(err, jc.ErrorIsNil) 112 sanIPs := make([]string, len(srvCert.IPAddresses)) 113 for i, ip := range srvCert.IPAddresses { 114 sanIPs[i] = ip.String() 115 } 116 if len(sanIPs) == 1 && sanIPs[0] == "0.1.2.3" { 117 close(updated) 118 } 119 return nil 120 } 121 changes := make(chan struct{}) 122 certChangedChan := make(chan params.StateServingInfo) 123 worker := certupdater.NewCertificateUpdater( 124 &mockMachine{changes}, &mockStateServingGetter{}, &mockConfigGetter{}, setter, certChangedChan, 125 ) 126 defer func() { c.Assert(worker.Wait(), gc.IsNil) }() 127 defer worker.Kill() 128 129 changes <- struct{}{} 130 // Certificate should be updated with the address value. 131 select { 132 case <-updated: 133 case <-time.After(coretesting.LongWait): 134 c.Fatalf("timed out waiting for certificate to be updated") 135 } 136 137 // The server certificates must report "juju-apiserver" as a DNS 138 // name for backwards-compatibility with API clients. They must 139 // also report "juju-mongodb" because these certicates are also 140 // used for serving MongoDB connections. 141 c.Assert(srvCert.DNSNames, gc.DeepEquals, 142 []string{"localhost", "juju-apiserver", "juju-mongodb", "anything"}) 143 } 144 145 type mockStateServingGetterNoCAKey struct{} 146 147 func (g *mockStateServingGetterNoCAKey) StateServingInfo() (params.StateServingInfo, bool) { 148 return params.StateServingInfo{ 149 Cert: coretesting.ServerCert, 150 PrivateKey: coretesting.ServerKey, 151 StatePort: 123, 152 APIPort: 456, 153 }, true 154 155 } 156 157 func (s *CertUpdaterSuite) TestAddressChangeNoCAKey(c *gc.C) { 158 updated := make(chan struct{}) 159 setter := func(info params.StateServingInfo, dying <-chan struct{}) error { 160 close(updated) 161 return nil 162 } 163 changes := make(chan struct{}) 164 certChangedChan := make(chan params.StateServingInfo) 165 worker := certupdater.NewCertificateUpdater( 166 &mockMachine{changes}, &mockStateServingGetterNoCAKey{}, &mockConfigGetter{}, setter, certChangedChan, 167 ) 168 defer func() { c.Assert(worker.Wait(), gc.IsNil) }() 169 defer worker.Kill() 170 171 changes <- struct{}{} 172 // Certificate should not be updated with the address value. 173 select { 174 case <-time.After(coretesting.ShortWait): 175 case <-updated: 176 c.Fatalf("set state serving info unexpectedly called") 177 } 178 }