Merge pull request #531 from aaron-prindle/pkg-errors
Changed minikube code to use pkg/errors, this is to improve errorpull/511/head
commit
cca3ff3271
|
@ -1382,6 +1382,11 @@
|
|||
"ImportPath": "github.com/pkg/browser",
|
||||
"Rev": "9302be274faad99162b9d48ec97b24306872ebb0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pkg/errors",
|
||||
"Comment": "v0.7.1",
|
||||
"Rev": "17b591df37844cde689f4d5813e5cea0927d8dd2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/shell"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
@ -104,12 +105,12 @@ func shellCfgSet(api libmachine.API) (*ShellConfig, error) {
|
|||
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting IP: %s", err)
|
||||
return nil, errors.Wrap(err, "Error getting IP: ")
|
||||
}
|
||||
|
||||
ip, err := host.Driver.GetIP()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting host IP: %s", err)
|
||||
return nil, errors.Wrap(err, "Error getting host IP: %s")
|
||||
}
|
||||
|
||||
noProxyVar, noProxyValue := findNoProxyFromEnv()
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
kubeApi "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
|
@ -100,13 +101,13 @@ func CheckService(namespace string, service string) error {
|
|||
|
||||
func CheckEndpointReady(endpoint *kubeApi.Endpoints) error {
|
||||
if len(endpoint.Subsets) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Waiting, endpoint for service is not ready yet...\n")
|
||||
return fmt.Errorf("Endpoint for service is not ready yet\n")
|
||||
fmt.Fprintf(os.Stderr, "Waiting, endpoint for service is not ready yet...")
|
||||
return errors.New("Endpoint for service is not ready yet")
|
||||
}
|
||||
for _, subset := range endpoint.Subsets {
|
||||
if len(subset.NotReadyAddresses) != 0 {
|
||||
fmt.Fprintf(os.Stderr, "Waiting, endpoint for service is not ready yet...\n")
|
||||
return fmt.Errorf("Endpoint for service is not ready yet\n")
|
||||
fmt.Fprintf(os.Stderr, "Waiting, endpoint for service is not ready yet...")
|
||||
return errors.New("Endpoint for service is not ready yet")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -41,6 +40,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
kubeApi "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
|
@ -66,7 +66,7 @@ func init() {
|
|||
func StartHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
||||
exists, err := api.Exists(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error checking if host exists: %s", err)
|
||||
return nil, errors.Wrapf(err, "Error checking if host exists: %s", constants.MachineName)
|
||||
}
|
||||
if !exists {
|
||||
return createHost(api, config)
|
||||
|
@ -75,27 +75,26 @@ func StartHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
glog.Infoln("Machine exists!")
|
||||
h, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"Error loading existing host: %s. Please try running [minikube delete], then run [minikube start] again.", err)
|
||||
return nil, errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.")
|
||||
}
|
||||
|
||||
s, err := h.Driver.GetState()
|
||||
glog.Infoln("Machine state: ", s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting state for host: %s", err)
|
||||
return nil, errors.Wrap(err, "Error getting state for host")
|
||||
}
|
||||
|
||||
if s != state.Running {
|
||||
if err := h.Driver.Start(); err != nil {
|
||||
return nil, fmt.Errorf("Error starting stopped host: %s", err)
|
||||
return nil, errors.Wrapf(err, "Error starting stopped host")
|
||||
}
|
||||
if err := api.Save(h); err != nil {
|
||||
return nil, fmt.Errorf("Error saving started host: %s", err)
|
||||
return nil, errors.Wrapf(err, "Error saving started host")
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.ConfigureAuth(); err != nil {
|
||||
return nil, fmt.Errorf("Error configuring auth on host: %s", err)
|
||||
return nil, errors.Wrap(err, "Error configuring auth on host: %s")
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
@ -104,10 +103,10 @@ func StartHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
func StopHost(api libmachine.API) error {
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error loading host: %s", constants.MachineName)
|
||||
}
|
||||
if err := host.Stop(); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error stopping host: %s", constants.MachineName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -116,7 +115,7 @@ func StopHost(api libmachine.API) error {
|
|||
func DeleteHost(api libmachine.API) error {
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error deleting host: %s", constants.MachineName)
|
||||
}
|
||||
m := util.MultiError{}
|
||||
m.Collect(host.Driver.Remove())
|
||||
|
@ -129,7 +128,7 @@ func GetHostStatus(api libmachine.API) (string, error) {
|
|||
dne := "Does Not Exist"
|
||||
exists, err := api.Exists(constants.MachineName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "Error checking that api exists for: ", constants.MachineName)
|
||||
}
|
||||
if !exists {
|
||||
return dne, nil
|
||||
|
@ -137,14 +136,17 @@ func GetHostStatus(api libmachine.API) (string, error) {
|
|||
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "Error loading api for: ", constants.MachineName)
|
||||
}
|
||||
|
||||
s, err := host.Driver.GetState()
|
||||
if s.String() == "" {
|
||||
return dne, err
|
||||
return dne, nil
|
||||
}
|
||||
return s.String(), err
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "Error getting host state")
|
||||
}
|
||||
return s.String(), nil
|
||||
}
|
||||
|
||||
// GetLocalkubeStatus gets the status of localkube from the host VM.
|
||||
|
@ -199,7 +201,7 @@ func StartCluster(h sshAble, kubernetesConfig KubernetesConfig) error {
|
|||
output, err := h.RunSSHCommand(cmd)
|
||||
glog.Infoln(output)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error running ssh command: %s", cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +258,7 @@ func NewFileAsset(assetName, targetDir, targetName, permissions string) (*FileAs
|
|||
}
|
||||
file, err := os.Open(f.AssetName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error opening file asset: %s", f.AssetName)
|
||||
}
|
||||
f.reader = file
|
||||
return f, nil
|
||||
|
@ -339,18 +341,18 @@ var memoryAssets = []CopyableFile{
|
|||
func UpdateCluster(h sshAble, d drivers.Driver, config KubernetesConfig) error {
|
||||
client, err := sshutil.NewSSHClient(d)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating new ssh client")
|
||||
}
|
||||
|
||||
// transfer localkube from cache/asset to vm
|
||||
if localkubeURIWasSpecified(config) {
|
||||
lCacher := localkubeCacher{config}
|
||||
if err = lCacher.updateLocalkubeFromURI(client); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error updating localkube from uri")
|
||||
}
|
||||
} else {
|
||||
if err = updateLocalkubeFromAsset(client); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error updating localkube from asset")
|
||||
}
|
||||
}
|
||||
fileAssets := []CopyableFile{}
|
||||
|
@ -380,7 +382,7 @@ func SetupCerts(d drivers.Driver) error {
|
|||
localPath := constants.Minipath
|
||||
ipStr, err := d.GetIP()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error getting ip from driver")
|
||||
}
|
||||
glog.Infoln("Setting up certificates for IP: %s", ipStr)
|
||||
|
||||
|
@ -390,26 +392,26 @@ func SetupCerts(d drivers.Driver) error {
|
|||
publicPath := filepath.Join(localPath, "apiserver.crt")
|
||||
privatePath := filepath.Join(localPath, "apiserver.key")
|
||||
if err := GenerateCerts(caCert, caKey, publicPath, privatePath, ip); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error generating certs")
|
||||
}
|
||||
|
||||
client, err := sshutil.NewSSHClient(d)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating new ssh client")
|
||||
}
|
||||
|
||||
for _, cert := range certs {
|
||||
p := filepath.Join(localPath, cert)
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error reading file: %s", p)
|
||||
}
|
||||
perms := "0644"
|
||||
if strings.HasSuffix(cert, ".key") {
|
||||
perms = "0600"
|
||||
}
|
||||
if err := sshutil.Transfer(bytes.NewReader(data), len(data), util.DefaultCertPath, cert, perms, client); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error transferring data: %s", string(data))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -467,34 +469,34 @@ func (m *MachineConfig) CacheMinikubeISOFromURL() error {
|
|||
// store the miniube-iso inside the .minikube dir
|
||||
response, err := http.Get(m.MinikubeISO)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error getting minikube iso at %s via http", m.MinikubeISO)
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
isoData, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error reading minikubeISO url response")
|
||||
}
|
||||
|
||||
// Validate the ISO if it was the default URL, before writing it to disk.
|
||||
if m.MinikubeISO == constants.DefaultIsoUrl {
|
||||
if !isIsoChecksumValid(&isoData, constants.DefaultIsoShaUrl) {
|
||||
return fmt.Errorf("Error validating ISO checksum.")
|
||||
return errors.New("Error validating ISO checksum.")
|
||||
}
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("Received %d response from %s while trying to download minikube.iso", response.StatusCode, m.MinikubeISO)
|
||||
return errors.Errorf("Received %d response from %s while trying to download minikube.iso", response.StatusCode, m.MinikubeISO)
|
||||
}
|
||||
|
||||
out, err := os.Create(m.GetISOCacheFilepath())
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating minikube iso cache filepath")
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if _, err = out.Write(isoData); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error writing iso data to file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -544,7 +546,7 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
|
||||
if config.ShouldCacheMinikubeISO() {
|
||||
if err := config.CacheMinikubeISOFromURL(); err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error attempting to cache minikube iso from url")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,12 +567,12 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
|
||||
data, err := json.Marshal(driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error marshalling json")
|
||||
}
|
||||
|
||||
h, err := api.NewHost(config.VMDriver, data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error creating new host: %s", err)
|
||||
return nil, errors.Wrap(err, "Error creating new host: %s")
|
||||
}
|
||||
|
||||
h.HostOptions.AuthOptions.CertDir = constants.Minipath
|
||||
|
@ -580,11 +582,11 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
if err := api.Create(h); err != nil {
|
||||
// Wait for all the logs to reach the client
|
||||
time.Sleep(2 * time.Second)
|
||||
return nil, fmt.Errorf("Error creating. %s", err)
|
||||
return nil, errors.Wrap(err, "Error creating host")
|
||||
}
|
||||
|
||||
if err := api.Save(h); err != nil {
|
||||
return nil, fmt.Errorf("Error attempting to save store: %s", err)
|
||||
return nil, errors.Wrap(err, "Error attempting to save")
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
@ -593,11 +595,11 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
func GetHostDockerEnv(api libmachine.API) (map[string]string, error) {
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error checking that api exists and loading it")
|
||||
}
|
||||
ip, err := host.Driver.GetIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error getting ip from host")
|
||||
}
|
||||
|
||||
tcpPrefix := "tcp://"
|
||||
|
@ -616,27 +618,27 @@ func GetHostDockerEnv(api libmachine.API) (map[string]string, error) {
|
|||
func GetHostLogs(api libmachine.API) (string, error) {
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "Error checking that api exists and loading it")
|
||||
}
|
||||
s, err := host.RunSSHCommand(logsCommand)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s, err
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func checkIfApiExistsAndLoad(api libmachine.API) (*host.Host, error) {
|
||||
exists, err := api.Exists(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error checking that api exists for: ", constants.MachineName)
|
||||
}
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("Machine does not exist for api.Exists(%s)", constants.MachineName)
|
||||
return nil, errors.Errorf("Machine does not exist for api.Exists(%s)", constants.MachineName)
|
||||
}
|
||||
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error loading api for: ", constants.MachineName)
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
@ -644,21 +646,21 @@ func checkIfApiExistsAndLoad(api libmachine.API) (*host.Host, error) {
|
|||
func CreateSSHShell(api libmachine.API, args []string) error {
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error checking if api exist and loading it")
|
||||
}
|
||||
|
||||
currentState, err := host.Driver.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error getting state of host")
|
||||
}
|
||||
|
||||
if currentState != state.Running {
|
||||
return fmt.Errorf("Error: Cannot run ssh command: Host %q is not running", constants.MachineName)
|
||||
return errors.Errorf("Error: Cannot run ssh command: Host %q is not running", constants.MachineName)
|
||||
}
|
||||
|
||||
client, err := host.CreateSSHClient()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating ssh client")
|
||||
}
|
||||
return client.Shell(strings.Join(args, " "))
|
||||
}
|
||||
|
@ -666,17 +668,17 @@ func CreateSSHShell(api libmachine.API, args []string) error {
|
|||
func GetServiceURL(api libmachine.API, namespace, service string) (string, error) {
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "Error checking if api exist and loading it")
|
||||
}
|
||||
|
||||
ip, err := host.Driver.GetIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "Error getting ip from host")
|
||||
}
|
||||
|
||||
port, err := getServicePort(namespace, service)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "Error getting service port from %s, %s", namespace, service)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("http://%s:%d", ip, port), nil
|
||||
|
@ -693,7 +695,7 @@ type endpointGetter interface {
|
|||
func getServicePort(namespace, service string) (int, error) {
|
||||
services, err := GetKubernetesServicesWithNamespace(namespace)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrapf(err, "Error getting kubernetes service with namespace", namespace)
|
||||
}
|
||||
return getServicePortFromServiceGetter(services, service)
|
||||
}
|
||||
|
@ -701,14 +703,14 @@ func getServicePort(namespace, service string) (int, error) {
|
|||
func getServicePortFromServiceGetter(services serviceGetter, service string) (int, error) {
|
||||
svc, err := services.Get(service)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("Error getting %s service: %s", service, err)
|
||||
return 0, errors.Wrapf(err, "Error getting %s service: %s", service)
|
||||
}
|
||||
nodePort := 0
|
||||
if len(svc.Spec.Ports) > 0 {
|
||||
nodePort = int(svc.Spec.Ports[0].NodePort)
|
||||
}
|
||||
if nodePort == 0 {
|
||||
return 0, fmt.Errorf("Service %s does not have a node port. To have one assigned automatically, the service type must be NodePort or LoadBalancer, but this service is of type %s.", service, svc.Spec.Type)
|
||||
return 0, errors.Errorf("Service %s does not have a node port. To have one assigned automatically, the service type must be NodePort or LoadBalancer, but this service is of type %s.", service, svc.Spec.Type)
|
||||
}
|
||||
return nodePort, nil
|
||||
}
|
||||
|
@ -719,11 +721,11 @@ func GetKubernetesClient() (*unversioned.Client, error) {
|
|||
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
|
||||
config, err := kubeConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error creating kubeConfig: %s", err)
|
||||
return nil, errors.Wrap(err, "Error creating kubeConfig: %s")
|
||||
}
|
||||
client, err := unversioned.New(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error creating new client from kubeConfig.ClientConfig()")
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
@ -731,7 +733,7 @@ func GetKubernetesClient() (*unversioned.Client, error) {
|
|||
func GetKubernetesServicesWithNamespace(namespace string) (serviceGetter, error) {
|
||||
client, err := GetKubernetesClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error getting kubernetes client")
|
||||
}
|
||||
services := client.Services(namespace)
|
||||
return services, nil
|
||||
|
@ -740,7 +742,7 @@ func GetKubernetesServicesWithNamespace(namespace string) (serviceGetter, error)
|
|||
func GetKubernetesEndpointsWithNamespace(namespace string) (endpointGetter, error) {
|
||||
client, err := GetKubernetesClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error getting kubernetes client")
|
||||
}
|
||||
endpoints := client.Endpoints(namespace)
|
||||
return endpoints, nil
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -34,6 +33,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/provision"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/tests"
|
||||
|
@ -498,7 +498,7 @@ func NewMockServiceGetter() *MockServiceGetter {
|
|||
func (mockServiceGetter *MockServiceGetter) Get(name string) (*api.Service, error) {
|
||||
service, ok := mockServiceGetter.services[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Error getting %s service from mockServiceGetter", name)
|
||||
return nil, errors.Errorf("Error getting %s service from mockServiceGetter", name)
|
||||
}
|
||||
return &service, nil
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package cluster
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -30,13 +31,13 @@ var (
|
|||
func GenerateCerts(caCert, caKey, pub, priv string, ip net.IP) error {
|
||||
if !(util.CanReadFile(caCert) && util.CanReadFile(caKey)) {
|
||||
if err := util.GenerateCACert(caCert, caKey); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error generating certificate")
|
||||
}
|
||||
}
|
||||
|
||||
ips := []net.IP{ip, internalIP}
|
||||
if err := util.GenerateSignedCert(pub, priv, ips, util.GetAlternateDNS(util.DefaultDNSDomain), caCert, caKey); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error generating signed cert")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package cluster
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -27,7 +26,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
|
@ -37,12 +36,11 @@ import (
|
|||
func updateLocalkubeFromAsset(client *ssh.Client) error {
|
||||
contents, err := Asset("out/localkube")
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
return errors.Wrap(err, "Error loading asset out/localkube")
|
||||
}
|
||||
if err := sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error transferring localkube via ssh")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -68,12 +66,12 @@ func (l *localkubeCacher) cacheLocalkube(body io.ReadCloser) error {
|
|||
// store localkube inside the .minikube dir
|
||||
out, err := os.Create(l.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating localkube local file")
|
||||
}
|
||||
defer out.Close()
|
||||
defer body.Close()
|
||||
if _, err = io.Copy(out, body); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error writing localkube to file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -85,17 +83,19 @@ func (l *localkubeCacher) downloadAndCacheLocalkube() error {
|
|||
url, err := util.GetLocalkubeDownloadURL(l.k8sConf.KubernetesVersion,
|
||||
constants.LocalkubeLinuxFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error getting localkube download url")
|
||||
}
|
||||
resp, err = http.Get(url)
|
||||
return err
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error downloading localkube via http")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = util.Retry(5, downloader); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Max error attempts retrying localkube downloader")
|
||||
}
|
||||
if err = l.cacheLocalkube(resp.Body); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error caching localkube to local directory")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ func (l *localkubeCacher) downloadAndCacheLocalkube() error {
|
|||
func (l *localkubeCacher) updateLocalkubeFromURI(client *ssh.Client) error {
|
||||
urlObj, err := url.Parse(l.k8sConf.KubernetesVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error parsing --kubernetes-version url")
|
||||
}
|
||||
if urlObj.Scheme == fileScheme {
|
||||
return l.updateLocalkubeFromFile(client)
|
||||
|
@ -115,11 +115,11 @@ func (l *localkubeCacher) updateLocalkubeFromURI(client *ssh.Client) error {
|
|||
func (l *localkubeCacher) updateLocalkubeFromURL(client *ssh.Client) error {
|
||||
if !l.isLocalkubeCached() {
|
||||
if err := l.downloadAndCacheLocalkube(); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error attempting to download and cache localkube")
|
||||
}
|
||||
}
|
||||
if err := l.transferCachedLocalkubeToVM(client); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error transferring cached localkube to VM")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -127,13 +127,12 @@ func (l *localkubeCacher) updateLocalkubeFromURL(client *ssh.Client) error {
|
|||
func (l *localkubeCacher) transferCachedLocalkubeToVM(client *ssh.Client) error {
|
||||
contents, err := ioutil.ReadFile(l.getLocalkubeCacheFilepath())
|
||||
if err != nil {
|
||||
glog.Infof("Error loading asset out/localkube: %s", err)
|
||||
return err
|
||||
return errors.Wrap(err, "Error reading file: localkube cache filepath")
|
||||
}
|
||||
|
||||
if err = sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error transferring cached localkube to VM via ssh")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -143,12 +142,11 @@ func (l *localkubeCacher) updateLocalkubeFromFile(client *ssh.Client) error {
|
|||
path = filepath.FromSlash(path)
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
glog.Infof("Error loading file %s: %s", path, err)
|
||||
return err
|
||||
return errors.Wrapf(err, "Error reading localkube file at %s", path)
|
||||
}
|
||||
if err := sshutil.Transfer(bytes.NewReader(contents), len(contents), "/usr/local/bin",
|
||||
"localkube", "0777", client); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error transferring specified localkube file at %s to VM via ssh", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ limitations under the License.
|
|||
package kubeconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/latest"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
|
@ -35,13 +35,13 @@ func ReadConfigOrNew(filename string) (*api.Config, error) {
|
|||
if os.IsNotExist(err) {
|
||||
return api.NewConfig(), nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error reading file", filename)
|
||||
}
|
||||
|
||||
// decode config, empty if no bytes
|
||||
config, err := decode(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read config: %v", err)
|
||||
return nil, errors.Errorf("could not read config: %v", err)
|
||||
}
|
||||
|
||||
// initialize nil maps
|
||||
|
@ -68,20 +68,20 @@ func WriteConfig(config *api.Config, filename string) error {
|
|||
// encode config to YAML
|
||||
data, err := runtime.Encode(latest.Codec, config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write to '%s': failed to encode config: %v", filename, err)
|
||||
return errors.Errorf("could not write to '%s': failed to encode config: %v", filename, err)
|
||||
}
|
||||
|
||||
// create parent dir if doesn't exist
|
||||
dir := filepath.Dir(filename)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error creating directory: %s", dir)
|
||||
}
|
||||
}
|
||||
|
||||
// write with restricted permissions
|
||||
if err := ioutil.WriteFile(filename, data, 0600); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error writing file %s", filename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func decode(data []byte) (*api.Config, error) {
|
|||
|
||||
config, _, err := latest.Codec.Decode(data, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error decoding config from data: %s", string(data))
|
||||
}
|
||||
|
||||
return config.(*api.Config), nil
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const kubernetesVersionGCSURL = "https://storage.googleapis.com/minikube/k8s_releases.json"
|
||||
|
@ -53,7 +54,7 @@ type k8sReleases []k8sRelease
|
|||
func getJson(url string, target *k8sReleases) error {
|
||||
r, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error getting json from url: %s via http", url)
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
|
@ -63,10 +64,10 @@ func getJson(url string, target *k8sReleases) error {
|
|||
func getK8sVersionsFromURL(url string) (k8sReleases, error) {
|
||||
var k8sVersions k8sReleases
|
||||
if err := getJson(url, &k8sVersions); err != nil {
|
||||
return k8sReleases{}, err
|
||||
return k8sReleases{}, errors.Wrapf(err, "Error getting json via http with url: %s", url)
|
||||
}
|
||||
if len(k8sVersions) == 0 {
|
||||
return k8sReleases{}, fmt.Errorf("There were no json k8s Releases at the url specified: %s", url)
|
||||
return k8sReleases{}, errors.Errorf("There were no json k8s Releases at the url specified: %s", url)
|
||||
}
|
||||
return k8sVersions, nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/blang/semver"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
@ -90,7 +91,7 @@ type releases []release
|
|||
func getJson(url string, target *releases) error {
|
||||
r, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error getting minikube version url via http")
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
|
@ -101,10 +102,10 @@ func getLatestVersionFromURL(url string) (semver.Version, error) {
|
|||
var releases releases
|
||||
glog.Infof("Checking for updates...")
|
||||
if err := getJson(url, &releases); err != nil {
|
||||
return semver.Version{}, err
|
||||
return semver.Version{}, errors.Wrap(err, "Error getting json from minikube version url")
|
||||
}
|
||||
if len(releases) == 0 {
|
||||
return semver.Version{}, fmt.Errorf("There were no json releases at the url specified: %s", url)
|
||||
return semver.Version{}, errors.Errorf("There were no json releases at the url specified: %s", url)
|
||||
}
|
||||
latestVersionString := releases[0].Name
|
||||
return semver.Make(strings.TrimPrefix(latestVersionString, version.VersionPrefix))
|
||||
|
@ -113,7 +114,7 @@ func getLatestVersionFromURL(url string) (semver.Version, error) {
|
|||
func writeTimeToFile(path string, inputTime time.Time) error {
|
||||
err := ioutil.WriteFile(path, []byte(inputTime.Format(timeLayout)), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error writing current update time to file: %s", err)
|
||||
return errors.Wrap(err, "Error writing current update time to file: ")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
machinessh "github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
|
@ -39,7 +40,7 @@ type SSHSession interface {
|
|||
func NewSSHClient(d drivers.Driver) (*ssh.Client, error) {
|
||||
h, err := newSSHHost(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error creating new ssh host from driver")
|
||||
|
||||
}
|
||||
auth := &machinessh.Auth{}
|
||||
|
@ -48,12 +49,12 @@ func NewSSHClient(d drivers.Driver) (*ssh.Client, error) {
|
|||
}
|
||||
config, err := machinessh.NewNativeConfig(h.Username, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "Error creating new native config from ssh using: %s, %s", h.Username, auth)
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", h.IP, h.Port), &config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error dialing tcp via ssh client")
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
@ -65,18 +66,18 @@ func Transfer(reader io.Reader, readerLen int, remotedir, filename string, perm
|
|||
mkdirCmd := fmt.Sprintf("sudo mkdir -p %s", remotedir)
|
||||
for _, cmd := range []string{deleteCmd, mkdirCmd} {
|
||||
if err := RunCommand(c, cmd); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "Error running command: %s", cmd)
|
||||
}
|
||||
}
|
||||
|
||||
s, err := c.NewSession()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating new session via ssh client")
|
||||
}
|
||||
|
||||
w, err := s.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error accessing StdinPipe via ssh session")
|
||||
}
|
||||
// The scpcmd below *should not* return until all data is copied and the
|
||||
// StdinPipe is closed. But let's use a WaitGroup to make it expicit.
|
||||
|
@ -92,7 +93,7 @@ func Transfer(reader io.Reader, readerLen int, remotedir, filename string, perm
|
|||
}()
|
||||
scpcmd := fmt.Sprintf("sudo /usr/local/bin/scp -t %s", remotedir)
|
||||
if err := s.Run(scpcmd); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error running scp command")
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
@ -103,7 +104,7 @@ func RunCommand(c *ssh.Client, cmd string) error {
|
|||
s, err := c.NewSession()
|
||||
defer s.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating new session for ssh client")
|
||||
}
|
||||
|
||||
return s.Run(cmd)
|
||||
|
@ -120,11 +121,11 @@ func newSSHHost(d drivers.Driver) (*sshHost, error) {
|
|||
|
||||
ip, err := d.GetSSHHostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error getting ssh host name for driver")
|
||||
}
|
||||
port, err := d.GetSSHPort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error getting ssh port for driver")
|
||||
}
|
||||
return &sshHost{
|
||||
IP: ip,
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/mcnerror"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// MockAPI is a struct used to mock out libmachine.API
|
||||
|
@ -51,7 +52,7 @@ func (api *MockAPI) Close() error {
|
|||
func (api *MockAPI) NewHost(driverName string, rawDriver []byte) (*host.Host, error) {
|
||||
var driver MockDriver
|
||||
if err := json.Unmarshal(rawDriver, &driver); err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error unmarshalling json")
|
||||
}
|
||||
h := &host.Host{
|
||||
DriverName: driverName,
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
|
@ -50,11 +51,11 @@ func NewSSHServer() (*SSHServer, error) {
|
|||
|
||||
private, err := rsa.GenerateKey(rand.Reader, 2014)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error generating RSA key")
|
||||
}
|
||||
signer, err := ssh.NewSignerFromKey(private)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error creating signer from key")
|
||||
}
|
||||
s.Config.AddHostKey(signer)
|
||||
return s, nil
|
||||
|
@ -68,7 +69,7 @@ type execRequest struct {
|
|||
func (s *SSHServer) Start() (int, error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(err, "Error creating tcp listener for ssh server")
|
||||
}
|
||||
|
||||
// Main loop, listen for connections and store the commands.
|
||||
|
@ -126,11 +127,11 @@ func (s *SSHServer) Start() (int, error) {
|
|||
// Parse and return the port.
|
||||
_, p, err := net.SplitHostPort(listener.Addr().String())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(err, "Error splitting host port")
|
||||
}
|
||||
port, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(err, "Error converting port string to integer")
|
||||
}
|
||||
return port, nil
|
||||
}
|
||||
|
|
|
@ -23,19 +23,20 @@ import (
|
|||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func GenerateCACert(certPath, keyPath string) error {
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error generating rsa key")
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
|
@ -62,27 +63,27 @@ func GenerateCACert(certPath, keyPath string) error {
|
|||
func GenerateSignedCert(certPath, keyPath string, ips []net.IP, alternateDNS []string, signerCertPath, signerKeyPath string) error {
|
||||
signerCertBytes, err := ioutil.ReadFile(signerCertPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error reading file: signerCertPath")
|
||||
}
|
||||
decodedSignerCert, _ := pem.Decode(signerCertBytes)
|
||||
if decodedSignerCert == nil {
|
||||
return fmt.Errorf("Unable to decode certificate.")
|
||||
return errors.New("Unable to decode certificate.")
|
||||
}
|
||||
signerCert, err := x509.ParseCertificate(decodedSignerCert.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error parsing certificate: decodedSignerCert.Bytes")
|
||||
}
|
||||
signerKeyBytes, err := ioutil.ReadFile(signerKeyPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error reading file: signerKeyPath")
|
||||
}
|
||||
decodedSignerKey, _ := pem.Decode(signerKeyBytes)
|
||||
if decodedSignerKey == nil {
|
||||
return fmt.Errorf("Unable to decode key.")
|
||||
return errors.New("Unable to decode key.")
|
||||
}
|
||||
signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error parsing prive key: decodedSignerKey.Bytes")
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
|
@ -103,7 +104,7 @@ func GenerateSignedCert(certPath, keyPath string, ips []net.IP, alternateDNS []s
|
|||
|
||||
priv, err := loadOrGeneratePrivateKey(keyPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error loading or generating private key: keyPath")
|
||||
}
|
||||
|
||||
return writeCertsAndKeys(&template, certPath, priv, keyPath, signerCert, signerKey)
|
||||
|
@ -122,7 +123,7 @@ func loadOrGeneratePrivateKey(keyPath string) (*rsa.PrivateKey, error) {
|
|||
}
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error generating RSA key")
|
||||
}
|
||||
return priv, nil
|
||||
}
|
||||
|
@ -130,31 +131,31 @@ func loadOrGeneratePrivateKey(keyPath string) (*rsa.PrivateKey, error) {
|
|||
func writeCertsAndKeys(template *x509.Certificate, certPath string, signeeKey *rsa.PrivateKey, keyPath string, parent *x509.Certificate, signingKey *rsa.PrivateKey) error {
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, &signeeKey.PublicKey, signingKey)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating certificate")
|
||||
}
|
||||
|
||||
certBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error encoding certificate")
|
||||
}
|
||||
|
||||
keyBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(signeeKey)}); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error encoding key")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating certificate directory")
|
||||
}
|
||||
if err := ioutil.WriteFile(certPath, certBuffer.Bytes(), os.FileMode(0644)); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error writing certificate to cert path")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error creating key directory")
|
||||
}
|
||||
if err := ioutil.WriteFile(keyPath, keyBuffer.Bytes(), os.FileMode(0600)); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Error writing key file")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
@ -88,7 +89,7 @@ func RetryAfter(attempts int, callback func() error, d time.Duration) (err error
|
|||
func GetLocalkubeDownloadURL(versionOrURL string, filename string) (string, error) {
|
||||
urlObj, err := url.Parse(versionOrURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "Error parsing localkube download url")
|
||||
}
|
||||
if urlObj.IsAbs() {
|
||||
// scheme was specified in input, is a valid URI.
|
||||
|
@ -100,7 +101,7 @@ func GetLocalkubeDownloadURL(versionOrURL string, filename string) (string, erro
|
|||
versionOrURL = "v" + versionOrURL
|
||||
}
|
||||
if _, err = semver.Make(strings.TrimPrefix(versionOrURL, version.VersionPrefix)); err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrap(err, "Error creating semver version from localkube version input string")
|
||||
}
|
||||
return fmt.Sprintf("%s%s/%s", constants.LocalkubeDownloadURLPrefix, versionOrURL, filename), nil
|
||||
}
|
||||
|
@ -124,13 +125,23 @@ func (m MultiError) ToError() error {
|
|||
for _, err := range m.Errors {
|
||||
errStrings = append(errStrings, err.Error())
|
||||
}
|
||||
return fmt.Errorf(strings.Join(errStrings, "\n"))
|
||||
return errors.New(strings.Join(errStrings, "\n"))
|
||||
}
|
||||
|
||||
type ServiceContext struct {
|
||||
Service string `json:"service"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Message string `json:"message"`
|
||||
ServiceContext `json:"serviceContext"`
|
||||
}
|
||||
|
||||
func IsDirectory(path string) (bool, error) {
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, errors.Wrapf(err, "Error calling os.Stat on file %s", path)
|
||||
}
|
||||
return fileInfo.IsDir(), nil
|
||||
}
|
||||
|
|
|
@ -17,19 +17,19 @@ limitations under the License.
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
// Returns a function that will return n errors, then return successfully forever.
|
||||
func errorGenerator(n int) func() error {
|
||||
errors := 0
|
||||
errorCount := 0
|
||||
return func() (err error) {
|
||||
if errors < n {
|
||||
errors += 1
|
||||
return fmt.Errorf("Error!")
|
||||
if errorCount < n {
|
||||
errorCount += 1
|
||||
return errors.New("Error!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -93,8 +93,8 @@ func TestGetLocalkubeDownloadURL(t *testing.T) {
|
|||
func TestMultiError(t *testing.T) {
|
||||
m := MultiError{}
|
||||
|
||||
m.Collect(fmt.Errorf("Error 1"))
|
||||
m.Collect(fmt.Errorf("Error 2"))
|
||||
m.Collect(errors.New("Error 1"))
|
||||
m.Collect(errors.New("Error 2"))
|
||||
|
||||
err := m.ToError()
|
||||
expected := `Error 1
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
|
@ -0,0 +1,10 @@
|
|||
language: go
|
||||
go_import_path: github.com/pkg/errors
|
||||
go:
|
||||
- 1.4.3
|
||||
- 1.5.4
|
||||
- 1.6.2
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,52 @@
|
|||
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
|
||||
|
||||
Package errors provides simple error handling primitives.
|
||||
|
||||
`go get github.com/pkg/errors`
|
||||
|
||||
The traditional error handling idiom in Go is roughly akin to
|
||||
```go
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
|
||||
|
||||
## Adding context to an error
|
||||
|
||||
The errors.Wrap function returns a new error that adds context to the original error. For example
|
||||
```go
|
||||
_, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "read failed")
|
||||
}
|
||||
```
|
||||
## Retrieving the cause of an error
|
||||
|
||||
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
|
||||
```go
|
||||
type causer interface {
|
||||
Cause() error
|
||||
}
|
||||
```
|
||||
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
|
||||
```go
|
||||
switch err := errors.Cause(err).(type) {
|
||||
case *MyError:
|
||||
// handle specifically
|
||||
default:
|
||||
// unknown error
|
||||
}
|
||||
```
|
||||
|
||||
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
|
||||
|
||||
Before proposing a change, please discuss your change by raising an issue.
|
||||
|
||||
## Licence
|
||||
|
||||
BSD-2-Clause
|
|
@ -0,0 +1,32 @@
|
|||
version: build-{build}.{branch}
|
||||
|
||||
clone_folder: C:\gopath\src\github.com\pkg\errors
|
||||
shallow_clone: true # for startup speed
|
||||
|
||||
environment:
|
||||
GOPATH: C:\gopath
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
# http://www.appveyor.com/docs/installed-software
|
||||
install:
|
||||
# some helpful output for debugging builds
|
||||
- go version
|
||||
- go env
|
||||
# pre-installed MinGW at C:\MinGW is 32bit only
|
||||
# but MSYS2 at C:\msys64 has mingw64
|
||||
- set PATH=C:\msys64\mingw64\bin;%PATH%
|
||||
- gcc --version
|
||||
- g++ --version
|
||||
|
||||
build_script:
|
||||
- go install -v ./...
|
||||
|
||||
test_script:
|
||||
- set PATH=C:\gopath\bin;%PATH%
|
||||
- go test -v ./...
|
||||
|
||||
#artifacts:
|
||||
# - path: '%GOPATH%\bin\*.exe'
|
||||
deploy: off
|
|
@ -0,0 +1,238 @@
|
|||
// Package errors provides simple error handling primitives.
|
||||
//
|
||||
// The traditional error handling idiom in Go is roughly akin to
|
||||
//
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// which applied recursively up the call stack results in error reports
|
||||
// without context or debugging information. The errors package allows
|
||||
// programmers to add context to the failure path in their code in a way
|
||||
// that does not destroy the original value of the error.
|
||||
//
|
||||
// Adding context to an error
|
||||
//
|
||||
// The errors.Wrap function returns a new error that adds context to the
|
||||
// original error. For example
|
||||
//
|
||||
// _, err := ioutil.ReadAll(r)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(err, "read failed")
|
||||
// }
|
||||
//
|
||||
// Retrieving the cause of an error
|
||||
//
|
||||
// Using errors.Wrap constructs a stack of errors, adding context to the
|
||||
// preceding error. Depending on the nature of the error it may be necessary
|
||||
// to reverse the operation of errors.Wrap to retrieve the original error
|
||||
// for inspection. Any error value which implements this interface
|
||||
//
|
||||
// type causer interface {
|
||||
// Cause() error
|
||||
// }
|
||||
//
|
||||
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
||||
// the topmost error which does not implement causer, which is assumed to be
|
||||
// the original cause. For example:
|
||||
//
|
||||
// switch err := errors.Cause(err).(type) {
|
||||
// case *MyError:
|
||||
// // handle specifically
|
||||
// default:
|
||||
// // unknown error
|
||||
// }
|
||||
//
|
||||
// causer interface is not exported by this package, but is considered a part
|
||||
// of stable public API.
|
||||
//
|
||||
// Formatted printing of errors
|
||||
//
|
||||
// All error values returned from this package implement fmt.Formatter and can
|
||||
// be formatted by the fmt package. The following verbs are supported
|
||||
//
|
||||
// %s print the error. If the error has a Cause it will be
|
||||
// printed recursively
|
||||
// %v see %s
|
||||
// %+v extended format. Each Frame of the error's StackTrace will
|
||||
// be printed in detail.
|
||||
//
|
||||
// Retrieving the stack trace of an error or wrapper
|
||||
//
|
||||
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
||||
// invoked. This information can be retrieved with the following interface.
|
||||
//
|
||||
// type stackTracer interface {
|
||||
// StackTrace() errors.StackTrace
|
||||
// }
|
||||
//
|
||||
// Where errors.StackTrace is defined as
|
||||
//
|
||||
// type StackTrace []Frame
|
||||
//
|
||||
// The Frame type represents a call site in the stack trace. Frame supports
|
||||
// the fmt.Formatter interface that can be used for printing information about
|
||||
// the stack trace of this error. For example:
|
||||
//
|
||||
// if err, ok := err.(stackTracer); ok {
|
||||
// for _, f := range err.StackTrace() {
|
||||
// fmt.Printf("%+s:%d", f)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// stackTracer interface is not exported by this package, but is considered a part
|
||||
// of stable public API.
|
||||
//
|
||||
// See the documentation for Frame.Format for more details.
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// New returns an error with the supplied message.
|
||||
// New also records the stack trace at the point it was called.
|
||||
func New(message string) error {
|
||||
return &fundamental{
|
||||
msg: message,
|
||||
stack: callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf formats according to a format specifier and returns the string
|
||||
// as a value that satisfies error.
|
||||
// Errorf also records the stack trace at the point it was called.
|
||||
func Errorf(format string, args ...interface{}) error {
|
||||
return &fundamental{
|
||||
msg: fmt.Sprintf(format, args...),
|
||||
stack: callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// fundamental is an error that has a message and a stack, but no caller.
|
||||
type fundamental struct {
|
||||
msg string
|
||||
*stack
|
||||
}
|
||||
|
||||
func (f *fundamental) Error() string { return f.msg }
|
||||
|
||||
func (f *fundamental) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
io.WriteString(s, f.msg)
|
||||
f.stack.Format(s, verb)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's':
|
||||
io.WriteString(s, f.msg)
|
||||
case 'q':
|
||||
fmt.Fprintf(s, "%q", f.msg)
|
||||
}
|
||||
}
|
||||
|
||||
type withStack struct {
|
||||
error
|
||||
*stack
|
||||
}
|
||||
|
||||
func (w *withStack) Cause() error { return w.error }
|
||||
|
||||
func (w *withStack) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprintf(s, "%+v", w.Cause())
|
||||
w.stack.Format(s, verb)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's':
|
||||
io.WriteString(s, w.Error())
|
||||
case 'q':
|
||||
fmt.Fprintf(s, "%q", w.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap returns an error annotating err with message.
|
||||
// If err is nil, Wrap returns nil.
|
||||
func Wrap(err error, message string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
err = &withMessage{
|
||||
cause: err,
|
||||
msg: message,
|
||||
}
|
||||
return &withStack{
|
||||
err,
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapf returns an error annotating err with the format specifier.
|
||||
// If err is nil, Wrapf returns nil.
|
||||
func Wrapf(err error, format string, args ...interface{}) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
err = &withMessage{
|
||||
cause: err,
|
||||
msg: fmt.Sprintf(format, args...),
|
||||
}
|
||||
return &withStack{
|
||||
err,
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
|
||||
type withMessage struct {
|
||||
cause error
|
||||
msg string
|
||||
}
|
||||
|
||||
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
||||
func (w *withMessage) Cause() error { return w.cause }
|
||||
|
||||
func (w *withMessage) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprintf(s, "%+v\n", w.Cause())
|
||||
io.WriteString(s, w.msg)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
io.WriteString(s, w.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Cause returns the underlying cause of the error, if possible.
|
||||
// An error value has a cause if it implements the following
|
||||
// interface:
|
||||
//
|
||||
// type causer interface {
|
||||
// Cause() error
|
||||
// }
|
||||
//
|
||||
// If the error does not implement Cause, the original error will
|
||||
// be returned. If the error is nil, nil will be returned without further
|
||||
// investigation.
|
||||
func Cause(err error) error {
|
||||
type causer interface {
|
||||
Cause() error
|
||||
}
|
||||
|
||||
for err != nil {
|
||||
cause, ok := err.(causer)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err = cause.Cause()
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Frame represents a program counter inside a stack frame.
|
||||
type Frame uintptr
|
||||
|
||||
// pc returns the program counter for this frame;
|
||||
// multiple frames may have the same PC value.
|
||||
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
|
||||
|
||||
// file returns the full path to the file that contains the
|
||||
// function for this Frame's pc.
|
||||
func (f Frame) file() string {
|
||||
fn := runtime.FuncForPC(f.pc())
|
||||
if fn == nil {
|
||||
return "unknown"
|
||||
}
|
||||
file, _ := fn.FileLine(f.pc())
|
||||
return file
|
||||
}
|
||||
|
||||
// line returns the line number of source code of the
|
||||
// function for this Frame's pc.
|
||||
func (f Frame) line() int {
|
||||
fn := runtime.FuncForPC(f.pc())
|
||||
if fn == nil {
|
||||
return 0
|
||||
}
|
||||
_, line := fn.FileLine(f.pc())
|
||||
return line
|
||||
}
|
||||
|
||||
// Format formats the frame according to the fmt.Formatter interface.
|
||||
//
|
||||
// %s source file
|
||||
// %d source line
|
||||
// %n function name
|
||||
// %v equivalent to %s:%d
|
||||
//
|
||||
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||
//
|
||||
// %+s path of source file relative to the compile time GOPATH
|
||||
// %+v equivalent to %+s:%d
|
||||
func (f Frame) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 's':
|
||||
switch {
|
||||
case s.Flag('+'):
|
||||
pc := f.pc()
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
io.WriteString(s, "unknown")
|
||||
} else {
|
||||
file, _ := fn.FileLine(pc)
|
||||
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
|
||||
}
|
||||
default:
|
||||
io.WriteString(s, path.Base(f.file()))
|
||||
}
|
||||
case 'd':
|
||||
fmt.Fprintf(s, "%d", f.line())
|
||||
case 'n':
|
||||
name := runtime.FuncForPC(f.pc()).Name()
|
||||
io.WriteString(s, funcname(name))
|
||||
case 'v':
|
||||
f.Format(s, 's')
|
||||
io.WriteString(s, ":")
|
||||
f.Format(s, 'd')
|
||||
}
|
||||
}
|
||||
|
||||
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||
type StackTrace []Frame
|
||||
|
||||
func (st StackTrace) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
switch {
|
||||
case s.Flag('+'):
|
||||
for _, f := range st {
|
||||
fmt.Fprintf(s, "\n%+v", f)
|
||||
}
|
||||
case s.Flag('#'):
|
||||
fmt.Fprintf(s, "%#v", []Frame(st))
|
||||
default:
|
||||
fmt.Fprintf(s, "%v", []Frame(st))
|
||||
}
|
||||
case 's':
|
||||
fmt.Fprintf(s, "%s", []Frame(st))
|
||||
}
|
||||
}
|
||||
|
||||
// stack represents a stack of program counters.
|
||||
type stack []uintptr
|
||||
|
||||
func (s *stack) Format(st fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
switch {
|
||||
case st.Flag('+'):
|
||||
for _, pc := range *s {
|
||||
f := Frame(pc)
|
||||
fmt.Fprintf(st, "\n%+v", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stack) StackTrace() StackTrace {
|
||||
f := make([]Frame, len(*s))
|
||||
for i := 0; i < len(f); i++ {
|
||||
f[i] = Frame((*s)[i])
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func callers() *stack {
|
||||
const depth = 32
|
||||
var pcs [depth]uintptr
|
||||
n := runtime.Callers(3, pcs[:])
|
||||
var st stack = pcs[0:n]
|
||||
return &st
|
||||
}
|
||||
|
||||
// funcname removes the path prefix component of a function's name reported by func.Name().
|
||||
func funcname(name string) string {
|
||||
i := strings.LastIndex(name, "/")
|
||||
name = name[i+1:]
|
||||
i = strings.Index(name, ".")
|
||||
return name[i+1:]
|
||||
}
|
||||
|
||||
func trimGOPATH(name, file string) string {
|
||||
// Here we want to get the source file path relative to the compile time
|
||||
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
|
||||
// GOPATH at runtime, but we can infer the number of path segments in the
|
||||
// GOPATH. We note that fn.Name() returns the function name qualified by
|
||||
// the import path, which does not include the GOPATH. Thus we can trim
|
||||
// segments from the beginning of the file path until the number of path
|
||||
// separators remaining is one more than the number of path separators in
|
||||
// the function name. For example, given:
|
||||
//
|
||||
// GOPATH /home/user
|
||||
// file /home/user/src/pkg/sub/file.go
|
||||
// fn.Name() pkg/sub.Type.Method
|
||||
//
|
||||
// We want to produce:
|
||||
//
|
||||
// pkg/sub/file.go
|
||||
//
|
||||
// From this we can easily see that fn.Name() has one less path separator
|
||||
// than our desired output. We count separators from the end of the file
|
||||
// path until it finds two more than in the function name and then move
|
||||
// one character forward to preserve the initial path segment without a
|
||||
// leading separator.
|
||||
const sep = "/"
|
||||
goal := strings.Count(name, sep) + 2
|
||||
i := len(file)
|
||||
for n := 0; n < goal; n++ {
|
||||
i = strings.LastIndex(file[:i], sep)
|
||||
if i == -1 {
|
||||
// not enough separators found, set i so that the slice expression
|
||||
// below leaves file unmodified
|
||||
i = -len(sep)
|
||||
break
|
||||
}
|
||||
}
|
||||
// get back to 0 or trim the leading separator
|
||||
file = file[i+len(sep):]
|
||||
return file
|
||||
}
|
Loading…
Reference in New Issue