<commit_before>/*
Copyright 2019 The Kubernetes 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 validation

import (
	"fmt"
	"net"
	"net/url"
	"strings"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/klog"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/pkg/cloudinstances"
	"k8s.io/kops/pkg/dns"
	"k8s.io/kops/upup/pkg/fi/cloudup"
)

// ValidationCluster uses a cluster to validate.
type ValidationCluster struct {
	Failures []*ValidationError `json:"failures,omitempty"`

	Nodes []*ValidationNode `json:"nodes,omitempty"`
}

// ValidationError holds a validation failure
type ValidationError struct {
	Kind    string `json:"type,omitempty"`
	Name    string `json:"name,omitempty"`
	Message string `json:"message,omitempty"`
}

type ClusterValidator interface {
	// Validate validates a k8s cluster
	Validate() (*ValidationCluster, error)
}

type clusterValidatorImpl struct {
	cluster           *kops.Cluster
	instanceGroupList *kops.InstanceGroupList
	k8sClient         kubernetes.Interface
}

func (v *ValidationCluster) addError(failure *ValidationError) {
	v.Failures = append(v.Failures, failure)
}

// ValidationNode represents the validation status for a node
type ValidationNode struct {
	Name     string             `json:"name,omitempty"`
	Zone     string             `json:"zone,omitempty"`
	Role     string             `json:"role,omitempty"`
	Hostname string             `json:"hostname,omitempty"`
	Status   v1.ConditionStatus `json:"status,omitempty"`
}

// hasPlaceHolderIP checks if the API DNS has been updated.
func hasPlaceHolderIP(clusterName string) (bool, error) {

	config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{CurrentContext: clusterName}).ClientConfig()
	if err != nil {
		return false, fmt.Errorf("error building configuration: %v", err)
	}

	apiAddr, err := url.Parse(config.Host)
	if err != nil {
		return true, fmt.Errorf("unable to parse Kubernetes cluster API URL: %v", err)
	}
	hostAddrs, err := net.LookupHost(apiAddr.Hostname())
	if err != nil {
		return true, fmt.Errorf("unable to resolve Kubernetes cluster API URL dns: %v", err)
	}

	for _, h := range hostAddrs {
		if h == "203.0.113.123" {
			return true, nil
		}
	}

	return false, nil
}

func NewClusterValidator(cluster *kops.Cluster, instanceGroupList *kops.InstanceGroupList, k8sClient kubernetes.Interface) (ClusterValidator, error) {
	return &clusterValidatorImpl{
		cluster:           cluster,
		instanceGroupList: instanceGroupList,
		k8sClient:         k8sClient,
	}, nil
}

func (v *clusterValidatorImpl) Validate() (*ValidationCluster, error) {
	return validateCluster(v.cluster, v.instanceGroupList, v.k8sClient)
}

// validateCluster validates a k8s cluster with a provided instance group list
func validateCluster(cluster *kops.Cluster, instanceGroupList *kops.InstanceGroupList, k8sClient kubernetes.Interface) (*ValidationCluster, error) {
	clusterName := cluster.Name

	v := &ValidationCluster{}

	// Do not use if we are running gossip
	if !dns.IsGossipHostname(clusterName) {
		contextName := clusterName

		hasPlaceHolderIPAddress, err := hasPlaceHolderIP(contextName)
		if err != nil {
			return nil, err
		}

		if hasPlaceHolderIPAddress {
			message := "Validation Failed\n\n" +
				"The dns-controller Kubernetes deployment has not updated the Kubernetes cluster's API DNS entry to the correct IP address." +
				"  The API DNS IP address is the placeholder address that kops creates: 203.0.113.123." +
				"  Please wait about 5-10 minutes for a master to start, dns-controller to launch, and DNS to propagate." +
				"  The protokube container and dns-controller deployment logs may contain more diagnostic information." +
				"  Etcd and the API DNS entries must be updated for a kops Kubernetes cluster to start."
			v.addError(&ValidationError{
				Kind:    "dns",
				Name:    "apiserver",
				Message: message,
			})
			return v, nil
		}
	}

	var instanceGroups []*kops.InstanceGroup

	for i := range instanceGroupList.Items {
		ig := &instanceGroupList.Items[i]
		instanceGroups = append(instanceGroups, ig)
	}

	if len(instanceGroups) == 0 {
		return nil, fmt.Errorf("no InstanceGroup objects found")
	}

	cloud, err := cloudup.BuildCloud(cluster)
	if err != nil {
		return nil, err
	}

	nodeList, err := k8sClient.CoreV1().Nodes().List(metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("error listing nodes: %v", err)
	}

	warnUnmatched := false
	cloudGroups, err := cloud.GetCloudGroups(cluster, instanceGroups, warnUnmatched, nodeList.Items)
	if err != nil {
		return nil, err
	}
	v.validateNodes(cloudGroups)

	if err := v.collectComponentFailures(k8sClient); err != nil {
		return nil, fmt.Errorf("cannot get component status for %q: %v", clusterName, err)
	}

	if err = v.collectPodFailures(k8sClient); err != nil {
		return nil, fmt.Errorf("cannot get pod health for %q: %v", clusterName, err)
	}

	return v, nil
}

func (v *ValidationCluster) collectComponentFailures(client kubernetes.Interface) error {
	componentList, err := client.CoreV1().ComponentStatuses().List(metav1.ListOptions{})
	if err != nil {
		return fmt.Errorf("error listing ComponentStatuses: %v", err)
	}

	for _, component := range componentList.Items {
		for _, condition := range component.Conditions {
			if condition.Status != v1.ConditionTrue {
				v.addError(&ValidationError{
					Kind:    "ComponentStatus",
					Name:    component.Name,
					Message: fmt.Sprintf("component %q is unhealthy", component.Name),
				})
			}
		}
	}
	return nil
}

func (v *ValidationCluster) collectPodFailures(client kubernetes.Interface) error {
	pods, err := client.CoreV1().Pods("kube-system").List(metav1.ListOptions{})
	if err != nil {
		return fmt.Errorf("error listing Pods: %v", err)
	}

	for _, pod := range pods.Items {
		if pod.Status.Phase == v1.PodSucceeded {
			continue
		}
		if pod.Status.Phase == v1.PodPending {
			v.addError(&ValidationError{
				Kind:    "Pod",
				Name:    "kube-system/" + pod.Name,
				Message: fmt.Sprintf("kube-system pod %q is pending", pod.Name),
			})
			continue
		}
		var notready []string
		for _, container := range pod.Status.ContainerStatuses {
			if !container.Ready {
				notready = append(notready, container.Name)
			}
		}
		if len(notready) != 0 {
			v.addError(&ValidationError{
				Kind:    "Pod",
				Name:    "kube-system/" + pod.Name,
				Message: fmt.Sprintf("kube-system pod %q is not ready (%s)", pod.Name, strings.Join(notready, ",")),
			})

		}
	}
	return nil
}

func (v *ValidationCluster) validateNodes(cloudGroups map[string]*cloudinstances.CloudInstanceGroup) {
	for _, cloudGroup := range cloudGroups {
		var allMembers []*cloudinstances.CloudInstanceGroupMember
		allMembers = append(allMembers, cloudGroup.Ready...)
		allMembers = append(allMembers, cloudGroup.NeedUpdate...)
		if len(allMembers) < cloudGroup.MinSize {
			v.addError(&ValidationError{
				Kind: "InstanceGroup",
				Name: cloudGroup.InstanceGroup.Name,
				Message: fmt.Sprintf("InstanceGroup %q did not have enough nodes %d vs %d",
					cloudGroup.InstanceGroup.Name,
					len(allMembers),
					cloudGroup.MinSize),
			})
		}

		for _, member := range allMembers {
			node := member.Node

			if node == nil {
				nodeExpectedToJoin := true
				if cloudGroup.InstanceGroup.Spec.Role == kops.InstanceGroupRoleBastion {
					// bastion nodes don't join the cluster
					nodeExpectedToJoin = false
				}

				if nodeExpectedToJoin {
					v.addError(&ValidationError{
						Kind:    "Machine",
						Name:    member.ID,
						Message: fmt.Sprintf("machine %q has not yet joined cluster", member.ID),
					})
				}
				continue
			}

			role := util.GetNodeRole(node)
			if role == "" {
				role = "node"
			}

			n := &ValidationNode{
				Name:     node.Name,
				Zone:     node.ObjectMeta.Labels["failure-domain.beta.kubernetes.io/zone"],
				Hostname: node.ObjectMeta.Labels["kubernetes.io/hostname"],
				Role:     role,
				Status:   getNodeReadyStatus(node),
			}

			ready := isNodeReady(node)

			// TODO: Use instance group role instead...
			if n.Role == "master" {
				if !ready {
					v.addError(&ValidationError{
						Kind:    "Node",
						Name:    node.Name,
						Message: fmt.Sprintf("master %q is not ready", node.Name),
					})
				}

				v.Nodes = append(v.Nodes, n)
			} else if n.Role == "node" {
				if !ready {
					v.addError(&ValidationError{
						Kind:    "Node",
						Name:    node.Name,
						Message: fmt.Sprintf("node %q is not ready", node.Name),
					})
				}

				v.Nodes = append(v.Nodes, n)
			} else {
				klog.Warningf("ignoring node with role %q", n.Role)
			}
		}
	}
}
<commit_msg>Extract the list of instance groups earlier in validation<commit_after>/*
Copyright 2019 The Kubernetes 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 validation

import (
	"fmt"
	"net"
	"net/url"
	"strings"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/klog"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/pkg/cloudinstances"
	"k8s.io/kops/pkg/dns"
	"k8s.io/kops/upup/pkg/fi/cloudup"
)

// ValidationCluster uses a cluster to validate.
type ValidationCluster struct {
	Failures []*ValidationError `json:"failures,omitempty"`

	Nodes []*ValidationNode `json:"nodes,omitempty"`
}

// ValidationError holds a validation failure
type ValidationError struct {
	Kind    string `json:"type,omitempty"`
	Name    string `json:"name,omitempty"`
	Message string `json:"message,omitempty"`
}

type ClusterValidator interface {
	// Validate validates a k8s cluster
	Validate() (*ValidationCluster, error)
}

type clusterValidatorImpl struct {
	cluster        *kops.Cluster
	instanceGroups []*kops.InstanceGroup
	k8sClient      kubernetes.Interface
}

func (v *ValidationCluster) addError(failure *ValidationError) {
	v.Failures = append(v.Failures, failure)
}

// ValidationNode represents the validation status for a node
type ValidationNode struct {
	Name     string             `json:"name,omitempty"`
	Zone     string             `json:"zone,omitempty"`
	Role     string             `json:"role,omitempty"`
	Hostname string             `json:"hostname,omitempty"`
	Status   v1.ConditionStatus `json:"status,omitempty"`
}

// hasPlaceHolderIP checks if the API DNS has been updated.
func hasPlaceHolderIP(clusterName string) (bool, error) {

	config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{CurrentContext: clusterName}).ClientConfig()
	if err != nil {
		return false, fmt.Errorf("error building configuration: %v", err)
	}

	apiAddr, err := url.Parse(config.Host)
	if err != nil {
		return true, fmt.Errorf("unable to parse Kubernetes cluster API URL: %v", err)
	}
	hostAddrs, err := net.LookupHost(apiAddr.Hostname())
	if err != nil {
		return true, fmt.Errorf("unable to resolve Kubernetes cluster API URL dns: %v", err)
	}

	for _, h := range hostAddrs {
		if h == "203.0.113.123" {
			return true, nil
		}
	}

	return false, nil
}

func NewClusterValidator(cluster *kops.Cluster, instanceGroupList *kops.InstanceGroupList, k8sClient kubernetes.Interface) (ClusterValidator, error) {
	var instanceGroups []*kops.InstanceGroup

	for i := range instanceGroupList.Items {
		ig := &instanceGroupList.Items[i]
		instanceGroups = append(instanceGroups, ig)
	}

	if len(instanceGroups) == 0 {
		return nil, fmt.Errorf("no InstanceGroup objects found")
	}

	return &clusterValidatorImpl{
		cluster:        cluster,
		instanceGroups: instanceGroups,
		k8sClient:      k8sClient,
	}, nil
}

func (v *clusterValidatorImpl) Validate() (*ValidationCluster, error) {
	return validateCluster(v.cluster, v.instanceGroups, v.k8sClient)
}

// validateCluster validates a k8s cluster with a provided instance group list
func validateCluster(cluster *kops.Cluster, instanceGroups []*kops.InstanceGroup, k8sClient kubernetes.Interface) (*ValidationCluster, error) {
	clusterName := cluster.Name

	v := &ValidationCluster{}

	// Do not use if we are running gossip
	if !dns.IsGossipHostname(clusterName) {
		contextName := clusterName

		hasPlaceHolderIPAddress, err := hasPlaceHolderIP(contextName)
		if err != nil {
			return nil, err
		}

		if hasPlaceHolderIPAddress {
			message := "Validation Failed\n\n" +
				"The dns-controller Kubernetes deployment has not updated the Kubernetes cluster's API DNS entry to the correct IP address." +
				"  The API DNS IP address is the placeholder address that kops creates: 203.0.113.123." +
				"  Please wait about 5-10 minutes for a master to start, dns-controller to launch, and DNS to propagate." +
				"  The protokube container and dns-controller deployment logs may contain more diagnostic information." +
				"  Etcd and the API DNS entries must be updated for a kops Kubernetes cluster to start."
			v.addError(&ValidationError{
				Kind:    "dns",
				Name:    "apiserver",
				Message: message,
			})
			return v, nil
		}
	}

	cloud, err := cloudup.BuildCloud(cluster)
	if err != nil {
		return nil, err
	}

	nodeList, err := k8sClient.CoreV1().Nodes().List(metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("error listing nodes: %v", err)
	}

	warnUnmatched := false
	cloudGroups, err := cloud.GetCloudGroups(cluster, instanceGroups, warnUnmatched, nodeList.Items)
	if err != nil {
		return nil, err
	}
	v.validateNodes(cloudGroups)

	if err := v.collectComponentFailures(k8sClient); err != nil {
		return nil, fmt.Errorf("cannot get component status for %q: %v", clusterName, err)
	}

	if err = v.collectPodFailures(k8sClient); err != nil {
		return nil, fmt.Errorf("cannot get pod health for %q: %v", clusterName, err)
	}

	return v, nil
}

func (v *ValidationCluster) collectComponentFailures(client kubernetes.Interface) error {
	componentList, err := client.CoreV1().ComponentStatuses().List(metav1.ListOptions{})
	if err != nil {
		return fmt.Errorf("error listing ComponentStatuses: %v", err)
	}

	for _, component := range componentList.Items {
		for _, condition := range component.Conditions {
			if condition.Status != v1.ConditionTrue {
				v.addError(&ValidationError{
					Kind:    "ComponentStatus",
					Name:    component.Name,
					Message: fmt.Sprintf("component %q is unhealthy", component.Name),
				})
			}
		}
	}
	return nil
}

func (v *ValidationCluster) collectPodFailures(client kubernetes.Interface) error {
	pods, err := client.CoreV1().Pods("kube-system").List(metav1.ListOptions{})
	if err != nil {
		return fmt.Errorf("error listing Pods: %v", err)
	}

	for _, pod := range pods.Items {
		if pod.Status.Phase == v1.PodSucceeded {
			continue
		}
		if pod.Status.Phase == v1.PodPending {
			v.addError(&ValidationError{
				Kind:    "Pod",
				Name:    "kube-system/" + pod.Name,
				Message: fmt.Sprintf("kube-system pod %q is pending", pod.Name),
			})
			continue
		}
		var notready []string
		for _, container := range pod.Status.ContainerStatuses {
			if !container.Ready {
				notready = append(notready, container.Name)
			}
		}
		if len(notready) != 0 {
			v.addError(&ValidationError{
				Kind:    "Pod",
				Name:    "kube-system/" + pod.Name,
				Message: fmt.Sprintf("kube-system pod %q is not ready (%s)", pod.Name, strings.Join(notready, ",")),
			})

		}
	}
	return nil
}

func (v *ValidationCluster) validateNodes(cloudGroups map[string]*cloudinstances.CloudInstanceGroup) {
	for _, cloudGroup := range cloudGroups {
		var allMembers []*cloudinstances.CloudInstanceGroupMember
		allMembers = append(allMembers, cloudGroup.Ready...)
		allMembers = append(allMembers, cloudGroup.NeedUpdate...)
		if len(allMembers) < cloudGroup.MinSize {
			v.addError(&ValidationError{
				Kind: "InstanceGroup",
				Name: cloudGroup.InstanceGroup.Name,
				Message: fmt.Sprintf("InstanceGroup %q did not have enough nodes %d vs %d",
					cloudGroup.InstanceGroup.Name,
					len(allMembers),
					cloudGroup.MinSize),
			})
		}

		for _, member := range allMembers {
			node := member.Node

			if node == nil {
				nodeExpectedToJoin := true
				if cloudGroup.InstanceGroup.Spec.Role == kops.InstanceGroupRoleBastion {
					// bastion nodes don't join the cluster
					nodeExpectedToJoin = false
				}

				if nodeExpectedToJoin {
					v.addError(&ValidationError{
						Kind:    "Machine",
						Name:    member.ID,
						Message: fmt.Sprintf("machine %q has not yet joined cluster", member.ID),
					})
				}
				continue
			}

			role := util.GetNodeRole(node)
			if role == "" {
				role = "node"
			}

			n := &ValidationNode{
				Name:     node.Name,
				Zone:     node.ObjectMeta.Labels["failure-domain.beta.kubernetes.io/zone"],
				Hostname: node.ObjectMeta.Labels["kubernetes.io/hostname"],
				Role:     role,
				Status:   getNodeReadyStatus(node),
			}

			ready := isNodeReady(node)

			// TODO: Use instance group role instead...
			if n.Role == "master" {
				if !ready {
					v.addError(&ValidationError{
						Kind:    "Node",
						Name:    node.Name,
						Message: fmt.Sprintf("master %q is not ready", node.Name),
					})
				}

				v.Nodes = append(v.Nodes, n)
			} else if n.Role == "node" {
				if !ready {
					v.addError(&ValidationError{
						Kind:    "Node",
						Name:    node.Name,
						Message: fmt.Sprintf("node %q is not ready", node.Name),
					})
				}

				v.Nodes = append(v.Nodes, n)
			} else {
				klog.Warningf("ignoring node with role %q", n.Role)
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 TSUYUSATO Kitsune
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

// Package heredoc_dot is the set of shortcuts for dot import.
//
// For example:
//     package main
//
//     import (
//     	"fmt"
//     	"runtime"
//     	. "github.com/MakeNowJust/heredoc/dot"
//     )
//
//     func main() {
//     	fmt.Printf(D(`
//     		GOROOT: %s
//     		GOARCH: %s
//     		GOOS  : %s
//     	`), runtime.GOROOT(), runtime.GOARCH, runtime.GOOS)
//     }
package heredoc_dot

import "github.com/MakeNowJust/heredoc"

// Shortcut heredoc.Doc
func D(raw string) string {
	return heredoc.Doc(raw)
}

// Shortcut heredoc.Docf
func Df(raw string, args ...interface{}) string {
	return heredoc.Docf(raw, args...)
}
<commit_msg>go fmt<commit_after>// Copyright (c) 2014 TSUYUSATO Kitsune
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

// Package heredoc_dot is the set of shortcuts for dot import.
//
// For example:
//     package main
//
//     import (
//     	"fmt"
//     	"runtime"
//     	. "github.com/MakeNowJust/heredoc/dot"
//     )
//
//     func main() {
//     	fmt.Printf(D(`
//     		GOROOT: %s
//     		GOARCH: %s
//     		GOOS  : %s
//     	`), runtime.GOROOT(), runtime.GOARCH, runtime.GOOS)
//     }
package heredoc_dot

import "github.com/MakeNowJust/heredoc"

// Shortcut heredoc.Doc
func D(raw string) string {
	return heredoc.Doc(raw)
}

// Shortcut heredoc.Docf
func Df(raw string, args ...interface{}) string {
	return heredoc.Docf(raw, args...)
}
<|endoftext|>


<commit_before>// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"

	"github.com/google/syzkaller/pkg/ast"
	"github.com/google/syzkaller/pkg/compiler"
	"github.com/google/syzkaller/pkg/osutil"
	"github.com/google/syzkaller/sys/targets"
)

var (
	flagOS        = flag.String("os", "", "target OS")
	flagBuild     = flag.Bool("build", false, "regenerate arch-specific kernel headers")
	flagSourceDir = flag.String("sourcedir", "", "path to kernel source checkout dir")
	flagBuildDir  = flag.String("builddir", "", "path to kernel build dir")
	flagArch      = flag.String("arch", "", "comma-separated list of arches to generate (all by default)")
)

type Arch struct {
	target    *targets.Target
	sourceDir string
	buildDir  string
	build     bool
	files     []*File
	err       error
	done      chan bool
}

type File struct {
	arch       *Arch
	name       string
	consts     map[string]uint64
	undeclared map[string]bool
	info       *compiler.ConstInfo
	err        error
	done       chan bool
}

type OS interface {
	prepare(sourcedir string, build bool, arches []string) error
	prepareArch(arch *Arch) error
	processFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error)
}

var oses = map[string]OS{
	"akaros":  new(akaros),
	"linux":   new(linux),
	"freebsd": new(freebsd),
	"netbsd":  new(netbsd),
	"android": new(linux),
	"fuchsia": new(fuchsia),
	"windows": new(windows),
}

func main() {
	failf := func(msg string, args ...interface{}) {
		fmt.Fprintf(os.Stderr, msg+"\n", args...)
		os.Exit(1)
	}
	flag.Parse()

	OS := oses[*flagOS]
	if OS == nil {
		failf("unknown os: %v", *flagOS)
	}
	if *flagBuild && *flagBuildDir != "" {
		failf("-build and -builddir is an invalid combination")
	}
	android := false
	if *flagOS == "android" {
		android = true
		*flagOS = "linux"
	}
	var archArray []string
	if *flagArch != "" {
		archArray = strings.Split(*flagArch, ",")
	} else {
		for arch := range targets.List[*flagOS] {
			archArray = append(archArray, arch)
		}
		if android {
			archArray = []string{"amd64", "arm64"}
		}
		sort.Strings(archArray)
	}
	files := flag.Args()
	if len(files) == 0 {
		matches, err := filepath.Glob(filepath.Join("sys", *flagOS, "*.txt"))
		if err != nil || len(matches) == 0 {
			failf("failed to find sys files: %v", err)
		}
		androidFiles := map[string]bool{
			"tlk_device.txt": true,
		}
		for _, f := range matches {
			f = filepath.Base(f)
			if *flagOS == "linux" && android != androidFiles[f] {
				continue
			}
			files = append(files, filepath.Base(f))
		}
		sort.Strings(files)
	}

	if err := OS.prepare(*flagSourceDir, *flagBuild, archArray); err != nil {
		failf("%v", err)
	}

	jobC := make(chan interface{}, len(archArray)*len(files))

	var arches []*Arch
	for _, archStr := range archArray {
		buildDir := ""
		if *flagBuild {
			dir, err := ioutil.TempDir("", "syzkaller-kernel-build")
			if err != nil {
				failf("failed to create temp dir: %v", err)
			}
			buildDir = dir
		} else if *flagBuildDir != "" {
			buildDir = *flagBuildDir
		} else {
			buildDir = *flagSourceDir
		}

		target := targets.List[*flagOS][archStr]
		if target == nil {
			failf("unknown arch: %v", archStr)
		}

		arch := &Arch{
			target:    target,
			sourceDir: *flagSourceDir,
			buildDir:  buildDir,
			build:     *flagBuild,
			done:      make(chan bool),
		}
		for _, f := range files {
			arch.files = append(arch.files, &File{
				arch: arch,
				name: f,
				done: make(chan bool),
			})
		}
		arches = append(arches, arch)
		jobC <- arch
	}

	for p := 0; p < runtime.GOMAXPROCS(0); p++ {
		go func() {
			for job := range jobC {
				switch j := job.(type) {
				case *Arch:
					infos, err := processArch(OS, j)
					j.err = err
					close(j.done)
					if j.err == nil {
						for _, f := range j.files {
							f.info = infos[f.name]
							jobC <- f
						}
					}
				case *File:
					j.consts, j.undeclared, j.err = processFile(OS, j.arch, j)
					close(j.done)
				}
			}
		}()
	}

	failed := false
	for _, arch := range arches {
		fmt.Printf("generating %v/%v...\n", arch.target.OS, arch.target.Arch)
		<-arch.done
		if arch.err != nil {
			failed = true
			fmt.Printf("	%v\n", arch.err)
			continue
		}
		for _, f := range arch.files {
			fmt.Printf("extracting from %v\n", f.name)
			<-f.done
			if f.err != nil {
				failed = true
				fmt.Printf("	%v\n", f.err)
				continue
			}
		}
		fmt.Printf("\n")
	}

	if !failed {
		supported := make(map[string]bool)
		unsupported := make(map[string]string)
		for _, arch := range arches {
			for _, f := range arch.files {
				for name := range f.consts {
					supported[name] = true
				}
				for name := range f.undeclared {
					unsupported[name] = f.name
				}
			}
		}
		for name, file := range unsupported {
			if supported[name] {
				continue
			}
			failed = true
			fmt.Printf("%v: %v is unsupported on all arches (typo?)\n",
				file, name)
		}
	}

	for _, arch := range arches {
		if arch.build {
			os.RemoveAll(arch.buildDir)
		}
	}
	if failed {
		os.Exit(1)
	}
}

func processArch(OS OS, arch *Arch) (map[string]*compiler.ConstInfo, error) {
	errBuf := new(bytes.Buffer)
	eh := func(pos ast.Pos, msg string) {
		fmt.Fprintf(errBuf, "%v: %v\n", pos, msg)
	}
	top := ast.ParseGlob(filepath.Join("sys", arch.target.OS, "*.txt"), eh)
	if top == nil {
		return nil, fmt.Errorf("%v", errBuf.String())
	}
	infos := compiler.ExtractConsts(top, arch.target, eh)
	if infos == nil {
		return nil, fmt.Errorf("%v", errBuf.String())
	}
	if err := OS.prepareArch(arch); err != nil {
		return nil, err
	}
	return infos, nil
}

func processFile(OS OS, arch *Arch, file *File) (map[string]uint64, map[string]bool, error) {
	inname := filepath.Join("sys", arch.target.OS, file.name)
	outname := strings.TrimSuffix(inname, ".txt") + "_" + arch.target.Arch + ".const"
	if len(file.info.Consts) == 0 {
		os.Remove(outname)
		return nil, nil, nil
	}
	consts, undeclared, err := OS.processFile(arch, file.info)
	if err != nil {
		return nil, nil, err
	}
	data := compiler.SerializeConsts(consts, undeclared)
	if err := osutil.WriteFile(outname, data); err != nil {
		return nil, nil, fmt.Errorf("failed to write output file: %v", err)
	}
	return consts, undeclared, nil
}
<commit_msg>sys/syz-extract: provide readable error on missing input file<commit_after>// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"

	"github.com/google/syzkaller/pkg/ast"
	"github.com/google/syzkaller/pkg/compiler"
	"github.com/google/syzkaller/pkg/osutil"
	"github.com/google/syzkaller/sys/targets"
)

var (
	flagOS        = flag.String("os", "", "target OS")
	flagBuild     = flag.Bool("build", false, "regenerate arch-specific kernel headers")
	flagSourceDir = flag.String("sourcedir", "", "path to kernel source checkout dir")
	flagBuildDir  = flag.String("builddir", "", "path to kernel build dir")
	flagArch      = flag.String("arch", "", "comma-separated list of arches to generate (all by default)")
)

type Arch struct {
	target    *targets.Target
	sourceDir string
	buildDir  string
	build     bool
	files     []*File
	err       error
	done      chan bool
}

type File struct {
	arch       *Arch
	name       string
	consts     map[string]uint64
	undeclared map[string]bool
	info       *compiler.ConstInfo
	err        error
	done       chan bool
}

type OS interface {
	prepare(sourcedir string, build bool, arches []string) error
	prepareArch(arch *Arch) error
	processFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error)
}

var oses = map[string]OS{
	"akaros":  new(akaros),
	"linux":   new(linux),
	"freebsd": new(freebsd),
	"netbsd":  new(netbsd),
	"android": new(linux),
	"fuchsia": new(fuchsia),
	"windows": new(windows),
}

func main() {
	failf := func(msg string, args ...interface{}) {
		fmt.Fprintf(os.Stderr, msg+"\n", args...)
		os.Exit(1)
	}
	flag.Parse()

	OS := oses[*flagOS]
	if OS == nil {
		failf("unknown os: %v", *flagOS)
	}
	if *flagBuild && *flagBuildDir != "" {
		failf("-build and -builddir is an invalid combination")
	}
	android := false
	if *flagOS == "android" {
		android = true
		*flagOS = "linux"
	}
	var archArray []string
	if *flagArch != "" {
		archArray = strings.Split(*flagArch, ",")
	} else {
		for arch := range targets.List[*flagOS] {
			archArray = append(archArray, arch)
		}
		if android {
			archArray = []string{"amd64", "arm64"}
		}
		sort.Strings(archArray)
	}
	files := flag.Args()
	if len(files) == 0 {
		matches, err := filepath.Glob(filepath.Join("sys", *flagOS, "*.txt"))
		if err != nil || len(matches) == 0 {
			failf("failed to find sys files: %v", err)
		}
		androidFiles := map[string]bool{
			"tlk_device.txt": true,
		}
		for _, f := range matches {
			f = filepath.Base(f)
			if *flagOS == "linux" && android != androidFiles[f] {
				continue
			}
			files = append(files, filepath.Base(f))
		}
		sort.Strings(files)
	}

	if err := OS.prepare(*flagSourceDir, *flagBuild, archArray); err != nil {
		failf("%v", err)
	}

	jobC := make(chan interface{}, len(archArray)*len(files))

	var arches []*Arch
	for _, archStr := range archArray {
		buildDir := ""
		if *flagBuild {
			dir, err := ioutil.TempDir("", "syzkaller-kernel-build")
			if err != nil {
				failf("failed to create temp dir: %v", err)
			}
			buildDir = dir
		} else if *flagBuildDir != "" {
			buildDir = *flagBuildDir
		} else {
			buildDir = *flagSourceDir
		}

		target := targets.List[*flagOS][archStr]
		if target == nil {
			failf("unknown arch: %v", archStr)
		}

		arch := &Arch{
			target:    target,
			sourceDir: *flagSourceDir,
			buildDir:  buildDir,
			build:     *flagBuild,
			done:      make(chan bool),
		}
		for _, f := range files {
			arch.files = append(arch.files, &File{
				arch: arch,
				name: f,
				done: make(chan bool),
			})
		}
		arches = append(arches, arch)
		jobC <- arch
	}

	for p := 0; p < runtime.GOMAXPROCS(0); p++ {
		go func() {
			for job := range jobC {
				switch j := job.(type) {
				case *Arch:
					infos, err := processArch(OS, j)
					j.err = err
					close(j.done)
					if j.err == nil {
						for _, f := range j.files {
							f.info = infos[f.name]
							jobC <- f
						}
					}
				case *File:
					j.consts, j.undeclared, j.err = processFile(OS, j.arch, j)
					close(j.done)
				}
			}
		}()
	}

	failed := false
	for _, arch := range arches {
		fmt.Printf("generating %v/%v...\n", arch.target.OS, arch.target.Arch)
		<-arch.done
		if arch.err != nil {
			failed = true
			fmt.Printf("	%v\n", arch.err)
			continue
		}
		for _, f := range arch.files {
			fmt.Printf("extracting from %v\n", f.name)
			<-f.done
			if f.err != nil {
				failed = true
				fmt.Printf("	%v\n", f.err)
				continue
			}
		}
		fmt.Printf("\n")
	}

	if !failed {
		supported := make(map[string]bool)
		unsupported := make(map[string]string)
		for _, arch := range arches {
			for _, f := range arch.files {
				for name := range f.consts {
					supported[name] = true
				}
				for name := range f.undeclared {
					unsupported[name] = f.name
				}
			}
		}
		for name, file := range unsupported {
			if supported[name] {
				continue
			}
			failed = true
			fmt.Printf("%v: %v is unsupported on all arches (typo?)\n",
				file, name)
		}
	}

	for _, arch := range arches {
		if arch.build {
			os.RemoveAll(arch.buildDir)
		}
	}
	if failed {
		os.Exit(1)
	}
}

func processArch(OS OS, arch *Arch) (map[string]*compiler.ConstInfo, error) {
	errBuf := new(bytes.Buffer)
	eh := func(pos ast.Pos, msg string) {
		fmt.Fprintf(errBuf, "%v: %v\n", pos, msg)
	}
	top := ast.ParseGlob(filepath.Join("sys", arch.target.OS, "*.txt"), eh)
	if top == nil {
		return nil, fmt.Errorf("%v", errBuf.String())
	}
	infos := compiler.ExtractConsts(top, arch.target, eh)
	if infos == nil {
		return nil, fmt.Errorf("%v", errBuf.String())
	}
	if err := OS.prepareArch(arch); err != nil {
		return nil, err
	}
	return infos, nil
}

func processFile(OS OS, arch *Arch, file *File) (map[string]uint64, map[string]bool, error) {
	inname := filepath.Join("sys", arch.target.OS, file.name)
	outname := strings.TrimSuffix(inname, ".txt") + "_" + arch.target.Arch + ".const"
	if file.info == nil {
		return nil, nil, fmt.Errorf("input file %v is missing", inname)
	}
	if len(file.info.Consts) == 0 {
		os.Remove(outname)
		return nil, nil, nil
	}
	consts, undeclared, err := OS.processFile(arch, file.info)
	if err != nil {
		return nil, nil, err
	}
	data := compiler.SerializeConsts(consts, undeclared)
	if err := osutil.WriteFile(outname, data); err != nil {
		return nil, nil, fmt.Errorf("failed to write output file: %v", err)
	}
	return consts, undeclared, nil
}
<|endoftext|>


<commit_before>package plugins

import (
	"fmt"
	"strings"
)

type PluginManager interface {
	AddPlugin(key interface{}, val BotMessagePlugin)
	ExecPlugins(botEvent BotEvent)
	StopReply()
	StartReply()
	IsReply() bool
	GetPlugins() []Plugin
}

type plugins struct {
	plugins       []Plugin
	isReply       bool
	messageSender MessageSender
}

var _ PluginManager = (*plugins)(nil)

type MessageSender interface {
	SendMessage(message string, channel string)
}

func NewPluginManager(sender MessageSender) PluginManager {
	return &plugins{
		plugins:       []Plugin{},
		isReply:       true,
		messageSender: sender,
	}
}

func (ps *plugins) AddPlugin(key interface{}, val BotMessagePlugin) {
	ps.plugins = append(ps.plugins, Plugin{key, val})
}

func (ps *plugins) StopReply() {
	ps.isReply = false
}

func (ps *plugins) StartReply() {
	ps.isReply = true
}

func (ps *plugins) IsReply() bool {
	return ps.isReply
}

func (ps *plugins) ExecPlugins(botEvent BotEvent) {
	for _, p := range ps.plugins {
		ok, m := p.CheckMessage(botEvent, botEvent.text)
		if !ok {
			continue
		}

		next := p.DoAction(botEvent, m)
		if !next {
			break
		}
	}
}

func (ps *plugins) SendMessage(message string, channel string) {
	ps.messageSender.SendMessage(message, channel)
}

func (ps *plugins) GetPlugins() []Plugin {
	return ps.plugins
}

type BotMessagePlugin interface {
	CheckMessage(event BotEvent, message string) (bool, string)
	DoAction(event BotEvent, message string) bool
}

type Plugin struct {
	Key interface{}
	BotMessagePlugin
}

func (p Plugin) Name() string {
	return fmt.Sprintf("%s", p.Key)
}

type BotID string

func (b BotID) Equal(bot string) bool {
	if string(b) == bot {
		return true
	}

	if b.LinkID() == bot {
		return true
	}

	return false
}

func (b BotID) LinkID() string {
	return fmt.Sprintf("<@%s>:", b)
}

type BotEvent struct {
	messageSender MessageSender

	botID   BotID
	botName string

	senderID   string
	senderName string
	text       string
	channel    string
}

var _ MessageSender = (*BotEvent)(nil)

func NewBotEvent(sender MessageSender, botID, botName, senderID, senderName, text, channel string) BotEvent {
	return BotEvent{
		messageSender: sender,
		botID:         BotID(botID),
		botName:       botName,
		senderID:      senderID,
		senderName:    senderName,
		text:          text,
		channel:       channel,
	}
}

func (b *BotEvent) Reply(message string) {
	b.SendMessage(message, b.Channel())
}

func (b *BotEvent) SendMessage(message string, channel string) {
	b.messageSender.SendMessage(message, channel)
}

func (b *BotEvent) BaseText() string {
	return b.text
}

func (b *BotEvent) Channel() string {
	return b.channel
}

func (b *BotEvent) BotID() string {
	return string(b.botID)
}

func (b *BotEvent) BotName() string {
	return string(b.botName)
}

func (b *BotEvent) BotLinkID() string {
	return b.botID.LinkID()
}

func (b *BotEvent) SenderID() string {
	return b.senderID
}

func (b *BotEvent) SenderName() string {
	return b.senderName
}

func (b *BotEvent) BotCmdArgs(message string) ([]string, bool) {
	switch {
	case strings.HasPrefix(message, b.BotLinkID()):
		return strings.Fields(message[len(b.BotLinkID()):]), true
	case strings.HasPrefix(message, b.BotName()):
		return strings.Fields(message[len(b.BotName()):]), true
	case strings.HasPrefix(message, b.BotID()):
		return strings.Fields(message[len(b.BotID()):]), true
	default:
		return []string{}, false
	}
}
<commit_msg>botEventを拡張できるように<commit_after>package plugins

import (
	"fmt"
	"strings"
)

type PluginManager interface {
	AddPlugin(key interface{}, val BotMessagePlugin)
	ExecPlugins(botEvent BotEvent)
	StopReply()
	StartReply()
	IsReply() bool
	GetPlugins() []Plugin
}

type plugins struct {
	plugins       []Plugin
	isReply       bool
	messageSender MessageSender
}

var _ PluginManager = (*plugins)(nil)

type MessageSender interface {
	SendMessage(message string, channel string)
}

func NewPluginManager(sender MessageSender) PluginManager {
	return &plugins{
		plugins:       []Plugin{},
		isReply:       true,
		messageSender: sender,
	}
}

func (ps *plugins) AddPlugin(key interface{}, val BotMessagePlugin) {
	ps.plugins = append(ps.plugins, Plugin{key, val})
}

func (ps *plugins) StopReply() {
	ps.isReply = false
}

func (ps *plugins) StartReply() {
	ps.isReply = true
}

func (ps *plugins) IsReply() bool {
	return ps.isReply
}

func (ps *plugins) ExecPlugins(botEvent BotEvent) {
	for _, p := range ps.plugins {
		ok, m := p.CheckMessage(botEvent, botEvent.text)
		if !ok {
			continue
		}

		next := p.DoAction(botEvent, m)
		if !next {
			break
		}
	}
}

func (ps *plugins) SendMessage(message string, channel string) {
	ps.messageSender.SendMessage(message, channel)
}

func (ps *plugins) GetPlugins() []Plugin {
	return ps.plugins
}

type BotMessagePlugin interface {
	CheckMessage(event BotEvent, message string) (bool, string)
	DoAction(event BotEvent, message string) bool
}

type Plugin struct {
	Key interface{}
	BotMessagePlugin
}

func (p Plugin) Name() string {
	return fmt.Sprintf("%s", p.Key)
}

type BotID string

func (b BotID) Equal(bot string) bool {
	if string(b) == bot {
		return true
	}

	if b.LinkID() == bot {
		return true
	}

	return false
}

func (b BotID) LinkID() string {
	return fmt.Sprintf("<@%s>:", b)
}

type BotEvent struct {
	messageSender MessageSender

	botID   BotID
	botName string

	senderID   string
	senderName string
	text       string
	channel    string
}

var _ MessageSender = (*BotEvent)(nil)

func NewBotEvent(sender MessageSender, botID, botName, senderID, senderName, text, channel string) BotEvent {
	return BotEvent{
		messageSender: sender,
		botID:         BotID(botID),
		botName:       botName,
		senderID:      senderID,
		senderName:    senderName,
		text:          text,
		channel:       channel,
	}
}

func (b *BotEvent) Reply(message string) {
	b.SendMessage(message, b.Channel())
}

func (b *BotEvent) SendMessage(message string, channel string) {
	b.messageSender.SendMessage(message, channel)
}

func (b *BotEvent) BaseText() string {
	return b.text
}

func (b *BotEvent) Channel() string {
	return b.channel
}

func (b *BotEvent) BotID() string {
	return string(b.botID)
}

func (b *BotEvent) BotName() string {
	return string(b.botName)
}

func (b *BotEvent) BotLinkID() string {
	return b.botID.LinkID()
}

func (b *BotEvent) SenderID() string {
	return b.senderID
}

func (b *BotEvent) SenderName() string {
	return b.senderName
}

func (b *BotEvent) BotCmdArgs(message string) ([]string, bool) {
	switch {
	case strings.HasPrefix(message, b.BotLinkID()):
		return strings.Fields(message[len(b.BotLinkID()):]), true
	case strings.HasPrefix(message, b.BotName()):
		return strings.Fields(message[len(b.BotName()):]), true
	case strings.HasPrefix(message, b.BotID()):
		return strings.Fields(message[len(b.BotID()):]), true
	default:
		return []string{}, false
	}
}

func (b *BotEvent) GetMessageSender() MessageSender {
	return b.messageSender
}
<|endoftext|>


<commit_before>// +build linux

package cgroups

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/docker/go-units"
)

const cgroupNamePrefix = "name="

// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
func FindCgroupMountpoint(subsystem string) (string, error) {
	// We are not using mount.GetMounts() because it's super-inefficient,
	// parsing it directly sped up x10 times because of not using Sscanf.
	// It was one of two major performance drawbacks in container start.
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		fields := strings.Split(txt, " ")
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if opt == subsystem {
				return fields[4], nil
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return "", err
	}

	return "", NewNotFoundError(subsystem)
}

func FindCgroupMountpointAndRoot(subsystem string) (string, string, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		fields := strings.Split(txt, " ")
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if opt == subsystem {
				return fields[4], fields[3], nil
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return "", "", err
	}

	return "", "", NewNotFoundError(subsystem)
}

func FindCgroupMountpointDir() (string, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()
		fields := strings.Split(text, " ")
		// Safe as mountinfo encodes mountpoints with spaces as \040.
		index := strings.Index(text, " - ")
		postSeparatorFields := strings.Fields(text[index+3:])
		numPostFields := len(postSeparatorFields)

		// This is an error as we can't detect if the mount is for "cgroup"
		if numPostFields == 0 {
			return "", fmt.Errorf("Found no fields post '-' in %q", text)
		}

		if postSeparatorFields[0] == "cgroup" {
			// Check that the mount is properly formated.
			if numPostFields < 3 {
				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
			}

			return filepath.Dir(fields[4]), nil
		}
	}
	if err := scanner.Err(); err != nil {
		return "", err
	}

	return "", NewNotFoundError("cgroup")
}

type Mount struct {
	Mountpoint string
	Root       string
	Subsystems []string
}

func (m Mount) GetThisCgroupDir(cgroups map[string]string) (string, error) {
	if len(m.Subsystems) == 0 {
		return "", fmt.Errorf("no subsystem for mount")
	}

	return getControllerPath(m.Subsystems[0], cgroups)
}

func getCgroupMountsHelper(ss map[string]bool, mi io.Reader) ([]Mount, error) {
	res := make([]Mount, 0, len(ss))
	scanner := bufio.NewScanner(mi)
	for scanner.Scan() {
		txt := scanner.Text()
		sepIdx := strings.Index(txt, " - ")
		if sepIdx == -1 {
			return nil, fmt.Errorf("invalid mountinfo format")
		}
		if txt[sepIdx+3:sepIdx+9] != "cgroup" {
			continue
		}
		fields := strings.Split(txt, " ")
		m := Mount{
			Mountpoint: fields[4],
			Root:       fields[3],
		}
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if strings.HasPrefix(opt, cgroupNamePrefix) {
				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
			}
			if ss[opt] {
				m.Subsystems = append(m.Subsystems, opt)
			}
		}
		res = append(res, m)
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return res, nil
}

func GetCgroupMounts() ([]Mount, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	all, err := GetAllSubsystems()
	if err != nil {
		return nil, err
	}

	allMap := make(map[string]bool)
	for _, s := range all {
		allMap[s] = true
	}
	return getCgroupMountsHelper(allMap, f)
}

// GetAllSubsystems returns all the cgroup subsystems supported by the kernel
func GetAllSubsystems() ([]string, error) {
	f, err := os.Open("/proc/cgroups")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	subsystems := []string{}

	s := bufio.NewScanner(f)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}
		text := s.Text()
		if text[0] != '#' {
			parts := strings.Fields(text)
			if len(parts) >= 4 && parts[3] != "0" {
				subsystems = append(subsystems, parts[0])
			}
		}
	}
	return subsystems, nil
}

// GetThisCgroupDir returns the relative path to the cgroup docker is running in.
func GetThisCgroupDir(subsystem string) (string, error) {
	cgroups, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return "", err
	}

	return getControllerPath(subsystem, cgroups)
}

func GetInitCgroupDir(subsystem string) (string, error) {

	cgroups, err := ParseCgroupFile("/proc/1/cgroup")
	if err != nil {
		return "", err
	}

	return getControllerPath(subsystem, cgroups)
}

func readProcsFile(dir string) ([]int, error) {
	f, err := os.Open(filepath.Join(dir, "cgroup.procs"))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var (
		s   = bufio.NewScanner(f)
		out = []int{}
	)

	for s.Scan() {
		if t := s.Text(); t != "" {
			pid, err := strconv.Atoi(t)
			if err != nil {
				return nil, err
			}
			out = append(out, pid)
		}
	}
	return out, nil
}

func ParseCgroupFile(path string) (map[string]string, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	cgroups := make(map[string]string)

	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}

		text := s.Text()
		parts := strings.Split(text, ":")

		for _, subs := range strings.Split(parts[1], ",") {
			cgroups[subs] = parts[2]
		}
	}
	return cgroups, nil
}

func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {

	if p, ok := cgroups[subsystem]; ok {
		return p, nil
	}

	if p, ok := cgroups[cgroupNamePrefix+subsystem]; ok {
		return p, nil
	}

	return "", NewNotFoundError(subsystem)
}

func PathExists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		return false
	}
	return true
}

func EnterPid(cgroupPaths map[string]string, pid int) error {
	for _, path := range cgroupPaths {
		if PathExists(path) {
			if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"),
				[]byte(strconv.Itoa(pid)), 0700); err != nil {
				return err
			}
		}
	}
	return nil
}

// RemovePaths iterates over the provided paths removing them.
// We trying to remove all paths five times with increasing delay between tries.
// If after all there are not removed cgroups - appropriate error will be
// returned.
func RemovePaths(paths map[string]string) (err error) {
	delay := 10 * time.Millisecond
	for i := 0; i < 5; i++ {
		if i != 0 {
			time.Sleep(delay)
			delay *= 2
		}
		for s, p := range paths {
			os.RemoveAll(p)
			// TODO: here probably should be logging
			_, err := os.Stat(p)
			// We need this strange way of checking cgroups existence because
			// RemoveAll almost always returns error, even on already removed
			// cgroups
			if os.IsNotExist(err) {
				delete(paths, s)
			}
		}
		if len(paths) == 0 {
			return nil
		}
	}
	return fmt.Errorf("Failed to remove paths: %v", paths)
}

func GetHugePageSize() ([]string, error) {
	var pageSizes []string
	sizeList := []string{"B", "kB", "MB", "GB", "TB", "PB"}
	files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
	if err != nil {
		return pageSizes, err
	}
	for _, st := range files {
		nameArray := strings.Split(st.Name(), "-")
		pageSize, err := units.RAMInBytes(nameArray[1])
		if err != nil {
			return []string{}, err
		}
		sizeString := units.CustomSize("%g%s", float64(pageSize), 1024.0, sizeList)
		pageSizes = append(pageSizes, sizeString)
	}

	return pageSizes, nil
}

// GetPids returns all pids, that were added to cgroup at path.
func GetPids(path string) ([]int, error) {
	return readProcsFile(path)
}

// GetAllPids returns all pids, that were added to cgroup at path and to all its
// subcgroups.
func GetAllPids(path string) ([]int, error) {
	var pids []int
	// collect pids from all sub-cgroups
	err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
		dir, file := filepath.Split(p)
		if file != "cgroup.procs" {
			return nil
		}
		if iErr != nil {
			return iErr
		}
		cPids, err := readProcsFile(dir)
		if err != nil {
			return err
		}
		pids = append(pids, cPids...)
		return nil
	})
	return pids, err
}
<commit_msg>Cgroup: reduce redundant parsing of mountinfo<commit_after>// +build linux

package cgroups

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/docker/go-units"
)

const cgroupNamePrefix = "name="

// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
func FindCgroupMountpoint(subsystem string) (string, error) {
	// We are not using mount.GetMounts() because it's super-inefficient,
	// parsing it directly sped up x10 times because of not using Sscanf.
	// It was one of two major performance drawbacks in container start.
	if !isSubsystemAvailable(subsystem) {
		return "", NewNotFoundError(subsystem)
	}
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		fields := strings.Split(txt, " ")
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if opt == subsystem {
				return fields[4], nil
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return "", err
	}

	return "", NewNotFoundError(subsystem)
}

func FindCgroupMountpointAndRoot(subsystem string) (string, string, error) {
	if !isSubsystemAvailable(subsystem) {
		return "", "", NewNotFoundError(subsystem)
	}
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		fields := strings.Split(txt, " ")
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if opt == subsystem {
				return fields[4], fields[3], nil
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return "", "", err
	}

	return "", "", NewNotFoundError(subsystem)
}

func isSubsystemAvailable(subsystem string) bool {
	cgroups, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return false
	}
	_, avail := cgroups[subsystem]
	return avail
}

func FindCgroupMountpointDir() (string, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()
		fields := strings.Split(text, " ")
		// Safe as mountinfo encodes mountpoints with spaces as \040.
		index := strings.Index(text, " - ")
		postSeparatorFields := strings.Fields(text[index+3:])
		numPostFields := len(postSeparatorFields)

		// This is an error as we can't detect if the mount is for "cgroup"
		if numPostFields == 0 {
			return "", fmt.Errorf("Found no fields post '-' in %q", text)
		}

		if postSeparatorFields[0] == "cgroup" {
			// Check that the mount is properly formated.
			if numPostFields < 3 {
				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
			}

			return filepath.Dir(fields[4]), nil
		}
	}
	if err := scanner.Err(); err != nil {
		return "", err
	}

	return "", NewNotFoundError("cgroup")
}

type Mount struct {
	Mountpoint string
	Root       string
	Subsystems []string
}

func (m Mount) GetThisCgroupDir(cgroups map[string]string) (string, error) {
	if len(m.Subsystems) == 0 {
		return "", fmt.Errorf("no subsystem for mount")
	}

	return getControllerPath(m.Subsystems[0], cgroups)
}

func getCgroupMountsHelper(ss map[string]bool, mi io.Reader) ([]Mount, error) {
	res := make([]Mount, 0, len(ss))
	scanner := bufio.NewScanner(mi)
	numFound := 0
	for scanner.Scan() && numFound < len(ss) {
		txt := scanner.Text()
		sepIdx := strings.Index(txt, " - ")
		if sepIdx == -1 {
			return nil, fmt.Errorf("invalid mountinfo format")
		}
		if txt[sepIdx+3:sepIdx+9] != "cgroup" {
			continue
		}
		fields := strings.Split(txt, " ")
		m := Mount{
			Mountpoint: fields[4],
			Root:       fields[3],
		}
		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
			if !ss[opt] {
				continue
			}
			if strings.HasPrefix(opt, cgroupNamePrefix) {
				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
			} else {
				m.Subsystems = append(m.Subsystems, opt)
			}
			numFound++
		}
		res = append(res, m)
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return res, nil
}

func GetCgroupMounts() ([]Mount, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	all, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return nil, err
	}

	allMap := make(map[string]bool)
	for s := range all {
		allMap[s] = true
	}
	return getCgroupMountsHelper(allMap, f)
}

// GetAllSubsystems returns all the cgroup subsystems supported by the kernel
func GetAllSubsystems() ([]string, error) {
	f, err := os.Open("/proc/cgroups")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	subsystems := []string{}

	s := bufio.NewScanner(f)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}
		text := s.Text()
		if text[0] != '#' {
			parts := strings.Fields(text)
			if len(parts) >= 4 && parts[3] != "0" {
				subsystems = append(subsystems, parts[0])
			}
		}
	}
	return subsystems, nil
}

// GetThisCgroupDir returns the relative path to the cgroup docker is running in.
func GetThisCgroupDir(subsystem string) (string, error) {
	cgroups, err := ParseCgroupFile("/proc/self/cgroup")
	if err != nil {
		return "", err
	}

	return getControllerPath(subsystem, cgroups)
}

func GetInitCgroupDir(subsystem string) (string, error) {

	cgroups, err := ParseCgroupFile("/proc/1/cgroup")
	if err != nil {
		return "", err
	}

	return getControllerPath(subsystem, cgroups)
}

func readProcsFile(dir string) ([]int, error) {
	f, err := os.Open(filepath.Join(dir, "cgroup.procs"))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var (
		s   = bufio.NewScanner(f)
		out = []int{}
	)

	for s.Scan() {
		if t := s.Text(); t != "" {
			pid, err := strconv.Atoi(t)
			if err != nil {
				return nil, err
			}
			out = append(out, pid)
		}
	}
	return out, nil
}

func ParseCgroupFile(path string) (map[string]string, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	cgroups := make(map[string]string)

	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}

		text := s.Text()
		parts := strings.Split(text, ":")

		for _, subs := range strings.Split(parts[1], ",") {
			cgroups[subs] = parts[2]
		}
	}
	return cgroups, nil
}

func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {

	if p, ok := cgroups[subsystem]; ok {
		return p, nil
	}

	if p, ok := cgroups[cgroupNamePrefix+subsystem]; ok {
		return p, nil
	}

	return "", NewNotFoundError(subsystem)
}

func PathExists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		return false
	}
	return true
}

func EnterPid(cgroupPaths map[string]string, pid int) error {
	for _, path := range cgroupPaths {
		if PathExists(path) {
			if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"),
				[]byte(strconv.Itoa(pid)), 0700); err != nil {
				return err
			}
		}
	}
	return nil
}

// RemovePaths iterates over the provided paths removing them.
// We trying to remove all paths five times with increasing delay between tries.
// If after all there are not removed cgroups - appropriate error will be
// returned.
func RemovePaths(paths map[string]string) (err error) {
	delay := 10 * time.Millisecond
	for i := 0; i < 5; i++ {
		if i != 0 {
			time.Sleep(delay)
			delay *= 2
		}
		for s, p := range paths {
			os.RemoveAll(p)
			// TODO: here probably should be logging
			_, err := os.Stat(p)
			// We need this strange way of checking cgroups existence because
			// RemoveAll almost always returns error, even on already removed
			// cgroups
			if os.IsNotExist(err) {
				delete(paths, s)
			}
		}
		if len(paths) == 0 {
			return nil
		}
	}
	return fmt.Errorf("Failed to remove paths: %v", paths)
}

func GetHugePageSize() ([]string, error) {
	var pageSizes []string
	sizeList := []string{"B", "kB", "MB", "GB", "TB", "PB"}
	files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
	if err != nil {
		return pageSizes, err
	}
	for _, st := range files {
		nameArray := strings.Split(st.Name(), "-")
		pageSize, err := units.RAMInBytes(nameArray[1])
		if err != nil {
			return []string{}, err
		}
		sizeString := units.CustomSize("%g%s", float64(pageSize), 1024.0, sizeList)
		pageSizes = append(pageSizes, sizeString)
	}

	return pageSizes, nil
}

// GetPids returns all pids, that were added to cgroup at path.
func GetPids(path string) ([]int, error) {
	return readProcsFile(path)
}

// GetAllPids returns all pids, that were added to cgroup at path and to all its
// subcgroups.
func GetAllPids(path string) ([]int, error) {
	var pids []int
	// collect pids from all sub-cgroups
	err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
		dir, file := filepath.Split(p)
		if file != "cgroup.procs" {
			return nil
		}
		if iErr != nil {
			return iErr
		}
		cPids, err := readProcsFile(dir)
		if err != nil {
			return err
		}
		pids = append(pids, cPids...)
		return nil
	})
	return pids, err
}
<|endoftext|>


<commit_before>package target

import (
	"io"
	"io/ioutil"
	"net/http"
	"testing"
	"time"

	"github.com/valyala/fasthttp"
)

func RunHTTPTarget(cfg Config) (*HttpTarget, error) {
	sLn, err := StatsListen(cfg.BindAddress)
	if err != nil {
		return nil, err
	}
	target := &httpTarget{
		ln: sLn,
	}
	server := fasthttp.Server{
		Handler:            target.HandleFastHTTP,
		MaxRequestBodySize: 999999999,
	}
	if cfg.PrintLog {
		go target.PrintStats(5 * time.Second)
	}
	go server.Serve(target.ln)
	return target, nil
}

func TestConnection(t *testing.T) {
	cfg := Config{
		BindAddress: "0.0.0.0:8888",
		PrintLog:    true,
	}

	target, err := RunHTTPTarget(cfg)
	if err != nil {
		t.Errorf("failed to start target: %s", err)
	}
	time.Sleep(1 * time.Second)

	// use not keep alive request as by default http client will keep conntection
	transport := http.Transport{
		DisableKeepAlives: true,
	}

	client := http.Client{
		Transport: &transport,
	}
	req, err := http.NewRequest("GET", "http://127.0.0.1:8888", nil)
	if err != nil {
		t.Errorf("%s", err)
	}

	res, err := client.Do(req)
	if err != nil {
		t.Errorf("failed to connect, %s", err)
	}
	// check ConnNum
	if target.ConnNumber() != 1 {
		t.Errorf("ConnNumber incorrect, not 1, actual: %v", target.ConnNumber())
	}
	// close connection
	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()
	time.Sleep(1 * time.Second)

	// check ConnNum again
	if target.ConnNumber() != 0 {
		t.Errorf("ConnNumber incorrect, not 0, actual: %v", target.ConnNumber())
	}
}
<commit_msg>fix unit test<commit_after>package target

import (
	"io"
	"io/ioutil"
	"net/http"
	"testing"
	"time"

	"github.com/valyala/fasthttp"
)

func RunHTTPTarget(cfg Config) (*httpTarget, error) {
	sLn, err := StatsListen(cfg.BindAddress)
	if err != nil {
		return nil, err
	}
	target := &httpTarget{
		ln: sLn,
	}
	server := fasthttp.Server{
		Handler:            target.HandleFastHTTP,
		MaxRequestBodySize: 999999999,
	}
	if cfg.PrintLog {
		go target.PrintStats(true)
	}
	go server.Serve(target.ln)
	return target, nil
}

func TestConnection(t *testing.T) {
	cfg := Config{
		BindAddress: "0.0.0.0:8888",
		PrintLog:    true,
	}

	target, err := RunHTTPTarget(cfg)
	if err != nil {
		t.Errorf("failed to start target: %s", err)
	}
	time.Sleep(1 * time.Second)

	// use not keep alive request as by default http client will keep conntection
	transport := http.Transport{
		DisableKeepAlives: true,
	}

	client := http.Client{
		Transport: &transport,
	}
	req, err := http.NewRequest("GET", "http://127.0.0.1:8888", nil)
	if err != nil {
		t.Errorf("%s", err)
	}

	res, err := client.Do(req)
	if err != nil {
		t.Errorf("failed to connect, %s", err)
	}
	// check ConnNum
	if target.ConnNumber() != 1 {
		t.Errorf("ConnNumber incorrect, not 1, actual: %v", target.ConnNumber())
	}
	// close connection
	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()
	time.Sleep(1 * time.Second)

	// check ConnNum again
	if target.ConnNumber() != 0 {
		t.Errorf("ConnNumber incorrect, not 0, actual: %v", target.ConnNumber())
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net/http"
	"time"

	"github.com/cloudfoundry-samples/test-app/helpers"
)

type Hello struct {
	Time time.Time
}

func (p *Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	index, _ := helpers.FetchIndex()

	styledTemplate.Execute(w, Body{Body: fmt.Sprintf(`

	Atos Demo App 2017

atosDemo.hopto.org

My Index Is

%d

Uptime: %s

    `, index, time.Since(p.Time))})
}
<commit_msg>Update hello.go<commit_after>package handlers

import (
	"fmt"
	"net/http"
	"time"

	"github.com/cloudfoundry-samples/test-app/helpers"
)

type Hello struct {
	Time time.Time
}

func (p *Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	index, _ := helpers.FetchIndex()

	styledTemplate.Execute(w, Body{Body: fmt.Sprintf(`

	Atos Demo App 2018

atosDemo.hopto.org

My Index Is

%d

Uptime: %s

    `, index, time.Since(p.Time))})
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net/http"
	"time"

	"github.com/aripka-pivotal/lattice-app/helpers"
)

type Hello struct {
	Time time.Time
}

func (p *Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	index, _ := helpers.FetchIndex()
	appName := "APP 1"
	colors := helpers.FetchColors()

	styledColoredTemplate.Execute(w, ColoredBody{Body: fmt.Sprintf(`

	ALattice - %s

My Index Is

%d

Uptime: %s

    `, appName, index, time.Since(p.Time)), Colors:colors})
}
<commit_msg>add logic to fetch app name<commit_after>package handlers

import (
	"fmt"
	"net/http"
	"time"

	"github.com/aripka-pivotal/lattice-app/helpers"
)

type Hello struct {
	Time time.Time
}

func (p *Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	index, _ := helpers.FetchIndex()
	appName := helpers.FetchAppName();
	if appName == "Lattice-app" {
	 	appName = ""
	}else{
		appName = " - " + appName
	}

	colors := helpers.FetchColors()

	styledColoredTemplate.Execute(w, ColoredBody{Body: fmt.Sprintf(`

	Lattice%s

My Index Is

%d

Uptime: %s

    `, appName, index, time.Since(p.Time)), Colors:colors})
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"net/http"
)

func (sh *ServerHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	sh.logger.Info("Someone is saying hello!")
	fmt.Fprintf(response, "%s", []byte("Heyo whaddup!\n"))

	myBuf := new(bytes.Buffer)
	myBuf.ReadFrom(request.Body)
	myPayload := myBuf.Bytes()

	sh.workerPool.Send(func(workerID int) { sh.HandleRequest(workerID, myPayload) })
	request.Body.Close()
}

func (sh *ServerHandler) HandleRequest(workerID int, inPayload []byte) {
	sh.logger.Info("Worker ID #%d is handling a request...", workerID)

	sh.logger.Info("Worker ID #%d is printing the payload: %s", workerID, string(inPayload))
}
<commit_msg>This way looks way cleaner though so I will do this instead.<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func (sh *ServerHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	sh.logger.Info("Someone is saying hello!")
	fmt.Fprintf(response, "%s", []byte("Heyo whaddup!\n"))

	myPayload, err := ioutil.ReadAll(request.Body)
	if err != nil {
		fmt.Fprintf(response, "%s", []byte("Unable to retrieve request body!\n"))
	} else {
		sh.workerPool.Send(func(workerID int) { sh.HandleRequest(workerID, myPayload) })
	}

	request.Body.Close()
}

func (sh *ServerHandler) HandleRequest(workerID int, inPayload []byte) {
	sh.logger.Info("Worker ID #%d is handling a request...", workerID)

	sh.logger.Info("Worker ID #%d is printing the payload: %s", workerID, string(inPayload))
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes 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 discovery

import (
	"fmt"
	"net/url"

	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/https"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/token"
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
)

const TokenUser = "tls-bootstrap-token-user"

// For returns a KubeConfig object that can be used for doing the TLS Bootstrap with the right credentials
// Also, before returning anything, it makes sure it can trust the API Server
func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
	// TODO: Print summary info about the CA certificate, along with the the checksum signature
	// we also need an ability for the user to configure the client to validate received CA cert against a checksum
	clusterinfo, err := GetValidatedClusterInfoObject(cfg)
	if err != nil {
		return nil, fmt.Errorf("couldn't validate the identity of the API Server: %v", err)
	}

	return kubeconfigutil.CreateWithToken(
		clusterinfo.Server,
		"kubernetes",
		TokenUser,
		clusterinfo.CertificateAuthorityData,
		cfg.TLSBootstrapToken,
	), nil
}

// GetValidatedClusterInfoObject returns a validated Cluster object that specifies where the cluster is and the CA cert to trust
func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) {
	switch {
	case len(cfg.DiscoveryFile) != 0:
		if isHTTPSURL(cfg.DiscoveryFile) {
			return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
		}
		return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
	case len(cfg.DiscoveryToken) != 0:
		return token.RetrieveValidatedClusterInfo(cfg.DiscoveryToken, cfg.DiscoveryTokenAPIServers)
	default:
		return nil, fmt.Errorf("couldn't find a valid discovery configuration.")
	}
}

// isHTTPSURL checks whether the string is parsable as an URL
func isHTTPSURL(s string) bool {
	u, err := url.Parse(s)
	return err == nil && u.Scheme == "https"
}
<commit_msg>Fix comment of isHTTPSURL<commit_after>/*
Copyright 2016 The Kubernetes 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 discovery

import (
	"fmt"
	"net/url"

	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/https"
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery/token"
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
)

const TokenUser = "tls-bootstrap-token-user"

// For returns a KubeConfig object that can be used for doing the TLS Bootstrap with the right credentials
// Also, before returning anything, it makes sure it can trust the API Server
func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
	// TODO: Print summary info about the CA certificate, along with the the checksum signature
	// we also need an ability for the user to configure the client to validate received CA cert against a checksum
	clusterinfo, err := GetValidatedClusterInfoObject(cfg)
	if err != nil {
		return nil, fmt.Errorf("couldn't validate the identity of the API Server: %v", err)
	}

	return kubeconfigutil.CreateWithToken(
		clusterinfo.Server,
		"kubernetes",
		TokenUser,
		clusterinfo.CertificateAuthorityData,
		cfg.TLSBootstrapToken,
	), nil
}

// GetValidatedClusterInfoObject returns a validated Cluster object that specifies where the cluster is and the CA cert to trust
func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) {
	switch {
	case len(cfg.DiscoveryFile) != 0:
		if isHTTPSURL(cfg.DiscoveryFile) {
			return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
		}
		return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
	case len(cfg.DiscoveryToken) != 0:
		return token.RetrieveValidatedClusterInfo(cfg.DiscoveryToken, cfg.DiscoveryTokenAPIServers)
	default:
		return nil, fmt.Errorf("couldn't find a valid discovery configuration.")
	}
}

// isHTTPSURL checks whether the string is parsable as an URL and whether the Scheme is https
func isHTTPSURL(s string) bool {
	u, err := url.Parse(s)
	return err == nil && u.Scheme == "https"
}
<|endoftext|>


<commit_before><commit_msg>fix basic test<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"testing"
)

/*func TestRndpwdError(t *testing.T) {
	os.Args = []string{"rndpwd", "--quantity=0"}
	//defer func() {
	//	if err := recover(); err == nil {
	//		t.Error(fmt.Errorf("An error was expected"))
	//	}
	//}()
	main()
}*/

