<commit_before>package cachet

import (
	"fmt"
)

// ComponentsService contains REST endpoints that belongs to cachet components.
type ComponentsService struct {
	client *Client
}

// Component entity reflects one single component
type Component struct {
	ID          int    `json:"id,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Link        string `json:"link,omitempty"`
	Status      int    `json:"status,omitempty"`
	Order       int    `json:"order,omitempty"`
	GroupID     int    `json:"group_id,omitempty"`
	CreatedAt   string `json:"created_at,omitempty"`
	UpdatedAt   string `json:"updated_at,omitempty"`
	DeletedAt   string `json:"deleted_at,omitempty"`
	StatusName  string `json:"status_name,omitempty"`
}

// ComponentResponse reflects the response of /components call
type ComponentResponse struct {
	Meta       Meta        `json:"meta,omitempty"`
	Components []Component `json:"data,omitempty"`
}

// componentApiResponse is an internal type to hide
// some the "data" nested level from the API.
// Some calls (e.g. Get or Create) return the component in the "data" key.
type componentAPIResponse struct {
	Data *Component `json:"data"`
}

// GetAll return all components that have been created.
//
// Docs: https://docs.cachethq.io/docs/get-components
func (s *ComponentsService) GetAll() (*ComponentResponse, *Response, error) {
	u := "api/v1/components"
	v := new(ComponentResponse)

	resp, err := s.client.Call("GET", u, nil, v)
	return v, resp, err
}

// Get return a single component.
//
// Docs: https://docs.cachethq.io/docs/get-a-component
func (s *ComponentsService) Get(id int) (*Component, *Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)
	v := new(componentAPIResponse)

	resp, err := s.client.Call("GET", u, nil, v)
	return v.Data, resp, err
}

// Create a new component.
//
// Docs: https://docs.cachethq.io/docs/components
func (s *ComponentsService) Create(c *Component) (*Component, *Response, error) {
	u := "api/v1/components"
	v := new(componentAPIResponse)

	resp, err := s.client.Call("POST", u, c, v)
	return v.Data, resp, err
}

// Update updates a component.
//
// Docs: https://docs.cachethq.io/docs/update-a-component
func (s *ComponentsService) Update(id int, c *Component) (*Component, *Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)
	v := new(componentAPIResponse)

	resp, err := s.client.Call("PUT", u, c, v)
	return v.Data, resp, err
}

// Update deletes a component.
//
// Docs: https://docs.cachethq.io/docs/delete-a-component
func (s *ComponentsService) Delete(id int) (*Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)

	resp, err := s.client.Call("DELETE", u, nil, nil)
	return resp, err
}<commit_msg>Added component statuses<commit_after>package cachet

import (
	"fmt"
)

const (
	// Docs: https://docs.cachethq.io/docs/component-statuses

	// ComponentStatusOperational means "The component is working."
	ComponentStatusOperational = 1
	// ComponentStatusPerformanceIssues means "The component is experiencing some slowness."
	ComponentStatusPerformanceIssues = 2
	// ComponentStatusPartialOutage means "The component may not be working for everybody."
	// This could be a geographical issue for example.
	ComponentStatusPartialOutage = 3
	// ComponentStatusMajorOutage means "The component is not working for anybody."
	ComponentStatusMajorOutage = 4
)

// ComponentsService contains REST endpoints that belongs to cachet components.
type ComponentsService struct {
	client *Client
}

// Component entity reflects one single component
type Component struct {
	ID          int    `json:"id,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Link        string `json:"link,omitempty"`
	Status      int    `json:"status,omitempty"`
	Order       int    `json:"order,omitempty"`
	GroupID     int    `json:"group_id,omitempty"`
	CreatedAt   string `json:"created_at,omitempty"`
	UpdatedAt   string `json:"updated_at,omitempty"`
	DeletedAt   string `json:"deleted_at,omitempty"`
	StatusName  string `json:"status_name,omitempty"`
}

// ComponentResponse reflects the response of /components call
type ComponentResponse struct {
	Meta       Meta        `json:"meta,omitempty"`
	Components []Component `json:"data,omitempty"`
}

// componentApiResponse is an internal type to hide
// some the "data" nested level from the API.
// Some calls (e.g. Get or Create) return the component in the "data" key.
type componentAPIResponse struct {
	Data *Component `json:"data"`
}

// GetAll return all components that have been created.
//
// Docs: https://docs.cachethq.io/docs/get-components
func (s *ComponentsService) GetAll() (*ComponentResponse, *Response, error) {
	u := "api/v1/components"
	v := new(ComponentResponse)

	resp, err := s.client.Call("GET", u, nil, v)
	return v, resp, err
}

// Get return a single component.
//
// Docs: https://docs.cachethq.io/docs/get-a-component
func (s *ComponentsService) Get(id int) (*Component, *Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)
	v := new(componentAPIResponse)

	resp, err := s.client.Call("GET", u, nil, v)
	return v.Data, resp, err
}

// Create a new component.
//
// Docs: https://docs.cachethq.io/docs/components
func (s *ComponentsService) Create(c *Component) (*Component, *Response, error) {
	u := "api/v1/components"
	v := new(componentAPIResponse)

	resp, err := s.client.Call("POST", u, c, v)
	return v.Data, resp, err
}

// Update updates a component.
//
// Docs: https://docs.cachethq.io/docs/update-a-component
func (s *ComponentsService) Update(id int, c *Component) (*Component, *Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)
	v := new(componentAPIResponse)

	resp, err := s.client.Call("PUT", u, c, v)
	return v.Data, resp, err
}

// Update deletes a component.
//
// Docs: https://docs.cachethq.io/docs/delete-a-component
func (s *ComponentsService) Delete(id int) (*Response, error) {
	u := fmt.Sprintf("api/v1/components/%d", id)

	resp, err := s.client.Call("DELETE", u, nil, nil)
	return resp, err
}<|endoftext|>


<commit_before>// The zagent package allows you to query zabbix agents running over a network.
package zagent

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"strconv"
	"time"
)

var (
	// http://localhost:6060/pkg/encoding/binary/#Uvarint
	DataLengthBufferTooSmall = errors.New("DataLength buffer too small")
	DataLengthOverflow       = errors.New("DataLength is too large")

	// This is the default timeout when contacting a Zabbix Agent.
	DefaultTimeout = time.Duration(30 * time.Second)
)

const (
	NotSupported = "ZBX_NOTSUPPORTED"
)

// Creates a new Agent with a default port of 10050
func NewAgent(host string) *Agent {
	return &Agent{Host: host, Port: 10050}
}

// Agent represents a remote zabbix agent
type Agent struct {
	Host string
	Port int
}

// Returns a string with the host and port concatenated to host:port
func (a *Agent) hostPort() string {
	portS := fmt.Sprintf("%v", a.Port)
	return net.JoinHostPort(a.Host, portS)
}

/*
	Run the check (key) against the Zabbix agent with the specified timeout.
	If timeout is < 1 DefaultTimeout will be used.
*/
func (a *Agent) Query(key string, timeout time.Duration) (*Response, error) {
	res := newResponse()

	if timeout < 1 {
		timeout = DefaultTimeout
	}

	conn, err := net.DialTimeout("tcp", a.hostPort(), timeout)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	_, err = fmt.Fprintf(conn, key)
	if err != nil {
		return nil, err
	}

	dataLength := make([]byte, 8)

	reader := bufio.NewReader(conn)
	reader.Read(res.Header)
	reader.Read(dataLength)
	res.Data, _ = ioutil.ReadAll(reader)

	// Convert dataLength from binary to uint
	var bytesRead int
	res.DataLength, bytesRead = binary.Uvarint(dataLength)
	if bytesRead <= 0 {
		if bytesRead == 0 {
			return nil, DataLengthBufferTooSmall
		}
		return nil, DataLengthOverflow
	}

	if res.Supported() == false {
		return res, fmt.Errorf("%s is not supported", key)
	}

	return res, nil
}

// Run query and return the result (Response.Data) as a string.
func (a *Agent) QueryS(key string, timeout time.Duration) (string, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return "", err
	}

	return res.DataS(), nil
}

// Run query and return the result (Response.Data) as a bool.
func (a *Agent) QueryBool(key string, timeout time.Duration) (bool, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return false, err
	}

	return strconv.ParseBool(res.DataS())
}

// Run query and return the result (Response.Data) as an int.
func (a *Agent) QueryInt(key string, timeout time.Duration) (int, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.Atoi(res.DataS())
}

// Run query and return the result (Response.Data) as an int64.
func (a *Agent) QueryInt64(key string, timeout time.Duration) (int64, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.ParseInt(res.DataS(), 10, 64)
}

// Run query and return the result (Response.Data) as an float64.
func (a *Agent) QueryFloat64(key string, timeout time.Duration) (float64, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.ParseFloat(res.DataS(), 64)
}

// Call agent.hostname on the zabbix agent.
func (a *Agent) AgentHostname(timeout time.Duration) (string, error) {
	return a.QueryS("agent.hostname", timeout)
}

/*
	Call agent.ping on the zabbix agent. Returns true if it
	gets the correct response ("1") and doesn't receive any
	errors in the process.
*/
func (a *Agent) AgentPing(timeout time.Duration) (bool, error) {
	return a.QueryBool("agent.ping", timeout)
}

/*
	Calls agent.version on the zabbix agent and returns the version
	and/or any errors associated with the action.
*/
func (a *Agent) AgentVersion(timeout time.Duration) (string, error) {
	return a.QueryS("agent.version", timeout)
}
<commit_msg>Add Discovery* methods.<commit_after>// The zagent package allows you to query zabbix agents running over a network.
package zagent

import (
	"bufio"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"strconv"
	"time"
)

var (
	// http://localhost:6060/pkg/encoding/binary/#Uvarint
	DataLengthBufferTooSmall = errors.New("DataLength buffer too small")
	DataLengthOverflow       = errors.New("DataLength is too large")

	// This is the default timeout when contacting a Zabbix Agent.
	DefaultTimeout = time.Duration(30 * time.Second)
)

