<commit_before>package cli

import (
	"flag"
	"testing"

	rpcpb "github.com/google/shipshape/shipshape/proto/shipshape_rpc_proto"
)

var dockerTag = flag.String("shipshape_test_docker_tag", "", "the docker tag for the images to use for testing")

func countFailures(resp rpcpb.ShipshapeResponse) int {
	failures := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		failures += len(analyzeResp.Failure)
	}
	return failures
}

func countNotes(resp rpcpb.ShipshapeResponse) int {
	notes := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		notes += len(analyzeResp.Note)
	}
	return notes
}

func countCategoryNotes(resp rpcpb.ShipshapeResponse, category string) int {
	notes := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		for _, note := range analyzeResp.Note {
			if *note.Category == category {
				notes += 1
			}
		}
	}
	return notes
}

func TestExternalAnalyzers(t *testing.T) {
	// Replaces part of the e2e test
	// Create a fake maven project with android failures

	// Run CLI using a .shipshape file
}

func TestBuiltInAnalyzersPreBuild(t *testing.T) {
	options := Options{
		File:                "shipshape/cli/testdata/workspace1",
		ThirdPartyAnalyzers: []string{},
		Build:               "",
		TriggerCats:         []string{"PostMessage", "JSHint", "go vet", "PyLint"},
		Dind:                false,
		Event:               DefaultEvent,
		Repo:                DefaultRepo,
		StayUp:              true,
		Tag:                 *dockerTag,
		// TODO(rsk): current e2e test can be run both with & without kythe.
		LocalKythe:          false,
	}
	var allResponses rpcpb.ShipshapeResponse
	options.HandleResponse = func(shipshapeResp *rpcpb.ShipshapeResponse, _ string) error {
		allResponses.AnalyzeResponse = append(allResponses.AnalyzeResponse, shipshapeResp.AnalyzeResponse...)
		return nil
	}
	returnedNotesCount, err := New(options).Run()
	if err != nil {
		t.Fatal(err)
	}
	testName := "TestBuiltInAnalyzerPreBuild"

	if got, want := countFailures(allResponses), 0; got != want {
		t.Errorf("%v: Wrong number of failures; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if countedNotes := countNotes(allResponses); returnedNotesCount != countedNotes {
		t.Errorf("%v: Inconsistent note count: returned %v, counted %v (proto data: %v", testName, returnedNotesCount, countedNotes, allResponses)
	}
	if got, want := returnedNotesCount, 38; got != want {
		t.Errorf("%v: Wrong number of notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "PostMessage"), 2; got != want {
		t.Errorf("%v: Wrong number of PostMessage notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "JSHint"), 3; got != want {
		t.Errorf("%v: Wrong number of JSHint notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "go vet"), 0; got != want {
		t.Errorf("%v: Wrong number of go vet notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "PyLint"), 33; got != want {
		t.Errorf("%v: Wrong number of PyLint notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
}

func TestBuiltInAnalyzersPostBuild(t *testing.T) {
	// Replaces part of the e2e test
	// Test with a kythe maven build
	// PostMessage and ErrorProne
}

func TestStreamsMode(t *testing.T) {
	// Test whether it works in streams mode
	// Before creating this, ensure that streams mode
	// is actually still something we need to support.
}

func TestChangingDirectories(t *testing.T) {
	// Replaces the changedir test
	// Make sure to test changing down, changing up, running on the same directory, running on a single file in the same directory, and changing to a sibling
}

func dumpLogs() {

}

func checkOutput(category string, numResults int) {

}
<commit_msg>Updates expected test values<commit_after>package cli

import (
	"flag"
	"testing"

	rpcpb "github.com/google/shipshape/shipshape/proto/shipshape_rpc_proto"
)

var dockerTag = flag.String("shipshape_test_docker_tag", "", "the docker tag for the images to use for testing")

func countFailures(resp rpcpb.ShipshapeResponse) int {
	failures := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		failures += len(analyzeResp.Failure)
	}
	return failures
}

func countNotes(resp rpcpb.ShipshapeResponse) int {
	notes := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		notes += len(analyzeResp.Note)
	}
	return notes
}

func countCategoryNotes(resp rpcpb.ShipshapeResponse, category string) int {
	notes := 0
	for _, analyzeResp := range resp.AnalyzeResponse {
		for _, note := range analyzeResp.Note {
			if *note.Category == category {
				notes += 1
			}
		}
	}
	return notes
}

func TestExternalAnalyzers(t *testing.T) {
	// Replaces part of the e2e test
	// Create a fake maven project with android failures

	// Run CLI using a .shipshape file
}

func TestBuiltInAnalyzersPreBuild(t *testing.T) {
	options := Options{
		File:                "shipshape/cli/testdata/workspace1",
		ThirdPartyAnalyzers: []string{},
		Build:               "",
		TriggerCats:         []string{"PostMessage", "JSHint", "go vet", "PyLint"},
		Dind:                false,
		Event:               DefaultEvent,
		Repo:                DefaultRepo,
		StayUp:              true,
		Tag:                 *dockerTag,
		// TODO(rsk): current e2e test can be run both with & without kythe.
		LocalKythe: false,
	}
	var allResponses rpcpb.ShipshapeResponse
	options.HandleResponse = func(shipshapeResp *rpcpb.ShipshapeResponse, _ string) error {
		allResponses.AnalyzeResponse = append(allResponses.AnalyzeResponse, shipshapeResp.AnalyzeResponse...)
		return nil
	}
	returnedNotesCount, err := New(options).Run()
	if err != nil {
		t.Fatal(err)
	}
	testName := "TestBuiltInAnalyzerPreBuild"

	if got, want := countFailures(allResponses), 0; got != want {
		t.Errorf("%v: Wrong number of failures; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if countedNotes := countNotes(allResponses); returnedNotesCount != countedNotes {
		t.Errorf("%v: Inconsistent note count: returned %v, counted %v (proto data: %v", testName, returnedNotesCount, countedNotes, allResponses)
	}
	if got, want := returnedNotesCount, 39; got != want {
		t.Errorf("%v: Wrong number of notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "PostMessage"), 2; got != want {
		t.Errorf("%v: Wrong number of PostMessage notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "JSHint"), 3; got != want {
		t.Errorf("%v: Wrong number of JSHint notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "go vet"), 1; got != want {
		t.Errorf("%v: Wrong number of go vet notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
	if got, want := countCategoryNotes(allResponses, "PyLint"), 33; got != want {
		t.Errorf("%v: Wrong number of PyLint notes; got %v, want %v (proto data: %v)", testName, got, want, allResponses)
	}
}

func TestBuiltInAnalyzersPostBuild(t *testing.T) {
	// Replaces part of the e2e test
	// Test with a kythe maven build
	// PostMessage and ErrorProne
}

func TestStreamsMode(t *testing.T) {
	// Test whether it works in streams mode
	// Before creating this, ensure that streams mode
	// is actually still something we need to support.
}

func TestChangingDirectories(t *testing.T) {
	// Replaces the changedir test
	// Make sure to test changing down, changing up, running on the same directory, running on a single file in the same directory, and changing to a sibling
}

func dumpLogs() {

}

func checkOutput(category string, numResults int) {

}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"syscall"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
	pkg_config "k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/console"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/machine"
)

// kubectlCmd represents the kubectl command
var kubectlCmd = &cobra.Command{
	Use:   "kubectl",
	Short: "Run kubectl",
	Long:  `Run the kubernetes client, download it if necessary.`,
	Run: func(cmd *cobra.Command, args []string) {
		api, err := machine.NewAPIClient()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error getting client: %v\n", err)
			os.Exit(1)
		}
		defer api.Close()

		cc, err := pkg_config.Load()
		if err != nil && !os.IsNotExist(err) {
			console.ErrLn("Error loading profile config: %v", err)
		}

		binary := "kubectl"
		if runtime.GOOS == "windows" {
			binary = "kubectl.exe"
		}

		version := constants.DefaultKubernetesVersion
		if cc != nil {
			version = cc.KubernetesConfig.KubernetesVersion
		}

		path, err := machine.CacheBinary(binary, version, runtime.GOOS, runtime.GOARCH)
		if err != nil {
			exit.WithError("Failed to download kubectl", err)
		}

		glog.Infof("Running %s %v", path, args)
		c := exec.Command(path, args...)
		c.Stdin = os.Stdin
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		if err := c.Run(); err != nil {
			var rc int
			if exitError, ok := err.(*exec.ExitError); ok {
				waitStatus := exitError.Sys().(syscall.WaitStatus)
				rc = waitStatus.ExitStatus()
			} else {
				fmt.Fprintf(os.Stderr, "Error running %s: %v\n", path, err)
				rc = 1
			}
			os.Exit(rc)
		}
	},
}

func init() {
	RootCmd.AddCommand(kubectlCmd)
}
<commit_msg>Add kubectl examples<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"syscall"

	"github.com/golang/glog"
	"github.com/spf13/cobra"
	pkg_config "k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/console"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/machine"
)

// kubectlCmd represents the kubectl command
var kubectlCmd = &cobra.Command{
	Use:   "kubectl",
	Short: "Run kubectl",
	Long: `Run the kubernetes client, download it if necessary.
Examples:
minikube kubectl -- --help
kubectl get pods --namespace kube-system`,
	Run: func(cmd *cobra.Command, args []string) {
		api, err := machine.NewAPIClient()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error getting client: %v\n", err)
			os.Exit(1)
		}
		defer api.Close()

		cc, err := pkg_config.Load()
		if err != nil && !os.IsNotExist(err) {
			console.ErrLn("Error loading profile config: %v", err)
		}

		binary := "kubectl"
		if runtime.GOOS == "windows" {
			binary = "kubectl.exe"
		}

		version := constants.DefaultKubernetesVersion
		if cc != nil {
			version = cc.KubernetesConfig.KubernetesVersion
		}

		path, err := machine.CacheBinary(binary, version, runtime.GOOS, runtime.GOARCH)
		if err != nil {
			exit.WithError("Failed to download kubectl", err)
		}

		glog.Infof("Running %s %v", path, args)
		c := exec.Command(path, args...)
		c.Stdin = os.Stdin
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		if err := c.Run(); err != nil {
			var rc int
			if exitError, ok := err.(*exec.ExitError); ok {
				waitStatus := exitError.Sys().(syscall.WaitStatus)
				rc = waitStatus.ExitStatus()
			} else {
				fmt.Fprintf(os.Stderr, "Error running %s: %v\n", path, err)
				rc = 1
			}
			os.Exit(rc)
		}
	},
}

func init() {
	RootCmd.AddCommand(kubectlCmd)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"fmt"
	"os"
	"strings"
	"text/template"

	"github.com/docker/machine/libmachine"
	"github.com/docker/machine/libmachine/state"
	"github.com/minishift/minishift/pkg/minikube/cluster"
	"github.com/minishift/minishift/pkg/minikube/constants"
	openshiftVersion "github.com/minishift/minishift/pkg/minishift/openshift/version"
	profileActions "github.com/minishift/minishift/pkg/minishift/profile"
	"github.com/minishift/minishift/pkg/util/os/atexit"
	"github.com/spf13/cobra"
)

var statusFormat = `Minishift:  {{.MinishiftStatus}}
Profile:    {{.ProfileName}}
OpenShift:  {{.ClusterStatus}}
DiskUsage:  {{.DiskUsage}}
`

type Status struct {
	MinishiftStatus string
	ProfileName     string
	ClusterStatus   string
	DiskUsage       string
}

// statusCmd represents the status command
var statusCmd = &cobra.Command{
	Use:   "status",
	Short: "Gets the status of the local OpenShift cluster.",
	Long:  `Gets the status of the local OpenShift cluster.`,
	Run:   runStatus,
}

func runStatus(cmd *cobra.Command, args []string) {
	api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
	defer api.Close()

	host, err := api.Load(constants.MachineName)
	if err != nil {
		s, err := cluster.GetHostStatus(api)
		if err != nil {
			atexit.ExitWithMessage(1, fmt.Sprintf("Error getting cluster status: %s", err.Error()))
		}
		atexit.ExitWithMessage(0, s)
	}

	openshiftStatus := "Stopped"
	diskUsage := "Unknown"
	profileName := profileActions.GetActiveProfile()

	vmStatus, err := cluster.GetHostStatus(api)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error getting cluster status: %s", err.Error()))
	}

	if vmStatus == state.Running.String() {
		openshiftVersion, err := openshiftVersion.GetOpenshiftVersion(host)
		if err == nil {
			openshiftStatus = fmt.Sprintf("Running (%s)", strings.Split(openshiftVersion, "\n")[0])
		}

		diskSize, diskUse := getDiskUsage(host.Driver, StorageDisk)
		diskUsage = fmt.Sprintf("%s of %s", diskUse, diskSize)
	}

	status := Status{vmStatus, profileName, openshiftStatus, diskUsage}

	tmpl, err := template.New("status").Parse(statusFormat)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error creating status template: %s", err.Error()))
	}
	err = tmpl.Execute(os.Stdout, status)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error executing status template:: %s", err.Error()))
	}
}

func init() {
	RootCmd.AddCommand(statusCmd)
}
<commit_msg>Issue #1524 Using constants.ProfileName to get the profile name<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"fmt"
	"os"
	"strings"
	"text/template"

	"github.com/docker/machine/libmachine"
	"github.com/docker/machine/libmachine/state"
	"github.com/minishift/minishift/pkg/minikube/cluster"
	"github.com/minishift/minishift/pkg/minikube/constants"
	openshiftVersion "github.com/minishift/minishift/pkg/minishift/openshift/version"
	"github.com/minishift/minishift/pkg/util/os/atexit"
	"github.com/spf13/cobra"
)

var statusFormat = `Minishift:  {{.MinishiftStatus}}
Profile:    {{.ProfileName}}
OpenShift:  {{.ClusterStatus}}
DiskUsage:  {{.DiskUsage}}
`

type Status struct {
	MinishiftStatus string
	ProfileName     string
	ClusterStatus   string
	DiskUsage       string
}

// statusCmd represents the status command
var statusCmd = &cobra.Command{
	Use:   "status",
	Short: "Gets the status of the local OpenShift cluster.",
	Long:  `Gets the status of the local OpenShift cluster.`,
	Run:   runStatus,
}

func runStatus(cmd *cobra.Command, args []string) {
	api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
	defer api.Close()

	host, err := api.Load(constants.MachineName)
	if err != nil {
		s, err := cluster.GetHostStatus(api)
		if err != nil {
			atexit.ExitWithMessage(1, fmt.Sprintf("Error getting cluster status: %s", err.Error()))
		}
		atexit.ExitWithMessage(0, s)
	}

	openshiftStatus := "Stopped"
	diskUsage := "Unknown"
	profileName := constants.ProfileName

	vmStatus, err := cluster.GetHostStatus(api)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error getting cluster status: %s", err.Error()))
	}

	if vmStatus == state.Running.String() {
		openshiftVersion, err := openshiftVersion.GetOpenshiftVersion(host)
		if err == nil {
			openshiftStatus = fmt.Sprintf("Running (%s)", strings.Split(openshiftVersion, "\n")[0])
		}

		diskSize, diskUse := getDiskUsage(host.Driver, StorageDisk)
		diskUsage = fmt.Sprintf("%s of %s", diskUse, diskSize)
	}

	status := Status{vmStatus, profileName, openshiftStatus, diskUsage}

	tmpl, err := template.New("status").Parse(statusFormat)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error creating status template: %s", err.Error()))
	}
	err = tmpl.Execute(os.Stdout, status)
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Error executing status template:: %s", err.Error()))
	}
}