func TestRndpwdVersion(t *testing.T) {
	os.Args = []string{"rndpwd", "version"}
	out := getMainOutput()
	match, _ := regexp.MatchString("^[\\d]+\\.[\\d]+\\.[\\d]+[\\s]*$", out)
	if !match {
		t.Error(fmt.Errorf("The expected version hs not been returned"))
	}
}

func TestRndpwd(t *testing.T) {
	os.Args = []string{"rndpwd"}
	out := getMainOutput()
	if len(out) != 330 {
		t.Error(fmt.Errorf("Expected 330 characters output (10 x 33 chars) %v", out))
	}
}

func TestRndpwdOne(t *testing.T) {
	os.Args = []string{"rndpwd", "--length=64", "--quantity=1"}
	out := getMainOutput()
	if len(out) != 65 {
		t.Error(fmt.Errorf("Expected 1 64 character password + newline"))
	}
}

func TestRndpwdFixed(t *testing.T) {
	os.Args = []string{"rndpwd", "--charset=abc", "--length=4", "--quantity=1"}
	out := getMainOutput()
	match, _ := regexp.MatchString("^[abc]{4}[\\s]*$", out)
	if !match {
		t.Error(fmt.Errorf("Expected 'aaaa' password %s", out))
	}
}

func getMainOutput() string {
	old := os.Stdout // keep backup of the real stdout
	defer func() { os.Stdout = old }()
	r, w, _ := os.Pipe()
	os.Stdout = w

	// execute the main function
	main()

	outC := make(chan string)
	// copy the output in a separate goroutine so printing can't block indefinitely
	go func() {
		var buf bytes.Buffer
		io.Copy(&buf, r)
		outC <- buf.String()
	}()

	// back to normal state
	w.Close()
	out := <-outC

	return out
}
<commit_msg>process errors<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"testing"
)

