<commit_before>package handlers

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/gorilla/schema"
	"net/http"
	"vmango/models"
	"vmango/web"
)

func MachineDelete(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return fmt.Errorf("failed to fetch machine info: %s", err)
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}

	if req.Method == "POST" {
		if err := ctx.IPPool.Fetch(machine); err != nil {
			return err
		}
		if err := ctx.Machines.Remove(machine); err != nil {
			return err
		}
		if machine.Ip != nil {
			if err := ctx.IPPool.Release(machine.Ip); err != nil {
				return err
			}
		}
		url, err := ctx.Router.Get("machine-list").URL()
		if err != nil {
			panic(err)
		}
		http.Redirect(w, req, url.Path, http.StatusFound)
		return nil
	} else {
		ctx.Render.HTML(w, http.StatusOK, "machines/delete", map[string]interface{}{
			"Request": req,
			"Machine": machine,
		})
	}
	return nil
}

func MachineStateChange(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return fmt.Errorf("failed to fetch machine info: %s", err)
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}

	action := mux.Vars(req)["action"]
	if req.Method == "POST" {
		switch action {
		case "stop":
			if err := ctx.Machines.Stop(machine); err != nil {
				return fmt.Errorf("failed to stop machine: %s", err)
			}
		case "start":
			if err := ctx.Machines.Start(machine); err != nil {
				return fmt.Errorf("failed to start machine: %s", err)
			}
		case "reboot":
			if err := ctx.Machines.Reboot(machine); err != nil {
				return fmt.Errorf("failed to reboot machine: %s", err)
			}
		default:
			return web.BadRequest(fmt.Sprintf("unknown action '%s' requested", action))
		}
		url, err := ctx.Router.Get("machine-detail").URL("name", machine.Name)
		if err != nil {
			panic(err)
		}
		http.Redirect(w, req, url.Path, http.StatusFound)
		return nil
	} else {
		ctx.Render.HTML(w, http.StatusOK, "machines/changestate", map[string]interface{}{
			"Request": req,
			"Machine": machine,
			"Action":  action,
		})
		return nil
	}
}

func MachineList(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machines := &models.VirtualMachineList{}
	if err := ctx.Machines.List(machines); err != nil {
		return err
	}
	ctx.RenderResponse(w, req, http.StatusOK, "machines/list", map[string]interface{}{
		"Machines": machines,
	})
	return nil
}

func MachineDetail(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return err
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}
	if err := ctx.IPPool.Fetch(machine); err != nil {
		return err
	}
	ctx.RenderResponse(w, req, http.StatusOK, "machines/detail", map[string]interface{}{
		"Machine": machine,
	})
	return nil
}

type machineAddFormData struct {
	Name   string
	Plan   string
	Image  string
	SSHKey []string
}

func MachineAddForm(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	if req.Method == "POST" {
		if err := req.ParseForm(); err != nil {
			return err
		}
		form := &machineAddFormData{}
		if err := schema.NewDecoder().Decode(form, req.PostForm); err != nil {
			return web.BadRequest(err.Error())
		}
		plan := &models.Plan{Name: form.Plan}
		if exists, err := ctx.Plans.Get(plan); err != nil {
			return err
		} else if !exists {
			return web.BadRequest(fmt.Sprintf(`plan "%s" not found`, form.Plan))
		}

		image := &models.Image{FullName: form.Image}
		if exists, err := ctx.Images.Get(image); err != nil {
			return err
		} else if !exists {
			return web.BadRequest(fmt.Sprintf(`image "%s" not found`, form.Image))
		}
		sshkeys := []*models.SSHKey{}
		for _, keyName := range form.SSHKey {
			key := models.SSHKey{Name: keyName}
			if exists, err := ctx.SSHKeys.Get(&key); err != nil {
				return fmt.Errorf("failed to fetch ssh key %s: %s", keyName, err)
			} else if !exists {
				return web.BadRequest(fmt.Sprintf("ssh key '%s' doesn't exist", keyName))
			}
			sshkeys = append(sshkeys, &key)
		}

		ip := &models.IP{}
		if exists, err := ctx.IPPool.Get(ip); err != nil {
			return fmt.Errorf("cannot find ip address for vm: %s", err)
		} else if !exists {
			return fmt.Errorf("no free ip address availaible")
		}

		vm := &models.VirtualMachine{
			Name:      form.Name,
			Memory:    plan.Memory,
			Cpus:      plan.Cpus,
			ImageName: image.FullName,
			Ip:        ip,
			SSHKeys:   sshkeys,
		}

		if exists, err := ctx.Machines.Get(vm); err != nil {
			return err
		} else if exists {
			return web.BadRequest(fmt.Sprintf("machine with name '%s' already exists", vm.Name))
		}
		if err := ctx.Machines.Create(vm, image, plan); err != nil {
			return fmt.Errorf("failed to create machine: %s", err)
		}
		vm = &models.VirtualMachine{Name: vm.Name}
		if exists, err := ctx.Machines.Get(vm); err != nil {
			return err
		} else if !exists {
			return fmt.Errorf("failed to fetch info for just created machine: %s")
		}

		if err := ctx.IPPool.Assign(ip, vm); err != nil {
			return fmt.Errorf("failed to mark ip as used: %s", err)
		}
		ip.UsedBy = vm.Name
		if err := ctx.Machines.Start(vm); err != nil {
			return fmt.Errorf("failed to start machine: %s", err)
		}
		url, err := ctx.Router.Get("machine-detail").URL("name", vm.Name)
		if err != nil {<commit_msg>Remove unneccesary fetch after machine creation<commit_after>package handlers

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/gorilla/schema"
	"net/http"
	"vmango/models"
	"vmango/web"
)

func MachineDelete(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return fmt.Errorf("failed to fetch machine info: %s", err)
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}

	if req.Method == "POST" {
		if err := ctx.IPPool.Fetch(machine); err != nil {
			return err
		}
		if err := ctx.Machines.Remove(machine); err != nil {
			return err
		}
		if machine.Ip != nil {
			if err := ctx.IPPool.Release(machine.Ip); err != nil {
				return err
			}
		}
		url, err := ctx.Router.Get("machine-list").URL()
		if err != nil {
			panic(err)
		}
		http.Redirect(w, req, url.Path, http.StatusFound)
		return nil
	} else {
		ctx.Render.HTML(w, http.StatusOK, "machines/delete", map[string]interface{}{
			"Request": req,
			"Machine": machine,
		})
	}
	return nil
}

func MachineStateChange(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return fmt.Errorf("failed to fetch machine info: %s", err)
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}

	action := mux.Vars(req)["action"]
	if req.Method == "POST" {
		switch action {
		case "stop":
			if err := ctx.Machines.Stop(machine); err != nil {
				return fmt.Errorf("failed to stop machine: %s", err)
			}
		case "start":
			if err := ctx.Machines.Start(machine); err != nil {
				return fmt.Errorf("failed to start machine: %s", err)
			}
		case "reboot":
			if err := ctx.Machines.Reboot(machine); err != nil {
				return fmt.Errorf("failed to reboot machine: %s", err)
			}
		default:
			return web.BadRequest(fmt.Sprintf("unknown action '%s' requested", action))
		}
		url, err := ctx.Router.Get("machine-detail").URL("name", machine.Name)
		if err != nil {
			panic(err)
		}
		http.Redirect(w, req, url.Path, http.StatusFound)
		return nil
	} else {
		ctx.Render.HTML(w, http.StatusOK, "machines/changestate", map[string]interface{}{
			"Request": req,
			"Machine": machine,
			"Action":  action,
		})
		return nil
	}
}