func init() {
	RootCmd.AddCommand(statusCmd)
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2017 Red Hat, Inc.

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 cmd

import (
	"fmt"

	"github.com/minishift/minishift/pkg/minishift/update"
	"github.com/minishift/minishift/pkg/util/os/atexit"

	"encoding/json"
	cmdutil "github.com/minishift/minishift/cmd/minishift/cmd/util"
	"github.com/minishift/minishift/pkg/minikube/constants"
	"github.com/minishift/minishift/pkg/util"
	"github.com/minishift/minishift/pkg/version"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"path/filepath"
	"strings"
)

type UpdateMarker struct {
	InstallAddon    bool
	PreviousVersion string
}

const (
	addonForceFlag = "force"
)

var (
	addonForce bool
)

var updateCmd = &cobra.Command{
	Use:   "update",
	Short: "Updates Minishift to the latest version.",
	Long:  `Checks for the latest version of Minishift, prompts the user, and updates the binary if the user answers 'y'.`,
	Run:   runUpdate,
}

var (
	confirm string
)

func runUpdate(cmd *cobra.Command, args []string) {
	proxyConfig, err := util.NewProxyConfig(viper.GetString(cmdutil.HttpProxy), viper.GetString(cmdutil.HttpsProxy), "")
	if err != nil {
		atexit.ExitWithMessage(1, err.Error())
	}

	if proxyConfig.IsEnabled() {
		proxyConfig.ApplyToEnvironment()
	}

	localVersion, err := update.CurrentVersion()
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
	}

	latestVersion, err := update.LatestVersion()
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
	}

	if update.IsNewerVersion(localVersion, latestVersion) {
		if !addonForce {
			fmt.Printf("A newer version of minishift is available.\nDo you want to update from %s to %s now? [y/N]: ", localVersion, latestVersion)
			fmt.Scanln(&confirm)
		}

		if strings.ToLower(confirm) == "y" {
			err := update.Update(latestVersion)
			if err != nil {
				atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
			}

			fmt.Printf("\nUpdated successfully to Minishift version %s.\n", latestVersion)

			markerData := UpdateMarker{InstallAddon: false, PreviousVersion: version.GetMinishiftVersion()}

			fmt.Print("\nDo you want to update the default add-ons? [y/N]: ")
			fmt.Scanln(&confirm)

			if strings.ToLower(confirm) == "y" {
				markerData.InstallAddon = true
				fmt.Println("Default add-ons will be updated the next time you run any 'minishift' command.")
			}
			if err := createUpdateMarker(filepath.Join(constants.Minipath, constants.UpdateMarkerFileName), markerData); err != nil {
				atexit.ExitWithMessage(1, "Failed to create update marker file.")
			}

		}

	} else {
		fmt.Printf("Nothing to update.\nAlready using the latest version: %s.\n", latestVersion)
	}
}

func init() {
	RootCmd.AddCommand(updateCmd)
	updateCmd.Flags().AddFlag(cmdutil.HttpProxyFlag)
	updateCmd.Flags().AddFlag(cmdutil.HttpsProxyFlag)
	updateCmd.Flags().BoolVarP(&addonForce, addonForceFlag, "f", false, "Force update the add-ons after the binary update. Otherwise, prompt the user to update add-ons.")
}

func createUpdateMarker(markerPath string, data UpdateMarker) error {
	f, err := os.OpenFile(markerPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	defer f.Close()
	if err != nil {
		return err
	}

	b, err := json.Marshal(data)
	if err != nil {
		return err
	}

	f.Write(b)
	return nil
}
<commit_msg>Issue #1232 Add github and local file system location to review addon<commit_after>/*
Copyright (C) 2017 Red Hat, Inc.

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 cmd

import (
	"fmt"

	"github.com/minishift/minishift/pkg/minishift/update"
	"github.com/minishift/minishift/pkg/util/os/atexit"

	"encoding/json"
	cmdutil "github.com/minishift/minishift/cmd/minishift/cmd/util"
	"github.com/minishift/minishift/pkg/minikube/constants"
	"github.com/minishift/minishift/pkg/util"
	"github.com/minishift/minishift/pkg/version"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"path/filepath"
	"strings"
)

type UpdateMarker struct {
	InstallAddon    bool
	PreviousVersion string
}

const (
	addonForceFlag = "force"
)

var (
	addonForce bool
)

var updateCmd = &cobra.Command{
	Use:   "update",
	Short: "Updates Minishift to the latest version.",
	Long:  `Checks for the latest version of Minishift, prompts the user, and updates the binary if the user answers 'y'.`,
	Run:   runUpdate,
}

var (
	confirm string
)

func runUpdate(cmd *cobra.Command, args []string) {
	proxyConfig, err := util.NewProxyConfig(viper.GetString(cmdutil.HttpProxy), viper.GetString(cmdutil.HttpsProxy), "")
	if err != nil {
		atexit.ExitWithMessage(1, err.Error())
	}

	if proxyConfig.IsEnabled() {
		proxyConfig.ApplyToEnvironment()
	}

	localVersion, err := update.CurrentVersion()
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
	}

	latestVersion, err := update.LatestVersion()
	if err != nil {
		atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
	}

	if update.IsNewerVersion(localVersion, latestVersion) {
		if !addonForce {
			fmt.Printf("A newer version of minishift is available.\nDo you want to update from %s to %s now? [y/N]: ", localVersion, latestVersion)
			fmt.Scanln(&confirm)
		}

		if strings.ToLower(confirm) == "y" {
			err := update.Update(latestVersion)
			if err != nil {
				atexit.ExitWithMessage(1, fmt.Sprintf("Update failed: %s", err))
			}

			fmt.Printf("\nUpdated successfully to Minishift version %s.\n", latestVersion)

			markerData := UpdateMarker{InstallAddon: false, PreviousVersion: version.GetMinishiftVersion()}
			addonLocationForRelease := fmt.Sprintf("https://github.com/minishift/minishift/tree/v%s/addons", latestVersion)

			fmt.Printf("\nCurrent Installed add-ons are locally present at: %s\n", filepath.Join(constants.Minipath, "addons"))
			fmt.Printf("The add-ons for %s available at: %s\n", latestVersion, addonLocationForRelease)
			fmt.Printf("\nDo you want to update the default add-ons? [y/N]: ")
			fmt.Scanln(&confirm)

			if strings.ToLower(confirm) == "y" {
				markerData.InstallAddon = true
				fmt.Println("Default add-ons will be updated the next time you run any 'minishift' command.")
			}
			if err := createUpdateMarker(filepath.Join(constants.Minipath, constants.UpdateMarkerFileName), markerData); err != nil {
				atexit.ExitWithMessage(1, "Failed to create update marker file.")
			}

		}

	} else {
		fmt.Printf("Nothing to update.\nAlready using the latest version: %s.\n", latestVersion)
	}
}

func init() {
	RootCmd.AddCommand(updateCmd)
	updateCmd.Flags().AddFlag(cmdutil.HttpProxyFlag)
	updateCmd.Flags().AddFlag(cmdutil.HttpsProxyFlag)
	updateCmd.Flags().BoolVarP(&addonForce, addonForceFlag, "f", false, "Force update the add-ons after the binary update. Otherwise, prompt the user to update add-ons.")
}

func createUpdateMarker(markerPath string, data UpdateMarker) error {
	f, err := os.OpenFile(markerPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	defer f.Close()
	if err != nil {
		return err
	}

	b, err := json.Marshal(data)
	if err != nil {
		return err
	}

	f.Write(b)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/kkdai/youtube/v2"
	ytdl "github.com/kkdai/youtube/v2/downloader"
	"github.com/spf13/pflag"
	"golang.org/x/net/http/httpproxy"
)

var (
	insecureSkipVerify bool   // skip TLS server validation
	outputQuality      string // itag number or quality string
	mimetype           string // mimetype
	downloader         *ytdl.Downloader
)

func addQualityFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&outputQuality, "quality", "q", "medium", "The itag number or quality label (hd720, medium)")
}

func addMimeTypeFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&mimetype, "mimetype", "m", "mp4", "Mime-Type to filter (mp4, webm, av01, avc1) - applicable if --quality used is quality label")
}