/*func TestRndpwdError(t *testing.T) {
	os.Args = []string{"rndpwd", "--quantity=0"}
	//defer func() {
	//	if err := recover(); err == nil {
	//		t.Error(fmt.Errorf("An error was expected"))
	//	}
	//}()
	main()
}*/

func TestRndpwdVersion(t *testing.T) {
	os.Args = []string{"rndpwd", "version"}
	out := getMainOutput()
	match, err := regexp.MatchString("^[\\d]+\\.[\\d]+\\.[\\d]+[\\s]*$", out)
	if err != nil {
		t.Error(fmt.Errorf("An error wasn't expected: ", err))
	}
	if !match {
		t.Error(fmt.Errorf("The expected version hs not been returned"))
	}
}

func TestRndpwd(t *testing.T) {
	os.Args = []string{"rndpwd"}
	out := getMainOutput()
	if len(out) != 330 {
		t.Error(fmt.Errorf("Expected 330 characters output (10 x 33 chars) %v", out))
	}
}

func TestRndpwdOne(t *testing.T) {
	os.Args = []string{"rndpwd", "--length=64", "--quantity=1"}
	out := getMainOutput()
	if len(out) != 65 {
		t.Error(fmt.Errorf("Expected 1 64 character password + newline"))
	}
}

func TestRndpwdFixed(t *testing.T) {
	os.Args = []string{"rndpwd", "--charset=abc", "--length=4", "--quantity=1"}
	out := getMainOutput()
	match, err := regexp.MatchString("^[abc]{4}[\\s]*$", out)
	if err != nil {
		t.Error(fmt.Errorf("An error wasn't expected: ", err))
	}
	if !match {
		t.Error(fmt.Errorf("Expected 'aaaa' password %s", out))
	}
}

