Пример #1
0
func (s *BootstrapSuite) TestGUIArchiveInfoError(c *gc.C) {
	if runtime.GOOS == "windows" {
		// TODO frankban: skipping for now due to chmod problems with mode 0000
		// on Windows. We will re-enable this test after further investigation:
		// "jujud bootstrap" is never run on Windows anyway.
		c.Skip("needs chmod investigation")
	}
	dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
	info := filepath.Join(dir, "downloaded-gui.txt")
	err := os.Chmod(info, 0000)
	c.Assert(err, jc.ErrorIsNil)
	defer os.Chmod(info, 0600)
	_, cmd, err := s.initBootstrapCommand(
		c, nil, "--model-config", s.b64yamlControllerModelConfig,
		"--hosted-model-config", s.b64yamlHostedModelConfig,
		"--instance-id", string(s.instanceId))
	c.Assert(err, jc.ErrorIsNil)

	var tw loggo.TestWriter
	err = loggo.RegisterWriter("bootstrap-test", &tw, loggo.DEBUG)
	c.Assert(err, jc.ErrorIsNil)
	defer loggo.RemoveWriter("bootstrap-test")

	err = cmd.Run(nil)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{
		loggo.WARNING,
		`cannot set up Juju GUI: cannot fetch GUI info: cannot read GUI metadata in tools directory: .*`,
	}})
}
Пример #2
0
func (s *guiSuite) TestGUIDirectory(c *gc.C) {
	storage, err := s.State.GUIStorage()
	c.Assert(err, jc.ErrorIsNil)
	defer storage.Close()

	// Create a Juju GUI archive and save it into the storage.
	indexContent := "<!DOCTYPE html><html><body>Exterminate!</body></html>"
	vers := version.MustParse("2.0.0")
	hash := setupGUIArchive(c, storage, vers.String(), map[string]string{
		guiIndexPath:         indexContent,
		apiserver.SpritePath: "",
	})
	err = s.State.GUISetVersion(vers)
	c.Assert(err, jc.ErrorIsNil)

	// Initially the GUI directory on the server is empty.
	baseDir := agenttools.SharedGUIDir(s.DataDir())
	c.Assert(baseDir, jc.DoesNotExist)

	// Make a request for the Juju GUI.
	resp := s.sendRequest(c, httpRequestParams{
		url: s.guiURL(c, "", "/"),
	})
	body := assertResponse(c, resp, http.StatusOK, "text/html; charset=utf-8")
	c.Assert(string(body), gc.Equals, indexContent)

	// Now the GUI is stored on disk, in a directory corresponding to its
	// archive SHA256 hash.
	indexPath := filepath.Join(baseDir, hash, guiIndexPath)
	c.Assert(indexPath, jc.IsNonEmptyFile)
	b, err := ioutil.ReadFile(indexPath)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(string(b), gc.Equals, indexContent)
}
Пример #3
0
// populateGUIArchive stores the uploaded Juju GUI archive in provider storage,
// updates the GUI metadata and set the current Juju GUI version.
func (c *BootstrapCommand) populateGUIArchive(st *state.State, env environs.Environ) error {
	agentConfig := c.CurrentConfig()
	dataDir := agentConfig.DataDir()
	guistorage, err := st.GUIStorage()
	if err != nil {
		return errors.Trace(err)
	}
	defer guistorage.Close()
	gui, err := agenttools.ReadGUIArchive(dataDir)
	if err != nil {
		return errors.Annotate(err, "cannot fetch GUI info")
	}
	f, err := os.Open(filepath.Join(agenttools.SharedGUIDir(dataDir), "gui.tar.bz2"))
	if err != nil {
		return errors.Annotate(err, "cannot read GUI archive")
	}
	defer f.Close()
	if err := guistorage.Add(f, binarystorage.Metadata{
		Version: gui.Version.String(),
		Size:    gui.Size,
		SHA256:  gui.SHA256,
	}); err != nil {
		return errors.Annotate(err, "cannot store GUI archive")
	}
	if err = st.GUISetVersion(gui.Version); err != nil {
		return errors.Annotate(err, "cannot set current GUI version")
	}
	return nil
}
Пример #4
0
func (s *BootstrapSuite) writeDownloadedGUI(c *gc.C, gui *tools.GUIArchive) {
	guiDir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
	err := os.MkdirAll(guiDir, 0755)
	c.Assert(err, jc.ErrorIsNil)
	data, err := json.Marshal(gui)
	c.Assert(err, jc.ErrorIsNil)
	err = ioutil.WriteFile(filepath.Join(guiDir, "downloaded-gui.txt"), data, 0644)
	c.Assert(err, jc.ErrorIsNil)
}
Пример #5
0
func (t *ToolsSuite) TestReadGUIArchiveErrorNotValid(c *gc.C) {
	dir := agenttools.SharedGUIDir(t.dataDir)
	err := os.MkdirAll(dir, agenttools.DirPerm)
	c.Assert(err, jc.ErrorIsNil)

	err = ioutil.WriteFile(filepath.Join(dir, agenttools.GUIArchiveFile), []byte(" \t\n"), 0644)
	c.Assert(err, jc.ErrorIsNil)

	gui, err := agenttools.ReadGUIArchive(t.dataDir)
	c.Assert(err, gc.ErrorMatches, "invalid GUI metadata in tools directory .*")
	c.Assert(gui, gc.IsNil)
}
Пример #6
0
Файл: gui.go Проект: kat-co/juju
// ensureFiles checks that the GUI files are available on disk.
// If they are not, it means this is the first time this Juju GUI version is
// accessed. In this case, retrieve the Juju GUI archive from the storage and
// uncompress it to disk. This function returns the current GUI root directory
// and archive hash.
func (gr *guiRouter) ensureFiles(req *http.Request) (rootDir string, hash string, err error) {
	// Retrieve the Juju GUI info from the GUI storage.
	st, err := gr.ctxt.stateForRequestUnauthenticated(req)
	if err != nil {
		return "", "", errors.Annotate(err, "cannot open state")
	}
	storage, err := st.GUIStorage()
	if err != nil {
		return "", "", errors.Annotate(err, "cannot open GUI storage")
	}
	defer storage.Close()
	vers, hash, err := guiVersionAndHash(st, storage)
	if err != nil {
		return "", "", errors.Trace(err)
	}
	logger.Debugf("serving Juju GUI version %s", vers)

	// Check if the current Juju GUI archive has been already expanded on disk.
	baseDir := agenttools.SharedGUIDir(gr.dataDir)
	// Note that we include the hash in the root directory so that when the GUI
	// archive changes we can be sure that clients will not use files from
	// mixed versions.
	rootDir = filepath.Join(baseDir, hash)
	info, err := os.Stat(rootDir)
	if err == nil {
		if info.IsDir() {
			return rootDir, hash, nil
		}
		return "", "", errors.Errorf("cannot use Juju GUI root directory %q: not a directory", rootDir)
	}
	if !os.IsNotExist(err) {
		return "", "", errors.Annotate(err, "cannot stat Juju GUI root directory")
	}

	// Fetch the Juju GUI archive from the GUI storage and expand it.
	_, r, err := storage.Open(vers)
	if err != nil {
		return "", "", errors.Annotatef(err, "cannot find GUI archive version %q", vers)
	}
	defer r.Close()
	if err := os.MkdirAll(baseDir, 0755); err != nil {
		return "", "", errors.Annotate(err, "cannot create Juju GUI base directory")
	}
	guiDir := "jujugui-" + vers + "/jujugui"
	if err := uncompressGUI(r, guiDir, rootDir); err != nil {
		return "", "", errors.Annotate(err, "cannot uncompress Juju GUI archive")
	}
	return rootDir, hash, nil
}
Пример #7
0
func (t *ToolsSuite) TestReadGUIArchiveSuccess(c *gc.C) {
	dir := agenttools.SharedGUIDir(t.dataDir)
	err := os.MkdirAll(dir, agenttools.DirPerm)
	c.Assert(err, jc.ErrorIsNil)

	expectGUI := coretest.GUIArchive{
		Version: version.MustParse("2.0.42"),
		URL:     "file:///path/to/gui",
		SHA256:  "hash",
		Size:    47,
	}
	b, err := json.Marshal(expectGUI)
	c.Assert(err, jc.ErrorIsNil)
	err = ioutil.WriteFile(filepath.Join(dir, agenttools.GUIArchiveFile), b, 0644)
	c.Assert(err, jc.ErrorIsNil)

	gui, err := agenttools.ReadGUIArchive(t.dataDir)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(*gui, gc.Equals, expectGUI)
}
Пример #8
0
func (s *BootstrapSuite) TestGUIArchiveError(c *gc.C) {
	dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
	archive := filepath.Join(dir, "gui.tar.bz2")
	err := os.Remove(archive)
	c.Assert(err, jc.ErrorIsNil)
	_, cmd, err := s.initBootstrapCommand(
		c, nil, "--model-config", s.b64yamlControllerModelConfig,
		"--hosted-model-config", s.b64yamlHostedModelConfig,
		"--instance-id", string(s.instanceId))
	c.Assert(err, jc.ErrorIsNil)

	var tw loggo.TestWriter
	err = loggo.RegisterWriter("bootstrap-test", &tw, loggo.DEBUG)
	c.Assert(err, jc.ErrorIsNil)
	defer loggo.RemoveWriter("bootstrap-test")

	err = cmd.Run(nil)
	c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{
		loggo.WARNING,
		`cannot set up Juju GUI: cannot read GUI archive: .*`,
	}})
}
Пример #9
0
func (s *BootstrapSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.PatchValue(&sshGenerateKey, func(name string) (string, string, error) {
		return "private-key", "public-key", nil
	})

	s.MgoSuite.SetUpTest(c)
	s.dataDir = c.MkDir()
	s.logDir = c.MkDir()
	s.mongoOplogSize = "1234"
	s.fakeEnsureMongo = agenttesting.InstallFakeEnsureMongo(s)
	s.PatchValue(&initiateMongoServer, s.fakeEnsureMongo.InitiateMongo)

	// Create fake tools.tar.gz and downloaded-tools.txt.
	current := version.Binary{
		Number: jujuversion.Current,
		Arch:   arch.HostArch(),
		Series: series.HostSeries(),
	}
	toolsDir := filepath.FromSlash(agenttools.SharedToolsDir(s.dataDir, current))
	err := os.MkdirAll(toolsDir, 0755)
	c.Assert(err, jc.ErrorIsNil)
	err = ioutil.WriteFile(filepath.Join(toolsDir, "tools.tar.gz"), nil, 0644)
	c.Assert(err, jc.ErrorIsNil)
	s.writeDownloadedTools(c, &tools.Tools{Version: current})

	// Create fake gui.tar.bz2 and downloaded-gui.txt.
	guiDir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
	err = os.MkdirAll(guiDir, 0755)
	c.Assert(err, jc.ErrorIsNil)
	err = ioutil.WriteFile(filepath.Join(guiDir, "gui.tar.bz2"), nil, 0644)
	c.Assert(err, jc.ErrorIsNil)
	s.writeDownloadedGUI(c, &tools.GUIArchive{
		Version: version.MustParse("2.0.42"),
	})
}
Пример #10
0
// GUITools returns the directory where the Juju GUI release is stored.
func (cfg *InstanceConfig) GUITools() string {
	return agenttools.SharedGUIDir(cfg.DataDir)
}
Пример #11
0
func (s *guiSuite) TestGUIHandler(c *gc.C) {
	if runtime.GOOS == "windows" {
		// Skipping the tests on Windows is not a problem as the Juju GUI is
		// only served from Linux machines.
		c.Skip("bzip2 command not available")
	}
	sendRequest := func(setup guiSetupFunc, currentVersion, pathAndquery string) *http.Response {
		// Set up the GUI base directory.
		datadir := filepath.ToSlash(s.DataDir())
		baseDir := filepath.FromSlash(agenttools.SharedGUIDir(datadir))
		defer func() {
			os.Chmod(baseDir, 0755)
			os.Remove(baseDir)
		}()

		// Run specific test set up.
		var hash string
		if setup != nil {
			storage, err := s.State.GUIStorage()
			c.Assert(err, jc.ErrorIsNil)
			defer storage.Close()

			// Ensure the GUI storage is empty.
			allMeta, err := storage.AllMetadata()
			c.Assert(err, jc.ErrorIsNil)
			c.Assert(allMeta, gc.HasLen, 0)

			hash = setup(c, baseDir, storage)
		}

		// Set the current GUI version if required.
		if currentVersion != "" {
			err := s.State.GUISetVersion(version.MustParse(currentVersion))
			c.Assert(err, jc.ErrorIsNil)
		}

		// Send a request to the test path.
		if pathAndquery == "" {
			pathAndquery = "/"
		}
		return s.sendRequest(c, httpRequestParams{
			url: s.guiURL(c, hash, pathAndquery),
		})
	}

	for i, test := range guiHandlerTests {
		c.Logf("\n%d: %s", i, test.about)

		// Reset the db so that the GUI storage is empty in each test.
		s.Reset(c)

		// Perform the request.
		resp := sendRequest(test.setup, test.currentVersion, test.pathAndquery)

		// Check the response.
		if test.expectedStatus == 0 {
			test.expectedStatus = http.StatusOK
		}
		if test.expectedError != "" {
			test.expectedContentType = params.ContentTypeJSON
		}
		body := assertResponse(c, resp, test.expectedStatus, test.expectedContentType)
		if test.expectedError == "" {
			c.Check(string(body), gc.Equals, test.expectedBody)
		} else {
			var jsonResp params.ErrorResult
			err := json.Unmarshal(body, &jsonResp)
			if !c.Check(err, jc.ErrorIsNil, gc.Commentf("body: %s", body)) {
				continue
			}
			c.Check(jsonResp.Error.Message, gc.Matches, test.expectedError)
		}
	}
}
Пример #12
0
func (t *ToolsSuite) TestSharedGUIDir(c *gc.C) {
	dir := agenttools.SharedGUIDir("/var/lib/juju")
	c.Assert(dir, gc.Equals, "/var/lib/juju/gui")
}