func getDownloader() *ytdl.Downloader {
	if downloader != nil {
		return downloader
	}

	proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
	httpTransport := &http.Transport{
		// Proxy: http.ProxyFromEnvironment() does not work. Why?
		Proxy: func(r *http.Request) (uri *url.URL, err error) {
			return proxyFunc(r.URL)
		},
		IdleConnTimeout:       60 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		ForceAttemptHTTP2:     true,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
	}

	if insecureSkipVerify {
		log.Println("Skip server certificate verification")
		httpTransport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	downloader = &ytdl.Downloader{
		OutputDir: outputDir,
	}
	downloader.Client.Debug = verbose
	downloader.HTTPClient = &http.Client{Transport: httpTransport}

	return downloader
}

func getVideoWithFormat(id string) (*youtube.Video, *youtube.Format, error) {
	dl := getDownloader()
	video, err := dl.GetVideo(id)
	if err != nil {
		return nil, nil, err
	}
	formats := video.Formats
	if mimetype != "" {
		formats = formats.Type(mimetype)
	}
	if len(formats) == 0 {
		return nil, nil, errors.New("no formats found")
	}

	var format *youtube.Format
	itag, _ := strconv.Atoi(outputQuality)
	switch {
	case itag > 0:
		// When an itag is specified, do not filter format with mime-type
		format = video.Formats.WithAudioChannels().FindByItag(itag)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with itag %d", itag)
		}

	case outputQuality != "":
		format = formats.WithAudioChannels().FindByQuality(outputQuality)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with quality %s", outputQuality)
		}

	default:
		// select the first format
		formats.Sort()
		format = &formats[0]
	}

	return video, format, nil
}
<commit_msg>remove audio channel filter when using itag<commit_after>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/kkdai/youtube/v2"
	ytdl "github.com/kkdai/youtube/v2/downloader"
	"github.com/spf13/pflag"
	"golang.org/x/net/http/httpproxy"
)

var (
	insecureSkipVerify bool   // skip TLS server validation
	outputQuality      string // itag number or quality string
	mimetype           string // mimetype
	downloader         *ytdl.Downloader
)

func addQualityFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&outputQuality, "quality", "q", "medium", "The itag number or quality label (hd720, medium)")
}

func addMimeTypeFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&mimetype, "mimetype", "m", "mp4", "Mime-Type to filter (mp4, webm, av01, avc1) - applicable if --quality used is quality label")
}

func getDownloader() *ytdl.Downloader {
	if downloader != nil {
		return downloader
	}

	proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
	httpTransport := &http.Transport{
		// Proxy: http.ProxyFromEnvironment() does not work. Why?
		Proxy: func(r *http.Request) (uri *url.URL, err error) {
			return proxyFunc(r.URL)
		},
		IdleConnTimeout:       60 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		ForceAttemptHTTP2:     true,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
	}

	if insecureSkipVerify {
		log.Println("Skip server certificate verification")
		httpTransport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	downloader = &ytdl.Downloader{
		OutputDir: outputDir,
	}
	downloader.Client.Debug = verbose
	downloader.HTTPClient = &http.Client{Transport: httpTransport}

	return downloader
}

func getVideoWithFormat(id string) (*youtube.Video, *youtube.Format, error) {
	dl := getDownloader()
	video, err := dl.GetVideo(id)
	if err != nil {
		return nil, nil, err
	}
	formats := video.Formats
	if mimetype != "" {
		formats = formats.Type(mimetype)
	}
	if len(formats) == 0 {
		return nil, nil, errors.New("no formats found")
	}

	var format *youtube.Format
	itag, _ := strconv.Atoi(outputQuality)
	switch {
	case itag > 0:
		// When an itag is specified, do not filter format with mime-type
		format = video.Formats.FindByItag(itag)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with itag %d", itag)
		}

	case outputQuality != "":
		format = formats.WithAudioChannels().FindByQuality(outputQuality)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with quality %s", outputQuality)
		}

	default:
		// select the first format
		formats.Sort()
		format = &formats[0]
	}

	return video, format, nil
}
<|endoftext|>


<commit_before>package app

import (
	"net/http"

	"appengine/user"
	"github.com/GoogleCloudPlatform/go-endpoints/endpoints"
)

const (
	clientID = "***.apps.googleusercontent.com"
)

var (
	scopes    = []string{endpoints.EmailScope}
	clientIDs = []string{clientID, endpoints.APIExplorerClientID}
	audiences = []string{clientID}
)

func registerService() (
	rpcService *endpoints.RPCService,
	err error,
) {
	rpcService, err = endpoints.RegisterService(&API{},
		"api", "v1", "api", true)
	if err != nil {
		return
	}

	info := rpcService.MethodByName("Items").Info()
	info.Name, info.HTTPMethod, info.Path, info.Desc =
		"item.list", "GET", "items", "List items."
	info.Scopes, info.ClientIds, info.Audiences = scopes, clientIDs, audiences

	return
}

// API ...
type API struct {
}

// Items ...
func (api *API) Items(
	r *http.Request,
	req *ItemsRequestMessage,
	resp *ItemsResponseMessage,
) error {

	c := endpoints.NewContext(r)
	_, err := getCurrentUser(c)
	if err != nil {
		return err
	}

	return nil
}

func getCurrentUser(
	c endpoints.Context,
) (
	*user.User,
	error,
) {
	u, err := endpoints.CurrentUser(c, scopes, audiences, clientIDs)
	if err != nil {
		c.Infof("%v", err)
		return nil, endpoints.UnauthorizedError
	}
	if u == nil {
		return nil, endpoints.UnauthorizedError
	}
	return u, nil
}
<commit_msg>update log format<commit_after>package app

import (
	"net/http"

	"appengine/user"
	"github.com/GoogleCloudPlatform/go-endpoints/endpoints"
)

const (
	clientID = "***.apps.googleusercontent.com"
)

var (
	scopes    = []string{endpoints.EmailScope}
	clientIDs = []string{clientID, endpoints.APIExplorerClientID}
	audiences = []string{clientID}
)

func registerService() (
	rpcService *endpoints.RPCService,
	err error,
) {
	rpcService, err = endpoints.RegisterService(&API{},
		"api", "v1", "api", true)
	if err != nil {
		return
	}

	info := rpcService.MethodByName("Items").Info()
	info.Name, info.HTTPMethod, info.Path, info.Desc =
		"item.list", "GET", "items", "List items."
	info.Scopes, info.ClientIds, info.Audiences = scopes, clientIDs, audiences

	return
}

// API ...
type API struct {
}

// Items ...
func (api *API) Items(
	r *http.Request,
	req *ItemsRequestMessage,
	resp *ItemsResponseMessage,
) error {

	c := endpoints.NewContext(r)
	_, err := getCurrentUser(c)
	if err != nil {
		return err
	}

	return nil
}

func getCurrentUser(
	c endpoints.Context,
) (
	*user.User,
	error,
) {
	u, err := endpoints.CurrentUser(c, scopes, audiences, clientIDs)
	if err != nil {
		c.Infof("%q", err)
		return nil, endpoints.UnauthorizedError
	}
	if u == nil {
		return nil, endpoints.UnauthorizedError
	}
	return u, nil
}
<|endoftext|>


<commit_before>package base58

import (
	"encoding/hex"
	"reflect"
	"testing"
)

type encodeTestCase struct {
	in  string
	out string
	err error
}

type decodeTestCase struct {
	in  string
	out string
	err error
}

var (
	encodeTestCasesBitcoin = []encodeTestCase{
		{"", "", nil},
		{"00", "1", nil},
		{"00010966776006953d5567439e5e39f86a0d273beed61967f6", "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", nil},
	}
	decodeTestCasesBitcoin = []decodeTestCase{
		{"", "", nil},
		{"0", "", ErrInvalidChar},
		{"1", "00", nil},
		{"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", "00010966776006953d5567439e5e39f86a0d273beed61967f6", nil},
	}
)

func TestEncodeToString(t *testing.T) {
	for _, testCase := range encodeTestCasesBitcoin {
		inBytes, err := hex.DecodeString(testCase.in)
		if err != nil {
			t.Fatal("can not decode input string")
		}

		b58 := NewBitcoinBase58()

		out, err := b58.EncodeToString(inBytes)
		if !reflect.DeepEqual(err, testCase.err) {
			t.Errorf(`
invalid error
- got: %v
- expected: %v
`, err, testCase.err)
		}
		if out != testCase.out {
			t.Errorf(`
invalid encoding
- got: %s
- expected: %s
`, out, testCase.out)
		}
	}
}

func TestDecodeString(t *testing.T) {
	for _, testCase := range decodeTestCasesBitcoin {
		b58 := NewBitcoinBase58()

		outBytes, err := b58.DecodeString(testCase.in)
		if !reflect.DeepEqual(err, testCase.err) {
			t.Errorf(`
invalid error
- got: %v
- expected: %v
`, err, testCase.err)
		}

		out := hex.EncodeToString(outBytes)
		if out != testCase.out {
			t.Errorf(`
invalid decoding
- got: %s
- expected: %s
`, out, testCase.out)
		}
	}
}
<commit_msg>refactor tests<commit_after>package base58

import (
	"encoding/hex"
	"testing"
)

func TestEncodeToString(t *testing.T) {
	testCases := []struct {
		in  string
		out string
		err error
	}{
		{
			"",
			"",
			nil,
		},
		{
			"00",
			"1",
			nil,
		},
		{
			"00010966776006953d5567439e5e39f86a0d273beed61967f6",
			"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
			nil,
		},
	}

	b58 := NewBitcoinBase58()

	for _, tc := range testCases {
		t.Run(tc.in, func(t *testing.T) {
			inBytes, err := hex.DecodeString(tc.in)
			if err != nil {
				t.Fatal("can not decode input string")
			}

			out, err := b58.EncodeToString(inBytes)
			if err != tc.err {
				t.Errorf("expected: %v, actual: %v", tc.err, err)
			}
			if out != tc.out {
				t.Errorf("expected: %s, actual: %s", tc.out, out)
			}
		})
	}
}