func getMainOutput() string {
	old := os.Stdout // keep backup of the real stdout
	defer func() { os.Stdout = old }()
	r, w, err := os.Pipe()
	if err != nil {
		t.Error(fmt.Errorf("An error wasn't expected: ", err))
	}
	os.Stdout = w

	// execute the main function
	main()

	outC := make(chan string)
	// copy the output in a separate goroutine so printing can't block indefinitely
	go func() {
		var buf bytes.Buffer
		io.Copy(&buf, r)
		outC <- buf.String()
	}()

	// back to normal state
	w.Close()
	out := <-outC

	return out
}
<|endoftext|>


<commit_before>package kafka_test

import (
	"math/rand"
	"testing"

	kafka "github.com/segmentio/kafka-go"
	"github.com/segmentio/kafka-go/gzip"
	"github.com/segmentio/kafka-go/lz4"
	"github.com/segmentio/kafka-go/snappy"
)

func TestCompression(t *testing.T) {
	msg := kafka.Message{
		Value: []byte("message"),
	}

	testEncodeDecode(t, msg, kafka.CompressionNoneCode)
	testEncodeDecode(t, msg, gzip.Code)
	testEncodeDecode(t, msg, snappy.Code)
	testEncodeDecode(t, msg, lz4.Code)
	testUnknownCodec(t, msg, 42)
}

