Ejemplo n.º 1
0
// retrieveCommits fetches the latest deployed commits as well
// as the latest GitHub commits for a given Project.
// it will also check if the user has permission to pull.
func retrieveCommits(gcl githublib.Client, ac acl.AccessControl, r *http.Request, project goship.Project, deployUser string) (goship.Project, error) {
	// define a wait group to wait for all goroutines to finish
	var wg sync.WaitGroup
	for i, environment := range project.Environments {
		for j, host := range environment.Hosts {
			// start a goroutine for SSHing on to the machine
			wg.Add(1)
			go getCommit(&wg, project, environment, host, deployUser, i, j)
		}
		wg.Add(1)
		go getLatestGitHubCommit(&wg, project, environment, gcl, project.RepoOwner, project.RepoName, i)
	}
	// wait for goroutines to finish
	wg.Wait()
	for i, e := range project.Environments {

		project.Environments[i] = e
		for j, host := range e.Hosts {
			host.GitHubCommitURL = host.LatestGitHubCommitURL(project)
			host.GitHubDiffURL = host.LatestGitHubDiffURL(project, e)
			host.ShortCommitHash = host.LatestShortCommitHash()
			project.Environments[i].Hosts[j] = host
		}
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		log.Printf("Failed to get user %s", err)
	}
	return filterProject(ac, project, r, u), err
}
Ejemplo n.º 2
0
func (h DeployLogHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, fullEnv string, environment config.Environment, projectName string) {
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	d, err := readEntries(fullEnv)
	if err != nil {
		glog.Errorf("Failed to read entries: %v", err)
	}
	t, err := template.New("deploy_log.html").ParseFiles("templates/deploy_log.html", "templates/base.html")
	if err != nil {
		glog.Errorf("Failed to parse templates: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for i := range d {
		d[i].FormattedTime = formatTime(d[i].Time)
	}
	sort.Sort(ByTime(d))
	js, css := h.assets.Templates()

	params := map[string]interface{}{
		"Javascript":  js,
		"Stylesheet":  css,
		"Deployments": d,
		"User":        u,
		"Env":         fullEnv,
		"Environment": environment,
		"ProjectName": projectName,
	}
	helpers.RespondWithTemplate(w, "text/html", t, "base", params)
}
Ejemplo n.º 3
0
func (h deployPage) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	p := r.FormValue("project")
	env := r.FormValue("environment")
	fromRevision := r.FormValue("from_revision")
	toRevision := r.FormValue("to_revision")
	repoOwner := r.FormValue("repo_owner")
	repoName := r.FormValue("repo_name")
	t, err := template.New("deploy.html").ParseFiles("templates/deploy.html", "templates/base.html")
	if err != nil {
		glog.Errorf("Failed to parse templates: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	js, css := h.assets.Templates()

	params := map[string]interface{}{
		"Javascript":   js,
		"Stylesheet":   css,
		"Project":      p,
		"Env":          env,
		"User":         user,
		"PushAddress":  h.pushAddr,
		"RepoOwner":    repoOwner,
		"RepoName":     repoName,
		"ToRevision":   toRevision,
		"FromRevision": fromRevision,
	}
	helpers.RespondWithTemplate(w, "text/html", t, "base", params)
}
Ejemplo n.º 4
0
func (h HomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := goship.ParseETCD(h.ecl)
	if err != nil {
		log.Printf("Failed to Parse to ETCD data %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		log.Println("Failed to get User! ")
		http.Error(w, err.Error(), http.StatusUnauthorized)
	}
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		log.Printf("Failed to parse template: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	c.Projects = acl.ReadableProjects(h.ac, c.Projects, u)

	sort.Sort(ByName(c.Projects))

	// apply each plugin
	for _, pl := range plugin.Plugins {
		err := pl.Apply(c)
		if err != nil {
			log.Printf("Failed to apply plugin: %s", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
	js, css := h.assets.Templates()
	gt := os.Getenv(gitHubAPITokenEnvVar)
	pt := c.Pivotal.Token

	t.ExecuteTemplate(w, "base", map[string]interface{}{"Javascript": js, "Stylesheet": css, "Projects": c.Projects, "User": u, "Page": "home", "ConfirmDeployFlag": *confirmDeployFlag, "GithubToken": gt, "PivotalToken": pt})
}
Ejemplo n.º 5
0
func (h HomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := config.Load(h.ecl)
	if err != nil {
		glog.Errorf("Failed to Parse to ETCD data %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		glog.Errorf("Failed to parse template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	projs := acl.ReadableProjects(h.ac, c.Projects, u)

	sort.Sort(ByName(c.Projects))

	// columns maps a plugin name to a list of columns
	columns := make(map[string][]plugin.Column)
	for _, pl := range plugin.Plugins {
		for _, p := range c.Projects {
			cols, err := pl.Apply(p)
			if err != nil {
				glog.Errorf("Failed to apply plugin: %s", err)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			columns[p.Name] = append(columns[p.Name], cols...)
		}
	}
	js, css := h.assets.Templates()
	gt := os.Getenv(gitHubAPITokenEnvVar)
	pt := c.Pivotal.Token

	params := map[string]interface{}{
		"Javascript":        js,
		"Stylesheet":        css,
		"Projects":          projs,
		"PluginColumns":     columns,
		"User":              u,
		"Page":              "home",
		"ConfirmDeployFlag": *confirmDeployFlag,
		"GithubToken":       gt,
		"PivotalToken":      pt,
	}
	helpers.RespondWithTemplate(w, "text/html", t, "base", params)
}
Ejemplo n.º 6
0
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	components := strings.Split(r.URL.Path, "/")
	if len(components) != 3 || components[0] != "" || components[1] != "commits" {
		http.NotFound(w, r)
		return
	}
	projName := components[2]
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	envs, err := h.fetchStatuses(ctx, projName, u)
	if err == projectUnaccessible {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	buf, err := json.Marshal(envs)
	if err != nil {
		glog.Errorf("Failed to marshal response: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	if _, err := w.Write(buf); err != nil {
		glog.Errorf("Failed to send response: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
Ejemplo n.º 7
0
func (h ProjCommitsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, projName string) {
	c, err := goship.ParseETCD(h.ecl)
	if err != nil {
		log.Println("ERROR: Parsing etc ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		log.Println("ERROR:  Getting User", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	proj, err := goship.ProjectFromName(c.Projects, projName)
	if err != nil {
		log.Println("ERROR:  Getting Project from name", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// Remove projects that the user is not a collaborator on...
	fp := acl.ReadableProjects(h.ac, []goship.Project{*proj}, u)
	p, err := retrieveCommits(h.gcl, h.ac, r, fp[0], c.DeployUser)
	if err != nil {
		log.Println("ERROR: Retrieving Commits ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	j, err := json.Marshal(p)
	if err != nil {
		log.Println("ERROR: Marshalling Retrieving Commits ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(j)
	if err != nil {
		log.Println("ERROR: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
Ejemplo n.º 8
0
func extractDeployLogHandler(ac acl.AccessControl, ecl *etcd.Client, fn func(http.ResponseWriter, *http.Request, string, config.Environment, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPathWithEnv.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		c, err := config.Load(ecl)
		if err != nil {
			glog.Errorf("Failed to get current configuration: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// auth check for user
		u, err := auth.CurrentUser(r)
		if err != nil {
			glog.Error("Failed to get a user while deploying in Auth Mode: %v", err)
			http.Error(w, err.Error(), http.StatusUnauthorized)
		}
		c.Projects = acl.ReadableProjects(ac, c.Projects, u)
		// get project name and env from url
		a := strings.Split(m[2], "-")
		l := len(a)
		environmentName := a[l-1]
		var projectName string
		if m[1] == "commits" {
			projectName = m[2]
		} else {
			projectName = strings.Join(a[0:l-1], "-")
		}
		e, err := config.EnvironmentFromName(c.Projects, projectName, environmentName)
		if err != nil {
			glog.Errorf("Can't get environment from name: %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		fn(w, r, m[2], *e, projectName)
	}
}
Ejemplo n.º 9
0
func (h DeployLogHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, fullEnv string, environment goship.Environment, projectName string) {
	u, err := auth.CurrentUser(r)
	if err != nil {
		log.Println("Failed to get User! ")
		http.Error(w, err.Error(), http.StatusUnauthorized)
	}
	d, err := readEntries(fullEnv)
	if err != nil {
		log.Println("Error: ", err)
	}
	t, err := template.New("deploy_log.html").ParseFiles("templates/deploy_log.html", "templates/base.html")
	if err != nil {
		log.Println("ERROR: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for i := range d {
		d[i].FormattedTime = formatTime(d[i].Time)
	}
	sort.Sort(ByTime(d))
	js, css := h.assets.Templates()
	t.ExecuteTemplate(w, "base", map[string]interface{}{"Javascript": js, "Stylesheet": css, "Deployments": d, "User": u, "Env": fullEnv, "Environment": environment, "ProjectName": projectName})
}
Ejemplo n.º 10
0
func (h DeployHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := goship.ParseETCD(h.ecl)
	if err != nil {
		log.Println("ERROR: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		log.Println("Failed to get a User! ")
		http.Error(w, err.Error(), http.StatusUnauthorized)
	}
	user := u.Name
	p := r.FormValue("project")
	env := r.FormValue("environment")
	fromRevision := r.FormValue("from_revision")
	toRevision := r.FormValue("to_revision")
	owner := r.FormValue("repo_owner")
	name := r.FormValue("repo_name")
	if c.Notify != "" {
		err := startNotify(c.Notify, user, p, env)
		if err != nil {
			log.Println("Error: ", err.Error())
		}
	}

	deployTime := time.Now()
	success := true
	command, err := getDeployCommand(c.Projects, p, env)
	if err != nil {
		log.Println("ERROR: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	cmd := exec.Command(command[0], command[1:]...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Println("ERROR: could not get stdout of command:" + err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Println("ERROR: could not get stderr of command:" + err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if err = cmd.Start(); err != nil {
		log.Println("ERROR: could not run deployment command: " + err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	var wg sync.WaitGroup
	wg.Add(2)
	go h.sendOutput(&wg, bufio.NewScanner(stdout), p, env, deployTime)
	go h.sendOutput(&wg, bufio.NewScanner(stderr), p, env, deployTime)
	wg.Wait()

	err = cmd.Wait()
	if err != nil {
		success = false
		log.Println("Deployment failed: " + err.Error())
	}
	if c.Notify != "" {
		err = endNotify(c.Notify, p, env, success)
		if err != nil {
			log.Println("Error: ", err.Error())
		}
	}

	if (c.Pivotal.Token != "") && (c.Pivotal.Project != "") && success {
		err := goship.PostToPivotal(c.Pivotal, env, owner, name, toRevision, fromRevision)
		if err != nil {
			log.Println("ERROR: ", err)
		} else {
			log.Printf("Pivotal Info: %s %s", c.Pivotal.Token, c.Pivotal.Project)
		}
	}

	err = insertEntry(fmt.Sprintf("%s-%s", p, env), owner, name, fromRevision, toRevision, user, success, deployTime)
	if err != nil {
		log.Println("ERROR: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
Ejemplo n.º 11
0
func (h DeployHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := config.Load(h.ecl)
	if err != nil {
		glog.Errorf("Failed to fetch latest configuration: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to fetch current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	user := u.Name
	p := r.FormValue("project")
	env := r.FormValue("environment")
	fromRevision := r.FormValue("from_revision")
	toRevision := r.FormValue("to_revision")
	owner := r.FormValue("repo_owner")
	name := r.FormValue("repo_name")
	if c.Notify != "" {
		err := startNotify(c.Notify, user, p, env)
		if err != nil {
			glog.Errorf("Failed to notify start-deployment event of %s (%s): %v", p, env, err)
		}
	}

	deployTime := time.Now()
	success := true
	command, err := getDeployCommand(c.Projects, p, env)
	if err != nil {
		glog.Errorf("Failed to fetch deploy command: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	cmd := exec.Command(command[0], command[1:]...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		glog.Errorf("Could not get stdout of command: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		glog.Errorf("Could not get stderr of command: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	glog.Infof("Starting deployment of %s-%s (%s/%s) from %s to %s; requested by %s", p, env, owner, name, fromRevision, toRevision, user)
	if err = cmd.Start(); err != nil {
		glog.Errorf("Could not run deployment command: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	var wg sync.WaitGroup
	wg.Add(2)
	go h.sendOutput(&wg, bufio.NewScanner(stdout), p, env, deployTime)
	go h.sendOutput(&wg, bufio.NewScanner(stderr), p, env, deployTime)
	wg.Wait()

	err = cmd.Wait()
	if err != nil {
		success = false
		glog.Errorf("Deployment of %s failed: %v", p, err)
	} else {
		glog.Infof("Successfully deployed %s", p)
	}
	if c.Notify != "" {
		err = endNotify(c.Notify, p, env, success)
		if err != nil {
			glog.Errorf("Failed to notify start-deployment event of %s (%s): %v", p, env, err)
		}
	}

	if (c.Pivotal.Token != "") && (c.Pivotal.Project != "") && success {
		err := config.PostToPivotal(c.Pivotal, env, owner, name, toRevision, fromRevision)
		if err != nil {
			glog.Errorf("Failed to post to pivotal: %v", err)
		} else {
			glog.Infof("Pivotal Info: %s %s", c.Pivotal.Token, c.Pivotal.Project)
		}
	}

	err = insertEntry(fmt.Sprintf("%s-%s", p, env), owner, name, fromRevision, toRevision, user, success, deployTime)
	if err != nil {
		glog.Errorf("Failed to insert an entry: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}