func TestDecodeString(t *testing.T) {
	testCases := []struct {
		in  string
		out string
		err error
	}{
		{
			"",
			"",
			nil,
		},
		{
			"1",
			"00",
			nil,
		},
		{
			"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
			"00010966776006953d5567439e5e39f86a0d273beed61967f6",
			nil,
		},
		{
			"0",
			"",
			ErrInvalidChar,
		},
	}

	b58 := NewBitcoinBase58()

	for _, tc := range testCases {
		t.Run(tc.in, func(t *testing.T) {
			outBytes, err := b58.DecodeString(tc.in)
			if err != tc.err {
				t.Errorf("expected: %v, actual: %v", tc.err, err)
			}

			out := hex.EncodeToString(outBytes)
			if out != tc.out {
				t.Errorf("expected: %s, actual: %s", tc.out, out)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

const endpoint = "https://hooks.slack.com/services/"
<commit_msg>Delete unused file<commit_after><|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"github.com/gojp/kana"
	"github.com/gojp/nihongo/app/helpers"
	"github.com/gojp/nihongo/app/models"
	"github.com/gojp/nihongo/app/routes"
	"github.com/jgraham909/revmgo"
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"regexp"
	"strings"
)

type App struct {
	*revel.Controller
	revmgo.MongoController
}

type Word struct {
	*models.Word
}

// wrap a string in strong tags
func makeStrong(query string) string {
	return "" + query + ""
}

// convert the query to hiragana and katakana. if it's already in
// hiragana or katakana, it will just be the same.
func convertQueryToKana(query string) (hiragana, katakana string) {
	kana := kana.NewKana()
	h := kana.RomajiToHiragana(query)
	k := kana.RomajiToKatakana(query)
	return h, k
}

// Wrap the query in  tags so that we can highlight it in the results
func highlightQuery(w Word, query string) {
	// make regular expression that matches the original query
	re := regexp.MustCompile(`\b` + regexp.QuoteMeta(query) + `\b`)
	// convert original query to kana
	h, k := convertQueryToKana(query)
	// wrap the query in strong tags
	queryHighlighted := makeStrong(query)
	hiraganaHighlighted := makeStrong(h)
	katakanaHighlighted := makeStrong(k)

	// if the original input is Japanese, then the original input converted
	// to hiragana and katakana will be equal, so just choose one
	// to highlight so that we only end up with one pair of strong tags
	if hiraganaHighlighted == katakanaHighlighted {
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
	} else {
		// The original input is romaji, so we convert it to hiragana and katakana
		// and highlight both.
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
		w.Japanese = strings.Replace(w.Japanese, k, katakanaHighlighted, -1)
	}

	// highlight the furigana too, same as above
	w.Furigana = strings.Replace(w.Furigana, h, hiraganaHighlighted, -1)
	w.Furigana = strings.Replace(w.Furigana, k, katakanaHighlighted, -1)
	// highlight the query inside the list of English definitions
	for i, e := range w.English {
		e = re.ReplaceAllString(e, queryHighlighted)
		w.English[i] = e
	}
}

func getWordList(hits [][]byte, query string) (wordList []Word) {
	// highlight queries and build Word object
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			log.Println(err)
		}
		w.MainEntry = w.Japanese
		highlightQuery(w, query)
		wordList = append(wordList, w)
	}
	return wordList
}

func (a App) Search(query string) revel.Result {
	if len(query) == 0 {
		return a.Redirect(routes.App.Index())
	}
	hits := helpers.Search(query)
	wordList := getWordList(hits, query)
	return a.Render(wordList)
}

func (c App) Details(query string) revel.Result {
	if len(query) == 0 {
		return c.Redirect(routes.App.Index())
	}
	if strings.Contains(query, " ") {
		return c.Redirect(routes.App.Details(strings.Replace(query, " ", "-", -1)))
	}
	// Copy the query so that we maintain the dashes
	// when inserting into MongoDB
	mongoTerm := query
	query = strings.Replace(query, "-", " ", -1)
	hits := helpers.Search(query)
	wordList := getWordList(hits, query)
	pageTitle := query + " in Japanese"

	// log this call in mongo
	collection := c.MongoSession.DB("greenbook").C("hits")
	_, err := collection.Upsert(bson.M{"term": mongoTerm}, bson.M{"$inc": bson.M{"count": 1}})
	if err != nil {
		log.Println("DEBUG: mongo failed to upsert count: " + err.Error())
		// mongo failed to log, but who cares
	}

	index := mgo.Index{
		Key:        []string{"count"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}
	collection.EnsureIndex(index)

	return c.Render(wordList, query, pageTitle)
}

func (c App) SearchGet() revel.Result {
	if query, ok := c.Params.Values["q"]; ok && len(query) > 0 {
		return c.Redirect(routes.App.Details(query[0]))
	}
	return c.Redirect(routes.App.Index())
}

func (c App) About() revel.Result {
	return c.Render()
}

func (c App) Index() revel.Result {

	// get the popular searches
	collection := c.MongoSession.DB("greenbook").C("hits")
	q := collection.Find(nil).Sort("-count")

	termList := []models.SearchTerm{}
	iter := q.Limit(10).Iter()
	iter.All(&termList)

	return c.Render(termList)
}
<commit_msg>Fix hyphens highlighting and change url for spaces to underscore<commit_after>package controllers

import (
	"encoding/json"
	"github.com/gojp/kana"
	"github.com/gojp/nihongo/app/helpers"
	"github.com/gojp/nihongo/app/models"
	"github.com/gojp/nihongo/app/routes"
	"github.com/jgraham909/revmgo"
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"log"
	"regexp"
	"strings"
)

type App struct {
	*revel.Controller
	revmgo.MongoController
}

type Word struct {
	*models.Word
}

// wrap a string in strong tags
func makeStrong(query string) string {
	return "" + query + ""
}

// convert the query to hiragana and katakana. if it's already in
// hiragana or katakana, it will just be the same.
func convertQueryToKana(query string) (hiragana, katakana string) {
	kana := kana.NewKana()
	h := kana.RomajiToHiragana(query)
	k := kana.RomajiToKatakana(query)
	return h, k
}

// Wrap the query in  tags so that we can highlight it in the results
func highlightQuery(w Word, query string) {
	// make regular expression that matches the original query
	re := regexp.MustCompile(`\b` + regexp.QuoteMeta(query) + `\b`)
	// convert original query to kana
	h, k := convertQueryToKana(query)
	// wrap the query in strong tags
	queryHighlighted := makeStrong(query)
	hiraganaHighlighted := makeStrong(h)
	katakanaHighlighted := makeStrong(k)

	// if the original input is Japanese, then the original input converted
	// to hiragana and katakana will be equal, so just choose one
	// to highlight so that we only end up with one pair of strong tags
	if hiraganaHighlighted == katakanaHighlighted {
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
	} else {
		// The original input is romaji, so we convert it to hiragana and katakana
		// and highlight both.
		w.Japanese = strings.Replace(w.Japanese, h, hiraganaHighlighted, -1)
		w.Japanese = strings.Replace(w.Japanese, k, katakanaHighlighted, -1)
	}

	// highlight the furigana too, same as above
	w.Furigana = strings.Replace(w.Furigana, h, hiraganaHighlighted, -1)
	w.Furigana = strings.Replace(w.Furigana, k, katakanaHighlighted, -1)
	// highlight the query inside the list of English definitions
	for i, e := range w.English {
		e = re.ReplaceAllString(e, queryHighlighted)
		w.English[i] = e
	}
}

func getWordList(hits [][]byte, query string) (wordList []Word) {
	// highlight queries and build Word object
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			log.Println(err)
		}
		w.MainEntry = w.Japanese
		highlightQuery(w, query)
		wordList = append(wordList, w)
	}
	return wordList
}

func (a App) Search(query string) revel.Result {
	if len(query) == 0 {
		return a.Redirect(routes.App.Index())
	}
	hits := helpers.Search(query)
	wordList := getWordList(hits, query)
	return a.Render(wordList)
}

func (c App) Details(query string) revel.Result {
	if len(query) == 0 {
		return c.Redirect(routes.App.Index())
	}
	if strings.Contains(query, " ") {
		return c.Redirect(routes.App.Details(strings.Replace(query, " ", "_", -1)))
	}
	// Copy the query so that we maintain the dashes
	// when inserting into MongoDB
	mongoTerm := query
	query = strings.Replace(query, "_", " ", -1)
	hits := helpers.Search(query)
	wordList := getWordList(hits, query)
	pageTitle := query + " in Japanese"

	// log this call in mongo
	collection := c.MongoSession.DB("greenbook").C("hits")
	_, err := collection.Upsert(bson.M{"term": mongoTerm}, bson.M{"$inc": bson.M{"count": 1}})
	if err != nil {
		log.Println("DEBUG: mongo failed to upsert count: " + err.Error())
		// mongo failed to log, but who cares
	}

	index := mgo.Index{
		Key:        []string{"count"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}
	collection.EnsureIndex(index)

	return c.Render(wordList, query, pageTitle)
}

func (c App) SearchGet() revel.Result {
	if query, ok := c.Params.Values["q"]; ok && len(query) > 0 {
		return c.Redirect(routes.App.Details(query[0]))
	}
	return c.Redirect(routes.App.Index())
}

func (c App) About() revel.Result {
	return c.Render()
}

func (c App) Index() revel.Result {

	// get the popular searches
	collection := c.MongoSession.DB("greenbook").C("hits")
	q := collection.Find(nil).Sort("-count")

	termList := []models.SearchTerm{}
	iter := q.Limit(10).Iter()
	iter.All(&termList)

	return c.Render(termList)
}
<|endoftext|>


<commit_before>package clients

import (
	"errors"
	"strconv"
	"strings"
	"time"

	"net/http"

	"fmt"

	log "github.com/branch-app/log-go"
	"github.com/branch-app/service-xboxlive/helpers"
	"github.com/branch-app/service-xboxlive/models"
	"github.com/branch-app/service-xboxlive/models/xboxlive"
	sharedClients "github.com/branch-app/shared-go/clients"
	sharedModels "github.com/branch-app/shared-go/models"
	"github.com/branch-app/shared-go/types"
	"gopkg.in/robfig/cron.v2"
)

type XboxLiveClient struct {
	httpClient    *sharedClients.HTTPClient
	serviceClient *sharedClients.ServiceClient
	xblStore      *helpers.XboxLiveStore
	mongoClient   *sharedClients.MongoDBClient

	authentication *models.XboxLiveAuthentication
	cron           *cron.Cron
}

const (
	ErrorUnableToAuthenticateWithXbl = "unable_to_authenticate_with_xboxlive"
	ErrorIdentityDoesntExist         = "identity_doesnt_exist"
	ErrorInternalAuthDown            = "internal_auth_down"
	ErrorUnknown                     = "unknown_error"

	authorizationHeaderFormat = "XBL3.0 x=%s;%s"
)

func (client *XboxLiveClient) GetAuthentication() (*models.XboxLiveAuthentication, error) {
	if client.authentication != nil && client.authentication.ExpiresAt.After(time.Now().UTC()) {
		return client.authentication, nil
	}

	auth, err := client.UpdateAuthentication()
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}
	return auth, nil
}

func (client *XboxLiveClient) UpdateAuthentication() (*models.XboxLiveAuthentication, error) {
	var accountResp models.XboxLiveAuthResponse
	_, err := client.serviceClient.Get("service-auth", "/xbox-live", &accountResp)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	xblAuthenticationRequest := &models.XboxLiveAuthenticationRequest{
		Properties: &models.XboxLiveAuthenticationPropertiesRequest{
			AuthMethod: "RPS",
			RpsTicket:  fmt.Sprintf("t=%s", accountResp.AccessToken),
			SiteName:   "user.auth.xboxlive.com",
		},
		RelyingParty: "http://auth.xboxlive.com",
		TokenType:    "JWT",
	}
	var xblAuthenticationResponse models.XboxLiveAuthenticationResponse
	_, err = client.ExecuteRequest("POST", "https://user.auth.xboxlive.com/user/authenticate", nil, 0, xblAuthenticationRequest, &xblAuthenticationResponse)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	xblAuthorizationRequest := &models.XboxLiveAuthorizationRequest{
		Properties: &models.XboxLiveAuthorizationPropertiesRequest{
			SandboxID:  "RETAIL",
			UserTokens: []string{xblAuthenticationResponse.Token},
		},
		RelyingParty: "http://xboxlive.com",
		TokenType:    "JWT",
	}
	var xblAuthorizationResponse models.XboxLiveAuthorizationResponse
	_, err = client.ExecuteRequest("POST", "https://xsts.auth.xboxlive.com/xsts/authorize", nil, 0, xblAuthorizationRequest, &xblAuthorizationResponse)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	gamertag := xblAuthorizationResponse.DisplayClaims["xui"][0]["gtg"]
	userHash := xblAuthorizationResponse.DisplayClaims["xui"][0]["uhs"]
	xuid := xblAuthorizationResponse.DisplayClaims["xui"][0]["xid"]
	authentication := &models.XboxLiveAuthentication{
		ExpiresAt: time.Now().UTC().Add(55 * time.Minute),
		Identity:  sharedModels.NewXboxLiveIdentity(gamertag, xuid, time.Now().UTC()),
		Token:     xblAuthorizationResponse.Token,
		UserHash:  userHash,
	}

	client.authentication = authentication
	fmt.Println(client.authentication)
	return client.authentication, nil
}

func (client *XboxLiveClient) ExecuteRequest(method, endpoint string, auth *models.XboxLiveAuthentication, contractVersion int, body, respBody interface{}) (*http.Response, error) {
	headers := map[string]string{
		"x-xbl-contract-version": strconv.Itoa(contractVersion),
	}

	if auth != nil {
		headers["Authorization"] = fmt.Sprintf(authorizationHeaderFormat, auth.UserHash, auth.Token)
	}

	resp, err := client.httpClient.ExecuteRequest(method, endpoint, &headers, nil, body)
	if err != nil {
		if resp != nil && strings.Contains(resp.Header.Get("Content-Type"), sharedClients.ContentTypeJSON) {
			if err := sharedClients.UnmarshalJSON(resp.Body, &respBody); err != nil {
				return nil, err
			}

			return resp, err
		}
		return nil, err
	}

	err = sharedClients.UnmarshalJSON(resp.Body, &respBody)
	return resp, err
}

func (client *XboxLiveClient) ErrorToHTTPStatus(err error) int {
	switch err.Error() {
	case ErrorIdentityDoesntExist:
		return http.StatusNotFound

	case ErrorUnknown:
	default:
		return http.StatusInternalServerError
	}

	return http.StatusInternalServerError
}

func (client *XboxLiveClient) handleError(response interface{}, err error) error {
	if response != nil {
		var resp *xboxlive.Response
		resp, ok := response.(*xboxlive.Response)
		if ok {
			switch resp.Code {
			case xboxlive.ResponseUserDoesntExist:
				return errors.New(ErrorIdentityDoesntExist)
			}
		}
	}

	if err.Error() == ErrorUnableToAuthenticateWithXbl {
		return errors.New(ErrorInternalAuthDown)
	}

	// unknown_error
	return errors.New(ErrorUnknown)
}

func NewXboxLiveClient(env types.Environment, config *models.Configuration) *XboxLiveClient {
	client := &XboxLiveClient{
		httpClient:    sharedClients.NewHTTPClient(),
		serviceClient: sharedClients.NewServiceClient(env),
		xblStore:      helpers.NewXboxLiveStore(),
		mongoClient:   sharedClients.NewMongoDBClient(config.MongoConnectionString, config.MongoDatabaseName),
		cron:          cron.New(),
	}

	// Setup cron jobs
	client.cron.AddFunc("@every 45m", func() { client.UpdateAuthentication() })

	// Update authentication in the background
	go client.UpdateAuthentication()

	return client
}
<commit_msg>Would probably help if I actually started the cron jobs<commit_after>package clients

import (
	"errors"
	"strconv"
	"strings"
	"time"

	"net/http"

	"fmt"

	log "github.com/branch-app/log-go"
	"github.com/branch-app/service-xboxlive/helpers"
	"github.com/branch-app/service-xboxlive/models"
	"github.com/branch-app/service-xboxlive/models/xboxlive"
	sharedClients "github.com/branch-app/shared-go/clients"
	sharedModels "github.com/branch-app/shared-go/models"
	"github.com/branch-app/shared-go/types"
	"gopkg.in/robfig/cron.v2"
)

type XboxLiveClient struct {
	httpClient    *sharedClients.HTTPClient
	serviceClient *sharedClients.ServiceClient
	xblStore      *helpers.XboxLiveStore
	mongoClient   *sharedClients.MongoDBClient

	authentication *models.XboxLiveAuthentication
	cron           *cron.Cron
}

const (
	ErrorUnableToAuthenticateWithXbl = "unable_to_authenticate_with_xboxlive"
	ErrorIdentityDoesntExist         = "identity_doesnt_exist"
	ErrorInternalAuthDown            = "internal_auth_down"
	ErrorUnknown                     = "unknown_error"

	authorizationHeaderFormat = "XBL3.0 x=%s;%s"
)

func (client *XboxLiveClient) GetAuthentication() (*models.XboxLiveAuthentication, error) {
	if client.authentication != nil && client.authentication.ExpiresAt.After(time.Now().UTC()) {
		return client.authentication, nil
	}

	auth, err := client.UpdateAuthentication()
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}
	return auth, nil
}