const (
	NotSupported = "ZBX_NOTSUPPORTED"
)

// Filesystem respresents a Zabbix filesystem as presented by vfs.fs.discovery
type Filesystem struct {
	Name string
	Type string
}

// NetworkInterface represents a Zabbix network interface as presented by net.if.discovery
type NetworkInterface struct {
	Name string
}

// CPU represents a Zabbix cpu as presented by system.cpu.discovery
type CPU struct {
	Number float64
	Status string
}

// Agent represents a remote zabbix agent
type Agent struct {
	Host string
	Port int
}

// Creates a new Agent with a default port of 10050
func NewAgent(host string) *Agent {
	return &Agent{Host: host, Port: 10050}
}

// Returns a string with the host and port concatenated to host:port
func (a *Agent) hostPort() string {
	portS := fmt.Sprintf("%v", a.Port)
	return net.JoinHostPort(a.Host, portS)
}

/*
	Run the check (key) against the Zabbix agent with the specified timeout.
	If timeout is < 1 DefaultTimeout will be used.
*/
func (a *Agent) Query(key string, timeout time.Duration) (*Response, error) {
	res := newResponse()

	if timeout < 1 {
		timeout = DefaultTimeout
	}

	conn, err := net.DialTimeout("tcp", a.hostPort(), timeout)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	_, err = fmt.Fprintf(conn, key)
	if err != nil {
		return nil, err
	}

	dataLength := make([]byte, 8)

	reader := bufio.NewReader(conn)
	reader.Read(res.Header)
	reader.Read(dataLength)
	res.Data, _ = ioutil.ReadAll(reader)

	// Convert dataLength from binary to uint
	var bytesRead int
	res.DataLength, bytesRead = binary.Uvarint(dataLength)
	if bytesRead <= 0 {
		if bytesRead == 0 {
			return nil, DataLengthBufferTooSmall
		}
		return nil, DataLengthOverflow
	}

	if res.Supported() == false {
		return res, fmt.Errorf("%s is not supported", key)
	}

	return res, nil
}

// Run query and return the result (Response.Data) as a string.
func (a *Agent) QueryS(key string, timeout time.Duration) (string, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return "", err
	}

	return res.DataS(), nil
}

// Run query and return the result (Response.Data) as a bool.
func (a *Agent) QueryBool(key string, timeout time.Duration) (bool, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return false, err
	}

	return strconv.ParseBool(res.DataS())
}

// Run query and return the result (Response.Data) as an int.
func (a *Agent) QueryInt(key string, timeout time.Duration) (int, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.Atoi(res.DataS())
}

// Run query and return the result (Response.Data) as an int64.
func (a *Agent) QueryInt64(key string, timeout time.Duration) (int64, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.ParseInt(res.DataS(), 10, 64)
}

// Run query and return the result (Response.Data) as an float64.
func (a *Agent) QueryFloat64(key string, timeout time.Duration) (float64, error) {
	res, err := a.Query(key, timeout)
	if err != nil {
		return 0, err
	}

	return strconv.ParseFloat(res.DataS(), 64)
}

/*
	Run query and convert the JSON to a map[string][]map[string]interface{}.
	This is a raw version of the query and most people are expected to use
	the Discover* methods.
*/
func (a *Agent) queryJSON(key string, timeout time.Duration) (map[string][]map[string]interface{}, error) {
	data := make(map[string][]map[string]interface{})

	res, err := a.Query(key, timeout)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(res.Data, &data)
	return data, err
}

// Return an array of Filesystem structs.
func (a *Agent) DiscoverFilesystems(timeout time.Duration) ([]*Filesystem, error) {
	fs := []*Filesystem{}

	data, err := a.queryJSON("vfs.fs.discovery", timeout)
	if err != nil {
		return nil, err
	}

	for _, f := range data["data"] {
		filesystem := &Filesystem{
			Name: f["{#FSNAME}"].(string),
			Type: f["{#FSTYPE}"].(string),
		}

		fs = append(fs, filesystem)
	}

	return fs, err
}

// Return an array of NetworkInterface structs.
func (a *Agent) DiscoverNetworkInterfaces(timeout time.Duration) ([]*NetworkInterface, error) {
	in := []*NetworkInterface{}

	data, err := a.queryJSON("net.if.discovery", timeout)
	if err != nil {
		return nil, err
	}

	for _, i := range data["data"] {
		networkIface := &NetworkInterface{
			Name: i["{#IFNAME}"].(string),
		}

		in = append(in, networkIface)
	}

	return in, err
}

// Return an array of CPUs.
func (a *Agent) DiscoverCPUs(timeout time.Duration) ([]*CPU, error) {
	cpus := []*CPU{}

	data, err := a.queryJSON("system.cpu.discovery", timeout)
	if err != nil {
		return nil, err
	}

	for _, i := range data["data"] {
		cpu := &CPU{
			Number: i["{#CPU.NUMBER}"].(float64),
			Status: i["{#CPU.STATUS}"].(string),
		}

		cpus = append(cpus, cpu)
	}

	return cpus, err
}

// Call agent.hostname on the zabbix agent.
func (a *Agent) AgentHostname(timeout time.Duration) (string, error) {
	return a.QueryS("agent.hostname", timeout)
}

/*
	Call agent.ping on the zabbix agent. Returns true if it
	gets the correct response ("1") and doesn't receive any
	errors in the process.
*/
func (a *Agent) AgentPing(timeout time.Duration) (bool, error) {
	return a.QueryBool("agent.ping", timeout)
}

/*
	Calls agent.version on the zabbix agent and returns the version
	and/or any errors associated with the action.
*/
func (a *Agent) AgentVersion(timeout time.Duration) (string, error) {
	return a.QueryS("agent.version", timeout)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	swl "github.com/stohio/software-lab/lib"
)

var currentNodeId int
var currentNetworkId int
var currentStackId int

var nodes swl.Nodes
var networks swl.Networks

var stacks swl.Stacks

func init() {

	version1 := swl.Version {
		Id:		1,
		Version:	"1.0",
		OS:		"Windows",
		Architecture:	"64",
		Extension:	".txt",
		URL:		"http://www.textfiles.com/humor/failure.txt",
	}

	version2 := swl.Version {
		Id:		2,
		Version:	"1.0",
		OS:		"Mac",
		Architecture:	"64",
		Extension:	".txt",
		URL:		"http://www.textfiles.com/humor/failure.txt",
	}

	var versions swl.Versions
	versions = append(versions, &version1)
	versions = append(versions, &version2)

	software1 := swl.Software {
		Id:		1,
		Name:		"My Software",
		Publisher:	"Stohio",
		Versions:	versions,
	}

	software2 := swl.Software {
		Id:		2,
		Name:		"Not My Software",
		Publisher:	"Stohio",
		Versions:	versions,
	}

	var softwares swl.Softwares
	softwares = append(softwares, &software1)
	softwares = append(softwares, &software2)

	package1 := swl.Package {
		Id:		1,
		Name:		"Pack One",
		Description:	"This is a Package",
		Softwares:	softwares,
	}

	package2 := swl.Package {
		Id:		2,
		Name:		"Two Pack",
		Description:	"This is also a Package",
		Softwares:	softwares,
	}
	var packages swl.Packages
	packages = append(packages, &package1)
	packages = append(packages, &package2)

	stack := swl.Stack {
		Id:		1,
		Name:		"My First Stack",
		Packages:	packages,
		Softwares:	softwares,
	}
	stacks = append(stacks, &stack)

}

func RepoFindStack(id int) *swl.Stack {
	for _, s :=range stacks {
		if s.Id == id {
			return s
		}
	}
	return nil
}

func RepoCreateStack(s *swl.Stack) *swl.Stack {
	currentStackId += 1
	s.Id = currentStackId
	stacks = append(stacks, s)
	return s
}