func testEncodeDecode(t *testing.T, m kafka.Message, codec int8) {
	var r1, r2 kafka.Message
	var err error

	t.Run("encode with "+codecToStr(codec), func(t *testing.T) {
		m.CompressionCodec = codec
		r1, err = m.Encode()
		if err != nil {
			t.Error(err)
		}
	})
	t.Run("encode with "+codecToStr(codec), func(t *testing.T) {
		r2, err = r1.Decode()
		if err != nil {
			t.Error(err)
		}
		if string(r2.Value) != "message" {
			t.Error("bad message")
			t.Log("got: ", r2.Value)
			t.Log("expected: ", []byte("message"))
		}
	})
}

func testUnknownCodec(t *testing.T, m kafka.Message, codec int8) {
	t.Run("unknown codec", func(t *testing.T) {
		expectedErr := "codec 42 not imported."
		m.CompressionCodec = codec
		_, err := m.Encode()
		if err.Error() != expectedErr {
			t.Error("wrong error")
			t.Log("got: ", err)
			t.Error("expected: ", expectedErr)
		}
	})
}

func codecToStr(codec int8) string {
	switch codec {
	case kafka.CompressionNoneCode:
		return "none"
	case gzip.Code:
		return "gzip"
	case snappy.Code:
		return "snappy"
	case lz4.Code:
		return "lz4"
	default:
		return "unknown"
	}
}