func (client *XboxLiveClient) UpdateAuthentication() (*models.XboxLiveAuthentication, error) {
	var accountResp models.XboxLiveAuthResponse
	_, err := client.serviceClient.Get("service-auth", "/xbox-live", &accountResp)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	xblAuthenticationRequest := &models.XboxLiveAuthenticationRequest{
		Properties: &models.XboxLiveAuthenticationPropertiesRequest{
			AuthMethod: "RPS",
			RpsTicket:  fmt.Sprintf("t=%s", accountResp.AccessToken),
			SiteName:   "user.auth.xboxlive.com",
		},
		RelyingParty: "http://auth.xboxlive.com",
		TokenType:    "JWT",
	}
	var xblAuthenticationResponse models.XboxLiveAuthenticationResponse
	_, err = client.ExecuteRequest("POST", "https://user.auth.xboxlive.com/user/authenticate", nil, 0, xblAuthenticationRequest, &xblAuthenticationResponse)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	xblAuthorizationRequest := &models.XboxLiveAuthorizationRequest{
		Properties: &models.XboxLiveAuthorizationPropertiesRequest{
			SandboxID:  "RETAIL",
			UserTokens: []string{xblAuthenticationResponse.Token},
		},
		RelyingParty: "http://xboxlive.com",
		TokenType:    "JWT",
	}
	var xblAuthorizationResponse models.XboxLiveAuthorizationResponse
	_, err = client.ExecuteRequest("POST", "https://xsts.auth.xboxlive.com/xsts/authorize", nil, 0, xblAuthorizationRequest, &xblAuthorizationResponse)
	if err != nil {
		return nil, log.Error(ErrorUnableToAuthenticateWithXbl, &log.M{"error": err}, nil).ToError()
	}

	gamertag := xblAuthorizationResponse.DisplayClaims["xui"][0]["gtg"]
	userHash := xblAuthorizationResponse.DisplayClaims["xui"][0]["uhs"]
	xuid := xblAuthorizationResponse.DisplayClaims["xui"][0]["xid"]
	authentication := &models.XboxLiveAuthentication{
		ExpiresAt: time.Now().UTC().Add(55 * time.Minute),
		Identity:  sharedModels.NewXboxLiveIdentity(gamertag, xuid, time.Now().UTC()),
		Token:     xblAuthorizationResponse.Token,
		UserHash:  userHash,
	}

	client.authentication = authentication
	fmt.Println(client.authentication)
	return client.authentication, nil
}

func (client *XboxLiveClient) ExecuteRequest(method, endpoint string, auth *models.XboxLiveAuthentication, contractVersion int, body, respBody interface{}) (*http.Response, error) {
	headers := map[string]string{
		"x-xbl-contract-version": strconv.Itoa(contractVersion),
	}

	if auth != nil {
		headers["Authorization"] = fmt.Sprintf(authorizationHeaderFormat, auth.UserHash, auth.Token)
	}

	resp, err := client.httpClient.ExecuteRequest(method, endpoint, &headers, nil, body)
	if err != nil {
		if resp != nil && strings.Contains(resp.Header.Get("Content-Type"), sharedClients.ContentTypeJSON) {
			if err := sharedClients.UnmarshalJSON(resp.Body, &respBody); err != nil {
				return nil, err
			}

			return resp, err
		}
		return nil, err
	}

	err = sharedClients.UnmarshalJSON(resp.Body, &respBody)
	return resp, err
}

func (client *XboxLiveClient) ErrorToHTTPStatus(err error) int {
	switch err.Error() {
	case ErrorIdentityDoesntExist:
		return http.StatusNotFound

	case ErrorUnknown:
	default:
		return http.StatusInternalServerError
	}

	return http.StatusInternalServerError
}

func (client *XboxLiveClient) handleError(response interface{}, err error) error {
	if response != nil {
		var resp *xboxlive.Response
		resp, ok := response.(*xboxlive.Response)
		if ok {
			switch resp.Code {
			case xboxlive.ResponseUserDoesntExist:
				return errors.New(ErrorIdentityDoesntExist)
			}
		}
	}

	if err.Error() == ErrorUnableToAuthenticateWithXbl {
		return errors.New(ErrorInternalAuthDown)
	}

	// unknown_error
	return errors.New(ErrorUnknown)
}

func NewXboxLiveClient(env types.Environment, config *models.Configuration) *XboxLiveClient {
	client := &XboxLiveClient{
		httpClient:    sharedClients.NewHTTPClient(),
		serviceClient: sharedClients.NewServiceClient(env),
		xblStore:      helpers.NewXboxLiveStore(),
		mongoClient:   sharedClients.NewMongoDBClient(config.MongoConnectionString, config.MongoDatabaseName),
		cron:          cron.New(),
	}

	// Setup cron jobs
	client.cron.AddFunc("@every 45m", func() { client.UpdateAuthentication() })
	client.cron.Start()

	// Update authentication in the background
	go client.UpdateAuthentication()

	return client
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"strings"

	"github.com/hashicorp/nomad/api/contexts"
	"github.com/posener/complete"
)

type NodeEligibilityCommand struct {
	Meta
}

func (c *NodeEligibilityCommand) Help() string {
	helpText := `
Usage: nomad node eligibility [options] <node>

  Toggles the nodes scheduling eligibility. When a node is marked as ineligible,
  no new allocations will be placed on it but existing allocations will remain.
  To remove existing allocations, use the node drain command.

  It is required that either -enable or -disable is specified, but not both.
  The -self flag is useful to set the scheduling eligibility of the local node.

General Options:

  ` + generalOptionsUsage() + `

Node Eligibility Options:

  -disable
    Mark the specified node as ineligible for new allocations.

  -enable
    Mark the specified node as eligible for new allocations.

  -self
    Set the eligibility of the local node.
`
	return strings.TrimSpace(helpText)
}

func (c *NodeEligibilityCommand) Synopsis() string {
	return "Toggle scheduling eligibility for a given node"
}

func (c *NodeEligibilityCommand) AutocompleteFlags() complete.Flags {
	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
		complete.Flags{
			"-disable": complete.PredictNothing,
			"-enable":  complete.PredictNothing,
			"-self":    complete.PredictNothing,
		})
}

func (c *NodeEligibilityCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictFunc(func(a complete.Args) []string {
		client, err := c.Meta.Client()
		if err != nil {
			return nil
		}

		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Nodes, nil)
		if err != nil {
			return []string{}
		}
		return resp.Matches[contexts.Nodes]
	})
}

func (c *NodeEligibilityCommand) Name() string { return "node-eligibility" }

func (c *NodeEligibilityCommand) Run(args []string) int {
	var enable, disable, self bool

	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
	flags.Usage = func() { c.Ui.Output(c.Help()) }
	flags.BoolVar(&enable, "enable", false, "Mark node as eligibile for scheduling")
	flags.BoolVar(&disable, "disable", false, "Mark node as ineligibile for scheduling")
	flags.BoolVar(&self, "self", false, "")

	if err := flags.Parse(args); err != nil {
		return 1
	}

	// Check that we got either enable or disable, but not both.
	if (enable && disable) || (!enable && !disable) {
		c.Ui.Error("Either the '-enable' or '-disable' flag must be set")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	// Check that we got a node ID
	args = flags.Args()
	if l := len(args); self && l != 0 || !self && l != 1 {
		c.Ui.Error("Node ID must be specified if -self isn't being used")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	// Get the HTTP client
	client, err := c.Meta.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
		return 1
	}

	// If -self flag is set then determine the current node.
	var nodeID string
	if !self {
		nodeID = args[0]
	} else {
		var err error
		if nodeID, err = getLocalNodeID(client); err != nil {
			c.Ui.Error(err.Error())
			return 1
		}
	}

	// Check if node exists
	if len(nodeID) == 1 {
		c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
		return 1
	}

	nodeID = sanitizeUUIDPrefix(nodeID)
	nodes, _, err := client.Nodes().PrefixList(nodeID)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}
	// Return error if no nodes are found
	if len(nodes) == 0 {
		c.Ui.Error(fmt.Sprintf("No node(s) with prefix or id %q found", nodeID))
		return 1
	}
	if len(nodes) > 1 {
		c.Ui.Error(fmt.Sprintf("Prefix matched multiple nodes\n\n%s",
			formatNodeStubList(nodes, true)))
		return 1
	}

	// Prefix lookup matched a single node
	node, _, err := client.Nodes().Info(nodes[0].ID, nil)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}

	// Toggle node eligibility
	if _, err := client.Nodes().ToggleEligibility(node.ID, enable, nil); err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}

	if enable {
		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: eligible for scheduling", node.ID))
	} else {
		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: ineligible for scheduling", node.ID))
	}
	return 0
}
<commit_msg>Fix cmd.Name() for NodeEligibilityCommand<commit_after>package command