func RepoDestroyStack(id int) error {
	for i, s := range stacks {
		if s.Id == id {
			stacks = append(stacks[:i], stacks[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Stack with id of %d to delete", id)
}

func RepoFindNetworkByIP(ip string) (*swl.Network) {
	for _, net := range networks {
		if net.IP == ip {
			return net
		}
	}
	return nil
}

func RepoFindBestNodeInNetworkByIP(ip string) (*swl.Node) {
	net := RepoFindNetworkByIP(ip)
	if net == nil {
		fmt.Println("Could Not Find Network")
		return nil
	}
	var bestNode *swl.Node
	bestDownloads := -1
	for _, n := range net.Nodes {
		fmt.Printf("Node, Best: %d. %d\n", n.Clients, bestDownloads)
		if (n.Clients < bestDownloads || bestDownloads == -1) && (n.Enabled) {
			fmt.Println("Best Node Updated!")
			bestNode = n
			bestDownloads = n.Clients
			if bestDownloads == 0 { return bestNode }
		}
	}
	if bestDownloads == -1 { return nil }
	return bestNode

}

func RepoCreateNetwork(n *swl.Network) *swl.Network {
	currentNetworkId += 1
	n.Id = currentNetworkId
	fmt.Println("Added Network")
	networks = append(networks, n)
	return n
}

func RepoDestroyNetwork(id int) error {
	for i, n := range networks {
		if n.Id == id {
			networks = append(networks[:i], networks[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Network with id of %d to delete", id)
}

func RepoFindNode(id int) *swl.Node {
	for _, n := range nodes {
		if n.Id == id {
			return n
		}
	}
	//Otherwise, Return Empty
	return nil
}

func RepoCreateNode(n *swl.Node) *swl.Node {
	currentNodeId += 1
	n.Id = currentNodeId
	n.Added = time.Now()
	nodes = append(nodes, n)
	return n
}

func RepoEnableNode(id int) *swl.Node {
	node := RepoFindNode(id)
	if node == nil { return nil }
	node.Enabled = true
	return node
}

func RepoDestroyNode(id int) error {
	for i, n := range nodes {
		if n.Id == id {
			nodes = append(nodes[:i], nodes[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Node with id of %d to delete", id)
}

func RepoUpdateNodeClients(id int, increment bool) error {
	for _, n := range nodes {
		if n.Id == id {
			if increment {
				n.Clients += 1
			} else {
				n.Clients -= 1
			}
		return nil
		}
	}
	return fmt.Errorf("Unable to find Node with id of %d to Update Clients", id)
}
<commit_msg>Changed File to Download<commit_after>package main

import (
	"fmt"
	"time"

	swl "github.com/stohio/software-lab/lib"
)

var currentNodeId int
var currentNetworkId int
var currentStackId int

var nodes swl.Nodes
var networks swl.Networks

var stacks swl.Stacks

func init() {

	version1 := swl.Version {
		Id:		1,
		Version:	"1.0",
		OS:		"Windows",
		Architecture:	"64",
		Extension:	".txt",
		URL:		"http://download.thinkbroadband.com/10MB.zip",
	}

	version2 := swl.Version {
		Id:		2,
		Version:	"1.0",
		OS:		"Mac",
		Architecture:	"64",
		Extension:	".txt",
		URL:		"http://download.thinkbroadband.com/10MB.zip",
	}

	var versions swl.Versions
	versions = append(versions, &version1)
	versions = append(versions, &version2)

	software1 := swl.Software {
		Id:		1,
		Name:		"My Software",
		Publisher:	"Stohio",
		Versions:	versions,
	}

	software2 := swl.Software {
		Id:		2,
		Name:		"Not My Software",
		Publisher:	"Stohio",
		Versions:	versions,
	}

	var softwares swl.Softwares
	softwares = append(softwares, &software1)
	softwares = append(softwares, &software2)

	package1 := swl.Package {
		Id:		1,
		Name:		"Pack One",
		Description:	"This is a Package",
		Softwares:	softwares,
	}

	package2 := swl.Package {
		Id:		2,
		Name:		"Two Pack",
		Description:	"This is also a Package",
		Softwares:	softwares,
	}
	var packages swl.Packages
	packages = append(packages, &package1)
	packages = append(packages, &package2)

	stack := swl.Stack {
		Id:		1,
		Name:		"My First Stack",
		Packages:	packages,
		Softwares:	softwares,
	}
	stacks = append(stacks, &stack)

}

func RepoFindStack(id int) *swl.Stack {
	for _, s :=range stacks {
		if s.Id == id {
			return s
		}
	}
	return nil
}

func RepoCreateStack(s *swl.Stack) *swl.Stack {
	currentStackId += 1
	s.Id = currentStackId
	stacks = append(stacks, s)
	return s
}

func RepoDestroyStack(id int) error {
	for i, s := range stacks {
		if s.Id == id {
			stacks = append(stacks[:i], stacks[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Stack with id of %d to delete", id)
}

func RepoFindNetworkByIP(ip string) (*swl.Network) {
	for _, net := range networks {
		if net.IP == ip {
			return net
		}
	}
	return nil
}

func RepoFindBestNodeInNetworkByIP(ip string) (*swl.Node) {
	net := RepoFindNetworkByIP(ip)
	if net == nil {
		fmt.Println("Could Not Find Network")
		return nil
	}
	var bestNode *swl.Node
	bestDownloads := -1
	for _, n := range net.Nodes {
		fmt.Printf("Node, Best: %d. %d\n", n.Clients, bestDownloads)
		if (n.Clients < bestDownloads || bestDownloads == -1) && (n.Enabled) {
			fmt.Println("Best Node Updated!")
			bestNode = n
			bestDownloads = n.Clients
			if bestDownloads == 0 { return bestNode }
		}
	}
	if bestDownloads == -1 { return nil }
	return bestNode

}

func RepoCreateNetwork(n *swl.Network) *swl.Network {
	currentNetworkId += 1
	n.Id = currentNetworkId
	fmt.Println("Added Network")
	networks = append(networks, n)
	return n
}

func RepoDestroyNetwork(id int) error {
	for i, n := range networks {
		if n.Id == id {
			networks = append(networks[:i], networks[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Network with id of %d to delete", id)
}

func RepoFindNode(id int) *swl.Node {
	for _, n := range nodes {
		if n.Id == id {
			return n
		}
	}
	//Otherwise, Return Empty
	return nil
}

func RepoCreateNode(n *swl.Node) *swl.Node {
	currentNodeId += 1
	n.Id = currentNodeId
	n.Added = time.Now()
	nodes = append(nodes, n)
	return n
}

func RepoEnableNode(id int) *swl.Node {
	node := RepoFindNode(id)
	if node == nil { return nil }
	node.Enabled = true
	return node
}

func RepoDestroyNode(id int) error {
	for i, n := range nodes {
		if n.Id == id {
			nodes = append(nodes[:i], nodes[i+1:]...)
			return nil
		}
	}
	return fmt.Errorf("Unable to find Node with id of %d to delete", id)
}

func RepoUpdateNodeClients(id int, increment bool) error {
	for _, n := range nodes {
		if n.Id == id {
			if increment {
				n.Clients += 1
			} else {
				n.Clients -= 1
			}
		return nil
		}
	}
	return fmt.Errorf("Unable to find Node with id of %d to Update Clients", id)
}
<|endoftext|>


<commit_before>package rest

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/toorop/tmail/scope"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
)

const (
	// Max size of the posted body
	body_read_limit = 1048576
)

// LaunchServer launches HTTP server
func LaunchServer() {
	router := mux.NewRouter()
	//router.HandleFunc("/", HomeHandler)
	router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, "coucou")
	})

	// Users handlers
	addUsersHandlers(router)

	// Server
	n := negroni.New(negroni.NewRecovery(), NewLogger())
	n.UseHandler(router)
	//n.Run(fmt.Sprintf("%s:%d", scope.Cfg.GetRestServerIp(), scope.Cfg.GetRestServerPort()))
	addr := fmt.Sprintf("%s:%d", scope.Cfg.GetRestServerIp(), scope.Cfg.GetRestServerPort())

	// TLS
	if scope.Cfg.GetRestServerIsTls() {
		scope.Log.Info("httpd " + addr + " TLS launched")
		log.Fatalln(http.ListenAndServeTLS(addr, path.Join(getBasePath(), "ssl/server.crt"), path.Join(getBasePath(), "ssl/server.key"), n))
	} else {
		scope.Log.Info("httpd " + addr + " launched")
		log.Fatalln(http.ListenAndServe(addr, n))
	}
}

// getBasePath is a helper for retrieving app path
func getBasePath() string {
	p, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	return p
}
<commit_msg>rest add ping/pong<commit_after>package rest

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/toorop/tmail/scope"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
)

const (
	// Max size of the posted body
	body_read_limit = 1048576
)

// LaunchServer launches HTTP server
func LaunchServer() {
	router := mux.NewRouter()
	//router.HandleFunc("/", HomeHandler)
	router.HandleFunc("/ping", func(w http.ResponseWriter, req *http.Request) {
		httpWriteJson(w, []byte(`{"msg": "pong"}`))
	})

	// Users handlers
	addUsersHandlers(router)

	// Server
	n := negroni.New(negroni.NewRecovery(), NewLogger())
	n.UseHandler(router)
	//n.Run(fmt.Sprintf("%s:%d", scope.Cfg.GetRestServerIp(), scope.Cfg.GetRestServerPort()))
	addr := fmt.Sprintf("%s:%d", scope.Cfg.GetRestServerIp(), scope.Cfg.GetRestServerPort())

	// TLS
	if scope.Cfg.GetRestServerIsTls() {
		scope.Log.Info("httpd " + addr + " TLS launched")
		log.Fatalln(http.ListenAndServeTLS(addr, path.Join(getBasePath(), "ssl/server.crt"), path.Join(getBasePath(), "ssl/server.key"), n))
	} else {
		scope.Log.Info("httpd " + addr + " launched")
		log.Fatalln(http.ListenAndServe(addr, n))
	}
}

// getBasePath is a helper for retrieving app path
func getBasePath() string {
	p, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	return p
}
<|endoftext|>


<commit_before>package management

import (
	"fmt"
	"os"
	"strings"

	v32 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"

	"github.com/rancher/rancher/pkg/controllers/management/drivers/kontainerdriver"
	v3 "github.com/rancher/rancher/pkg/generated/norman/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/types/config"
	"github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/api/errors"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func addKontainerDrivers(management *config.ManagementContext) error {
	// create binary drop location if not exists
	err := os.MkdirAll(kontainerdriver.DriverDir, 0777)
	if err != nil {
		return fmt.Errorf("error creating binary drop folder: %v", err)
	}

	creator := driverCreator{
		driversLister: management.Management.KontainerDrivers("").Controller().Lister(),
		drivers:       management.Management.KontainerDrivers(""),
	}

	if err := cleanupImportDriver(creator); err != nil {
		return err
	}

	if err := creator.add("rancherKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("googleKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("azureKubernetesService"); err != nil {
		return err
	}

	if err := creator.add("amazonElasticContainerService"); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"baiducloudcontainerengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/kontainer-engine-driver-baidu-linux",
		"4613e3be3ae5487b0e21dfa761b95de2144f80f98bf76847411e5fcada343d5e",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/component.js",
		false,
		"drivers.rancher.cn", "*.baidubce.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"aliyunkubernetescontainerservice",
		"https://drivers.rancher.cn/kontainer-engine-driver-aliyun/0.2.6/kontainer-engine-driver-aliyun-linux",
		"8a5360269ec803e3d8cf2c9cc94c66879da03a1fd2b580912c1a83454509c84c",
		"https://drivers.rancher.cn/pandaria/ui/cluster-driver-aliyun/0.1.1/component.js",
		false,
		"*.aliyuncs.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"tencentkubernetesengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-tencent/0.3.0/kontainer-engine-driver-tencent-linux",
		"ad5406502daf826874889963d7bdaed78db4689f147889ecf97394bc4e8d3d76",
		"",
		false,
		"*.tencentcloudapi.com", "*.qcloud.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"huaweicontainercloudengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-huawei/0.1.2/kontainer-engine-driver-huawei-linux",
		"0b6c1dfaa477a60a3bd9f8a60a55fcafd883866c2c5c387aec75b95d6ba81d45",
		"",
		false,
		"*.myhuaweicloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"oraclecontainerengine",
		"https://github.com/rancher-plugins/kontainer-engine-driver-oke/releases/download/v1.4.2/kontainer-engine-driver-oke-linux",
		"6cfdecfdafe229b695746af6773b79643dbedba2f690e5e14ef47d5813250805",
		"",
		false,
		"*.oraclecloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"linodekubernetesengine",
		"https://github.com/tamalsaha/kontainer-engine-driver-linode/releases/download/v0.0.21/kontainer-engine-driver-lke",
		"",
		"http://localhost:3000/component.js",
		false,
		"",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"opentelekomcloudcontainerengine",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/driver/1.0.2/kontainer-engine-driver-otccce_linux_amd64.tar.gz",
		"f2c0a8d1195cd51ae1ccdeb4a8defd2c3147b9a2c7510b091be0c12028740f5f",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/ui/v1.0.3/component.js",
		false,
		"*.otc.t-systems.com",
	); err != nil {
		return err
	}

	return nil
}

func cleanupImportDriver(creator driverCreator) error {
	var err error
	if _, err = creator.driversLister.Get("", "import"); err == nil {
		err = creator.drivers.Delete("import", &v1.DeleteOptions{})
	}

	if !errors.IsNotFound(err) {
		return err
	}

	return nil
}

type driverCreator struct {
	driversLister v3.KontainerDriverLister
	drivers       v3.KontainerDriverInterface
}

func (c *driverCreator) add(name string) error {
	logrus.Infof("adding kontainer driver %v", name)

	driver, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name:      strings.ToLower(name),
					Namespace: "",
				},
				Spec: v32.KontainerDriverSpec{
					URL:     "",
					BuiltIn: true,
					Active:  true,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	} else {
		driver.Spec.URL = ""

		_, err = c.drivers.Update(driver)
		if err != nil {
			return fmt.Errorf("error updating driver: %v", err)
		}
	}

	return nil
}

func (c *driverCreator) addCustomDriver(name, url, checksum, uiURL string, active bool, domains ...string) error {
	logrus.Infof("adding kontainer driver %v", name)
	_, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name: strings.ToLower(name),
				},
				Spec: v32.KontainerDriverSpec{
					URL:              url,
					BuiltIn:          false,
					Active:           active,
					Checksum:         checksum,
					UIURL:            uiURL,
					WhitelistDomains: domains,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	}
	return nil
}
<commit_msg>Update to newest linode release<commit_after>package management

import (
	"fmt"
	"os"
	"strings"

	v32 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"

	"github.com/rancher/rancher/pkg/controllers/management/drivers/kontainerdriver"
	v3 "github.com/rancher/rancher/pkg/generated/norman/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/types/config"
	"github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/api/errors"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func addKontainerDrivers(management *config.ManagementContext) error {
	// create binary drop location if not exists
	err := os.MkdirAll(kontainerdriver.DriverDir, 0777)
	if err != nil {
		return fmt.Errorf("error creating binary drop folder: %v", err)
	}

	creator := driverCreator{
		driversLister: management.Management.KontainerDrivers("").Controller().Lister(),
		drivers:       management.Management.KontainerDrivers(""),
	}

	if err := cleanupImportDriver(creator); err != nil {
		return err
	}

	if err := creator.add("rancherKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("googleKubernetesEngine"); err != nil {
		return err
	}

	if err := creator.add("azureKubernetesService"); err != nil {
		return err
	}

	if err := creator.add("amazonElasticContainerService"); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"baiducloudcontainerengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/kontainer-engine-driver-baidu-linux",
		"4613e3be3ae5487b0e21dfa761b95de2144f80f98bf76847411e5fcada343d5e",
		"https://drivers.rancher.cn/kontainer-engine-driver-baidu/0.2.0/component.js",
		false,
		"drivers.rancher.cn", "*.baidubce.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"aliyunkubernetescontainerservice",
		"https://drivers.rancher.cn/kontainer-engine-driver-aliyun/0.2.6/kontainer-engine-driver-aliyun-linux",
		"8a5360269ec803e3d8cf2c9cc94c66879da03a1fd2b580912c1a83454509c84c",
		"https://drivers.rancher.cn/pandaria/ui/cluster-driver-aliyun/0.1.1/component.js",
		false,
		"*.aliyuncs.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"tencentkubernetesengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-tencent/0.3.0/kontainer-engine-driver-tencent-linux",
		"ad5406502daf826874889963d7bdaed78db4689f147889ecf97394bc4e8d3d76",
		"",
		false,
		"*.tencentcloudapi.com", "*.qcloud.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"huaweicontainercloudengine",
		"https://drivers.rancher.cn/kontainer-engine-driver-huawei/0.1.2/kontainer-engine-driver-huawei-linux",
		"0b6c1dfaa477a60a3bd9f8a60a55fcafd883866c2c5c387aec75b95d6ba81d45",
		"",
		false,
		"*.myhuaweicloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"oraclecontainerengine",
		"https://github.com/rancher-plugins/kontainer-engine-driver-oke/releases/download/v1.4.2/kontainer-engine-driver-oke-linux",
		"6cfdecfdafe229b695746af6773b79643dbedba2f690e5e14ef47d5813250805",
		"",
		false,
		"*.oraclecloud.com",
	); err != nil {
		return err
	}
	if err := creator.addCustomDriver(
		"linodekubernetesengine",
		"https://github.com/linode/kontainer-engine-driver-lke/releases/download/v0.0.3/kontainer-engine-driver-lke-linux-amd64",
		"02fa95d24a1c6f9c520307e24a543c1777ed21fc3a4f060434e067806578e647",
		"https://github.com/linode/ui-cluster-driver-lke/releases/download/v0.0.3/component.js",
		false,
		"*.linode.com",
	); err != nil {
		return err
	}

	if err := creator.addCustomDriver(
		"opentelekomcloudcontainerengine",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/driver/1.0.2/kontainer-engine-driver-otccce_linux_amd64.tar.gz",
		"f2c0a8d1195cd51ae1ccdeb4a8defd2c3147b9a2c7510b091be0c12028740f5f",
		"https://otc-rancher.obs.eu-de.otc.t-systems.com/cluster/ui/v1.0.3/component.js",
		false,
		"*.otc.t-systems.com",
	); err != nil {
		return err
	}

	return nil
}

func cleanupImportDriver(creator driverCreator) error {
	var err error
	if _, err = creator.driversLister.Get("", "import"); err == nil {
		err = creator.drivers.Delete("import", &v1.DeleteOptions{})
	}

	if !errors.IsNotFound(err) {
		return err
	}

	return nil
}

type driverCreator struct {
	driversLister v3.KontainerDriverLister
	drivers       v3.KontainerDriverInterface
}

func (c *driverCreator) add(name string) error {
	logrus.Infof("adding kontainer driver %v", name)

	driver, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name:      strings.ToLower(name),
					Namespace: "",
				},
				Spec: v32.KontainerDriverSpec{
					URL:     "",
					BuiltIn: true,
					Active:  true,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	} else {
		driver.Spec.URL = ""

		_, err = c.drivers.Update(driver)
		if err != nil {
			return fmt.Errorf("error updating driver: %v", err)
		}
	}

	return nil
}

func (c *driverCreator) addCustomDriver(name, url, checksum, uiURL string, active bool, domains ...string) error {
	logrus.Infof("adding kontainer driver %v", name)
	_, err := c.driversLister.Get("", name)
	if err != nil {
		if errors.IsNotFound(err) {
			_, err = c.drivers.Create(&v3.KontainerDriver{
				ObjectMeta: v1.ObjectMeta{
					Name: strings.ToLower(name),
				},
				Spec: v32.KontainerDriverSpec{
					URL:              url,
					BuiltIn:          false,
					Active:           active,
					Checksum:         checksum,
					UIURL:            uiURL,
					WhitelistDomains: domains,
				},
				Status: v32.KontainerDriverStatus{
					DisplayName: name,
				},
			})
			if err != nil && !errors.IsAlreadyExists(err) {
				return fmt.Errorf("error creating driver: %v", err)
			}
		} else {
			return fmt.Errorf("error getting driver: %v", err)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>//
// Copyright 2022 The AFF Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package inmemory

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"

	"github.com/guacsec/guac/pkg/assembler"
	"github.com/guacsec/guac/pkg/handler/processor"
	"github.com/in-toto/in-toto-golang/in_toto"
)

const (
	algorithmSHA256 string = "sha256"
)

type InMemoryParser struct{}

func (m *InMemoryParser) ParseDocumentTree(processedDocTree processor.DocumentTree) (assembler.AssemblerInput, error) {

	nodes, edges, err := parserHelper(processedDocTree)
	if err != nil {
		return assembler.AssemblerInput{}, err
	}

	assemblerinput := assembler.AssemblerInput{
		V: nodes,
		E: edges,
	}

	return assemblerinput, nil
}

func (m *InMemoryParser) Type() string {
	return "inmemory"
}

func parserHelper(processedDocTree processor.DocumentTree) ([]assembler.GuacNode, []assembler.GuacEdge, error) {
	foundNodes := []assembler.GuacNode{}
	foundEdges := []assembler.GuacEdge{}

	nodes, edges, err := parseDoc(processedDocTree.Document)
	if err != nil {
		return nil, nil, err
	}

	foundNodes = append(foundNodes, nodes...)
	foundEdges = append(foundEdges, edges...)

	for _, d := range processedDocTree.Children {
		nodes, edges, err := parserHelper(processor.DocumentTree(d))
		if err != nil {
			return nil, nil, err
		}
		foundNodes = append(foundNodes, nodes...)
		foundEdges = append(foundEdges, edges...)
	}
	return foundNodes, foundEdges, nil
}

func parseDoc(doc *processor.Document) ([]assembler.GuacNode, []assembler.GuacEdge, error) {
	foundNodes := []assembler.GuacNode{}
	foundEdges := []assembler.GuacEdge{}
	switch doc.Type {
	case processor.DocumentDSSE:
		//verify the signatures and create the identity node
	case processor.DocumentSLSA:
		if len(doc.Blob) > 0 {
			// append attestation node
			h := sha256.Sum256(doc.Blob)
			attNode := assembler.AttestationNode{FilePath: "", Digest: algorithmSHA256 + ":" + hex.EncodeToString(h[:])}
			foundNodes = append(foundNodes, attNode)

			statement, err := parseSlsaPredicate(doc.Blob)
			if err != nil {
				return nil, nil, err
			}

			// append builder node for builder
			builderNode := assembler.BuilderNode{BuilderType: statement.Predicate.BuildType, BuilderId: statement.Predicate.Builder.ID}
			foundNodes = append(foundNodes, builderNode)

			// append dependency nodes for the materials
			mats := []assembler.ArtifactNode{}
			for _, mat := range statement.Predicate.Materials {
				for alg, ds := range mat.Digest {
					mat := assembler.ArtifactNode{Name: mat.URI, Digest: alg + ":" + ds}
					mats = append(mats, mat)
					foundNodes = append(foundNodes, mat)
				}
			}

			// append artifact node for the subjects
			for _, sub := range statement.Subject {
				for alg, ds := range sub.Digest {
					atfNode := assembler.ArtifactNode{Name: sub.Name, Digest: alg + ":" + ds}
					foundEdges = append(foundEdges, assembler.AttestationForEdge{AttestationNode: attNode, ArtifactNode: atfNode})
					foundEdges = append(foundEdges, assembler.BuiltByEdge{BuilderNode: builderNode, ArtifactNode: atfNode})
					foundNodes = append(foundNodes, atfNode)
					for _, m := range mats {
						foundEdges = append(foundEdges, assembler.DependsOnEdge{ArtifactNode: atfNode, Dependency: m})
					}
				}
			}
		}
	}
	return foundNodes, foundEdges, nil
}

func parseSlsaPredicate(p []byte) (*in_toto.ProvenanceStatement, error) {
	predicate := in_toto.ProvenanceStatement{}
	if err := json.Unmarshal(p, &predicate); err != nil {
		return nil, err
	}
	return &predicate, nil
}
<commit_msg>start dfs<commit_after><|endoftext|>


<commit_before>package planner

import (
	"errors"
	"fmt"

	rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1/plan"
	"github.com/rancher/rancher/pkg/controllers/provisioningv2/rke2"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/sirupsen/logrus"
)

// clearInitNodeMark removes the init node label on the given machine and updates the machine directly against the api
// server, effectively immediately demoting it from being an init node
func (p *Planner) clearInitNodeMark(entry *planEntry) error {
	if entry.Metadata.Labels[rke2.InitNodeLabel] == "" {
		return nil
	}

	if err := p.store.removePlanSecretLabel(entry, rke2.InitNodeLabel); err != nil {
		return err
	}
	// We've changed state, so let the caches sync up again
	return generic.ErrSkip
}

// setInitNodeMark sets the init node label on the given machine and updates the machine directly against the api
// server. It returns the modified/updated machine object
func (p *Planner) setInitNodeMark(entry *planEntry) error {
	if entry.Metadata.Labels[rke2.InitNodeLabel] == "true" {
		return nil
	}

	entry.Metadata.Labels[rke2.InitNodeLabel] = "true"
	if err := p.store.updatePlanSecretLabelsAndAnnotations(entry); err != nil {
		return err
	}

	// We've changed state, so let the caches sync up again
	return generic.ErrSkip
}

// findAndDesignateFixedInitNode is used for rancherd where an exact machine (determined by labeling the
// rkecontrolplane object) is desired to be the init node
func (p *Planner) findAndDesignateFixedInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (bool, string, *planEntry, error) {
	logrus.Debugf("rkecluster %s/%s: finding and designating fixed init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	fixedMachineID := rkeControlPlane.Labels[rke2.InitNodeMachineIDLabel]
	if fixedMachineID == "" {
		return false, "", nil, fmt.Errorf("fixed machine ID label did not exist on rkecontrolplane")
	}
	entries := collect(plan, func(entry *planEntry) bool {
		return entry.Metadata.Labels[rke2.MachineIDLabel] == fixedMachineID
	})
	if len(entries) > 1 {
		return false, "", nil, fmt.Errorf("multiple machines found with identical machine ID label %s=%s", rke2.MachineIDLabel, fixedMachineID)
	} else if len(entries) == 0 {
		return false, "", nil, fmt.Errorf("fixed machine with ID %s not found", fixedMachineID)
	}
	if rkeControlPlane.Labels[rke2.InitNodeMachineIDDoneLabel] == "" {
		logrus.Debugf("rkecluster %s/%s: setting designated init node to fixedMachineID: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fixedMachineID)
		allInitNodes := collect(plan, isEtcd)
		// clear all init node marks and return a generic.ErrSkip if we invalidated caches during clearing
		cachesInvalidated := false
		for _, entry := range allInitNodes {
			if entry.Machine.Labels[rke2.MachineIDLabel] == fixedMachineID {
				continue
			}
			err := p.clearInitNodeMark(entry)
			if err != nil && !errors.Is(err, generic.ErrSkip) {
				// if we received a strange error attempting to clear the init node mark
				return false, "", nil, err
			} else if errors.Is(err, generic.ErrSkip) {
				cachesInvalidated = true
			}
		}
		if cachesInvalidated {
			return false, "", nil, generic.ErrSkip
		}
		if err := p.setInitNodeMark(entries[0]); err != nil && !errors.Is(err, generic.ErrSkip) {
			return false, "", nil, err
		}
		rkeControlPlane = rkeControlPlane.DeepCopy()
		rkeControlPlane.Labels[rke2.InitNodeMachineIDDoneLabel] = "true"
		_, err := p.rkeControlPlanes.Update(rkeControlPlane)
		if err != nil {
			return false, "", nil, err
		}
		// if we set the designated init node on this iteration, return an errSkip so we know our cache is invalidated
		return true, entries[0].Metadata.Annotations[rke2.JoinURLAnnotation], entries[0], generic.ErrSkip
	}
	logrus.Debugf("rkecluster %s/%s: designated init node %s found", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fixedMachineID)
	return true, entries[0].Metadata.Annotations[rke2.JoinURLAnnotation], entries[0], nil
}

// findInitNode searches the given cluster for the init node. It returns a bool which is whether an init node was
// found, the init node join URL, and an error for a few conditions, i.e. if multiple init nodes were found or if there
// is a more suitable init node. Notably, if multiple init nodes are found, it will return false as it could not come to
// consensus on a single init node
func (p *Planner) findInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (bool, string, *planEntry, error) {
	logrus.Debugf("rkecluster %s/%s searching for init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	// if the rkecontrolplane object has an InitNodeMachineID label, we need to find the fixedInitNode.
	if rkeControlPlane.Labels[rke2.InitNodeMachineIDLabel] != "" {
		return p.findAndDesignateFixedInitNode(rkeControlPlane, plan)
	}

	joinURL := ""
	currentInitNodes := collect(plan, isInitNode)

	if len(currentInitNodes) > 1 {
		// if multiple init nodes are found, we don't know which one to return so return false with an error to hopefully trigger a re-election
		return false, "", nil, fmt.Errorf("multiple init nodes found")
	}

	initNodeFound := false

	// this loop should never execute more than once
	for _, entry := range currentInitNodes {
		if canBeInitNode(entry) {
			initNodeFound = true
			joinURL = entry.Metadata.Annotations[rke2.JoinURLAnnotation]
			logrus.Debugf("rkecluster %s/%s found current init node %s with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name, joinURL)
			if joinURL != "" {
				return true, joinURL, entry, nil
			}
		}
	}

	logrus.Debugf("rkecluster %s/%s: initNodeFound was %t and joinURL is empty", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, initNodeFound)
	// If the current init node has an empty joinURL annotation, we can look to see if there are other init nodes that are more suitable
	if initNodeFound {
		// if the init node was found but doesn't have a joinURL, let's see if there is possible a more suitable init node.
		possibleInitNodes := collect(plan, canBeInitNode)
		for _, entry := range possibleInitNodes {
			if entry.Metadata.Annotations[rke2.JoinURLAnnotation] != "" {
				// if a non-blank JoinURL was found, return that we found an init node but with an error
				return true, "", entry, fmt.Errorf("non-populated init node found, but more suitable alternative is available")
			}
		}
		// if we got through all possibleInitNodes (or there weren't any other possible init nodes), return true that we found an init node with no error.
		logrus.Debugf("rkecluster %s/%s: init node with empty JoinURLAnnotation was found, no suitable alternatives exist", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
		return true, "", nil, nil
	}

	return false, "", nil, fmt.Errorf("init node not found")
}

// electInitNode returns a joinURL and error (if one exists) of an init node. It will first search to see if an init node exists
// (using findInitNode), then will perform a re-election of the most suitable init node (one with a joinURL) and fall back to simply
// electing the first possible init node if no fully populated init node is found.
func (p *Planner) electInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (string, error) {
	logrus.Debugf("rkecluster %s/%s: determining if election of init node is necessary", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	initNodeFound, joinURL, _, err := p.findInitNode(rkeControlPlane, plan)
	if (initNodeFound && err == nil) || errors.Is(err, generic.ErrSkip) {
		logrus.Debugf("rkecluster %s/%s: init node was already elected and found with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, joinURL)
		return joinURL, err
	}
	// If the joinURL (or an errSkip) was not found, re-elect the init node.
	logrus.Debugf("rkecluster %s/%s: performing election of init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)

	possibleInitNodes := collect(plan, canBeInitNode)
	if len(possibleInitNodes) == 0 {
		logrus.Debugf("[planner] rkecluster %s/%s: no possible init nodes exist", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
		return joinURL, nil
	}

	// keep track of whether we invalidate our machine cache when we clear init node marks across nodes.
	cachesInvalidated := false
	// clear all etcd init node marks because we are re-electing our init node
	etcdEntries := collect(plan, isEtcd)
	for _, entry := range etcdEntries {
		// Ignore all etcd nodes that are not init nodes
		if !isInitNode(entry) {
			continue
		}
		logrus.Debugf("rkecluster %s/%s: clearing init node mark on machine %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name)
		if err := p.clearInitNodeMark(entry); err != nil && !errors.Is(err, generic.ErrSkip) {
			return "", err
		} else if errors.Is(err, generic.ErrSkip) {
			cachesInvalidated = true
		}
	}

	if cachesInvalidated {
		return "", generic.ErrSkip
	}

	var fallbackInitNode *planEntry
	fallbackInitNodeSet := false

	// Mark the first init node that has a joinURL as our new init node.
	for _, entry := range possibleInitNodes {
		if !fallbackInitNodeSet {
			// set the falbackInitNode to the first possible init node we encounter
			fallbackInitNode = entry
			fallbackInitNodeSet = true
		}
		if entry.Metadata.Annotations[rke2.JoinURLAnnotation] != "" {
			logrus.Debugf("rkecluster %s/%s: found %s as fully suitable init node with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name, entry.Metadata.Annotations[rke2.JoinURLAnnotation])
			// it is likely that the error returned by `electInitNode` is going to be `generic.ErrSkip`
			return entry.Metadata.Annotations[rke2.JoinURLAnnotation], p.setInitNodeMark(entry)
		}
	}

	if fallbackInitNodeSet {
		logrus.Debugf("rkecluster %s/%s: no fully suitable init node was found, marking %s as init node as fallback", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fallbackInitNode.Machine.Name)
		return "", p.setInitNodeMark(fallbackInitNode)
	}

	logrus.Debugf("rkecluster %s/%s: failed to elect init node, no suitable init nodes were found", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	return "", ErrWaiting("waiting for possible init node")
}

// designateInitNode is used to force-designate an init node in the cluster. This is especially useful for things like
// local etcd snapshot restore, where a snapshot may be contained on a specific node and that node needs to be the node that
// the snapshot is restored on.
func (p *Planner) designateInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan, nodeName string) (string, error) {
	logrus.Infof("rkecluster %s/%s: ensuring designated init node: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, nodeName)
	entries := collect(plan, isEtcd)
	cacheInvalidated := false
	joinURL := ""
	initNodeFound := false
	for _, entry := range entries {
		if entry.Machine.Status.NodeRef != nil &&
			entry.Machine.Status.NodeRef.Name == nodeName {
			// this is our new initNode
			initNodeFound = true
			if err := p.setInitNodeMark(entry); err != nil {
				if errors.Is(err, generic.ErrSkip) {
					cacheInvalidated = true
					continue
				}
				return "", err
			}
			joinURL = entry.Metadata.Annotations[rke2.JoinURLAnnotation]
		} else {
			if err := p.clearInitNodeMark(entry); err != nil {
				if errors.Is(err, generic.ErrSkip) {
					cacheInvalidated = true
					continue
				}
				return "", err
			}
		}
	}
	if !initNodeFound {
		return "", fmt.Errorf("rkecluster %s/%s: init node %s was not found during designation", rkeControlPlane.Namespace, rkeControlPlane.Name, nodeName)
	}
	if cacheInvalidated {
		return joinURL, generic.ErrSkip
	}
	return joinURL, nil
}
<commit_msg>change `designateInitNode` log from `INFO` to `DEBUG`<commit_after>package planner

import (
	"errors"
	"fmt"

	rkev1 "github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1"
	"github.com/rancher/rancher/pkg/apis/rke.cattle.io/v1/plan"
	"github.com/rancher/rancher/pkg/controllers/provisioningv2/rke2"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/sirupsen/logrus"
)

// clearInitNodeMark removes the init node label on the given machine and updates the machine directly against the api
// server, effectively immediately demoting it from being an init node
func (p *Planner) clearInitNodeMark(entry *planEntry) error {
	if entry.Metadata.Labels[rke2.InitNodeLabel] == "" {
		return nil
	}

	if err := p.store.removePlanSecretLabel(entry, rke2.InitNodeLabel); err != nil {
		return err
	}
	// We've changed state, so let the caches sync up again
	return generic.ErrSkip
}

// setInitNodeMark sets the init node label on the given machine and updates the machine directly against the api
// server. It returns the modified/updated machine object
func (p *Planner) setInitNodeMark(entry *planEntry) error {
	if entry.Metadata.Labels[rke2.InitNodeLabel] == "true" {
		return nil
	}

	entry.Metadata.Labels[rke2.InitNodeLabel] = "true"
	if err := p.store.updatePlanSecretLabelsAndAnnotations(entry); err != nil {
		return err
	}

	// We've changed state, so let the caches sync up again
	return generic.ErrSkip
}

// findAndDesignateFixedInitNode is used for rancherd where an exact machine (determined by labeling the
// rkecontrolplane object) is desired to be the init node
func (p *Planner) findAndDesignateFixedInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (bool, string, *planEntry, error) {
	logrus.Debugf("rkecluster %s/%s: finding and designating fixed init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	fixedMachineID := rkeControlPlane.Labels[rke2.InitNodeMachineIDLabel]
	if fixedMachineID == "" {
		return false, "", nil, fmt.Errorf("fixed machine ID label did not exist on rkecontrolplane")
	}
	entries := collect(plan, func(entry *planEntry) bool {
		return entry.Metadata.Labels[rke2.MachineIDLabel] == fixedMachineID
	})
	if len(entries) > 1 {
		return false, "", nil, fmt.Errorf("multiple machines found with identical machine ID label %s=%s", rke2.MachineIDLabel, fixedMachineID)
	} else if len(entries) == 0 {
		return false, "", nil, fmt.Errorf("fixed machine with ID %s not found", fixedMachineID)
	}
	if rkeControlPlane.Labels[rke2.InitNodeMachineIDDoneLabel] == "" {
		logrus.Debugf("rkecluster %s/%s: setting designated init node to fixedMachineID: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fixedMachineID)
		allInitNodes := collect(plan, isEtcd)
		// clear all init node marks and return a generic.ErrSkip if we invalidated caches during clearing
		cachesInvalidated := false
		for _, entry := range allInitNodes {
			if entry.Machine.Labels[rke2.MachineIDLabel] == fixedMachineID {
				continue
			}
			err := p.clearInitNodeMark(entry)
			if err != nil && !errors.Is(err, generic.ErrSkip) {
				// if we received a strange error attempting to clear the init node mark
				return false, "", nil, err
			} else if errors.Is(err, generic.ErrSkip) {
				cachesInvalidated = true
			}
		}
		if cachesInvalidated {
			return false, "", nil, generic.ErrSkip
		}
		if err := p.setInitNodeMark(entries[0]); err != nil && !errors.Is(err, generic.ErrSkip) {
			return false, "", nil, err
		}
		rkeControlPlane = rkeControlPlane.DeepCopy()
		rkeControlPlane.Labels[rke2.InitNodeMachineIDDoneLabel] = "true"
		_, err := p.rkeControlPlanes.Update(rkeControlPlane)
		if err != nil {
			return false, "", nil, err
		}
		// if we set the designated init node on this iteration, return an errSkip so we know our cache is invalidated
		return true, entries[0].Metadata.Annotations[rke2.JoinURLAnnotation], entries[0], generic.ErrSkip
	}
	logrus.Debugf("rkecluster %s/%s: designated init node %s found", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fixedMachineID)
	return true, entries[0].Metadata.Annotations[rke2.JoinURLAnnotation], entries[0], nil
}

// findInitNode searches the given cluster for the init node. It returns a bool which is whether an init node was
// found, the init node join URL, and an error for a few conditions, i.e. if multiple init nodes were found or if there
// is a more suitable init node. Notably, if multiple init nodes are found, it will return false as it could not come to
// consensus on a single init node
func (p *Planner) findInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (bool, string, *planEntry, error) {
	logrus.Debugf("rkecluster %s/%s searching for init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	// if the rkecontrolplane object has an InitNodeMachineID label, we need to find the fixedInitNode.
	if rkeControlPlane.Labels[rke2.InitNodeMachineIDLabel] != "" {
		return p.findAndDesignateFixedInitNode(rkeControlPlane, plan)
	}

	joinURL := ""
	currentInitNodes := collect(plan, isInitNode)

	if len(currentInitNodes) > 1 {
		// if multiple init nodes are found, we don't know which one to return so return false with an error to hopefully trigger a re-election
		return false, "", nil, fmt.Errorf("multiple init nodes found")
	}

	initNodeFound := false

	// this loop should never execute more than once
	for _, entry := range currentInitNodes {
		if canBeInitNode(entry) {
			initNodeFound = true
			joinURL = entry.Metadata.Annotations[rke2.JoinURLAnnotation]
			logrus.Debugf("rkecluster %s/%s found current init node %s with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name, joinURL)
			if joinURL != "" {
				return true, joinURL, entry, nil
			}
		}
	}

	logrus.Debugf("rkecluster %s/%s: initNodeFound was %t and joinURL is empty", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, initNodeFound)
	// If the current init node has an empty joinURL annotation, we can look to see if there are other init nodes that are more suitable
	if initNodeFound {
		// if the init node was found but doesn't have a joinURL, let's see if there is possible a more suitable init node.
		possibleInitNodes := collect(plan, canBeInitNode)
		for _, entry := range possibleInitNodes {
			if entry.Metadata.Annotations[rke2.JoinURLAnnotation] != "" {
				// if a non-blank JoinURL was found, return that we found an init node but with an error
				return true, "", entry, fmt.Errorf("non-populated init node found, but more suitable alternative is available")
			}
		}
		// if we got through all possibleInitNodes (or there weren't any other possible init nodes), return true that we found an init node with no error.
		logrus.Debugf("rkecluster %s/%s: init node with empty JoinURLAnnotation was found, no suitable alternatives exist", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
		return true, "", nil, nil
	}

	return false, "", nil, fmt.Errorf("init node not found")
}

// electInitNode returns a joinURL and error (if one exists) of an init node. It will first search to see if an init node exists
// (using findInitNode), then will perform a re-election of the most suitable init node (one with a joinURL) and fall back to simply
// electing the first possible init node if no fully populated init node is found.
func (p *Planner) electInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan) (string, error) {
	logrus.Debugf("rkecluster %s/%s: determining if election of init node is necessary", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	initNodeFound, joinURL, _, err := p.findInitNode(rkeControlPlane, plan)
	if (initNodeFound && err == nil) || errors.Is(err, generic.ErrSkip) {
		logrus.Debugf("rkecluster %s/%s: init node was already elected and found with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, joinURL)
		return joinURL, err
	}
	// If the joinURL (or an errSkip) was not found, re-elect the init node.
	logrus.Debugf("rkecluster %s/%s: performing election of init node", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)

	possibleInitNodes := collect(plan, canBeInitNode)
	if len(possibleInitNodes) == 0 {
		logrus.Debugf("[planner] rkecluster %s/%s: no possible init nodes exist", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
		return joinURL, nil
	}

	// keep track of whether we invalidate our machine cache when we clear init node marks across nodes.
	cachesInvalidated := false
	// clear all etcd init node marks because we are re-electing our init node
	etcdEntries := collect(plan, isEtcd)
	for _, entry := range etcdEntries {
		// Ignore all etcd nodes that are not init nodes
		if !isInitNode(entry) {
			continue
		}
		logrus.Debugf("rkecluster %s/%s: clearing init node mark on machine %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name)
		if err := p.clearInitNodeMark(entry); err != nil && !errors.Is(err, generic.ErrSkip) {
			return "", err
		} else if errors.Is(err, generic.ErrSkip) {
			cachesInvalidated = true
		}
	}

	if cachesInvalidated {
		return "", generic.ErrSkip
	}

	var fallbackInitNode *planEntry
	fallbackInitNodeSet := false

	// Mark the first init node that has a joinURL as our new init node.
	for _, entry := range possibleInitNodes {
		if !fallbackInitNodeSet {
			// set the falbackInitNode to the first possible init node we encounter
			fallbackInitNode = entry
			fallbackInitNodeSet = true
		}
		if entry.Metadata.Annotations[rke2.JoinURLAnnotation] != "" {
			logrus.Debugf("rkecluster %s/%s: found %s as fully suitable init node with joinURL: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, entry.Machine.Name, entry.Metadata.Annotations[rke2.JoinURLAnnotation])
			// it is likely that the error returned by `electInitNode` is going to be `generic.ErrSkip`
			return entry.Metadata.Annotations[rke2.JoinURLAnnotation], p.setInitNodeMark(entry)
		}
	}

	if fallbackInitNodeSet {
		logrus.Debugf("rkecluster %s/%s: no fully suitable init node was found, marking %s as init node as fallback", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, fallbackInitNode.Machine.Name)
		return "", p.setInitNodeMark(fallbackInitNode)
	}

	logrus.Debugf("rkecluster %s/%s: failed to elect init node, no suitable init nodes were found", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName)
	return "", ErrWaiting("waiting for possible init node")
}

// designateInitNode is used to force-designate an init node in the cluster. This is especially useful for things like
// local etcd snapshot restore, where a snapshot may be contained on a specific node and that node needs to be the node that
// the snapshot is restored on.
func (p *Planner) designateInitNode(rkeControlPlane *rkev1.RKEControlPlane, plan *plan.Plan, nodeName string) (string, error) {
	logrus.Debugf("rkecluster %s/%s: ensuring designated init node: %s", rkeControlPlane.Namespace, rkeControlPlane.Spec.ClusterName, nodeName)
	entries := collect(plan, isEtcd)
	cacheInvalidated := false
	joinURL := ""
	initNodeFound := false
	for _, entry := range entries {
		if entry.Machine.Status.NodeRef != nil &&
			entry.Machine.Status.NodeRef.Name == nodeName {
			// this is our new initNode
			initNodeFound = true
			if err := p.setInitNodeMark(entry); err != nil {
				if errors.Is(err, generic.ErrSkip) {
					cacheInvalidated = true
					continue
				}
				return "", err
			}
			joinURL = entry.Metadata.Annotations[rke2.JoinURLAnnotation]
		} else {
			if err := p.clearInitNodeMark(entry); err != nil {
				if errors.Is(err, generic.ErrSkip) {
					cacheInvalidated = true
					continue
				}
				return "", err
			}
		}
	}
	if !initNodeFound {
		return "", fmt.Errorf("rkecluster %s/%s: init node %s was not found during designation", rkeControlPlane.Namespace, rkeControlPlane.Name, nodeName)
	}
	if cacheInvalidated {
		return joinURL, generic.ErrSkip
	}
	return joinURL, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Skaffold Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package transform

import (
	"encoding/json"
	"fmt"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/util"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha1"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha3"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ToV1Alpha2 transforms v1alpha1 configs to v1alpha2
func ToV1Alpha2(vc util.VersionedConfig) (util.VersionedConfig, error) {
	if vc.GetVersion() != v1alpha1.Version {
		return nil, fmt.Errorf("Incompatible version: %s", vc.GetVersion())
	}
	oldConfig := vc.(*v1alpha1.SkaffoldConfig)

	var tagPolicy v1alpha2.TagPolicy
	if oldConfig.Build.TagPolicy == constants.TagStrategySha256 {
		tagPolicy = v1alpha2.TagPolicy{
			ShaTagger: &v1alpha2.ShaTagger{},
		}
	} else if oldConfig.Build.TagPolicy == constants.TagStrategyGitCommit {
		tagPolicy = v1alpha2.TagPolicy{
			GitTagger: &v1alpha2.GitTagger{},
		}
	}

	var newHelmDeploy *v1alpha2.HelmDeploy
	if oldConfig.Deploy.DeployType.HelmDeploy != nil {
		newReleases := make([]v1alpha2.HelmRelease, 0)
		for _, release := range oldConfig.Deploy.DeployType.HelmDeploy.Releases {
			newReleases = append(newReleases, v1alpha2.HelmRelease{
				Name:           release.Name,
				ChartPath:      release.ChartPath,
				ValuesFilePath: release.ValuesFilePath,
				Values:         release.Values,
				Namespace:      release.Namespace,
				Version:        release.Version,
			})
		}
		newHelmDeploy = &v1alpha2.HelmDeploy{
			Releases: newReleases,
		}
	}
	var newKubectlDeploy *v1alpha2.KubectlDeploy
	if oldConfig.Deploy.DeployType.KubectlDeploy != nil {
		newManifests := make([]string, 0)
		logrus.Warn("Ignoring manifest parameters when transforming v1alpha1 config; check kubernetes yaml before running skaffold")
		for _, manifest := range oldConfig.Deploy.DeployType.KubectlDeploy.Manifests {
			newManifests = append(newManifests, manifest.Paths...)
		}
		newKubectlDeploy = &v1alpha2.KubectlDeploy{
			Manifests: newManifests,
		}
	}

	var newArtifacts = make([]*v1alpha2.Artifact, 0)
	for _, artifact := range oldConfig.Build.Artifacts {
		newArtifacts = append(newArtifacts, &v1alpha2.Artifact{
			ImageName: artifact.ImageName,
			Workspace: artifact.Workspace,
			ArtifactType: v1alpha2.ArtifactType{
				DockerArtifact: &v1alpha2.DockerArtifact{
					DockerfilePath: artifact.DockerfilePath,
					BuildArgs:      artifact.BuildArgs,
				},
			},
		})
	}

	var newBuildType = v1alpha2.BuildType{}
	if oldConfig.Build.GoogleCloudBuild != nil {
		newBuildType.GoogleCloudBuild = &v1alpha2.GoogleCloudBuild{
			ProjectID: oldConfig.Build.GoogleCloudBuild.ProjectID,
		}
	}
	if oldConfig.Build.LocalBuild != nil {
		newBuildType.LocalBuild = &v1alpha2.LocalBuild{
			SkipPush: oldConfig.Build.LocalBuild.SkipPush,
		}
	}

	newConfig := &v1alpha2.SkaffoldConfig{
		APIVersion: v1alpha2.Version,
		Kind:       oldConfig.Kind,
		Deploy: v1alpha2.DeployConfig{
			DeployType: v1alpha2.DeployType{
				HelmDeploy:    newHelmDeploy,
				KubectlDeploy: newKubectlDeploy,
			},
		},
		Build: v1alpha2.BuildConfig{
			Artifacts: newArtifacts,
			BuildType: newBuildType,
			TagPolicy: tagPolicy,
		},
	}
	return newConfig, nil
}

// ToV1Alpha3 transforms configs from v1alpha2 to v1alpha3
func ToV1Alpha3(vc util.VersionedConfig) (util.VersionedConfig, error) {
	if vc.GetVersion() != v1alpha2.Version {
		return nil, fmt.Errorf("Incompatible version: %s", vc.GetVersion())
	}
	oldConfig := vc.(*v1alpha2.SkaffoldConfig)

	// convert v1alpha2.Deploy to v1alpha3.Deploy (should be the same)
	var newDeploy v1alpha3.DeployConfig
	if err := convert(oldConfig.Deploy, &newDeploy); err != nil {
		return nil, errors.Wrap(err, "converting deploy config")
	}
	// if the helm deploy config was set, then convert ValueFilePath to ValuesFiles
	if oldHelmDeploy := oldConfig.Deploy.DeployType.HelmDeploy; oldHelmDeploy != nil {
		for i, oldHelmRelease := range oldHelmDeploy.Releases {
			newDeploy.DeployType.HelmDeploy.Releases[i].ValuesFiles = []string{oldHelmRelease.ValuesFilePath}
		}
	}

	// convert v1alpha2.Profiles to v1alpha3.Profiles (should be the same)
	var newProfiles []v1alpha3.Profile
	if oldConfig.Profiles != nil {
		if err := convert(oldConfig.Profiles, &newProfiles); err != nil {
			return nil, errors.Wrap(err, "converting new profile")
		}
	}

	// convert v1alpha2.Build to v1alpha3.Build (different only for kaniko)
	oldKanikoBuilder := oldConfig.Build.KanikoBuild
	oldConfig.Build.KanikoBuild = nil

	// copy over old build config to new build config
	var newBuild v1alpha3.BuildConfig
	if err := convert(oldConfig.Build, &newBuild); err != nil {
		return nil, errors.Wrap(err, "converting new build")
	}
	// if the kaniko build was set, then convert it
	if oldKanikoBuilder != nil {
		newBuild.BuildType.KanikoBuild = &v1alpha3.KanikoBuild{
			BuildContext: v1alpha3.KanikoBuildContext{
				GCSBucket: oldKanikoBuilder.GCSBucket,
			},
			Namespace:      oldKanikoBuilder.Namespace,
			PullSecret:     oldKanikoBuilder.PullSecret,
			PullSecretName: oldKanikoBuilder.PullSecretName,
			Timeout:        oldKanikoBuilder.Timeout,
		}
	}
	newConfig := &v1alpha3.SkaffoldConfig{
		APIVersion: v1alpha3.Version,
		Kind:       oldConfig.Kind,
		Deploy:     newDeploy,
		Build:      newBuild,
		Profiles:   newProfiles,
	}
	return newConfig, nil
}

func convert(old interface{}, new interface{}) error {
	o, err := json.Marshal(old)
	if err != nil {
		return errors.Wrap(err, "marshalling old")
	}
	if err := json.Unmarshal(o, &new); err != nil {
		return errors.Wrap(err, "unmarshalling new")
	}
	return nil
}
<commit_msg>don't add empty ValuesFilePath to the dependencies list for Helm<commit_after>/*
Copyright 2018 The Skaffold Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package transform

import (
	"encoding/json"
	"fmt"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/util"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha1"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha3"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ToV1Alpha2 transforms v1alpha1 configs to v1alpha2
func ToV1Alpha2(vc util.VersionedConfig) (util.VersionedConfig, error) {
	if vc.GetVersion() != v1alpha1.Version {
		return nil, fmt.Errorf("Incompatible version: %s", vc.GetVersion())
	}
	oldConfig := vc.(*v1alpha1.SkaffoldConfig)

	var tagPolicy v1alpha2.TagPolicy
	if oldConfig.Build.TagPolicy == constants.TagStrategySha256 {
		tagPolicy = v1alpha2.TagPolicy{
			ShaTagger: &v1alpha2.ShaTagger{},
		}
	} else if oldConfig.Build.TagPolicy == constants.TagStrategyGitCommit {
		tagPolicy = v1alpha2.TagPolicy{
			GitTagger: &v1alpha2.GitTagger{},
		}
	}

	var newHelmDeploy *v1alpha2.HelmDeploy
	if oldConfig.Deploy.DeployType.HelmDeploy != nil {
		newReleases := make([]v1alpha2.HelmRelease, 0)
		for _, release := range oldConfig.Deploy.DeployType.HelmDeploy.Releases {
			newReleases = append(newReleases, v1alpha2.HelmRelease{
				Name:           release.Name,
				ChartPath:      release.ChartPath,
				ValuesFilePath: release.ValuesFilePath,
				Values:         release.Values,
				Namespace:      release.Namespace,
				Version:        release.Version,
			})
		}
		newHelmDeploy = &v1alpha2.HelmDeploy{
			Releases: newReleases,
		}
	}
	var newKubectlDeploy *v1alpha2.KubectlDeploy
	if oldConfig.Deploy.DeployType.KubectlDeploy != nil {
		newManifests := make([]string, 0)
		logrus.Warn("Ignoring manifest parameters when transforming v1alpha1 config; check kubernetes yaml before running skaffold")
		for _, manifest := range oldConfig.Deploy.DeployType.KubectlDeploy.Manifests {
			newManifests = append(newManifests, manifest.Paths...)
		}
		newKubectlDeploy = &v1alpha2.KubectlDeploy{
			Manifests: newManifests,
		}
	}

	var newArtifacts = make([]*v1alpha2.Artifact, 0)
	for _, artifact := range oldConfig.Build.Artifacts {
		newArtifacts = append(newArtifacts, &v1alpha2.Artifact{
			ImageName: artifact.ImageName,
			Workspace: artifact.Workspace,
			ArtifactType: v1alpha2.ArtifactType{
				DockerArtifact: &v1alpha2.DockerArtifact{
					DockerfilePath: artifact.DockerfilePath,
					BuildArgs:      artifact.BuildArgs,
				},
			},
		})
	}

	var newBuildType = v1alpha2.BuildType{}
	if oldConfig.Build.GoogleCloudBuild != nil {
		newBuildType.GoogleCloudBuild = &v1alpha2.GoogleCloudBuild{
			ProjectID: oldConfig.Build.GoogleCloudBuild.ProjectID,
		}
	}
	if oldConfig.Build.LocalBuild != nil {
		newBuildType.LocalBuild = &v1alpha2.LocalBuild{
			SkipPush: oldConfig.Build.LocalBuild.SkipPush,
		}
	}

	newConfig := &v1alpha2.SkaffoldConfig{
		APIVersion: v1alpha2.Version,
		Kind:       oldConfig.Kind,
		Deploy: v1alpha2.DeployConfig{
			DeployType: v1alpha2.DeployType{
				HelmDeploy:    newHelmDeploy,
				KubectlDeploy: newKubectlDeploy,
			},
		},
		Build: v1alpha2.BuildConfig{
			Artifacts: newArtifacts,
			BuildType: newBuildType,
			TagPolicy: tagPolicy,
		},
	}
	return newConfig, nil
}

// ToV1Alpha3 transforms configs from v1alpha2 to v1alpha3
func ToV1Alpha3(vc util.VersionedConfig) (util.VersionedConfig, error) {
	if vc.GetVersion() != v1alpha2.Version {
		return nil, fmt.Errorf("Incompatible version: %s", vc.GetVersion())
	}
	oldConfig := vc.(*v1alpha2.SkaffoldConfig)

	// convert v1alpha2.Deploy to v1alpha3.Deploy (should be the same)
	var newDeploy v1alpha3.DeployConfig
	if err := convert(oldConfig.Deploy, &newDeploy); err != nil {
		return nil, errors.Wrap(err, "converting deploy config")
	}
	// if the helm deploy config was set, then convert ValueFilePath to ValuesFiles
	if oldHelmDeploy := oldConfig.Deploy.DeployType.HelmDeploy; oldHelmDeploy != nil {
		for i, oldHelmRelease := range oldHelmDeploy.Releases {
			if oldHelmRelease.ValuesFilePath != "" {
				newDeploy.DeployType.HelmDeploy.Releases[i].ValuesFiles = []string{oldHelmRelease.ValuesFilePath}
			}
		}
	}

	// convert v1alpha2.Profiles to v1alpha3.Profiles (should be the same)
	var newProfiles []v1alpha3.Profile
	if oldConfig.Profiles != nil {
		if err := convert(oldConfig.Profiles, &newProfiles); err != nil {
			return nil, errors.Wrap(err, "converting new profile")
		}
	}

	// convert v1alpha2.Build to v1alpha3.Build (different only for kaniko)
	oldKanikoBuilder := oldConfig.Build.KanikoBuild
	oldConfig.Build.KanikoBuild = nil

	// copy over old build config to new build config
	var newBuild v1alpha3.BuildConfig
	if err := convert(oldConfig.Build, &newBuild); err != nil {
		return nil, errors.Wrap(err, "converting new build")
	}
	// if the kaniko build was set, then convert it
	if oldKanikoBuilder != nil {
		newBuild.BuildType.KanikoBuild = &v1alpha3.KanikoBuild{
			BuildContext: v1alpha3.KanikoBuildContext{
				GCSBucket: oldKanikoBuilder.GCSBucket,
			},
			Namespace:      oldKanikoBuilder.Namespace,
			PullSecret:     oldKanikoBuilder.PullSecret,
			PullSecretName: oldKanikoBuilder.PullSecretName,
			Timeout:        oldKanikoBuilder.Timeout,
		}
	}
	newConfig := &v1alpha3.SkaffoldConfig{
		APIVersion: v1alpha3.Version,
		Kind:       oldConfig.Kind,
		Deploy:     newDeploy,
		Build:      newBuild,
		Profiles:   newProfiles,
	}
	return newConfig, nil
}

func convert(old interface{}, new interface{}) error {
	o, err := json.Marshal(old)
	if err != nil {
		return errors.Wrap(err, "marshalling old")
	}
	if err := json.Unmarshal(o, &new); err != nil {
		return errors.Wrap(err, "unmarshalling new")
	}
	return nil
}
<|endoftext|>