func (s *CacheAPIEndpointsSuite) TestResolveSkippedWhenHostnamesUnchanged(c *gc.C) { // Test that if new endpoints hostnames are the same as the // cached, no DNS resolution happens (i.e. we don't resolve on // every connection, but as needed). info := s.store.CreateInfo("env-name") hps := network.NewHostPorts(1234, "8.8.8.8", "example.com", "10.0.0.1", ) info.SetAPIEndpoint(configstore.APIEndpoint{ Hostnames: network.HostPortsToStrings(hps), }) err := info.Write() c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( info, [][]network.HostPort{hps}, network.HostPort{}, ) c.Assert(addrs, gc.IsNil) c.Assert(hosts, gc.IsNil) c.Assert(changed, jc.IsFalse) c.Assert(s.resolveNumCalls, gc.Equals, 0) c.Assert( c.GetTestLog(), jc.Contains, "DEBUG juju.api API hostnames unchanged - not resolving", ) }
func (s *CacheAPIEndpointsSuite) TestResolveSkippedWhenHostnamesUnchanged(c *gc.C) { // Test that if new endpoints hostnames are the same as the // cached, no DNS resolution happens (i.e. we don't resolve on // every connection, but as needed). hps := network.NewHostPorts(1234, "8.8.8.8", "example.com", "10.0.0.1", ) controllerDetails := jujuclient.ControllerDetails{ ControllerUUID: fakeUUID, CACert: "certificate", UnresolvedAPIEndpoints: network.HostPortsToStrings(hps), } err := s.ControllerStore.AddController("controller-name", controllerDetails) c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( controllerDetails, [][]network.HostPort{hps}, ) c.Assert(addrs, gc.IsNil) c.Assert(hosts, gc.IsNil) c.Assert(changed, jc.IsFalse) c.Assert(s.resolveNumCalls, gc.Equals, 0) c.Assert( c.GetTestLog(), jc.Contains, "DEBUG juju.juju API hostnames unchanged - not resolving", ) }
func (s *CacheAPIEndpointsSuite) TestAfterResolvingUnchangedAddressesNotCached(c *gc.C) { // Test that if new endpoints hostnames are different than the // cached hostnames, but after resolving the addresses match the // cached addresses, the cache is not changed. // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) strUnsorted := network.HostPortsToStrings(unsortedHPs) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) controllerDetails := jujuclient.ControllerDetails{ ControllerUUID: fakeUUID, CACert: "certificate", UnresolvedAPIEndpoints: strUnsorted, APIEndpoints: strResolved, } err := s.ControllerStore.AddController("controller-name", controllerDetails) c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( controllerDetails, [][]network.HostPort{unsortedHPs}, ) c.Assert(addrs, gc.IsNil) c.Assert(hosts, gc.IsNil) c.Assert(changed, jc.IsFalse) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.juju API hostnames changed from %v to %v - resolving hostnames", unsortedHPs, sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = "DEBUG juju.juju API addresses unchanged" c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (s *CacheAPIEndpointsSuite) TestResolveCalledWithChangedHostnames(c *gc.C) { // Test that if new endpoints hostnames are different than the // cached hostnames DNS resolution happens and we compare resolved // addresses. // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) strUnsorted := network.HostPortsToStrings(unsortedHPs) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) strSorted := network.HostPortsToStrings(sortedHPs) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) controllerDetails := jujuclient.ControllerDetails{ ControllerUUID: fakeUUID, CACert: "certificate", UnresolvedAPIEndpoints: strUnsorted, } err := s.ControllerStore.AddController("controller-name", controllerDetails) c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( controllerDetails, [][]network.HostPort{unsortedHPs}, ) c.Assert(addrs, jc.DeepEquals, strResolved) c.Assert(hosts, jc.DeepEquals, strSorted) c.Assert(changed, jc.IsTrue) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.juju API hostnames changed from %v to %v - resolving hostnames", unsortedHPs, sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = fmt.Sprintf("INFO juju.juju new API addresses to cache %v", resolvedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (s *CacheAPIEndpointsSuite) TestResolveCalledWithChangedHostnames(c *gc.C) { // Test that if new endpoints hostnames are different than the // cached hostnames DNS resolution happens and we compare resolved // addresses. info := s.store.CreateInfo("env-name") // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) strUnsorted := network.HostPortsToStrings(unsortedHPs) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) strSorted := network.HostPortsToStrings(sortedHPs) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) info.SetAPIEndpoint(configstore.APIEndpoint{ Hostnames: strUnsorted, }) err := info.Write() c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( info, [][]network.HostPort{unsortedHPs}, network.HostPort{}, ) c.Assert(addrs, jc.DeepEquals, strResolved) c.Assert(hosts, jc.DeepEquals, strSorted) c.Assert(changed, jc.IsTrue) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.api API hostnames changed from %v to %v - resolving hostnames", unsortedHPs, sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = fmt.Sprintf("INFO juju.api new API addresses to cache %v", resolvedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (s *CacheAPIEndpointsSuite) TestAfterResolvingUnchangedAddressesNotCached(c *gc.C) { // Test that if new endpoints hostnames are different than the // cached hostnames, but after resolving the addresses match the // cached addresses, the cache is not changed. info := s.store.CreateInfo("env-name") // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) strUnsorted := network.HostPortsToStrings(unsortedHPs) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) info.SetAPIEndpoint(configstore.APIEndpoint{ Hostnames: strUnsorted, Addresses: strResolved, }) err := info.Write() c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( info, [][]network.HostPort{unsortedHPs}, network.HostPort{}, ) c.Assert(addrs, gc.IsNil) c.Assert(hosts, gc.IsNil) c.Assert(changed, jc.IsFalse) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.api API hostnames changed from %v to %v - resolving hostnames", unsortedHPs, sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = "DEBUG juju.api API addresses unchanged" c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (s *CacheAPIEndpointsSuite) TestResolveCalledWithInitialEndpoints(c *gc.C) { // Test that if no hostnames exist cached we call resolve (i.e. // simulate the behavior right after bootstrap) // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) strSorted := network.HostPortsToStrings(sortedHPs) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) controllerDetails := jujuclient.ControllerDetails{ ControllerUUID: fakeUUID, CACert: "certificate", } err := s.ControllerStore.AddController("controller-name", controllerDetails) c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( controllerDetails, [][]network.HostPort{unsortedHPs}, ) c.Assert(addrs, jc.DeepEquals, strResolved) c.Assert(hosts, jc.DeepEquals, strSorted) c.Assert(changed, jc.IsTrue) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.juju API hostnames %v - resolving hostnames", sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = fmt.Sprintf("INFO juju.juju new API addresses to cache %v", resolvedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (c *LoginCommand) cacheConnectionInfo(serverDetails envcmd.ServerFile, apiState api.Connection) (configstore.EnvironInfo, error) { store, err := configstore.Default() if err != nil { return nil, errors.Trace(err) } serverInfo := store.CreateInfo(c.Name) serverTag, err := apiState.ServerTag() if err != nil { return nil, errors.Wrap(err, errors.New("juju system too old to support login")) } connectedAddresses, err := network.ParseHostPorts(apiState.Addr()) if err != nil { // Should never happen, since we've just connected with it. return nil, errors.Annotatef(err, "invalid API address %q", apiState.Addr()) } addressConnectedTo := connectedAddresses[0] addrs, hosts, changed := juju.PrepareEndpointsForCaching(serverInfo, apiState.APIHostPorts(), addressConnectedTo) if !changed { logger.Infof("api addresses: %v", apiState.APIHostPorts()) logger.Infof("address connected to: %v", addressConnectedTo) return nil, errors.New("no addresses returned from prepare for caching") } serverInfo.SetAPICredentials( configstore.APICredentials{ User: serverDetails.Username, Password: serverDetails.Password, }) serverInfo.SetAPIEndpoint(configstore.APIEndpoint{ Addresses: addrs, Hostnames: hosts, CACert: serverDetails.CACert, ServerUUID: serverTag.Id(), }) if err = serverInfo.Write(); err != nil { return nil, errors.Trace(err) } return serverInfo, nil }
func (s *CacheAPIEndpointsSuite) TestResolveCalledWithInitialEndpoints(c *gc.C) { // Test that if no hostnames exist cached we call resolve (i.e. // simulate the behavior right after bootstrap) info := s.store.CreateInfo("env-name") // Because Hostnames are sorted before caching, reordering them // will simulate they have changed. unsortedHPs := network.NewHostPorts(1234, "ipv4.example.com", "8.8.8.8", "ipv6.example.com", "10.0.0.1", ) sortedHPs := network.NewHostPorts(1234, "8.8.8.8", "ipv4.example.com", "ipv6.example.com", "10.0.0.1", ) strSorted := network.HostPortsToStrings(sortedHPs) resolvedHPs := network.NewHostPorts(1234, "0.1.2.1", // from ipv4.example.com "8.8.8.8", "10.0.0.1", "fc00::2", // from ipv6.example.com ) strResolved := network.HostPortsToStrings(resolvedHPs) info.SetAPIEndpoint(configstore.APIEndpoint{}) err := info.Write() c.Assert(err, jc.ErrorIsNil) addrs, hosts, changed := juju.PrepareEndpointsForCaching( info, [][]network.HostPort{unsortedHPs}, network.HostPort{}, ) c.Assert(addrs, jc.DeepEquals, strResolved) c.Assert(hosts, jc.DeepEquals, strSorted) c.Assert(changed, jc.IsTrue) c.Assert(s.resolveNumCalls, gc.Equals, 1) c.Assert(s.numResolved, gc.Equals, 2) expectLog := fmt.Sprintf("DEBUG juju.api API hostnames %v - resolving hostnames", sortedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) expectLog = fmt.Sprintf("INFO juju.api new API addresses to cache %v", resolvedHPs) c.Assert(c.GetTestLog(), jc.Contains, expectLog) }
func (s *BootstrapSuite) run(c *gc.C, test bootstrapTest) (restore gitjujutesting.Restorer) { // Create home with dummy provider and remove all // of its envtools. env := resetJujuHome(c, "peckham") // Although we're testing PrepareEndpointsForCaching interactions // separately in the juju package, here we just ensure it gets // called with the right arguments. prepareCalled := false addrConnectedTo := "localhost:17070" restore = gitjujutesting.PatchValue( &prepareEndpointsForCaching, func(info configstore.EnvironInfo, hps [][]network.HostPort, addr network.HostPort) (_, _ []string, _ bool) { prepareCalled = true addrs, hosts, changed := juju.PrepareEndpointsForCaching(info, hps, addr) // Because we're bootstrapping the addresses will always // change, as there's no .jenv file saved yet. c.Assert(changed, jc.IsTrue) return addrs, hosts, changed }, ) if test.version != "" { useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1) origVersion := version.Current version.Current = version.MustParseBinary(useVersion) restore = restore.Add(func() { version.Current = origVersion }) } if test.hostArch != "" { origArch := arch.HostArch arch.HostArch = func() string { return test.hostArch } restore = restore.Add(func() { arch.HostArch = origArch }) } // Run command and check for uploads. opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand)), test.args...) // Check for remaining operations/errors. if test.err != "" { err := <-errc c.Assert(err, gc.NotNil) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, test.err) return restore } if !c.Check(<-errc, gc.IsNil) { return restore } opBootstrap := (<-opc).(dummy.OpBootstrap) c.Check(opBootstrap.Env, gc.Equals, "peckham") c.Check(opBootstrap.Args.Constraints, gc.DeepEquals, test.constraints) c.Check(opBootstrap.Args.Placement, gc.Equals, test.placement) opFinalizeBootstrap := (<-opc).(dummy.OpFinalizeBootstrap) c.Check(opFinalizeBootstrap.Env, gc.Equals, "peckham") c.Check(opFinalizeBootstrap.InstanceConfig.Tools, gc.NotNil) if test.upload != "" { c.Check(opFinalizeBootstrap.InstanceConfig.Tools.Version.String(), gc.Equals, test.upload) } store, err := configstore.Default() c.Assert(err, jc.ErrorIsNil) // Check a CA cert/key was generated by reloading the environment. env, err = environs.NewFromName("peckham", store) c.Assert(err, jc.ErrorIsNil) _, hasCert := env.Config().CACert() c.Check(hasCert, jc.IsTrue) _, hasKey := env.Config().CAPrivateKey() c.Check(hasKey, jc.IsTrue) info, err := store.ReadInfo("peckham") c.Assert(err, jc.ErrorIsNil) c.Assert(info, gc.NotNil) c.Assert(prepareCalled, jc.IsTrue) c.Assert(info.APIEndpoint().Addresses, gc.DeepEquals, []string{addrConnectedTo}) return restore }