import (
	"fmt"
	"strings"

	"github.com/hashicorp/nomad/api/contexts"
	"github.com/posener/complete"
)

type NodeEligibilityCommand struct {
	Meta
}

func (c *NodeEligibilityCommand) Help() string {
	helpText := `
Usage: nomad node eligibility [options] <node>

  Toggles the nodes scheduling eligibility. When a node is marked as ineligible,
  no new allocations will be placed on it but existing allocations will remain.
  To remove existing allocations, use the node drain command.

  It is required that either -enable or -disable is specified, but not both.
  The -self flag is useful to set the scheduling eligibility of the local node.

General Options:

  ` + generalOptionsUsage() + `

Node Eligibility Options:

  -disable
    Mark the specified node as ineligible for new allocations.

  -enable
    Mark the specified node as eligible for new allocations.

  -self
    Set the eligibility of the local node.
`
	return strings.TrimSpace(helpText)
}

func (c *NodeEligibilityCommand) Synopsis() string {
	return "Toggle scheduling eligibility for a given node"
}

func (c *NodeEligibilityCommand) AutocompleteFlags() complete.Flags {
	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
		complete.Flags{
			"-disable": complete.PredictNothing,
			"-enable":  complete.PredictNothing,
			"-self":    complete.PredictNothing,
		})
}

func (c *NodeEligibilityCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictFunc(func(a complete.Args) []string {
		client, err := c.Meta.Client()
		if err != nil {
			return nil
		}

		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Nodes, nil)
		if err != nil {
			return []string{}
		}
		return resp.Matches[contexts.Nodes]
	})
}

func (c *NodeEligibilityCommand) Name() string { return "node eligibility" }

func (c *NodeEligibilityCommand) Run(args []string) int {
	var enable, disable, self bool

	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
	flags.Usage = func() { c.Ui.Output(c.Help()) }
	flags.BoolVar(&enable, "enable", false, "Mark node as eligibile for scheduling")
	flags.BoolVar(&disable, "disable", false, "Mark node as ineligibile for scheduling")
	flags.BoolVar(&self, "self", false, "")

	if err := flags.Parse(args); err != nil {
		return 1
	}

	// Check that we got either enable or disable, but not both.
	if (enable && disable) || (!enable && !disable) {
		c.Ui.Error("Either the '-enable' or '-disable' flag must be set")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	// Check that we got a node ID
	args = flags.Args()
	if l := len(args); self && l != 0 || !self && l != 1 {
		c.Ui.Error("Node ID must be specified if -self isn't being used")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	// Get the HTTP client
	client, err := c.Meta.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
		return 1
	}

	// If -self flag is set then determine the current node.
	var nodeID string
	if !self {
		nodeID = args[0]
	} else {
		var err error
		if nodeID, err = getLocalNodeID(client); err != nil {
			c.Ui.Error(err.Error())
			return 1
		}
	}

	// Check if node exists
	if len(nodeID) == 1 {
		c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
		return 1
	}

	nodeID = sanitizeUUIDPrefix(nodeID)
	nodes, _, err := client.Nodes().PrefixList(nodeID)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}
	// Return error if no nodes are found
	if len(nodes) == 0 {
		c.Ui.Error(fmt.Sprintf("No node(s) with prefix or id %q found", nodeID))
		return 1
	}
	if len(nodes) > 1 {
		c.Ui.Error(fmt.Sprintf("Prefix matched multiple nodes\n\n%s",
			formatNodeStubList(nodes, true)))
		return 1
	}

	// Prefix lookup matched a single node
	node, _, err := client.Nodes().Info(nodes[0].ID, nil)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}

	// Toggle node eligibility
	if _, err := client.Nodes().ToggleEligibility(node.ID, enable, nil); err != nil {
		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
		return 1
	}

	if enable {
		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: eligible for scheduling", node.ID))
	} else {
		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: ineligible for scheduling", node.ID))
	}
	return 0
}
<|endoftext|>


<commit_before>package v2

import (
	"fmt"
	"os"
	"strings"

	"code.cloudfoundry.org/cli/actor/sharedaction"
	"code.cloudfoundry.org/cli/actor/v2action"
	"code.cloudfoundry.org/cli/actor/v3action"
	oldCmd "code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
	"code.cloudfoundry.org/cli/command/v2/shared"
	sharedV3 "code.cloudfoundry.org/cli/command/v3/shared"
)

//go:generate counterfeiter . SpaceActor

type SpaceActor interface {
	GetSpaceByOrganizationAndName(orgGUID string, spaceName string) (v2action.Space, v2action.Warnings, error)
	GetSpaceSummaryByOrganizationAndName(orgGUID string, spaceName string) (v2action.SpaceSummary, v2action.Warnings, error)
}

//go:generate counterfeiter . SpaceActorV3

type SpaceActorV3 interface {
	GetIsolationSegmentBySpace(spaceGUID string) (v3action.IsolationSegment, v3action.Warnings, error)
	CloudControllerAPIVersion() string
}

type SpaceCommand struct {
	RequiredArgs       flag.Space  `positional-args:"yes"`
	GUID               bool        `long:"guid" description:"Retrieve and display the given space's guid.  All other output for the space is suppressed."`
	SecurityGroupRules bool        `long:"security-group-rules" description:"Retrieve the rules for all the security groups associated with the space."`
	usage              interface{} `usage:"CF_NAME space SPACE [--guid] [--security-group-rules]"`
	relatedCommands    interface{} `related_commands:"space-users"`

	UI          command.UI
	Config      command.Config
	SharedActor command.SharedActor
	Actor       SpaceActor
	ActorV3     SpaceActorV3
}

func (cmd *SpaceCommand) Setup(config command.Config, ui command.UI) error {
	cmd.Config = config
	cmd.UI = ui
	cmd.SharedActor = sharedaction.NewActor()

	ccClient, _, err := shared.NewClients(config, ui, true)
	if err != nil {
		return err
	}
	cmd.Actor = v2action.NewActor(ccClient, nil)

	ccClientV3, err := sharedV3.NewClients(config, ui, true)
	if err != nil {
		return err
	}
	cmd.ActorV3 = v3action.NewActor(ccClientV3)

	return nil
}

func (cmd SpaceCommand) Execute(args []string) error {
	if cmd.Config.Experimental() == false {
		oldCmd.Main(os.Getenv("CF_TRACE"), os.Args)
		return nil
	}
	cmd.UI.DisplayText(command.ExperimentalWarning)
	cmd.UI.DisplayNewline()

	err := cmd.SharedActor.CheckTarget(cmd.Config, true, false)

	if err == nil {
		if cmd.GUID {
			err = cmd.displaySpaceGUID()
		} else {
			err = cmd.displaySpaceSummary(cmd.SecurityGroupRules)
		}
	}

	return shared.HandleError(err)
}

func (cmd SpaceCommand) displaySpaceGUID() error {
	org, warnings, err := cmd.Actor.GetSpaceByOrganizationAndName(cmd.Config.TargetedOrganization().GUID, cmd.RequiredArgs.Space)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	cmd.UI.DisplayText(org.GUID)

	return nil
}

func (cmd SpaceCommand) displaySpaceSummary(displaySecurityGroupRules bool) error {
	user, err := cmd.Config.CurrentUser()
	if err != nil {
		return err
	}

	cmd.UI.DisplayText("Getting info for space {{.TargetSpace}} in org {{.OrgName}} as {{.CurrentUser}}...", map[string]interface{}{
		"TargetSpace": cmd.RequiredArgs.Space,
		"OrgName":     cmd.Config.TargetedOrganization().Name,
		"CurrentUser": user.Name,
	})
	cmd.UI.DisplayNewline()

	spaceSummary, warnings, err := cmd.Actor.GetSpaceSummaryByOrganizationAndName(cmd.Config.TargetedOrganization().GUID, cmd.RequiredArgs.Space)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	table := [][]string{
		{cmd.UI.TranslateText("name:"), spaceSummary.SpaceName},
		{cmd.UI.TranslateText("org:"), spaceSummary.OrgName},
		{cmd.UI.TranslateText("apps:"), strings.Join(spaceSummary.AppNames, ", ")},
		{cmd.UI.TranslateText("services:"), strings.Join(spaceSummary.ServiceInstanceNames, ", ")},
		{cmd.UI.TranslateText("space quota:"), spaceSummary.SpaceQuotaName},
		{cmd.UI.TranslateText("security groups:"), strings.Join(spaceSummary.SecurityGroupNames, ", ")},
	}

	apiCheck := command.MinimumAPIVersionCheck(cmd.ActorV3.CloudControllerAPIVersion(), "3.11.0")
	if apiCheck == nil {
		isolationSegment, v3Warnings, err := cmd.ActorV3.GetIsolationSegmentBySpace(spaceSummary.SpaceGUID)
		cmd.UI.DisplayWarnings(v3Warnings)
		if err != nil {
			return sharedV3.HandleError(err)
		}

		table = append(table[:4], append([][]string{
			{cmd.UI.TranslateText("isolation segment:"), isolationSegment.Name},
		}, table[4:]...)...)
	}

	cmd.UI.DisplayKeyValueTable("", table, 3)

	if displaySecurityGroupRules {
		table := [][]string{
			{
				cmd.UI.TranslateText(""),
				cmd.UI.TranslateText("security group"),
				cmd.UI.TranslateText("destination"),
				cmd.UI.TranslateText("ports"),
				cmd.UI.TranslateText("protocol"),
				cmd.UI.TranslateText("lifecycle"),
				cmd.UI.TranslateText("description"),
			},
		}

		currentGroupIndex := -1
		var currentGroupName string
		for _, securityGroupRule := range spaceSummary.SecurityGroupRules {
			var currentGroupIndexString string

			if securityGroupRule.Name != currentGroupName {
				currentGroupIndex += 1
				currentGroupIndexString = fmt.Sprintf("#%d", currentGroupIndex)
				currentGroupName = securityGroupRule.Name
			}

			table = append(table, []string{
				currentGroupIndexString,
				securityGroupRule.Name,
				securityGroupRule.Destination,
				securityGroupRule.Ports,
				securityGroupRule.Protocol,
				securityGroupRule.Lifecycle,
				securityGroupRule.Description,
			})
		}

		cmd.UI.DisplayNewline()
		cmd.UI.DisplayTableWithHeader("", table, 3)
	}

	return nil
}
<commit_msg>space command displays variables with color<commit_after>package v2

import (
	"fmt"
	"os"
	"strings"

	"code.cloudfoundry.org/cli/actor/sharedaction"
	"code.cloudfoundry.org/cli/actor/v2action"
	"code.cloudfoundry.org/cli/actor/v3action"
	oldCmd "code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
	"code.cloudfoundry.org/cli/command/v2/shared"
	sharedV3 "code.cloudfoundry.org/cli/command/v3/shared"
)

//go:generate counterfeiter . SpaceActor

type SpaceActor interface {
	GetSpaceByOrganizationAndName(orgGUID string, spaceName string) (v2action.Space, v2action.Warnings, error)
	GetSpaceSummaryByOrganizationAndName(orgGUID string, spaceName string) (v2action.SpaceSummary, v2action.Warnings, error)
}

//go:generate counterfeiter . SpaceActorV3

type SpaceActorV3 interface {
	GetIsolationSegmentBySpace(spaceGUID string) (v3action.IsolationSegment, v3action.Warnings, error)
	CloudControllerAPIVersion() string
}

type SpaceCommand struct {
	RequiredArgs       flag.Space  `positional-args:"yes"`
	GUID               bool        `long:"guid" description:"Retrieve and display the given space's guid.  All other output for the space is suppressed."`
	SecurityGroupRules bool        `long:"security-group-rules" description:"Retrieve the rules for all the security groups associated with the space."`
	usage              interface{} `usage:"CF_NAME space SPACE [--guid] [--security-group-rules]"`
	relatedCommands    interface{} `related_commands:"space-users"`

	UI          command.UI
	Config      command.Config
	SharedActor command.SharedActor
	Actor       SpaceActor
	ActorV3     SpaceActorV3
}