func MachineList(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machines := &models.VirtualMachineList{}
	if err := ctx.Machines.List(machines); err != nil {
		return err
	}
	ctx.RenderResponse(w, req, http.StatusOK, "machines/list", map[string]interface{}{
		"Machines": machines,
	})
	return nil
}

func MachineDetail(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	machine := &models.VirtualMachine{
		Name: mux.Vars(req)["name"],
	}
	if exists, err := ctx.Machines.Get(machine); err != nil {
		return err
	} else if !exists {
		return web.NotFound(fmt.Sprintf("Machine with name %s not found", machine.Name))
	}
	if err := ctx.IPPool.Fetch(machine); err != nil {
		return err
	}
	ctx.RenderResponse(w, req, http.StatusOK, "machines/detail", map[string]interface{}{
		"Machine": machine,
	})
	return nil
}

type machineAddFormData struct {
	Name   string
	Plan   string
	Image  string
	SSHKey []string
}

func MachineAddForm(ctx *web.Context, w http.ResponseWriter, req *http.Request) error {
	if req.Method == "POST" {
		if err := req.ParseForm(); err != nil {
			return err
		}
		form := &machineAddFormData{}
		if err := schema.NewDecoder().Decode(form, req.PostForm); err != nil {
			return web.BadRequest(err.Error())
		}
		plan := &models.Plan{Name: form.Plan}
		if exists, err := ctx.Plans.Get(plan); err != nil {
			return err
		} else if !exists {
			return web.BadRequest(fmt.Sprintf(`plan "%s" not found`, form.Plan))
		}

		image := &models.Image{FullName: form.Image}
		if exists, err := ctx.Images.Get(image); err != nil {
			return err
		} else if !exists {
			return web.BadRequest(fmt.Sprintf(`image "%s" not found`, form.Image))
		}
		sshkeys := []*models.SSHKey{}
		for _, keyName := range form.SSHKey {
			key := models.SSHKey{Name: keyName}
			if exists, err := ctx.SSHKeys.Get(&key); err != nil {
				return fmt.Errorf("failed to fetch ssh key %s: %s", keyName, err)
			} else if !exists {
				return web.BadRequest(fmt.Sprintf("ssh key '%s' doesn't exist", keyName))
			}
			sshkeys = append(sshkeys, &key)
		}

		ip := &models.IP{}
		if exists, err := ctx.IPPool.Get(ip); err != nil {
			return fmt.Errorf("cannot find ip address for vm: %s", err)
		} else if !exists {
			return fmt.Errorf("no free ip address availaible")
		}

		vm := &models.VirtualMachine{
			Name:      form.Name,
			Memory:    plan.Memory,
			Cpus:      plan.Cpus,
			ImageName: image.FullName,
			Ip:        ip,
			SSHKeys:   sshkeys,
		}

		if exists, err := ctx.Machines.Get(vm); err != nil {
			return err
		} else if exists {
			return web.BadRequest(fmt.Sprintf("machine with name '%s' already exists", vm.Name))
		}
		if err := ctx.Machines.Create(vm, image, plan); err != nil {
			return fmt.Errorf("failed to create machine: %s", err)
		}

		if err := ctx.IPPool.Assign(ip, vm); err != nil {
			return fmt.Errorf("failed to mark ip as used: %s", err)
		}
		ip.UsedBy = vm.Name
		if err := ctx.Machines.Start(vm); err != nil {
			return fmt.Errorf("failed to start machine: %s", err)
		}
		url, err := ctx.Router.Get("machine-detail").URL("name", vm.Name)
		if err != nil {
{'fraction_non_alphanumeric': 0.15973684210526315, 'fraction_numerical': 0.0, 'mean_word_length': 3.5313990461049283, 'pattern_counts': {'":': 20, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6517097', 'n_tokens_mistral': 4383, 'n_tokens_neox': 3961, 'n_words': 1061}