func BenchmarkCompression(b *testing.B) {
	benchmarks := []struct {
		scenario string
		codec    int8
		function func(*testing.B, int8, int, map[int][]byte)
	}{
		{
			scenario: "None",
			codec:    kafka.CompressionNoneCode,
			function: benchmarkCompression,
		},
		{
			scenario: "GZIP",
			codec:    gzip.Code,
			function: benchmarkCompression,
		},
		{
			scenario: "Snappy",
			codec:    snappy.Code,
			function: benchmarkCompression,
		},
		{
			scenario: "LZ4",
			codec:    lz4.Code,
			function: benchmarkCompression,
		},
	}

	payload := map[int][]byte{
		1024:  randomPayload(1024),
		4096:  randomPayload(4096),
		8192:  randomPayload(8192),
		16384: randomPayload(16384),
	}

	for _, benchmark := range benchmarks {
		b.Run(benchmark.scenario+"1024", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 1024, payload)
		})
		b.Run(benchmark.scenario+"4096", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 4096, payload)
		})
		b.Run(benchmark.scenario+"8192", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 8192, payload)
		})
		b.Run(benchmark.scenario+"16384", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 16384, payload)
		})
	}

}

func benchmarkCompression(b *testing.B, codec int8, payloadSize int, payload map[int][]byte) {
	msg := kafka.Message{
		Value:            payload[payloadSize],
		CompressionCodec: codec,
	}

	for i := 0; i < b.N; i++ {
		m1, err := msg.Encode()
		if err != nil {
			b.Fatal(err)
		}

		_, err = m1.Decode()
		if err != nil {
			b.Fatal(err)
		}

	}
}