func (cmd *SpaceCommand) Setup(config command.Config, ui command.UI) error {
	cmd.Config = config
	cmd.UI = ui
	cmd.SharedActor = sharedaction.NewActor()

	ccClient, _, err := shared.NewClients(config, ui, true)
	if err != nil {
		return err
	}
	cmd.Actor = v2action.NewActor(ccClient, nil)

	ccClientV3, err := sharedV3.NewClients(config, ui, true)
	if err != nil {
		return err
	}
	cmd.ActorV3 = v3action.NewActor(ccClientV3)

	return nil
}

func (cmd SpaceCommand) Execute(args []string) error {
	if cmd.Config.Experimental() == false {
		oldCmd.Main(os.Getenv("CF_TRACE"), os.Args)
		return nil
	}
	cmd.UI.DisplayText(command.ExperimentalWarning)
	cmd.UI.DisplayNewline()

	err := cmd.SharedActor.CheckTarget(cmd.Config, true, false)

	if err == nil {
		if cmd.GUID {
			err = cmd.displaySpaceGUID()
		} else {
			err = cmd.displaySpaceSummary(cmd.SecurityGroupRules)
		}
	}

	return shared.HandleError(err)
}

func (cmd SpaceCommand) displaySpaceGUID() error {
	org, warnings, err := cmd.Actor.GetSpaceByOrganizationAndName(cmd.Config.TargetedOrganization().GUID, cmd.RequiredArgs.Space)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	cmd.UI.DisplayText(org.GUID)

	return nil
}

func (cmd SpaceCommand) displaySpaceSummary(displaySecurityGroupRules bool) error {
	user, err := cmd.Config.CurrentUser()
	if err != nil {
		return err
	}

	cmd.UI.DisplayTextWithFlavor("Getting info for space {{.TargetSpace}} in org {{.OrgName}} as {{.CurrentUser}}...", map[string]interface{}{
		"TargetSpace": cmd.RequiredArgs.Space,
		"OrgName":     cmd.Config.TargetedOrganization().Name,
		"CurrentUser": user.Name,
	})
	cmd.UI.DisplayNewline()

	spaceSummary, warnings, err := cmd.Actor.GetSpaceSummaryByOrganizationAndName(cmd.Config.TargetedOrganization().GUID, cmd.RequiredArgs.Space)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	table := [][]string{
		{cmd.UI.TranslateText("name:"), spaceSummary.SpaceName},
		{cmd.UI.TranslateText("org:"), spaceSummary.OrgName},
		{cmd.UI.TranslateText("apps:"), strings.Join(spaceSummary.AppNames, ", ")},
		{cmd.UI.TranslateText("services:"), strings.Join(spaceSummary.ServiceInstanceNames, ", ")},
		{cmd.UI.TranslateText("space quota:"), spaceSummary.SpaceQuotaName},
		{cmd.UI.TranslateText("security groups:"), strings.Join(spaceSummary.SecurityGroupNames, ", ")},
	}

	apiCheck := command.MinimumAPIVersionCheck(cmd.ActorV3.CloudControllerAPIVersion(), "3.11.0")
	if apiCheck == nil {
		isolationSegment, v3Warnings, err := cmd.ActorV3.GetIsolationSegmentBySpace(spaceSummary.SpaceGUID)
		cmd.UI.DisplayWarnings(v3Warnings)
		if err != nil {
			return sharedV3.HandleError(err)
		}

		table = append(table[:4], append([][]string{
			{cmd.UI.TranslateText("isolation segment:"), isolationSegment.Name},
		}, table[4:]...)...)
	}

	cmd.UI.DisplayKeyValueTable("", table, 3)

	if displaySecurityGroupRules {
		table := [][]string{
			{
				cmd.UI.TranslateText(""),
				cmd.UI.TranslateText("security group"),
				cmd.UI.TranslateText("destination"),
				cmd.UI.TranslateText("ports"),
				cmd.UI.TranslateText("protocol"),
				cmd.UI.TranslateText("lifecycle"),
				cmd.UI.TranslateText("description"),
			},
		}

		currentGroupIndex := -1
		var currentGroupName string
		for _, securityGroupRule := range spaceSummary.SecurityGroupRules {
			var currentGroupIndexString string

			if securityGroupRule.Name != currentGroupName {
				currentGroupIndex += 1
				currentGroupIndexString = fmt.Sprintf("#%d", currentGroupIndex)
				currentGroupName = securityGroupRule.Name
			}

			table = append(table, []string{
				currentGroupIndexString,
				securityGroupRule.Name,
				securityGroupRule.Destination,
				securityGroupRule.Ports,
				securityGroupRule.Protocol,
				securityGroupRule.Lifecycle,
				securityGroupRule.Description,
			})
		}

		cmd.UI.DisplayNewline()
		cmd.UI.DisplayTableWithHeader("", table, 3)
	}

	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"crypto/x509"
	"fmt"
	"io/ioutil"

	kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"

	"github.com/openshift/origin/pkg/client"
	"github.com/openshift/origin/pkg/cmd/server/crypto"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
)

func RelativizeMasterConfigPaths(config *MasterConfig, base string) error {
	return cmdutil.RelativizePathWithNoBacksteps(GetMasterFileReferences(config), base)
}

func ResolveMasterConfigPaths(config *MasterConfig, base string) error {
	return cmdutil.ResolvePaths(GetMasterFileReferences(config), base)
}

func GetMasterFileReferences(config *MasterConfig) []*string {
	refs := []*string{}

	refs = append(refs, &config.ServingInfo.ServerCert.CertFile)
	refs = append(refs, &config.ServingInfo.ServerCert.KeyFile)
	refs = append(refs, &config.ServingInfo.ClientCA)

	refs = append(refs, &config.EtcdClientInfo.ClientCert.CertFile)
	refs = append(refs, &config.EtcdClientInfo.ClientCert.KeyFile)
	refs = append(refs, &config.EtcdClientInfo.CA)

	if config.EtcdConfig != nil {
		refs = append(refs, &config.EtcdConfig.ServingInfo.ServerCert.CertFile)
		refs = append(refs, &config.EtcdConfig.ServingInfo.ServerCert.KeyFile)
		refs = append(refs, &config.EtcdConfig.ServingInfo.ClientCA)
		refs = append(refs, &config.EtcdConfig.StorageDir)
	}

	if config.OAuthConfig != nil {
		refs = append(refs, &config.OAuthConfig.ProxyCA)
	}

	if config.AssetConfig != nil {
		refs = append(refs, &config.AssetConfig.ServingInfo.ServerCert.CertFile)
		refs = append(refs, &config.AssetConfig.ServingInfo.ServerCert.KeyFile)
		refs = append(refs, &config.AssetConfig.ServingInfo.ClientCA)
	}

	refs = append(refs, &config.MasterClients.DeployerKubeConfig)
	refs = append(refs, &config.MasterClients.OpenShiftLoopbackKubeConfig)
	refs = append(refs, &config.MasterClients.KubernetesKubeConfig)

	return refs
}

func RelativizeNodeConfigPaths(config *NodeConfig, base string) error {
	return cmdutil.RelativizePathWithNoBacksteps(GetNodeFileReferences(config), base)
}

func ResolveNodeConfigPaths(config *NodeConfig, base string) error {
	return cmdutil.ResolvePaths(GetNodeFileReferences(config), base)
}

func GetNodeFileReferences(config *NodeConfig) []*string {
	refs := []*string{}

	refs = append(refs, &config.ServingInfo.ServerCert.CertFile)
	refs = append(refs, &config.ServingInfo.ServerCert.KeyFile)
	refs = append(refs, &config.ServingInfo.ClientCA)

	refs = append(refs, &config.MasterKubeConfig)

	refs = append(refs, &config.VolumeDirectory)

	return refs
}

func GetKubeClient(kubeConfigFile string) (*kclient.Client, *kclient.Config, error) {
	loadingRules := &clientcmd.ClientConfigLoadingRules{}
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	kubeConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, nil, err
	}
	kubeClient, err := kclient.New(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	return kubeClient, kubeConfig, nil
}

func GetOpenShiftClient(kubeConfigFile string) (*client.Client, *kclient.Config, error) {
	loadingRules := &clientcmd.ClientConfigLoadingRules{}
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	kubeConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, nil, err
	}
	openshiftClient, err := client.New(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	return openshiftClient, kubeConfig, nil
}

func UseTLS(servingInfo ServingInfo) bool {
	return len(servingInfo.ServerCert.CertFile) > 0
}

// GetAPIClientCertCAPool returns the cert pool used to validate client certificates to the API server
func GetAPIClientCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	certs, err := getAPIClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	roots := x509.NewCertPool()
	for _, root := range certs {
		roots.AddCert(root)
	}
	return roots, nil
}

// GetClientCertCAPool returns a cert pool containing all client CAs that could be presented (union of API and OAuth)
func GetClientCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	roots := x509.NewCertPool()

	// Add CAs for OAuth
	certs, err := getOAuthClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	for _, root := range certs {
		roots.AddCert(root)
	}

	// Add CAs for API
	certs, err = getAPIClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	for _, root := range certs {
		roots.AddCert(root)
	}

	return roots, nil
}

// GetAPIServerCertCAPool returns the cert pool containing the roots for the API server cert
func GetAPIServerCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	if !UseTLS(options.ServingInfo) {
		return x509.NewCertPool(), nil
	}

	caRoots, err := crypto.GetTLSCARoots(options.ServingInfo.ClientCA)
	if err != nil {
		return nil, err
	}
	roots := x509.NewCertPool()
	for _, root := range caRoots.Roots {
		roots.AddCert(root)
	}
	return roots, nil
}

func getOAuthClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
	if !UseTLS(options.ServingInfo) {
		return nil, nil
	}

	caFile := options.OAuthConfig.ProxyCA
	if len(caFile) == 0 {
		return nil, nil
	}
	caPEMBlock, err := ioutil.ReadFile(caFile)
	if err != nil {
		return nil, err
	}
	certs, err := crypto.CertsFromPEM(caPEMBlock)
	if err != nil {
		return nil, fmt.Errorf("Error reading %s: %s", caFile, err)
	}
	return certs, nil
}

func getAPIClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
	if !UseTLS(options.ServingInfo) {
		return nil, nil
	}

	apiClientCertCAs, err := crypto.GetTLSCARoots(options.ServingInfo.ClientCA)
	if err != nil {
		return nil, err
	}

	return apiClientCertCAs.Roots, nil
}
<commit_msg>relativize paths for master config<commit_after>package api

import (
	"crypto/x509"
	"fmt"
	"io/ioutil"

	kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"

	"github.com/openshift/origin/pkg/client"
	"github.com/openshift/origin/pkg/cmd/server/crypto"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
)

func RelativizeMasterConfigPaths(config *MasterConfig, base string) error {
	return cmdutil.RelativizePathWithNoBacksteps(GetMasterFileReferences(config), base)
}

func ResolveMasterConfigPaths(config *MasterConfig, base string) error {
	return cmdutil.ResolvePaths(GetMasterFileReferences(config), base)
}