const dataset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

func randomPayload(n int) []byte {
	b := make([]byte, n)
	for i := range b {
		b[i] = dataset[rand.Intn(len(dataset))]
	}
	return b
}
<commit_msg>Add b.SetBytes<commit_after>package kafka_test

import (
	"math/rand"
	"testing"

	kafka "github.com/segmentio/kafka-go"
	"github.com/segmentio/kafka-go/gzip"
	"github.com/segmentio/kafka-go/lz4"
	"github.com/segmentio/kafka-go/snappy"
)

func TestCompression(t *testing.T) {
	msg := kafka.Message{
		Value: []byte("message"),
	}

	testEncodeDecode(t, msg, kafka.CompressionNoneCode)
	testEncodeDecode(t, msg, gzip.Code)
	testEncodeDecode(t, msg, snappy.Code)
	testEncodeDecode(t, msg, lz4.Code)
	testUnknownCodec(t, msg, 42)
}

func testEncodeDecode(t *testing.T, m kafka.Message, codec int8) {
	var r1, r2 kafka.Message
	var err error

	t.Run("encode with "+codecToStr(codec), func(t *testing.T) {
		m.CompressionCodec = codec
		r1, err = m.Encode()
		if err != nil {
			t.Error(err)
		}
	})
	t.Run("encode with "+codecToStr(codec), func(t *testing.T) {
		r2, err = r1.Decode()
		if err != nil {
			t.Error(err)
		}
		if string(r2.Value) != "message" {
			t.Error("bad message")
			t.Log("got: ", r2.Value)
			t.Log("expected: ", []byte("message"))
		}
	})
}

func testUnknownCodec(t *testing.T, m kafka.Message, codec int8) {
	t.Run("unknown codec", func(t *testing.T) {
		expectedErr := "codec 42 not imported."
		m.CompressionCodec = codec
		_, err := m.Encode()
		if err.Error() != expectedErr {
			t.Error("wrong error")
			t.Log("got: ", err)
			t.Error("expected: ", expectedErr)
		}
	})
}

func codecToStr(codec int8) string {
	switch codec {
	case kafka.CompressionNoneCode:
		return "none"
	case gzip.Code:
		return "gzip"
	case snappy.Code:
		return "snappy"
	case lz4.Code:
		return "lz4"
	default:
		return "unknown"
	}
}

func BenchmarkCompression(b *testing.B) {
	benchmarks := []struct {
		scenario string
		codec    int8
		function func(*testing.B, int8, int, map[int][]byte)
	}{
		{
			scenario: "None",
			codec:    kafka.CompressionNoneCode,
			function: benchmarkCompression,
		},
		{
			scenario: "GZIP",
			codec:    gzip.Code,
			function: benchmarkCompression,
		},
		{
			scenario: "Snappy",
			codec:    snappy.Code,
			function: benchmarkCompression,
		},
		{
			scenario: "LZ4",
			codec:    lz4.Code,
			function: benchmarkCompression,
		},
	}

	payload := map[int][]byte{
		1024:  randomPayload(1024),
		4096:  randomPayload(4096),
		8192:  randomPayload(8192),
		16384: randomPayload(16384),
	}

	for _, benchmark := range benchmarks {
		b.Run(benchmark.scenario+"1024", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 1024, payload)
		})
		b.Run(benchmark.scenario+"4096", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 4096, payload)
		})
		b.Run(benchmark.scenario+"8192", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 8192, payload)
		})
		b.Run(benchmark.scenario+"16384", func(b *testing.B) {
			benchmark.function(b, benchmark.codec, 16384, payload)
		})
	}

}

func benchmarkCompression(b *testing.B, codec int8, payloadSize int, payload map[int][]byte) {
	msg := kafka.Message{
		Value:            payload[payloadSize],
		CompressionCodec: codec,
	}

	for i := 0; i < b.N; i++ {
		m1, err := msg.Encode()
		if err != nil {
			b.Fatal(err)
		}

		b.SetBytes(int64(len(m1.Value)))

		_, err = m1.Decode()
		if err != nil {
			b.Fatal(err)
		}

	}
}

const dataset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

func randomPayload(n int) []byte {
	b := make([]byte, n)
	for i := range b {
		b[i] = dataset[rand.Intn(len(dataset))]
	}
	return b
}
<|endoftext|>


<commit_before>package vmware

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"path/filepath"
	"strings"
)

// Workstation9LinuxDriver is a driver that can run VMware Workstation 9
// on Linux.
type Workstation9LinuxDriver struct {
	AppPath          string
	VdiskManagerPath string
	VmrunPath        string
}

func (d *Workstation9LinuxDriver) CompactDisk(diskPath string) error {
	defragCmd := exec.Command(d.VdiskManagerPath, "-d", diskPath)
	if _, _, err := d.runAndLog(defragCmd); err != nil {
		return err
	}

	shrinkCmd := exec.Command(d.VdiskManagerPath, "-k", diskPath)
	if _, _, err := d.runAndLog(shrinkCmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) CreateDisk(output string, size string) error {
	cmd := exec.Command(d.VdiskManagerPath, "-c", "-s", size, "-a", "lsilogic", "-t", "1", output)
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) IsRunning(vmxPath string) (bool, error) {
	vmxPath, err := filepath.Abs(vmxPath)
	if err != nil {
		return false, err
	}

	cmd := exec.Command(d.VmrunPath, "-T", "ws", "list")
	stdout, _, err := d.runAndLog(cmd)
	if err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout, "\n") {
		if line == vmxPath {
			return true, nil
		}
	}

	return false, nil
}

func (d *Workstation9LinuxDriver) Start(vmxPath string, headless bool) error {
	guiArgument := "gui"
	if headless {
		guiArgument = "nogui"
	}

	cmd := exec.Command(d.VmrunPath, "-T", "ws", "start", vmxPath, guiArgument)
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) Stop(vmxPath string) error {
	cmd := exec.Command(d.VmrunPath, "-T", "ws", "stop", vmxPath, "hard")
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) Verify() error {
	if err := d.findApp(); err != nil {
		return fmt.Errorf("VMware Workstation application ('vmware') not found in path.")
	}

	if err := d.findVmrun(); err != nil {
		return fmt.Errorf("Required application 'vmrun' not found in path.")
	}

	if err := d.findVdiskManager(); err != nil {
		return fmt.Errorf("Required application 'vmware-vdiskmanager' not found in path.")
	}

	return nil
}

func (d *Workstation9LinuxDriver) findApp() error {
	path, err := exec.LookPath("vmware")
	if err != nil {
		return err
	}
	d.AppPath = path
	return nil
}

func (d *Workstation9LinuxDriver) findVdiskManager() error {
	path, err := exec.LookPath("vmware-vdiskmanager")
	if err != nil {
		return err
	}
	d.VdiskManagerPath = path
	return nil
}

func (d *Workstation9LinuxDriver) findVmrun() error {
	path, err := exec.LookPath("vmrun")
	if err != nil {
		return err
	}
	d.VmrunPath = path
	return nil
}

func (d *Workstation9LinuxDriver) ToolsIsoPath(flavor string) string {
	return "/usr/lib/vmware/isoimages/" + flavor + ".iso"
}

func (d *Workstation9LinuxDriver) DhcpLeasesPath(device string) string {
	return "/etc/vmware/" + device + "/dhcpd/dhcpd.leases"
}

func (d *Workstation9LinuxDriver) runAndLog(cmd *exec.Cmd) (string, string, error) {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:])
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VMware error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return stdout.String(), stderr.String(), err
}
<commit_msg>builder/vmware: look for license for WS9<commit_after>package vmware

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os/exec"
	"path/filepath"
	"strings"
)

// Workstation9LinuxDriver is a driver that can run VMware Workstation 9
// on Linux.
type Workstation9LinuxDriver struct {
	AppPath          string
	VdiskManagerPath string
	VmrunPath        string
}

func (d *Workstation9LinuxDriver) CompactDisk(diskPath string) error {
	defragCmd := exec.Command(d.VdiskManagerPath, "-d", diskPath)
	if _, _, err := d.runAndLog(defragCmd); err != nil {
		return err
	}

	shrinkCmd := exec.Command(d.VdiskManagerPath, "-k", diskPath)
	if _, _, err := d.runAndLog(shrinkCmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) CreateDisk(output string, size string) error {
	cmd := exec.Command(d.VdiskManagerPath, "-c", "-s", size, "-a", "lsilogic", "-t", "1", output)
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) IsRunning(vmxPath string) (bool, error) {
	vmxPath, err := filepath.Abs(vmxPath)
	if err != nil {
		return false, err
	}

	cmd := exec.Command(d.VmrunPath, "-T", "ws", "list")
	stdout, _, err := d.runAndLog(cmd)
	if err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout, "\n") {
		if line == vmxPath {
			return true, nil
		}
	}

	return false, nil
}

func (d *Workstation9LinuxDriver) Start(vmxPath string, headless bool) error {
	guiArgument := "gui"
	if headless {
		guiArgument = "nogui"
	}

	cmd := exec.Command(d.VmrunPath, "-T", "ws", "start", vmxPath, guiArgument)
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) Stop(vmxPath string) error {
	cmd := exec.Command(d.VmrunPath, "-T", "ws", "stop", vmxPath, "hard")
	if _, _, err := d.runAndLog(cmd); err != nil {
		return err
	}

	return nil
}

func (d *Workstation9LinuxDriver) Verify() error {
	if err := d.findApp(); err != nil {
		return fmt.Errorf("VMware Workstation application ('vmware') not found in path.")
	}

	if err := d.findVmrun(); err != nil {
		return fmt.Errorf("Required application 'vmrun' not found in path.")
	}

	if err := d.findVdiskManager(); err != nil {
		return fmt.Errorf("Required application 'vmware-vdiskmanager' not found in path.")
	}

	// Check to see if it APPEARS to be licensed.
	matches, err := filepath.Glob("/etc/vmware/license-*")
	if err != nil {
		return fmt.Errorf("Error looking for VMware license: %s", err)
	}

	if len(matches) == 0 {
		return errors.New("Workstation does not appear to be licensed. Please license it.")
	}

	return nil
}

func (d *Workstation9LinuxDriver) findApp() error {
	path, err := exec.LookPath("vmware")
	if err != nil {
		return err
	}
	d.AppPath = path
	return nil
}

func (d *Workstation9LinuxDriver) findVdiskManager() error {
	path, err := exec.LookPath("vmware-vdiskmanager")
	if err != nil {
		return err
	}
	d.VdiskManagerPath = path
	return nil
}

func (d *Workstation9LinuxDriver) findVmrun() error {
	path, err := exec.LookPath("vmrun")
	if err != nil {
		return err
	}
	d.VmrunPath = path
	return nil
}

func (d *Workstation9LinuxDriver) ToolsIsoPath(flavor string) string {
	return "/usr/lib/vmware/isoimages/" + flavor + ".iso"
}

func (d *Workstation9LinuxDriver) DhcpLeasesPath(device string) string {
	return "/etc/vmware/" + device + "/dhcpd/dhcpd.leases"
}

func (d *Workstation9LinuxDriver) runAndLog(cmd *exec.Cmd) (string, string, error) {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:])
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VMware error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return stdout.String(), stderr.String(), err
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"os"
	"time"

	"github.com/unixpickle/gogui"
)

var canvas gogui.Canvas
var timeStart float64

type Point struct {
	X float64
	Y float64
}

var startPoints []Point = []Point{
	{-50, 300},
	{50, 50},
	{150, 150},
	{250, 170},
	{350, 100},
}

const deleteIndex = 2
const duration = 0.5
var animating bool = false

func main() {
	go gogui.RunOnMain(createWindow)
	gogui.Main(&gogui.AppInfo{Name: "Prototyper"})
}

func createWindow() {
	timeStart = CurrentTime()

	// Create the window.
	w, _ := gogui.NewWindow(gogui.Rect{0, 0, 400, 400})
	w.SetTitle("Prototyper")
	w.Center()
	w.Show()
	w.SetCloseHandler(func() {
		os.Exit(1)
	})
	w.SetKeyDownHandler(func(k gogui.KeyEvent) {
		switch k.CharCode {
		case 0x20:
			animating = false
		}
	})
	w.SetKeyUpHandler(func(k gogui.KeyEvent) {
		switch k.CharCode {
		case 0x20:
			animating = true
			timeStart = CurrentTime()
		}
	})

	// Create the canvas.
	canvas, _ = gogui.NewCanvas(gogui.Rect{0, 0, 400, 400})
	canvas.SetDrawHandler(drawHandler)
	w.Add(canvas)

	go func() {
		for {
			time.Sleep(time.Second / 24)
			gogui.RunOnMain(func() {
				canvas.NeedsUpdate()
			})
		}
	}()
}

func drawHandler(ctx gogui.DrawContext) {
	percent := (CurrentTime() - timeStart) / duration
	if percent > 1 {
		percent = 1
	}
	if !animating {
		percent = 0
	}
	pointsWithoutDeleting := []Point{}
	pointsWithDeleting := []Point{}
	for i := 0; i < len(startPoints); i++ {
		origPoint := startPoints[i]
		if i < deleteIndex {
			p := Point{origPoint.X + 100*percent, origPoint.Y}
			pointsWithDeleting = append(pointsWithDeleting, p)
			pointsWithoutDeleting = append(pointsWithoutDeleting, p)
		} else if i == deleteIndex {
			p := Point{origPoint.X + 50*percent, origPoint.Y}
			pointsWithoutDeleting = append(pointsWithoutDeleting, p)
		} else {
			pointsWithDeleting = append(pointsWithDeleting, origPoint)
			pointsWithoutDeleting = append(pointsWithoutDeleting, origPoint)
		}
	}
	initial := Spline(pointsWithoutDeleting)
	final := Spline(pointsWithDeleting)
	ctx.SetStroke(gogui.Color{0, 0, 1, 1})
	ctx.SetThickness(5)
	ctx.BeginPath()
	deletePoint := pointsWithoutDeleting[deleteIndex]
	for i, pi := range initial {
		pf := final[i]
		p := Point{pf.X, pi.Y + (pf.Y-pi.Y)*percent}
		if i == 0 {
			ctx.MoveTo(p.X, p.Y)
		} else {
			ctx.LineTo(p.X, p.Y)
		}
		if math.Abs(p.X - deletePoint.X) <= 1 {
			deletePoint.Y = p.Y
		}
	}
	ctx.StrokePath()
	ctx.SetFill(gogui.Color{1, 0, 0, 1})
	for _, p := range pointsWithDeleting {
		ctx.FillEllipse(gogui.Rect{p.X-5, p.Y-5, 10, 10})
	}
	deleteRadius := 5 - percent*5
	ctx.FillEllipse(gogui.Rect{deletePoint.X - deleteRadius, deletePoint.Y - deleteRadius, deleteRadius*2, deleteRadius*2})
}

// Spline generates a monotonic cubic spline for a bunch of x-sorted points.
// Thanks, http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
func Spline(p []Point) []Point {
	// Get secants and tangents.
	dxList := make([]float64, len(p)-1)
	dyList := make([]float64, len(p)-1)
	slopes := make([]float64, len(p)-1)
	for i := 0; i < len(p)-1; i++ {
		dxList[i] = p[i+1].X - p[i].X
		dyList[i] = p[i+1].Y - p[i].Y
		slopes[i] = dyList[i] / dxList[i]
	}

	// Get degree-1 coefficients.
	deg1 := make([]float64, len(p))
	deg1[0] = slopes[0]
	for i := 0; i < len(slopes)-1; i++ {
		slope := slopes[i]
		nextSlope := slopes[i+1]

		if slope*nextSlope <= 0 {
			// To keep monotonicity, this needs to be flat.
			deg1[i+1] = 0
			continue
		}

		dx := dxList[i]
		dxNext := dxList[i+1]
		common := dx + dxNext
		deg1[i+1] = 3 * common / ((common+dxNext)/slope + (common+dx)/nextSlope)
	}
	deg1[len(deg1)-1] = slopes[len(slopes)-1]

	// Get degree-2 and degree-3 coefficients.
	deg2 := make([]float64, len(deg1)-1)
	deg3 := make([]float64, len(deg1)-1)
	for i := 0; i < len(deg1)-1; i++ {
		c1 := deg1[i]
		slope := slopes[i]
		invDx := 1 / dxList[i]
		common := c1 + deg1[i+1] - 2*slope
		deg2[i] = (slope - c1 - common) * invDx
		deg3[i] = common * math.Pow(invDx, 2)
	}

	// Generate points for the result
	startX := p[0].X
	endX := p[len(p)-1].X
	res := make([]Point, 0)
	current := 0
	for x := startX; x < endX; x++ {
		if current < len(p)-1 && x >= p[current+1].X {
			current++
		}
		x1 := x - p[current].X
		x2 := math.Pow(x1, 2)
		x3 := math.Pow(x1, 3)
		y := p[current].Y + deg1[current]*x1 + deg2[current]*x2 +
			deg3[current]*x3
		res = append(res, Point{x, y})
	}
	return res
}

func CurrentTime() float64 {
	return float64(time.Now().UnixNano()) / float64(time.Second)
}
<commit_msg>alternate the deleted points<commit_after>package main

import (
	"math"
	"os"
	"time"

	"github.com/unixpickle/gogui"
)

var canvas gogui.Canvas
var timeStart float64

type Point struct {
	X float64
	Y float64
}

var startPoints []Point = []Point{
	{-50, 300},
	{50, 50},
	{150, 150},
	{250, 170},
	{350, 100},
}

var deleteIndex int = 3
const duration = 0.5
var animating bool = false

func main() {
	go gogui.RunOnMain(createWindow)
	gogui.Main(&gogui.AppInfo{Name: "Prototyper"})
}

func createWindow() {
	timeStart = CurrentTime()

	// Create the window.
	w, _ := gogui.NewWindow(gogui.Rect{0, 0, 400, 400})
	w.SetTitle("Prototyper")
	w.Center()
	w.Show()
	w.SetCloseHandler(func() {
		os.Exit(1)
	})
	w.SetKeyDownHandler(func(k gogui.KeyEvent) {
		switch k.CharCode {
		case 0x20:
			animating = false
		}
	})
	w.SetKeyUpHandler(func(k gogui.KeyEvent) {
		switch k.CharCode {
		case 0x20:
			deleteIndex = deleteIndex + 1
			if deleteIndex == 4 {
				deleteIndex = 1
			}
			animating = true
			timeStart = CurrentTime()
		}
	})

	// Create the canvas.
	canvas, _ = gogui.NewCanvas(gogui.Rect{0, 0, 400, 400})
	canvas.SetDrawHandler(drawHandler)
	w.Add(canvas)

	go func() {
		for {
			time.Sleep(time.Second / 24)
			gogui.RunOnMain(func() {
				canvas.NeedsUpdate()
			})
		}
	}()
}

func drawHandler(ctx gogui.DrawContext) {
	percent := (CurrentTime() - timeStart) / duration
	if percent > 1 {
		percent = 1
	}
	if !animating {
		percent = 0
	}
	pointsWithoutDeleting := []Point{}
	pointsWithDeleting := []Point{}
	for i := 0; i < len(startPoints); i++ {
		origPoint := startPoints[i]
		if i < deleteIndex {
			p := Point{origPoint.X + 100*percent, origPoint.Y}
			pointsWithDeleting = append(pointsWithDeleting, p)
			pointsWithoutDeleting = append(pointsWithoutDeleting, p)
		} else if i == deleteIndex {
			p := Point{origPoint.X + 50*percent, origPoint.Y}
			pointsWithoutDeleting = append(pointsWithoutDeleting, p)
		} else {
			pointsWithDeleting = append(pointsWithDeleting, origPoint)
			pointsWithoutDeleting = append(pointsWithoutDeleting, origPoint)
		}
	}
	initial := Spline(pointsWithoutDeleting)
	final := Spline(pointsWithDeleting)
	ctx.SetStroke(gogui.Color{0, 0, 1, 1})
	ctx.SetThickness(5)
	ctx.BeginPath()
	deletePoint := pointsWithoutDeleting[deleteIndex]
	for i, pi := range initial {
		pf := final[i]
		p := Point{pf.X, pi.Y + (pf.Y-pi.Y)*percent}
		if i == 0 {
			ctx.MoveTo(p.X, p.Y)
		} else {
			ctx.LineTo(p.X, p.Y)
		}
		if math.Abs(p.X - deletePoint.X) <= 1 {
			deletePoint.Y = p.Y
		}
	}
	ctx.StrokePath()
	ctx.SetFill(gogui.Color{1, 0, 0, 1})
	for _, p := range pointsWithDeleting {
		ctx.FillEllipse(gogui.Rect{p.X-5, p.Y-5, 10, 10})
	}
	deleteRadius := 5 - percent*5
	ctx.FillEllipse(gogui.Rect{deletePoint.X - deleteRadius, deletePoint.Y - deleteRadius, deleteRadius*2, deleteRadius*2})
}

// Spline generates a monotonic cubic spline for a bunch of x-sorted points.
// Thanks, http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
func Spline(p []Point) []Point {
	// Get secants and tangents.
	dxList := make([]float64, len(p)-1)
	dyList := make([]float64, len(p)-1)
	slopes := make([]float64, len(p)-1)
	for i := 0; i < len(p)-1; i++ {
		dxList[i] = p[i+1].X - p[i].X
		dyList[i] = p[i+1].Y - p[i].Y
		slopes[i] = dyList[i] / dxList[i]
	}

	// Get degree-1 coefficients.
	deg1 := make([]float64, len(p))
	deg1[0] = slopes[0]
	for i := 0; i < len(slopes)-1; i++ {
		slope := slopes[i]
		nextSlope := slopes[i+1]

		if slope*nextSlope <= 0 {
			// To keep monotonicity, this needs to be flat.
			deg1[i+1] = 0
			continue
		}

		dx := dxList[i]
		dxNext := dxList[i+1]
		common := dx + dxNext
		deg1[i+1] = 3 * common / ((common+dxNext)/slope + (common+dx)/nextSlope)
	}
	deg1[len(deg1)-1] = slopes[len(slopes)-1]

	// Get degree-2 and degree-3 coefficients.
	deg2 := make([]float64, len(deg1)-1)
	deg3 := make([]float64, len(deg1)-1)
	for i := 0; i < len(deg1)-1; i++ {
		c1 := deg1[i]
		slope := slopes[i]
		invDx := 1 / dxList[i]
		common := c1 + deg1[i+1] - 2*slope
		deg2[i] = (slope - c1 - common) * invDx
		deg3[i] = common * math.Pow(invDx, 2)
	}

	// Generate points for the result
	startX := p[0].X
	endX := p[len(p)-1].X
	res := make([]Point, 0)
	current := 0
	for x := startX; x < endX; x++ {
		if current < len(p)-1 && x >= p[current+1].X {
			current++
		}
		x1 := x - p[current].X
		x2 := math.Pow(x1, 2)
		x3 := math.Pow(x1, 3)
		y := p[current].Y + deg1[current]*x1 + deg2[current]*x2 +
			deg3[current]*x3
		res = append(res, Point{x, y})
	}
	return res
}

func CurrentTime() float64 {
	return float64(time.Now().UnixNano()) / float64(time.Second)
}
<|endoftext|>