func GetMasterFileReferences(config *MasterConfig) []*string {
	refs := []*string{}

	refs = append(refs, &config.ServingInfo.ServerCert.CertFile)
	refs = append(refs, &config.ServingInfo.ServerCert.KeyFile)
	refs = append(refs, &config.ServingInfo.ClientCA)

	refs = append(refs, &config.EtcdClientInfo.ClientCert.CertFile)
	refs = append(refs, &config.EtcdClientInfo.ClientCert.KeyFile)
	refs = append(refs, &config.EtcdClientInfo.CA)

	if config.EtcdConfig != nil {
		refs = append(refs, &config.EtcdConfig.ServingInfo.ServerCert.CertFile)
		refs = append(refs, &config.EtcdConfig.ServingInfo.ServerCert.KeyFile)
		refs = append(refs, &config.EtcdConfig.ServingInfo.ClientCA)
		refs = append(refs, &config.EtcdConfig.StorageDir)
	}

	if config.OAuthConfig != nil {
		refs = append(refs, &config.OAuthConfig.ProxyCA)
	}

	if config.AssetConfig != nil {
		refs = append(refs, &config.AssetConfig.ServingInfo.ServerCert.CertFile)
		refs = append(refs, &config.AssetConfig.ServingInfo.ServerCert.KeyFile)
		refs = append(refs, &config.AssetConfig.ServingInfo.ClientCA)
	}

	if config.KubernetesMasterConfig != nil {
		refs = append(refs, &config.KubernetesMasterConfig.SchedulerConfigFile)
	}

	refs = append(refs, &config.MasterClients.DeployerKubeConfig)
	refs = append(refs, &config.MasterClients.OpenShiftLoopbackKubeConfig)
	refs = append(refs, &config.MasterClients.KubernetesKubeConfig)

	refs = append(refs, &config.PolicyConfig.BootstrapPolicyFile)

	return refs
}

func RelativizeNodeConfigPaths(config *NodeConfig, base string) error {
	return cmdutil.RelativizePathWithNoBacksteps(GetNodeFileReferences(config), base)
}

func ResolveNodeConfigPaths(config *NodeConfig, base string) error {
	return cmdutil.ResolvePaths(GetNodeFileReferences(config), base)
}

func GetNodeFileReferences(config *NodeConfig) []*string {
	refs := []*string{}

	refs = append(refs, &config.ServingInfo.ServerCert.CertFile)
	refs = append(refs, &config.ServingInfo.ServerCert.KeyFile)
	refs = append(refs, &config.ServingInfo.ClientCA)

	refs = append(refs, &config.MasterKubeConfig)

	refs = append(refs, &config.VolumeDirectory)

	return refs
}

func GetKubeClient(kubeConfigFile string) (*kclient.Client, *kclient.Config, error) {
	loadingRules := &clientcmd.ClientConfigLoadingRules{}
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	kubeConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, nil, err
	}
	kubeClient, err := kclient.New(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	return kubeClient, kubeConfig, nil
}

func GetOpenShiftClient(kubeConfigFile string) (*client.Client, *kclient.Config, error) {
	loadingRules := &clientcmd.ClientConfigLoadingRules{}
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	kubeConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, nil, err
	}
	openshiftClient, err := client.New(kubeConfig)
	if err != nil {
		return nil, nil, err
	}

	return openshiftClient, kubeConfig, nil
}

func UseTLS(servingInfo ServingInfo) bool {
	return len(servingInfo.ServerCert.CertFile) > 0
}

// GetAPIClientCertCAPool returns the cert pool used to validate client certificates to the API server
func GetAPIClientCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	certs, err := getAPIClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	roots := x509.NewCertPool()
	for _, root := range certs {
		roots.AddCert(root)
	}
	return roots, nil
}

// GetClientCertCAPool returns a cert pool containing all client CAs that could be presented (union of API and OAuth)
func GetClientCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	roots := x509.NewCertPool()

	// Add CAs for OAuth
	certs, err := getOAuthClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	for _, root := range certs {
		roots.AddCert(root)
	}

	// Add CAs for API
	certs, err = getAPIClientCertCAs(options)
	if err != nil {
		return nil, err
	}
	for _, root := range certs {
		roots.AddCert(root)
	}

	return roots, nil
}

// GetAPIServerCertCAPool returns the cert pool containing the roots for the API server cert
func GetAPIServerCertCAPool(options MasterConfig) (*x509.CertPool, error) {
	if !UseTLS(options.ServingInfo) {
		return x509.NewCertPool(), nil
	}

	caRoots, err := crypto.GetTLSCARoots(options.ServingInfo.ClientCA)
	if err != nil {
		return nil, err
	}
	roots := x509.NewCertPool()
	for _, root := range caRoots.Roots {
		roots.AddCert(root)
	}
	return roots, nil
}

func getOAuthClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
	if !UseTLS(options.ServingInfo) {
		return nil, nil
	}

	caFile := options.OAuthConfig.ProxyCA
	if len(caFile) == 0 {
		return nil, nil
	}
	caPEMBlock, err := ioutil.ReadFile(caFile)
	if err != nil {
		return nil, err
	}
	certs, err := crypto.CertsFromPEM(caPEMBlock)
	if err != nil {
		return nil, fmt.Errorf("Error reading %s: %s", caFile, err)
	}
	return certs, nil
}

func getAPIClientCertCAs(options MasterConfig) ([]*x509.Certificate, error) {
	if !UseTLS(options.ServingInfo) {
		return nil, nil
	}

	apiClientCertCAs, err := crypto.GetTLSCARoots(options.ServingInfo.ClientCA)
	if err != nil {
		return nil, err
	}

	return apiClientCertCAs.Roots, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Rook Authors. All rights reserved.

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 mgr

import (
	"fmt"
	"path"

	"github.com/coreos/pkg/capnslog"
	"github.com/rook/rook/pkg/clusterd"
	"github.com/rook/rook/pkg/daemon/ceph/mon"
	"github.com/rook/rook/pkg/util"
)

var (
	logger          = capnslog.NewPackageLogger("github.com/rook/rook", "cephmgr")
	keyringTemplate = `
[mgr.%s]
	key = %s
	caps mon = "allow *"
`
)

const (
	cephmgr = "ceph-mgr"
)

type Config struct {
	ClusterInfo *mon.ClusterInfo
	Name        string
	Keyring     string
}

func Run(context *clusterd.Context, config *Config) error {
	logger.Infof("Starting MGR %s with keyring %s", config.Name, config.Keyring)
	if err := generateConfigFiles(context, config); err != nil {
		return fmt.Errorf("failed to generate mgr config files. %+v", err)
	}

	if err := startMgr(context, config); err != nil {
		return fmt.Errorf("failed to run mgr. %+v", err)
	}

	return nil
}

func generateConfigFiles(context *clusterd.Context, config *Config) error {

	keyringPath := getMgrKeyringPath(context.ConfigDir, config.Name)
	confDir := getMgrConfDir(context.ConfigDir, config.Name)
	username := fmt.Sprintf("mgr.%s", config.Name)
	settings := map[string]string{
		"mgr data": confDir,
	}
	logger.Infof("Conf files: dir=%s keyring=%s", confDir, keyringPath)
	_, err := mon.GenerateConfigFile(context, config.ClusterInfo, confDir,
		username, keyringPath, nil, settings)
	if err != nil {
		return fmt.Errorf("failed to create config file. %+v", err)
	}

	keyringEval := func(key string) string {
		return fmt.Sprintf(keyringTemplate, config.Name, key)
	}

	err = mon.WriteKeyring(keyringPath, config.Keyring, keyringEval)
	if err != nil {
		return fmt.Errorf("failed to create mds keyring. %+v", err)
	}

	return nil
}

func startMgr(context *clusterd.Context, config *Config) error {

	// start the mgr daemon in the foreground with the given config
	logger.Infof("starting ceph-mgr")

	confFile := getMgrConfFilePath(context.ConfigDir, config.Name, config.ClusterInfo.Name)
	util.WriteFileToLog(logger, confFile)

	keyringPath := getMgrKeyringPath(context.ConfigDir, config.Name)
	util.WriteFileToLog(logger, keyringPath)
	args := []string{
		"--foreground",
		fmt.Sprintf("--cluster=%s", config.ClusterInfo.Name),
		fmt.Sprintf("--conf=%s", confFile),
		fmt.Sprintf("--keyring=%s", keyringPath),
		"-i", config.Name,
	}

	if err := context.Executor.ExecuteCommand(false, cephmgr, cephmgr, args...); err != nil {
		return fmt.Errorf("failed to start mgr: %+v", err)
	}
	return nil
}

func getMgrConfDir(dir, name string) string {
	return path.Join(dir, fmt.Sprintf("mgr-%s", name))
}

func getMgrConfFilePath(dir, name, clusterName string) string {
	return path.Join(getMgrConfDir(dir, name), fmt.Sprintf("%s.config", clusterName))
}

func getMgrKeyringPath(dir, name string) string {
	return path.Join(getMgrConfDir(dir, name), "keyring")
}
<commit_msg>Grant mgr OSD and MDS caps<commit_after>/*
Copyright 2016 The Rook Authors. All rights reserved.

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 mgr

import (
	"fmt"
	"path"

	"github.com/coreos/pkg/capnslog"
	"github.com/rook/rook/pkg/clusterd"
	"github.com/rook/rook/pkg/daemon/ceph/mon"
	"github.com/rook/rook/pkg/util"
)

var (
	logger          = capnslog.NewPackageLogger("github.com/rook/rook", "cephmgr")
	keyringTemplate = `
[mgr.%s]
	key = %s
	caps mon = "allow *"
	caps mds = "allow *"
	caps osd = "allow *"
`
)

const (
	cephmgr = "ceph-mgr"
)

type Config struct {
	ClusterInfo *mon.ClusterInfo
	Name        string
	Keyring     string
}

func Run(context *clusterd.Context, config *Config) error {
	logger.Infof("Starting MGR %s with keyring %s", config.Name, config.Keyring)
	if err := generateConfigFiles(context, config); err != nil {
		return fmt.Errorf("failed to generate mgr config files. %+v", err)
	}

	if err := startMgr(context, config); err != nil {
		return fmt.Errorf("failed to run mgr. %+v", err)
	}

	return nil
}

func generateConfigFiles(context *clusterd.Context, config *Config) error {

	keyringPath := getMgrKeyringPath(context.ConfigDir, config.Name)
	confDir := getMgrConfDir(context.ConfigDir, config.Name)
	username := fmt.Sprintf("mgr.%s", config.Name)
	settings := map[string]string{
		"mgr data": confDir,
	}
	logger.Infof("Conf files: dir=%s keyring=%s", confDir, keyringPath)
	_, err := mon.GenerateConfigFile(context, config.ClusterInfo, confDir,
		username, keyringPath, nil, settings)
	if err != nil {
		return fmt.Errorf("failed to create config file. %+v", err)
	}

	keyringEval := func(key string) string {
		return fmt.Sprintf(keyringTemplate, config.Name, key)
	}

	err = mon.WriteKeyring(keyringPath, config.Keyring, keyringEval)
	if err != nil {
		return fmt.Errorf("failed to create mds keyring. %+v", err)
	}

	return nil
}

func startMgr(context *clusterd.Context, config *Config) error {

	// start the mgr daemon in the foreground with the given config
	logger.Infof("starting ceph-mgr")

	confFile := getMgrConfFilePath(context.ConfigDir, config.Name, config.ClusterInfo.Name)
	util.WriteFileToLog(logger, confFile)

	keyringPath := getMgrKeyringPath(context.ConfigDir, config.Name)
	util.WriteFileToLog(logger, keyringPath)
	args := []string{
		"--foreground",
		fmt.Sprintf("--cluster=%s", config.ClusterInfo.Name),
		fmt.Sprintf("--conf=%s", confFile),
		fmt.Sprintf("--keyring=%s", keyringPath),
		"-i", config.Name,
	}

	if err := context.Executor.ExecuteCommand(false, cephmgr, cephmgr, args...); err != nil {
		return fmt.Errorf("failed to start mgr: %+v", err)
	}
	return nil
}

func getMgrConfDir(dir, name string) string {
	return path.Join(dir, fmt.Sprintf("mgr-%s", name))
}

func getMgrConfFilePath(dir, name, clusterName string) string {
	return path.Join(getMgrConfDir(dir, name), fmt.Sprintf("%s.config", clusterName))
}

func getMgrKeyringPath(dir, name string) string {
	return path.Join(getMgrConfDir(dir, name), "keyring")
}
<|endoftext|>