<commit_before>package deploy

import (
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/pkg/errors"
)

type LocalDeployer struct {
	targetDirectory string
}

func NewLocalDeployer(target string) (*LocalDeployer, error) {
	t, err := filepath.Abs(target)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get absolute path")
	}

	d := &LocalDeployer{
		targetDirectory: t,
	}

	if os.MkdirAll(t, 0755); err != nil {
		return nil, errors.Wrap(err, "Failed to create target directory")
	}

	return d, nil
}

// targetDirectory にファイルを転送し、 path にシンボリックリンクを貼る
func (d LocalDeployer) SaveFile(body []byte, path string, permission os.FileMode) error {
	var target string
	if !filepath.IsAbs(path) {
		target = filepath.Join(d.targetDirectory, path)
	} else {
		filename := filepath.Base(path)
		target = filepath.Join(d.targetDirectory, filename)

		if _, err := os.Lstat(path); err == nil {
			if err := os.Remove(path); err != nil {
				return errors.Wrap(err, "Failed to remove old symbolic link")
			}
		}

		if err := os.Symlink(target, path); err != nil {
			return errors.Wrap(err, "Failed to create symbolic link")
		}
	}

	file, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, permission)
	if err != nil {
		return errors.Wrap(err, "Failed to create new file")
	}
	defer file.Close()

	if _, err := file.Write(body); err != nil {
		return errors.Wrap(err, "Failed to write to file")
	}

	return nil
}

func (d LocalDeployer) LinkSelf(path string) error {
	self, err := filepath.Abs(os.Args[0])
	if err != nil {
		return errors.Wrap(err, "Failed to get self absolute path")
	}

	dst, err := filepath.Abs(path)
	if err != nil {
		return errors.Wrap(err, "Failed to get destination absolute path")
	}

	if _, err := os.Lstat(dst); err == nil {
		if err := os.Remove(dst); err != nil {
			return errors.Wrap(err, "Failed to remove old symbolic link")
		}
	}

	if err := os.Symlink(self, dst); err != nil {
		return errors.Wrap(err, "Failed to create symbolic link")
	}

	return nil
}

func (d LocalDeployer) RestartDaemon(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"daemon-reload",
	}

	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	cmd = []string{
		"systemctl",
		"restart",
		daemon,
	}
	c = exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	cmd = []string{
		"systemctl",
		"enable",
		daemon,
	}
	c = exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	return nil
}

func (d LocalDeployer) DaemonStatus(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"status",
		daemon,
	}
	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	return nil
}

func (d LocalDeployer) StopDaemon(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"stop",
		daemon,
	}
	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		if ee, ok := err.(*exec.ExitError); ok {
			if status, ok := ee.Sys().(syscall.WaitStatus); ok {
				if status.ExitStatus() != 5 { // Failed to stop n0core-agent.service: Unit n0core-agent.service not loaded.
					return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
				}
			}
		} else {
			return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
		}
	}

	return nil
}

func (d LocalDeployer) InstallPackages(packages []string, stdout, stderr io.Writer) error {
	cmd := []string{
		"apt",
		"install",
		"-y",
	}
	cmd = append(cmd, packages...)

	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrap(err, "Failed to command 'apt'")
	}

	return nil
}
<commit_msg>apt update on InstallPackages<commit_after>package deploy

import (
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/pkg/errors"
)

type LocalDeployer struct {
	targetDirectory string
}

func NewLocalDeployer(target string) (*LocalDeployer, error) {
	t, err := filepath.Abs(target)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get absolute path")
	}

	d := &LocalDeployer{
		targetDirectory: t,
	}

	if os.MkdirAll(t, 0755); err != nil {
		return nil, errors.Wrap(err, "Failed to create target directory")
	}

	return d, nil
}

// targetDirectory にファイルを転送し、 path にシンボリックリンクを貼る
func (d LocalDeployer) SaveFile(body []byte, path string, permission os.FileMode) error {
	var target string
	if !filepath.IsAbs(path) {
		target = filepath.Join(d.targetDirectory, path)
	} else {
		filename := filepath.Base(path)
		target = filepath.Join(d.targetDirectory, filename)

		if _, err := os.Lstat(path); err == nil {
			if err := os.Remove(path); err != nil {
				return errors.Wrap(err, "Failed to remove old symbolic link")
			}
		}

		if err := os.Symlink(target, path); err != nil {
			return errors.Wrap(err, "Failed to create symbolic link")
		}
	}

	file, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, permission)
	if err != nil {
		return errors.Wrap(err, "Failed to create new file")
	}
	defer file.Close()

	if _, err := file.Write(body); err != nil {
		return errors.Wrap(err, "Failed to write to file")
	}

	return nil
}

func (d LocalDeployer) LinkSelf(path string) error {
	self, err := filepath.Abs(os.Args[0])
	if err != nil {
		return errors.Wrap(err, "Failed to get self absolute path")
	}

	dst, err := filepath.Abs(path)
	if err != nil {
		return errors.Wrap(err, "Failed to get destination absolute path")
	}

	if _, err := os.Lstat(dst); err == nil {
		if err := os.Remove(dst); err != nil {
			return errors.Wrap(err, "Failed to remove old symbolic link")
		}
	}

	if err := os.Symlink(self, dst); err != nil {
		return errors.Wrap(err, "Failed to create symbolic link")
	}

	return nil
}

func (d LocalDeployer) RestartDaemon(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"daemon-reload",
	}

	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	cmd = []string{
		"systemctl",
		"restart",
		daemon,
	}
	c = exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	cmd = []string{
		"systemctl",
		"enable",
		daemon,
	}
	c = exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	return nil
}

func (d LocalDeployer) DaemonStatus(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"status",
		daemon,
	}
	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
	}

	return nil
}

func (d LocalDeployer) StopDaemon(daemon string, stdout, stderr io.Writer) error {
	cmd := []string{
		"systemctl",
		"stop",
		daemon,
	}
	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = stdout
	c.Stderr = stderr
	if err := c.Run(); err != nil {
		if ee, ok := err.(*exec.ExitError); ok {
			if status, ok := ee.Sys().(syscall.WaitStatus); ok {
				if status.ExitStatus() != 5 { // Failed to stop n0core-agent.service: Unit n0core-agent.service not loaded.
					return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
				}
			}
		} else {
			return errors.Wrapf(err, "Failed to command '%s'", strings.Join(cmd, " "))
		}
	}

	return nil
}

func (d LocalDeployer) InstallPackages(packages []string, stdout, stderr io.Writer) error {
	{
		cmd := []string{
			"apt",
			"update",
		}

		c := exec.Command(cmd[0], cmd[1:]...)
		c.Stdout = stdout
		c.Stderr = stderr
		if err := c.Run(); err != nil {
			return errors.Wrap(err, "Failed to command 'apt'")
		}
	}

	{
		cmd := []string{
			"apt",
			"install",
			"-y",
		}
		cmd = append(cmd, packages...)

		c := exec.Command(cmd[0], cmd[1:]...)
		c.Stdout = stdout
		c.Stderr = stderr
		if err := c.Run(); err != nil {
			return errors.Wrap(err, "Failed to command 'apt'")
		}
	}

	return nil
}
<|endoftext|>


<commit_before>//+build smoke

package smoke

import (
	"bytes"
	"io/ioutil"
	"strings"
	"testing"
)

const simpleServer = `
FROM alpine
CMD if [ -z "$T" ]; then T=2; fi; echo -n "Sleeping ${T}s..."; sleep $T; echo "Done"; echo "Listening on :$PORT0"; while true; do echo -e "HTTP/1.1 200 OK\n\n$(date)" | nc -l -p $PORT0; done`

// setupProject creates a brand new git repo containing the provided Dockerfile,
// runs sous init, then manifest get/set to bump instances to 1 in all clusters.
func setupProject(t *testing.T, f Fixture, dockerfile string) TestClient {
	t.Helper()
	// Setup project git repo.
	projectDir := makeGitRepo(t, f.BaseDir, "projects/project1", GitRepoSpec{
		UserName:  "Sous User 1",
		UserEmail: "sous-user1@example.com",
		OriginURL: "git@github.com:opentable/bogus/repo1",
	})
	makeFileString(t, projectDir, "Dockerfile", dockerfile)
	mustDoCMD(t, projectDir, "git", "add", "Dockerfile")
	mustDoCMD(t, projectDir, "git", "commit", "-m", "Add Dockerfile")

	sous := f.Client

	// Dump sous version & config.
	t.Logf("Sous version: %s", sous.MustRun(t, "version"))
	sous.MustRun(t, "config")

	// cd into project dir
	sous.Dir = projectDir

	return sous
}

func initProjectNoFlavor(t *testing.T, sous TestClient) {
	t.Helper()
	// Prepare manifest.
	sous.MustRun(t, "init")
	manifest := sous.MustRun(t, "manifest", "get")
	manifest = strings.Replace(manifest, "NumInstances: 0", "NumInstances: 1", -1)
	manifestSetCmd := sous.Cmd(t, "manifest", "set")
	manifestSetCmd.Stdin = ioutil.NopCloser(bytes.NewReader([]byte(manifest)))
	if out, err := manifestSetCmd.CombinedOutput(); err != nil {
		t.Fatalf("manifest set failed: %s; output:\n%s", err, out)
	}
}

func initProjectWithFlavor(t *testing.T, sous TestClient, flavor string) {
	t.Helper()
	// Prepare manifest.
	sous.MustRun(t, "init", "-flavor", flavor)
	manifest := sous.MustRun(t, "manifest", "get", "-flavor", flavor)
	manifest = strings.Replace(manifest, "NumInstances: 0", "NumInstances: 1", -1)
	manifestSetCmd := sous.Cmd(t, "manifest", "set", "-flavor", flavor)
	manifestSetCmd.Stdin = ioutil.NopCloser(bytes.NewReader([]byte(manifest)))
	if out, err := manifestSetCmd.CombinedOutput(); err != nil {
		t.Fatalf("manifest set failed: %s; output:\n%s", err, out)
	}
}

func TestSousNewdeploy(t *testing.T) {

	t.Run("simple", func(t *testing.T) {
		f := setupEnv(t)
		sous := setupProject(t, f, simpleServer)
		initProjectNoFlavor(t, sous)
		// Build and deploy.
		sous.MustRun(t, "build", "-tag", "1.2.3")
		sous.MustRun(t, "newdeploy", "-cluster", "cluster1", "-tag", "1.2.3")
	})

	t.Run("flavors", func(t *testing.T) {
		f := setupEnv(t)
		sous := setupProject(t, f, simpleServer)
		flavor := "flavor1"
		initProjectWithFlavor(t, sous, flavor)
		sous.MustRun(t, "build", "-tag", "1.2.3")
		sous.MustRun(t, "newdeploy", "-cluster", "cluster1", "-tag", "1.2.3", "-flavor", flavor)
	})

}
<commit_msg>test/smoke: NewDeploy pause/unpause test<commit_after>//+build smoke

package smoke

import (
	"bytes"
	"io/ioutil"
	"strings"
	"testing"

	sous "github.com/opentable/sous/lib"
)

const simpleServer = `
FROM alpine
CMD if [ -z "$T" ]; then T=2; fi; echo -n "Sleeping ${T}s..."; sleep $T; echo "Done"; echo "Listening on :$PORT0"; while true; do echo -e "HTTP/1.1 200 OK\n\n$(date)" | nc -l -p $PORT0; done`

// setupProject creates a brand new git repo containing the provided Dockerfile,
// runs sous init, then manifest get/set to bump instances to 1 in all clusters.
func setupProject(t *testing.T, f Fixture, dockerfile string) TestClient {
	t.Helper()
	// Setup project git repo.
	projectDir := makeGitRepo(t, f.BaseDir, "projects/project1", GitRepoSpec{
		UserName:  "Sous User 1",
		UserEmail: "sous-user1@example.com",
		OriginURL: "git@github.com:user1/repo1.git",
	})
	makeFileString(t, projectDir, "Dockerfile", dockerfile)
	mustDoCMD(t, projectDir, "git", "add", "Dockerfile")
	mustDoCMD(t, projectDir, "git", "commit", "-m", "Add Dockerfile")

	sous := f.Client

	// Dump sous version & config.
	t.Logf("Sous version: %s", sous.MustRun(t, "version"))
	sous.MustRun(t, "config")

	// cd into project dir
	sous.Dir = projectDir

	return sous
}

func initProjectNoFlavor(t *testing.T, sous TestClient) {
	t.Helper()
	// Prepare manifest.
	sous.MustRun(t, "init")
	manifest := sous.MustRun(t, "manifest", "get")
	manifest = strings.Replace(manifest, "NumInstances: 0", "NumInstances: 1", -1)
	manifestSetCmd := sous.Cmd(t, "manifest", "set")
	manifestSetCmd.Stdin = ioutil.NopCloser(bytes.NewReader([]byte(manifest)))
	if out, err := manifestSetCmd.CombinedOutput(); err != nil {
		t.Fatalf("manifest set failed: %s; output:\n%s", err, out)
	}
}

func initProjectWithFlavor(t *testing.T, sous TestClient, flavor string) {
	t.Helper()
	// Prepare manifest.
	sous.MustRun(t, "init", "-flavor", flavor)
	manifest := sous.MustRun(t, "manifest", "get", "-flavor", flavor)
	manifest = strings.Replace(manifest, "NumInstances: 0", "NumInstances: 1", -1)
	manifestSetCmd := sous.Cmd(t, "manifest", "set", "-flavor", flavor)
	manifestSetCmd.Stdin = ioutil.NopCloser(bytes.NewReader([]byte(manifest)))
	if out, err := manifestSetCmd.CombinedOutput(); err != nil {
		t.Fatalf("manifest set failed: %s; output:\n%s", err, out)
	}
}

func defaultManifestID() sous.ManifestID {
	return sous.ManifestID{
		Source: sous.SourceLocation{
			Dir:  "",
			Repo: "github.com/user1/repo1",
		},
		Flavor: "",
	}
}

func manifestID(repo, dir, flavor string) sous.ManifestID {
	return sous.ManifestID{
		Source: sous.SourceLocation{
			Dir:  dir,
			Repo: repo,
		},
		Flavor: flavor,
	}
}

func deploymentID(mid sous.ManifestID, cluster string) sous.DeploymentID {
	return sous.DeploymentID{
		ManifestID: mid,
		Cluster:    cluster,
	}
}

func defaultDeploymentID() sous.DeploymentID {
	return sous.DeploymentID{
		ManifestID: defaultManifestID(),
		Cluster:    "cluster1",
	}
}

func TestSousNewdeploy(t *testing.T) {

	t.Run("simple", func(t *testing.T) {
		f := setupEnv(t)
		sous := setupProject(t, f, simpleServer)
		initProjectNoFlavor(t, sous)
		// Build and deploy.
		sous.MustRun(t, "build", "-tag", "1.2.3")
		sous.MustRun(t, "newdeploy", "-cluster", "cluster1", "-tag", "1.2.3")
	})

	t.Run("flavors", func(t *testing.T) {
		f := setupEnv(t)
		sous := setupProject(t, f, simpleServer)
		flavor := "flavor1"
		initProjectWithFlavor(t, sous, flavor)
		sous.MustRun(t, "build", "-tag", "1.2.3")
		sous.MustRun(t, "newdeploy", "-cluster", "cluster1", "-tag", "1.2.3", "-flavor", flavor)
	})

	t.Run("deploy-pause-faildeploy-unpause-deploy", func(t *testing.T) {
		f := setupEnv(t)
		sous := setupProject(t, f, simpleServer)
		initProjectNoFlavor(t, sous)
		sous.MustRun(t, "build", "-tag", "1")
		sous.MustRun(t, "build", "-tag", "2")
		sous.MustRun(t, "build", "-tag", "3")
		sous.MustRun(t, "newdeploy", "-cluster", "cluster1", "-tag", "1")
		f.Singularity.PauseRequestForDeployment(t, deploymentID(defaultManifestID(), "cluster1"))
		sous.MustFail(t, "newdeploy", "-cluster", "cluster1", "-tag", "2")
		f.Singularity.UnpauseRequestForDeployment(t, deploymentID(defaultManifestID(), "cluster1"))
		sous.Run(t, "newdeploy", "-cluster", "cluster1", "-tag", "3")
	})
}
<|endoftext|>


<commit_before>//
// Copyright 2019, Paul Shoemaker
//
// 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 gitlab

import (
	"fmt"
	"time"
)

// GroupClustersService handles communication with the
// group clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html
type GroupClustersService struct {
	client *Client
}

// GroupCluster represents a GitLab Group Cluster.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_clusters.html
type GroupCluster struct {
	ID                 int                 `json:"id"`
	Name               string              `json:"name"`
	Domain             string              `json:"domain"`
	CreatedAt          *time.Time          `json:"created_at"`
	ProviderType       string              `json:"provider_type"`
	PlatformType       string              `json:"platform_type"`
	EnvironmentScope   string              `json:"environment_scope"`
	ClusterType        string              `json:"cluster_type"`
	User               *User               `json:"user"`
	PlatformKubernetes *PlatformKubernetes `json:"platform_kubernetes"`
	Group              *Group              `json:"group"`
	ManagementProject  *ManagementProject  `json:"management_project"`
}

func (v GroupCluster) String() string {
	return Stringify(v)
}

// ListClusters gets a list of all clusters in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#list-group-clusters
func (s *GroupClustersService) ListClusters(pid interface{}, options ...OptionFunc) ([]*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var pcs []*GroupCluster
	resp, err := s.client.Do(req, &pcs)
	if err != nil {
		return nil, resp, err
	}

	return pcs, resp, err
}

// GetCluster gets a cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#get-a-single-group-cluster
func (s *GroupClustersService) GetCluster(pid interface{}, cluster int, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, &pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// AddGroupClusterOptions represents the available AddCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
type AddGroupClusterOptions struct {
	Name                *string                            `url:"name,omitempty" json:"name,omitempty"`
	Domain              *string                            `url:"domain,omitempty" json:"domain,omitempty"`
	Enabled             *bool                              `url:"enabled,omitempty" json:"enabled,omitempty"`
	Managed             *bool                              `url:"managed,omitempty" json:"managed,omitempty"`
	EnvironmentScope    *string                            `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
	ManagementProjectID *string                            `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
	PlatformKubernetes  *AddGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
}

// AddGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for adding.
type AddGroupPlatformKubernetesOptions struct {
	APIURL            *string `url:"api_url,omitempty" json:"api_url,omitempty"`
	Token             *string `url:"token,omitempty" json:"token,omitempty"`
	CaCert            *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
	Namespace         *string `url:"namespace,omitempty" json:"namespace,omitempty"`
	AuthorizationType *string `url:"authorization_type,omitempty" json:"authorization_type,omitempty"`
}

// AddCluster adds an existing cluster to the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
func (s *GroupClustersService) AddCluster(pid interface{}, opt *AddGroupClusterOptions, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/user", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// EditGroupClusterOptions represents the available EditCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
type EditGroupClusterOptions struct {
	Name                *string                             `url:"name,omitempty" json:"name,omitempty"`
	Domain              *string                             `url:"domain,omitempty" json:"domain,omitempty"`
	EnvironmentScope    *string                             `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
	ManagementProjectID *string                             `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
	PlatformKubernetes  *EditGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
}

// EditGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for editing.
type EditGroupPlatformKubernetesOptions struct {
	APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
	Token  *string `url:"token,omitempty" json:"token,omitempty"`
	CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
}

// EditCluster updates an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
func (s *GroupClustersService) EditCluster(pid interface{}, cluster int, opt *EditGroupClusterOptions, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// DeleteCluster deletes an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#delete-group-cluster
func (s *GroupClustersService) DeleteCluster(pid interface{}, cluster int, options ...OptionFunc) (*Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<commit_msg>Move ManagementProjectID down fmt<commit_after>//
// Copyright 2019, Paul Shoemaker
//
// 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 gitlab

import (
	"fmt"
	"time"
)

// GroupClustersService handles communication with the
// group clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html
type GroupClustersService struct {
	client *Client
}

// GroupCluster represents a GitLab Group Cluster.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_clusters.html
type GroupCluster struct {
	ID                 int                 `json:"id"`
	Name               string              `json:"name"`
	Domain             string              `json:"domain"`
	CreatedAt          *time.Time          `json:"created_at"`
	ProviderType       string              `json:"provider_type"`
	PlatformType       string              `json:"platform_type"`
	EnvironmentScope   string              `json:"environment_scope"`
	ClusterType        string              `json:"cluster_type"`
	User               *User               `json:"user"`
	PlatformKubernetes *PlatformKubernetes `json:"platform_kubernetes"`
	Group              *Group              `json:"group"`
	ManagementProject  *ManagementProject  `json:"management_project"`
}

func (v GroupCluster) String() string {
	return Stringify(v)
}

// ListClusters gets a list of all clusters in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#list-group-clusters
func (s *GroupClustersService) ListClusters(pid interface{}, options ...OptionFunc) ([]*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var pcs []*GroupCluster
	resp, err := s.client.Do(req, &pcs)
	if err != nil {
		return nil, resp, err
	}

	return pcs, resp, err
}

// GetCluster gets a cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#get-a-single-group-cluster
func (s *GroupClustersService) GetCluster(pid interface{}, cluster int, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, &pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// AddGroupClusterOptions represents the available AddCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
type AddGroupClusterOptions struct {
	Name                *string                            `url:"name,omitempty" json:"name,omitempty"`
	Domain              *string                            `url:"domain,omitempty" json:"domain,omitempty"`
	Enabled             *bool                              `url:"enabled,omitempty" json:"enabled,omitempty"`
	Managed             *bool                              `url:"managed,omitempty" json:"managed,omitempty"`
	EnvironmentScope    *string                            `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
	PlatformKubernetes  *AddGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
	ManagementProjectID *string                            `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
}

// AddGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for adding.
type AddGroupPlatformKubernetesOptions struct {
	APIURL            *string `url:"api_url,omitempty" json:"api_url,omitempty"`
	Token             *string `url:"token,omitempty" json:"token,omitempty"`
	CaCert            *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
	Namespace         *string `url:"namespace,omitempty" json:"namespace,omitempty"`
	AuthorizationType *string `url:"authorization_type,omitempty" json:"authorization_type,omitempty"`
}

// AddCluster adds an existing cluster to the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
func (s *GroupClustersService) AddCluster(pid interface{}, opt *AddGroupClusterOptions, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/user", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// EditGroupClusterOptions represents the available EditCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
type EditGroupClusterOptions struct {
	Name                *string                             `url:"name,omitempty" json:"name,omitempty"`
	Domain              *string                             `url:"domain,omitempty" json:"domain,omitempty"`
	EnvironmentScope    *string                             `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
	PlatformKubernetes  *EditGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
	ManagementProjectID *string                             `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
}

// EditGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for editing.
type EditGroupPlatformKubernetesOptions struct {
	APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
	Token  *string `url:"token,omitempty" json:"token,omitempty"`
	CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
}

// EditCluster updates an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
func (s *GroupClustersService) EditCluster(pid interface{}, cluster int, opt *EditGroupClusterOptions, options ...OptionFunc) (*GroupCluster, *Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	pc := new(GroupCluster)
	resp, err := s.client.Do(req, pc)
	if err != nil {
		return nil, resp, err
	}

	return pc, resp, err
}

// DeleteCluster deletes an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#delete-group-cluster
func (s *GroupClustersService) DeleteCluster(pid interface{}, cluster int, options ...OptionFunc) (*Response, error) {
	group, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/clusters/%d", pathEscape(group), cluster)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package handlers

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/boltdb/bolt"
)

const (
	// DBPath is the relative (or absolute) path to the bolt database file
	DBPath string = "goreportcard.db"

	// RepoBucket is the bucket in which repos will be cached in the bolt DB
	RepoBucket string = "repos"

	// MetaBucket is the bucket containing the names of the projects with the
	// top 100 high scores, and other meta information
	MetaBucket string = "meta"
)

// CheckHandler handles the request for checking a repo
func CheckHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	repo := r.FormValue("repo")
	log.Printf("Checking repo %s...", repo)
	if strings.ToLower(repo) == "golang/go" {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("We've decided to omit results for the Go repository because it has lots of test files that (purposely) don't pass our checks. Go gets an A+ in our books though!"))
		return
	}
	forceRefresh := r.Method != "GET" // if this is a GET request, try to fetch from cached version in boltdb first
	resp, err := newChecksResp(repo, forceRefresh)
	if err != nil {
		log.Println("ERROR: ", err)
		b, _ := json.Marshal(err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(b)
		return
	}

	respBytes, err := json.Marshal(resp)
	if err != nil {
		log.Println("ERROR: could not marshal json:", err)
		http.Error(w, err.Error(), 500)
		return
	}
	w.Write(respBytes)

	// write to boltdb
	db, err := bolt.Open(DBPath, 0755, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Println("Failed to open bolt database: ", err)
		return
	}
	defer db.Close()

	log.Printf("Saving repo %q to cache...", repo)

	// is this a new repo? if so, increase the count in the high scores bucket later
	isNewRepo := false
	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(RepoBucket))
		if b == nil {
			return fmt.Errorf("repo bucket not found")
		}
		isNewRepo = b.Get([]byte(repo)) == nil
		return nil
	})
	if err != nil {
		log.Println(err)
	}

	// if this is a new repo, or the user force-refreshed, update the cache
	if isNewRepo || forceRefresh {
		err = db.Update(func(tx *bolt.Tx) error {
			b := tx.Bucket([]byte(RepoBucket))
			if b == nil {
				return fmt.Errorf("repo bucket not found")
			}

			// save repo to cache
			err = b.Put([]byte(repo), respBytes)
			if err != nil {
				return err
			}

			// fetch meta-bucket
			mb := tx.Bucket([]byte(MetaBucket))
			if mb == nil {
				return fmt.Errorf("high score bucket not found")
			}

			// update total repos count
			if isNewRepo {
				err = updateReposCount(mb, resp, repo)
				if err != nil {
					return err
				}
			}

			return updateHighScores(mb, resp, repo)
		})

		if err != nil {
			log.Println("Bolt writing error:", err)
		}
	}

	return
}

func updateHighScores(mb *bolt.Bucket, resp checksResp, repo string) error {
	// check if we need to update the high score list
	if resp.Files < 100 {
		// only repos with >= 100 files are considered for the high score list
		return nil
	}

	// start updating high score list
	scoreBytes := mb.Get([]byte("scores"))
	if scoreBytes == nil {
		scoreBytes, _ = json.Marshal([]scoreHeap{})
	}
	scores := &scoreHeap{}
	json.Unmarshal(scoreBytes, scores)

	heap.Init(scores)
	if len(*scores) > 0 && (*scores)[0].Score > resp.Average*100.0 && len(*scores) == 50 {
		// lowest score on list is higher than this repo's score, so no need to add, unless
		// we do not have 50 high scores yet
		return nil
	}
	// if this repo is already in the list, remove the original entry:
	for i := range *scores {
		if (*scores)[i].Repo == repo {
			heap.Remove(scores, i)
			break
		}
	}
	// now we can safely push it onto the heap
	heap.Push(scores, scoreItem{
		Repo:  repo,
		Score: resp.Average * 100.0,
		Files: resp.Files,
	})
	if len(*scores) > 50 {
		// trim heap if it's grown to over 50
		*scores = (*scores)[1:51]
	}
	scoreBytes, err := json.Marshal(&scores)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("scores"), scoreBytes)
	if err != nil {
		return err
	}

	return nil
}

func updateReposCount(mb *bolt.Bucket, resp checksResp, repo string) (err error) {
	log.Printf("New repo %q, adding to repo count...", repo)
	totalInt := 0
	total := mb.Get([]byte("total_repos"))
	if total != nil {
		err = json.Unmarshal(total, &totalInt)
		if err != nil {
			return fmt.Errorf("could not unmarshal total repos count: %v", err)
		}
	}
	totalInt++ // increase repo count
	total, err = json.Marshal(totalInt)
	if err != nil {
		return fmt.Errorf("could not marshal total repos count: %v", err)
	}
	mb.Put([]byte("total_repos"), total)
	log.Println("Repo count is now", totalInt)
	return nil
}
<commit_msg>move log statement<commit_after>package handlers

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/boltdb/bolt"
)

const (
	// DBPath is the relative (or absolute) path to the bolt database file
	DBPath string = "goreportcard.db"

	// RepoBucket is the bucket in which repos will be cached in the bolt DB
	RepoBucket string = "repos"

	// MetaBucket is the bucket containing the names of the projects with the
	// top 100 high scores, and other meta information
	MetaBucket string = "meta"
)

// CheckHandler handles the request for checking a repo
func CheckHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	repo := r.FormValue("repo")
	log.Printf("Checking repo %s...", repo)
	if strings.ToLower(repo) == "golang/go" {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("We've decided to omit results for the Go repository because it has lots of test files that (purposely) don't pass our checks. Go gets an A+ in our books though!"))
		return
	}
	forceRefresh := r.Method != "GET" // if this is a GET request, try to fetch from cached version in boltdb first
	resp, err := newChecksResp(repo, forceRefresh)
	if err != nil {
		log.Println("ERROR: ", err)
		b, _ := json.Marshal(err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(b)
		return
	}

	respBytes, err := json.Marshal(resp)
	if err != nil {
		log.Println("ERROR: could not marshal json:", err)
		http.Error(w, err.Error(), 500)
		return
	}
	w.Write(respBytes)

	// write to boltdb
	db, err := bolt.Open(DBPath, 0755, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Println("Failed to open bolt database: ", err)
		return
	}
	defer db.Close()

	// is this a new repo? if so, increase the count in the high scores bucket later
	isNewRepo := false
	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(RepoBucket))
		if b == nil {
			return fmt.Errorf("repo bucket not found")
		}
		isNewRepo = b.Get([]byte(repo)) == nil
		return nil
	})
	if err != nil {
		log.Println(err)
	}

	// if this is a new repo, or the user force-refreshed, update the cache
	if isNewRepo || forceRefresh {
		err = db.Update(func(tx *bolt.Tx) error {
			log.Printf("Saving repo %q to cache...", repo)

			b := tx.Bucket([]byte(RepoBucket))
			if b == nil {
				return fmt.Errorf("repo bucket not found")
			}

			// save repo to cache
			err = b.Put([]byte(repo), respBytes)
			if err != nil {
				return err
			}

			// fetch meta-bucket
			mb := tx.Bucket([]byte(MetaBucket))
			if mb == nil {
				return fmt.Errorf("high score bucket not found")
			}

			// update total repos count
			if isNewRepo {
				err = updateReposCount(mb, resp, repo)
				if err != nil {
					return err
				}
			}

			return updateHighScores(mb, resp, repo)
		})

		if err != nil {
			log.Println("Bolt writing error:", err)
		}
	}

	return
}

func updateHighScores(mb *bolt.Bucket, resp checksResp, repo string) error {
	// check if we need to update the high score list
	if resp.Files < 100 {
		// only repos with >= 100 files are considered for the high score list
		return nil
	}

	// start updating high score list
	scoreBytes := mb.Get([]byte("scores"))
	if scoreBytes == nil {
		scoreBytes, _ = json.Marshal([]scoreHeap{})
	}
	scores := &scoreHeap{}
	json.Unmarshal(scoreBytes, scores)

	heap.Init(scores)
	if len(*scores) > 0 && (*scores)[0].Score > resp.Average*100.0 && len(*scores) == 50 {
		// lowest score on list is higher than this repo's score, so no need to add, unless
		// we do not have 50 high scores yet
		return nil
	}
	// if this repo is already in the list, remove the original entry:
	for i := range *scores {
		if (*scores)[i].Repo == repo {
			heap.Remove(scores, i)
			break
		}
	}
	// now we can safely push it onto the heap
	heap.Push(scores, scoreItem{
		Repo:  repo,
		Score: resp.Average * 100.0,
		Files: resp.Files,
	})
	if len(*scores) > 50 {
		// trim heap if it's grown to over 50
		*scores = (*scores)[1:51]
	}
	scoreBytes, err := json.Marshal(&scores)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("scores"), scoreBytes)
	if err != nil {
		return err
	}

	return nil
}

func updateReposCount(mb *bolt.Bucket, resp checksResp, repo string) (err error) {
	log.Printf("New repo %q, adding to repo count...", repo)
	totalInt := 0
	total := mb.Get([]byte("total_repos"))
	if total != nil {
		err = json.Unmarshal(total, &totalInt)
		if err != nil {
			return fmt.Errorf("could not unmarshal total repos count: %v", err)
		}
	}
	totalInt++ // increase repo count
	total, err = json.Marshal(totalInt)
	if err != nil {
		return fmt.Errorf("could not marshal total repos count: %v", err)
	}
	mb.Put([]byte("total_repos"), total)
	log.Println("Repo count is now", totalInt)
	return nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/exercism/cli/config"
)

// Debug provides information about the user's environment and configuration.
func Debug(ctx *cli.Context) {
	defer fmt.Printf("\nIf you are having any issues, please contact kytrinyx@exercism.io with this information.\n")

	fmt.Printf("\n**** Debug Information ****\n")
	fmt.Printf("Exercism CLI Version: %s\n", ctx.App.Version)
	fmt.Printf("OS/Architecture: %s/%s\n", runtime.GOOS, runtime.GOARCH)

	dir, err := config.Home()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Home Dir: %s\n", dir)

	file, err := config.FilePath(ctx.GlobalString("config"))
	configured := true
	if _, err = os.Stat(file); err != nil {
		if os.IsNotExist(err) {
			configured = false
		} else {
			log.Fatal(err)
		}
	}

	c, err := config.Read(file)
	if err != nil {
		log.Fatal(err)
	}

	if configured {
		fmt.Printf("Config file: %s\n", c.File())
		fmt.Printf("API Key: %s\n", c.APIKey)
	} else {
		fmt.Println("Config file: <not configured>")
		fmt.Println("API Key: <not configured>")
	}
	fmt.Printf("API: %s\n", c.API)
	fmt.Printf("Exercises Directory: %s\n", c.Dir)
}
<commit_msg>Redirect to GitHub, not email in debug output<commit_after>package handlers

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/exercism/cli/config"
)

// Debug provides information about the user's environment and configuration.
func Debug(ctx *cli.Context) {
	defer fmt.Printf("\nIf you are having trouble and need to file a GitHub issue (https://github.com/exercism/exercism.io/issues) please include this information (except your API key. Keep that private).\n")

	fmt.Printf("\n**** Debug Information ****\n")
	fmt.Printf("Exercism CLI Version: %s\n", ctx.App.Version)
	fmt.Printf("OS/Architecture: %s/%s\n", runtime.GOOS, runtime.GOARCH)

	dir, err := config.Home()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Home Dir: %s\n", dir)

	file, err := config.FilePath(ctx.GlobalString("config"))
	configured := true
	if _, err = os.Stat(file); err != nil {
		if os.IsNotExist(err) {
			configured = false
		} else {
			log.Fatal(err)
		}
	}

	c, err := config.Read(file)
	if err != nil {
		log.Fatal(err)
	}

	if configured {
		fmt.Printf("Config file: %s\n", c.File())
		fmt.Printf("API Key: %s\n", c.APIKey)
	} else {
		fmt.Println("Config file: <not configured>")
		fmt.Println("API Key: <not configured>")
	}
	fmt.Printf("API: %s\n", c.API)
	fmt.Printf("Exercises Directory: %s\n", c.Dir)
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"jimmify-server/db"
	"jimmify-server/firebase"
	"net/http"
)

//PushEnabled whether or not to send push
var PushEnabled bool

//Query : submit a query
func Query(w http.ResponseWriter, r *http.Request) {
	var q db.Query
	response := make(map[string]interface{})

	//read json
	err := json.NewDecoder(r.Body).Decode(&q)
	if err != nil {
		ReturnStatusBadRequest(w, "Failed to decode query json")
		return
	}

	//validate data
	err = validateQuery(q)
	if err != nil {
		ReturnStatusBadRequest(w, err.Error())
		return
	}

	//add query
	isDupe, d := db.IsDuplicate(q.Text)
	key := d.Key
	if !isDupe {
		key, err = db.AddQuery(q)
		if err != nil {
			ReturnInternalServerError(w, err.Error())
			return
		}
	}

	if PushEnabled == true {
		firebase.Push("Jimmy Query", q.Text)
	}

	w.WriteHeader(http.StatusOK)
	response["key"] = key
	response["status"] = true
	json.NewEncoder(w).Encode(response)
}
<commit_msg>allow duplicates for now<commit_after>package handlers

import (
	"encoding/json"
	"jimmify-server/db"
	"jimmify-server/firebase"
	"net/http"
)

//PushEnabled whether or not to send push
var PushEnabled bool

//Query : submit a query
func Query(w http.ResponseWriter, r *http.Request) {
	var q db.Query
	response := make(map[string]interface{})

	//read json
	err := json.NewDecoder(r.Body).Decode(&q)
	if err != nil {
		ReturnStatusBadRequest(w, "Failed to decode query json")
		return
	}

	//validate data
	err = validateQuery(q)
	if err != nil {
		ReturnStatusBadRequest(w, err.Error())
		return
	}

	//add query
	//isDupe, d := db.IsDuplicate(q.Text) this line can stop duplicates
	key, err := db.AddQuery(q)
	if err != nil {
		ReturnInternalServerError(w, err.Error())
		return
	}

	if PushEnabled == true {
		firebase.Push("Jimmy Query", q.Text)
	}

	w.WriteHeader(http.StatusOK)
	response["key"] = key
	response["status"] = true
	json.NewEncoder(w).Encode(response)
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net"
	"net/http"
	"os"
	"strings"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/av-api/helpers"
	"github.com/byuoitav/av-api/state"
	"github.com/byuoitav/common/db"
	"github.com/byuoitav/common/inputgraph"
	"github.com/byuoitav/common/log"
	"github.com/fatih/color"
	"github.com/labstack/echo"
)

// GetRoomResource returns the resourceID for a request
func GetRoomResource(context echo.Context) string {
	return context.Param("building") + "-" + context.Param("room")
}

//GetRoomState to get the current state of a room
func GetRoomState(context echo.Context) error {
	building, room := context.Param("building"), context.Param("room")

	status, err := state.GetRoomState(building, room)
	if err != nil {
		return context.JSON(http.StatusBadRequest, err.Error())
	}

	return context.JSON(http.StatusOK, status)
}

//GetRoomByNameAndBuilding is almost identical to GetRoomByName
func GetRoomByNameAndBuilding(context echo.Context) error {
	building, roomName := context.Param("building"), context.Param("room")

	log.L.Info("Getting room...")
	room, err := db.GetDB().GetRoom(fmt.Sprintf("%s-%s", building, roomName))
	if err != nil {
		return context.JSON(http.StatusBadRequest, helpers.ReturnError(err))
	}

	//we need to add the input reachability stuff
	reachable, err := inputgraph.GetVideoDeviceReachability(room)

	log.L.Info("Done.\n")
	return context.JSON(http.StatusOK, reachable)
}

// SetRoomState to update the state of the room
func SetRoomState(context echo.Context) error {
	building, room := context.Param("building"), context.Param("room")

	log.L.Infof("%s", color.HiGreenString("[handlers] putting room changes..."))

	var roomInQuestion base.PublicRoom
	err := context.Bind(&roomInQuestion)
	if err != nil {
		return context.JSON(http.StatusBadRequest, helpers.ReturnError(err))
	}

	roomInQuestion.Room = room
	roomInQuestion.Building = building
	var report base.PublicRoom

	hn, err := net.LookupAddr(context.RealIP())
	color.Set(color.FgYellow, color.Bold)
	if err != nil {
		log.L.Debugf("REQUESTOR: %s", context.RealIP())
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, context.RealIP())
	} else if strings.Contains(hn[0], "localhost") {
		log.L.Debugf("REQUESTOR: %s", os.Getenv("SYSTEM_ID"))
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, os.Getenv("SYSTEM_ID"))
	} else {
		log.L.Debugf("REQUESTOR: %s", hn[0])
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, hn[0])
	}

	if err != nil {
		log.L.Errorf("Error: %s", err.Error())
		return context.JSON(http.StatusInternalServerError, helpers.ReturnError(err))
	}

	//hasError := helpers.CheckReport(report)

	log.L.Info("Done.\n")

	//if hasError {
	//	return context.JSON(http.StatusInternalServerError, report)
	//}

	return context.JSON(http.StatusOK, report)
}
<commit_msg>added timeout on dns lookup<commit_after>package handlers

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/byuoitav/av-api/base"
	"github.com/byuoitav/av-api/helpers"
	"github.com/byuoitav/av-api/state"
	"github.com/byuoitav/common/db"
	"github.com/byuoitav/common/inputgraph"
	"github.com/byuoitav/common/log"
	"github.com/fatih/color"
	"github.com/labstack/echo"
)

const (
	timeout = 50 * time.Millisecond
)

// GetRoomResource returns the resourceID for a request
func GetRoomResource(context echo.Context) string {
	return context.Param("building") + "-" + context.Param("room")
}

//GetRoomState to get the current state of a room
func GetRoomState(context echo.Context) error {
	building, room := context.Param("building"), context.Param("room")

	status, err := state.GetRoomState(building, room)
	if err != nil {
		return context.JSON(http.StatusBadRequest, err.Error())
	}

	return context.JSON(http.StatusOK, status)
}

//GetRoomByNameAndBuilding is almost identical to GetRoomByName
func GetRoomByNameAndBuilding(context echo.Context) error {
	building, roomName := context.Param("building"), context.Param("room")

	log.L.Info("Getting room...")
	room, err := db.GetDB().GetRoom(fmt.Sprintf("%s-%s", building, roomName))
	if err != nil {
		return context.JSON(http.StatusBadRequest, helpers.ReturnError(err))
	}

	//we need to add the input reachability stuff
	reachable, err := inputgraph.GetVideoDeviceReachability(room)

	log.L.Info("Done.\n")
	return context.JSON(http.StatusOK, reachable)
}

// SetRoomState to update the state of the room
func SetRoomState(ctx echo.Context) error {
	building, room := ctx.Param("building"), ctx.Param("room")

	log.L.Infof("%s", color.HiGreenString("[handlers] putting room changes..."))

	var roomInQuestion base.PublicRoom
	err := ctx.Bind(&roomInQuestion)
	if err != nil {
		return ctx.JSON(http.StatusBadRequest, helpers.ReturnError(err))
	}

	roomInQuestion.Room = room
	roomInQuestion.Building = building
	var report base.PublicRoom

	gctx, cancel := context.WithTimeout(context.TODO(), timeout)
	defer cancel()

	r := net.Resolver{}
	hn, err := r.LookupAddr(gctx, ctx.RealIP())

	color.Set(color.FgYellow, color.Bold)
	if err != nil || len(hn) == 0 {
		log.L.Debugf("REQUESTOR: %s", ctx.RealIP())
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, ctx.RealIP())
	} else if strings.Contains(hn[0], "localhost") {
		log.L.Debugf("REQUESTOR: %s", os.Getenv("SYSTEM_ID"))
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, os.Getenv("SYSTEM_ID"))
	} else {
		log.L.Debugf("REQUESTOR: %s", hn[0])
		color.Unset()
		report, err = state.SetRoomState(roomInQuestion, hn[0])
	}

	if err != nil {
		log.L.Errorf("Error: %s", err.Error())
		return ctx.JSON(http.StatusInternalServerError, helpers.ReturnError(err))
	}

	log.L.Info("Done.\n")

	return ctx.JSON(http.StatusOK, report)
}
<|endoftext|>


<commit_before>// Copyright © 2014-2015, Christian Vozar
// Licensed under the MIT License.
// http://opensource.org/licenses/MIT

// Code based on Atlassian HipChat API v1.

package hipchat

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/mozilla-services/heka/message"
	. "github.com/mozilla-services/heka/pipeline"
	"io/ioutil"
	"net/http"
	"net/url"
)

// HipchatOutput maintains high-level configuration options for the plugin.
type HipchatOutput struct {
	conf   *HipchatOutputConfig
	url    string
	format string
}

// Hipchat Output config struct
type HipchatOutputConfig struct {
	// Outputs the payload attribute in the HipChat message vs a full JSON message dump
	PayloadOnly bool `toml:"payload_only"`
	// HipChat Authorization token. Notification token is appropriate.
	AuthToken string `toml:"auth_token"`
	// Required. ID or name of the room.
	RoomID string `toml:"room_id"`
	// Required. Name the message will appear be sent. Must be less than 15
	// characters long. May contain letters, numbers, -, _, and spaces.
	From string
	// Whether or not this message should trigger a notification for people
	// in the room (change the tab color, play a sound, etc).
	// Each recipient's notification preferences are taken into account.
	// Default is false
	Notify bool
}

func (ho *HipchatOutput) ConfigStruct() interface{} {
	return &HipchatOutputConfig{
		PayloadOnly: true,
		From:        "Heka",
		Notify:      false,
	}
}

func (ho *HipchatOutput) sendMessage(mc string, s int32) error {
	messageUri := fmt.Sprintf("%s/rooms/message?auth_token=%s", ho.url, url.QueryEscape(ho.conf.AuthToken))

	messagePayload := url.Values{
		"room_id":        {ho.conf.RoomID},
		"from":           {ho.conf.From},
		"message":        {mc},
		"message_format": {ho.format},
	}

	if ho.conf.Notify == true {
		messagePayload.Add("notify", "1")
	}

	switch s {
	case 0, 1, 2, 3:
		messagePayload.Add("color", "red")
	case 4:
		messagePayload.Add("color", "yellow")
	case 5, 6:
		messagePayload.Add("color", "green")
	default:
		messagePayload.Add("color", "gray")
	}

	resp, err := http.PostForm(messageUri, messagePayload)
	if err != nil {
		return err
	}

	switch resp.StatusCode {
	case 400:
		return errors.New("Bad request.")
	case 401:
		return errors.New("Provided authentication rejected.")
	case 403:
		return errors.New("Rate limit exceeded.")
	case 406:
		return errors.New("Message contains invalid content type.")
	case 500:
		return errors.New("Internal server error.")
	case 503:
		return errors.New("Service unavailable.")
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	messageResponse := &struct{ Status string }{}
	if err := json.Unmarshal(body, messageResponse); err != nil {
		return err
	}
	if messageResponse.Status != "sent" {
		return errors.New("Status response was not sent.")
	}

	return nil
}

func (ho *HipchatOutput) Init(config interface{}) (err error) {
	ho.conf = config.(*HipchatOutputConfig)

	if ho.conf.RoomID == "" {
		return fmt.Errorf("room_id must contain a HipChat room ID or name")
	}

	if len(ho.conf.From) > 15 {
		return fmt.Errorf("from must be less than 15 characters")
	}

	ho.url = "https://api.hipchat.com/v1"
	ho.format = "text"
	return
}

func (ho *HipchatOutput) Run(or OutputRunner, h PluginHelper) (err error) {
	inChan := or.InChan()

	var (
		pack     *PipelinePack
		msg      *message.Message
		contents []byte
	)

	for pack = range inChan {
		msg = pack.Message
		if ho.conf.PayloadOnly {
			err = ho.sendMessage(msg.GetPayload(), msg.GetSeverity())
		} else {
			if contents, err = json.Marshal(msg); err == nil {
				err = ho.sendMessage(string(contents), msg.GetSeverity())
			} else {
				or.LogError(err)
			}
		}
		if err != nil {
			or.LogError(err)
		}
		pack.Recycle()
	}
	return
}

func init() {
	RegisterPlugin("HipchatOutput", func() interface{} {
		return new(HipchatOutput)
	})
}
<commit_msg>var messageUri should be messageURI<commit_after>// Copyright © 2014-2015, Christian Vozar
// Licensed under the MIT License.
// http://opensource.org/licenses/MIT

// Code based on Atlassian HipChat API v1.

package hipchat

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/mozilla-services/heka/message"
	. "github.com/mozilla-services/heka/pipeline"
	"io/ioutil"
	"net/http"
	"net/url"
)

// HipchatOutput maintains high-level configuration options for the plugin.
type HipchatOutput struct {
	conf   *HipchatOutputConfig
	url    string
	format string
}

// Hipchat Output config struct
type HipchatOutputConfig struct {
	// Outputs the payload attribute in the HipChat message vs a full JSON message dump
	PayloadOnly bool `toml:"payload_only"`
	// HipChat Authorization token. Notification token is appropriate.
	AuthToken string `toml:"auth_token"`
	// Required. ID or name of the room.
	RoomID string `toml:"room_id"`
	// Required. Name the message will appear be sent. Must be less than 15
	// characters long. May contain letters, numbers, -, _, and spaces.
	From string
	// Whether or not this message should trigger a notification for people
	// in the room (change the tab color, play a sound, etc).
	// Each recipient's notification preferences are taken into account.
	// Default is false
	Notify bool
}

func (ho *HipchatOutput) ConfigStruct() interface{} {
	return &HipchatOutputConfig{
		PayloadOnly: true,
		From:        "Heka",
		Notify:      false,
	}
}

func (ho *HipchatOutput) sendMessage(mc string, s int32) error {
	messageURI := fmt.Sprintf("%s/rooms/message?auth_token=%s", ho.url, url.QueryEscape(ho.conf.AuthToken))

	messagePayload := url.Values{
		"room_id":        {ho.conf.RoomID},
		"from":           {ho.conf.From},
		"message":        {mc},
		"message_format": {ho.format},
	}

	if ho.conf.Notify == true {
		messagePayload.Add("notify", "1")
	}

	switch s {
	case 0, 1, 2, 3:
		messagePayload.Add("color", "red")
	case 4:
		messagePayload.Add("color", "yellow")
	case 5, 6:
		messagePayload.Add("color", "green")
	default:
		messagePayload.Add("color", "gray")
	}

	resp, err := http.PostForm(messageURI, messagePayload)
	if err != nil {
		return err
	}

	switch resp.StatusCode {
	case 400:
		return errors.New("Bad request.")
	case 401:
		return errors.New("Provided authentication rejected.")
	case 403:
		return errors.New("Rate limit exceeded.")
	case 406:
		return errors.New("Message contains invalid content type.")
	case 500:
		return errors.New("Internal server error.")
	case 503:
		return errors.New("Service unavailable.")
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	messageResponse := &struct{ Status string }{}
	if err := json.Unmarshal(body, messageResponse); err != nil {
		return err
	}
	if messageResponse.Status != "sent" {
		return errors.New("Status response was not sent.")
	}

	return nil
}

func (ho *HipchatOutput) Init(config interface{}) (err error) {
	ho.conf = config.(*HipchatOutputConfig)

	if ho.conf.RoomID == "" {
		return fmt.Errorf("room_id must contain a HipChat room ID or name")
	}

	if len(ho.conf.From) > 15 {
		return fmt.Errorf("from must be less than 15 characters")
	}

	ho.url = "https://api.hipchat.com/v1"
	ho.format = "text"
	return
}

func (ho *HipchatOutput) Run(or OutputRunner, h PluginHelper) (err error) {
	inChan := or.InChan()

	var (
		pack     *PipelinePack
		msg      *message.Message
		contents []byte
	)

	for pack = range inChan {
		msg = pack.Message
		if ho.conf.PayloadOnly {
			err = ho.sendMessage(msg.GetPayload(), msg.GetSeverity())
		} else {
			if contents, err = json.Marshal(msg); err == nil {
				err = ho.sendMessage(string(contents), msg.GetSeverity())
			} else {
				or.LogError(err)
			}
		}
		if err != nil {
			or.LogError(err)
		}
		pack.Recycle()
	}
	return
}

func init() {
	RegisterPlugin("HipchatOutput", func() interface{} {
		return new(HipchatOutput)
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Couchbase, 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 indexer

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/couchbase/indexing/secondary/collatejson"
	"github.com/couchbase/indexing/secondary/logging"
	"sync"
)

// Key is an array of JSON objects, per encoding/json
type Key struct {
	raw     []byte //raw key received from KV
	encoded []byte //collatejson byte representation of the key
}

// Value is the primary key of the relavent document
type Value struct {
	raw     Valuedata
	encoded []byte
}

type Valuedata struct {
	Docid []byte
}

var codecPool = sync.Pool{New: newCodec}
var codecBufPool = sync.Pool{New: newCodecBuf}

func newCodec() interface{} {
	return collatejson.NewCodec(16)
}

func newCodecBuf() interface{} {
	return make([]byte, 0, MAX_SEC_KEY_BUFFER_LEN)
}

func NewKey(data []byte) (Key, error) {
	var err error
	var key Key

	if len(data) > MAX_SEC_KEY_LEN {
		return key, errors.New("Key Too Long")
	}

	key.raw = data

	if bytes.Compare([]byte("[]"), data) == 0 || len(data) == 0 {
		key.encoded = nil
		return key, nil
	}

	jsoncodec := codecPool.Get().(*collatejson.Codec)
	defer codecPool.Put(jsoncodec)
	//TODO collatejson needs 3x buffer size. see if that can
	//be reduced. Also reuse buffer.
	buf := codecBufPool.Get().([]byte)
	defer codecBufPool.Put(buf)
	if buf, err = jsoncodec.Encode(data, buf); err != nil {
		return key, err
	}

	key.encoded = append([]byte(nil), buf...)
	return key, nil
}

func NewValue(docid []byte) (Value, error) {

	var val Value

	val.raw.Docid = docid

	var err error
	if val.encoded, err = json.Marshal(val.raw); err != nil {
		return val, err
	}
	return val, nil
}

func NewKeyFromEncodedBytes(encoded []byte) (Key, error) {

	var k Key
	k.encoded = encoded
	return k, nil

}

func NewValueFromEncodedBytes(b []byte) (Value, error) {

	var val Value
	var err error
	if b != nil {
		err = json.Unmarshal(b, &val.raw)
	}
	val.encoded = b
	return val, err

}

func (k *Key) Compare(than Key) int {

	b1 := k.encoded
	b2 := than.Encoded()
	return bytes.Compare(b1, b2)
}

func (k *Key) Encoded() []byte {

	return k.encoded
}

func (k *Key) Raw() []byte {

	var err error
	if k.raw == nil && k.encoded != nil {
		jsoncodec := collatejson.NewCodec(16)
		// TODO: Refactor to reuse tmp buffer
		buf := make([]byte, 0, MAX_SEC_KEY_LEN)
		if buf, err = jsoncodec.Decode(k.encoded, buf); err != nil {
			logging.Errorf("KV::Raw Error Decoding Key %v, Err %v", k.encoded,
				err)
			return nil
		}
		k.raw = append([]byte(nil), buf...)
	}

	return k.raw
}

func (k *Key) IsNull() bool {
	return k.encoded == nil
}

func (k *Key) String() string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("%v", string(k.raw)))
	return buf.String()
}

func (v *Value) Encoded() []byte {
	return v.encoded
}

func (v *Value) Raw() Valuedata {
	return v.raw
}

func (v *Value) Docid() []byte {
	return v.raw.Docid
}

func (v *Value) String() string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("Docid:%v ", v.raw.Docid))
	return buf.String()
}
<commit_msg>MB-13590 Remove json encoding for back index key<commit_after>// Copyright (c) 2013 Couchbase, 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 indexer

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/couchbase/indexing/secondary/collatejson"
	"github.com/couchbase/indexing/secondary/logging"
	"sync"
)

// Key is an array of JSON objects, per encoding/json
type Key struct {
	raw     []byte //raw key received from KV
	encoded []byte //collatejson byte representation of the key
}

// Value is the primary key of the relavent document
type Value []byte

var codecPool = sync.Pool{New: newCodec}
var codecBufPool = sync.Pool{New: newCodecBuf}

func newCodec() interface{} {
	return collatejson.NewCodec(16)
}

func newCodecBuf() interface{} {
	return make([]byte, 0, MAX_SEC_KEY_BUFFER_LEN)
}

func NewKey(data []byte) (Key, error) {
	var err error
	var key Key

	if len(data) > MAX_SEC_KEY_LEN {
		return key, errors.New("Key Too Long")
	}

	key.raw = data

	if bytes.Compare([]byte("[]"), data) == 0 || len(data) == 0 {
		key.encoded = nil
		return key, nil
	}

	jsoncodec := codecPool.Get().(*collatejson.Codec)
	defer codecPool.Put(jsoncodec)
	//TODO collatejson needs 3x buffer size. see if that can
	//be reduced. Also reuse buffer.
	buf := codecBufPool.Get().([]byte)
	defer codecBufPool.Put(buf)
	if buf, err = jsoncodec.Encode(data, buf); err != nil {
		return key, err
	}

	key.encoded = append([]byte(nil), buf...)
	return key, nil
}

func NewValue(docid []byte) (Value, error) {

	val := Value(docid)
	return val, nil
}

func NewKeyFromEncodedBytes(encoded []byte) (Key, error) {

	var k Key
	k.encoded = encoded
	return k, nil

}

func NewValueFromEncodedBytes(b []byte) (Value, error) {

	val := Value(b)
	return val, nil

}

func (k *Key) Compare(than Key) int {

	b1 := k.encoded
	b2 := than.Encoded()
	return bytes.Compare(b1, b2)
}

func (k *Key) Encoded() []byte {

	return k.encoded
}

func (k *Key) Raw() []byte {

	var err error
	if k.raw == nil && k.encoded != nil {
		jsoncodec := collatejson.NewCodec(16)
		// TODO: Refactor to reuse tmp buffer
		buf := make([]byte, 0, MAX_SEC_KEY_LEN)
		if buf, err = jsoncodec.Decode(k.encoded, buf); err != nil {
			logging.Errorf("KV::Raw Error Decoding Key %v, Err %v", k.encoded,
				err)
			return nil
		}
		k.raw = append([]byte(nil), buf...)
	}

	return k.raw
}

func (k *Key) IsNull() bool {
	return k.encoded == nil
}

func (k *Key) String() string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("%v", string(k.raw)))
	return buf.String()
}

func (v *Value) Encoded() []byte {
	return []byte(*v)
}

func (v *Value) Raw() []byte {
	return []byte(*v)
}

func (v *Value) Docid() []byte {
	return []byte(*v)
}

func (v *Value) String() string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("Docid:%s ", string(*v)))
	return buf.String()
}
<|endoftext|>


<commit_before>package section

import (
	"fmt"
)

// This a simple example
func Example() {
	s := Ibeam{H: 0.1, B: 0.1, Tf: 0.005, Tw: 0.002}
	fmt.Printf("Moment inertia of I-beam by axe X is %.4e m^-4", s.Jx())
	// Output: Moment inertia of I-beam by axe X is 2.3798e-06 m^-4
}

// This is a simple example
func ExamplePlate() {
	plate := Plate{Height: 0.080 /* meter */, Thickness: 0.008 /* meter */}
	fmt.Printf("Area of plate is %.1e m^2\n", plate.Area())
	// Output: Area of plate is 6.4e-4 m^2
}
<commit_msg>Fix test<commit_after>package section

import (
	"fmt"
)

// This a simple example
func Example() {
	s := Ibeam{H: 0.1, B: 0.1, Tf: 0.005, Tw: 0.002}
	fmt.Printf("Moment inertia of I-beam by axe X is %.4e m^-4", s.Jx())
	// Output: Moment inertia of I-beam by axe X is 2.3798e-06 m^-4
}

// This is a simple example
func ExamplePlate() {
	plate := Plate{Height: 0.080 /* meter */, Thickness: 0.008 /* meter */}
	fmt.Printf("Area of plate is %.1e m^2\n", plate.Area())
	// Output: Area of plate is 6.4e-04 m^2
}
<|endoftext|>


<commit_before>package brew

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"log"
	"strings"
	"text/template"

	"github.com/google/go-github/github"
	"github.com/goreleaser/releaser/config"
	"github.com/goreleaser/releaser/split"
	"golang.org/x/oauth2"
)

const formulae = `class {{ .Name }} < Formula
  desc "{{ .Desc }}"
  homepage "{{ .Homepage }}"
  url "https://github.com/{{ .Repo }}/releases/download/{{ .Tag }}/{{ .BinaryName }}_#{%x(uname -s).gsub(/\n/, '')}_#{%x(uname -m).gsub(/\n/, '')}.tar.gz"
  head "https://github.com/{{ .Repo }}.git"
  version "{{ .Tag }}"

  def install
    bin.install "{{ .BinaryName }}"
  end

  {{ if .Caveats }}def caveats
    "{{ .Caveats }}"
  end{{ end }}
end
`

type templateData struct {
	Name, Desc, Homepage, Repo, Tag, BinaryName, Caveats string
}

type Pipe struct{}

func (Pipe) Name() string {
	return "Homebrew"
}

func (Pipe) Work(config config.ProjectConfig) error {
	if config.Brew.Repo == "" {
		return nil
	}
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config.Token},
	)
	tc := oauth2.NewClient(context.Background(), ts)
	client := github.NewClient(tc)

	owner, repo := split.OnSlash(config.Brew.Repo)
	name := config.BinaryName + ".rb"

	log.Println("Updating", name, "on", config.Repo, "...")
	out, err := buildFormulae(config, client)
	if err != nil {
		return err
	}
	sha, err := sha(client, owner, repo, name, out)
	if err != nil {
		return err
	}
	_, _, err = client.Repositories.UpdateFile(
		owner, repo, name, &github.RepositoryContentFileOptions{
			Committer: &github.CommitAuthor{
				Name:  github.String("goreleaserbot"),
				Email: github.String("bot@goreleaser"),
			},
			Content: out.Bytes(),
			Message: github.String(config.BinaryName + " version " + config.Git.CurrentTag),
			SHA:     sha,
		},
	)
	return err
}
func sha(client *github.Client, owner, repo, name string, out bytes.Buffer) (*string, error) {
	var sha *string
	file, _, _, err := client.Repositories.GetContents(
		owner, repo, name, &github.RepositoryContentGetOptions{},
	)
	if err == nil {
		sha = file.SHA
	} else {
		sha = github.String(fmt.Sprintf("%s", sha256.Sum256(out.Bytes())))
	}
	return sha, err
}

func buildFormulae(config config.ProjectConfig, client *github.Client) (bytes.Buffer, error) {
	data, err := dataFor(config, client)
	if err != nil {
		return bytes.Buffer{}, err
	}
	return doBuildFormulae(data)
}

func doBuildFormulae(data templateData) (bytes.Buffer, error) {
	var out bytes.Buffer
	tmpl, err := template.New(data.BinaryName).Parse(formulae)
	if err != nil {
		return out, err
	}
	err = tmpl.Execute(&out, data)
	return out, err
}

func dataFor(config config.ProjectConfig, client *github.Client) (result templateData, err error) {
	var homepage string
	var description string
	owner, repo := split.OnSlash(config.Repo)
	rep, _, err := client.Repositories.Get(owner, repo)
	if err != nil {
		return result, err
	}
	if rep.Homepage == nil {
		homepage = *rep.HTMLURL
	} else {
		homepage = *rep.Homepage
	}
	if rep.Description == nil {
		description = "TODO"
	} else {
		description = *rep.Description
	}
	return templateData{
		Name:       formulaNameFor(config.BinaryName),
		Desc:       description,
		Homepage:   homepage,
		Repo:       config.Repo,
		Tag:        config.Git.CurrentTag,
		BinaryName: config.BinaryName,
		Caveats:    config.Brew.Caveats,
	}, err
}

func formulaNameFor(name string) string {
	name = strings.Replace(name, "-", " ", -1)
	name = strings.Replace(name, "_", " ", -1)
	return strings.Replace(strings.Title(name), " ", "", -1)
}
<commit_msg>wrong log<commit_after>package brew

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"log"
	"strings"
	"text/template"

	"github.com/google/go-github/github"
	"github.com/goreleaser/releaser/config"
	"github.com/goreleaser/releaser/split"
	"golang.org/x/oauth2"
)

const formulae = `class {{ .Name }} < Formula
  desc "{{ .Desc }}"
  homepage "{{ .Homepage }}"
  url "https://github.com/{{ .Repo }}/releases/download/{{ .Tag }}/{{ .BinaryName }}_#{%x(uname -s).gsub(/\n/, '')}_#{%x(uname -m).gsub(/\n/, '')}.tar.gz"
  head "https://github.com/{{ .Repo }}.git"
  version "{{ .Tag }}"

  def install
    bin.install "{{ .BinaryName }}"
  end

  {{ if .Caveats }}def caveats
    "{{ .Caveats }}"
  end{{ end }}
end
`

type templateData struct {
	Name, Desc, Homepage, Repo, Tag, BinaryName, Caveats string
}

type Pipe struct{}

func (Pipe) Name() string {
	return "Homebrew"
}

func (Pipe) Work(config config.ProjectConfig) error {
	if config.Brew.Repo == "" {
		return nil
	}
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config.Token},
	)
	tc := oauth2.NewClient(context.Background(), ts)
	client := github.NewClient(tc)

	owner, repo := split.OnSlash(config.Brew.Repo)
	name := config.BinaryName + ".rb"

	log.Println("Updating", name, "on", config.Brew.Repo, "...")
	out, err := buildFormulae(config, client)
	if err != nil {
		return err
	}
	sha, err := sha(client, owner, repo, name, out)
	if err != nil {
		return err
	}
	_, _, err = client.Repositories.UpdateFile(
		owner, repo, name, &github.RepositoryContentFileOptions{
			Committer: &github.CommitAuthor{
				Name:  github.String("goreleaserbot"),
				Email: github.String("bot@goreleaser"),
			},
			Content: out.Bytes(),
			Message: github.String(config.BinaryName + " version " + config.Git.CurrentTag),
			SHA:     sha,
		},
	)
	return err
}
func sha(client *github.Client, owner, repo, name string, out bytes.Buffer) (*string, error) {
	var sha *string
	file, _, _, err := client.Repositories.GetContents(
		owner, repo, name, &github.RepositoryContentGetOptions{},
	)
	if err == nil {
		sha = file.SHA
	} else {
		sha = github.String(fmt.Sprintf("%s", sha256.Sum256(out.Bytes())))
	}
	return sha, err
}

func buildFormulae(config config.ProjectConfig, client *github.Client) (bytes.Buffer, error) {
	data, err := dataFor(config, client)
	if err != nil {
		return bytes.Buffer{}, err
	}
	return doBuildFormulae(data)
}

func doBuildFormulae(data templateData) (bytes.Buffer, error) {
	var out bytes.Buffer
	tmpl, err := template.New(data.BinaryName).Parse(formulae)
	if err != nil {
		return out, err
	}
	err = tmpl.Execute(&out, data)
	return out, err
}

func dataFor(config config.ProjectConfig, client *github.Client) (result templateData, err error) {
	var homepage string
	var description string
	owner, repo := split.OnSlash(config.Repo)
	rep, _, err := client.Repositories.Get(owner, repo)
	if err != nil {
		return result, err
	}
	if rep.Homepage == nil {
		homepage = *rep.HTMLURL
	} else {
		homepage = *rep.Homepage
	}
	if rep.Description == nil {
		description = "TODO"
	} else {
		description = *rep.Description
	}
	return templateData{
		Name:       formulaNameFor(config.BinaryName),
		Desc:       description,
		Homepage:   homepage,
		Repo:       config.Repo,
		Tag:        config.Git.CurrentTag,
		BinaryName: config.BinaryName,
		Caveats:    config.Brew.Caveats,
	}, err
}

func formulaNameFor(name string) string {
	name = strings.Replace(name, "-", " ", -1)
	name = strings.Replace(name, "_", " ", -1)
	return strings.Replace(strings.Title(name), " ", "", -1)
}
<|endoftext|>


<commit_before>package util

import (
	"crypto/rand"
	"math/big"
	"net/http"
	"time"

	"github.com/jetstack/cert-manager/pkg/logs"
)

// RetryBackoff is the ACME client RetryBackoff that filters rate limit errors to our retry loop
// inspired by acme/http.go
func RetryBackoff(n int, r *http.Request, res *http.Response) time.Duration {
	var jitter time.Duration
	if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
		// Set the minimum to 1ms to avoid a case where
		// an invalid Retry-After value is parsed into 0 below,
		// resulting in the 0 returned value which would unintentionally
		// stop the retries.
		jitter = (1 + time.Duration(x.Int64())) * time.Millisecond
	}
	if _, ok := res.Header["Retry-After"]; ok {
		// if Retry-After is set we should
		// error and let the cert-manager logic retry instead
		return -1
	}

	// don't retry more than 10 times
	if n > 10 {
		return -1
	}

	// classic backoff here in case we got no reply
	// eg. flakes
	if n < 1 {
		n = 1
	}

	d := time.Duration(1<<uint(n-1))*time.Second + jitter
	logs.Log.V(logs.DebugLevel).WithValues("backoff", d).Info("Hit an error in golang.org/x/crypto/acme, retrying")
	if d > 10*time.Second {
		return 10 * time.Second
	}
	return d
}
<commit_msg>Add license<commit_after>/*
Copyright 2020 The Jetstack cert-manager contributors.

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 util

import (
	"crypto/rand"
	"math/big"
	"net/http"
	"time"

	"github.com/jetstack/cert-manager/pkg/logs"
)

// RetryBackoff is the ACME client RetryBackoff that filters rate limit errors to our retry loop
// inspired by acme/http.go
func RetryBackoff(n int, r *http.Request, res *http.Response) time.Duration {
	var jitter time.Duration
	if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
		// Set the minimum to 1ms to avoid a case where
		// an invalid Retry-After value is parsed into 0 below,
		// resulting in the 0 returned value which would unintentionally
		// stop the retries.
		jitter = (1 + time.Duration(x.Int64())) * time.Millisecond
	}
	if _, ok := res.Header["Retry-After"]; ok {
		// if Retry-After is set we should
		// error and let the cert-manager logic retry instead
		return -1
	}

	// don't retry more than 10 times
	if n > 10 {
		return -1
	}

	// classic backoff here in case we got no reply
	// eg. flakes
	if n < 1 {
		n = 1
	}

	d := time.Duration(1<<uint(n-1))*time.Second + jitter
	logs.Log.V(logs.DebugLevel).WithValues("backoff", d).Info("Hit an error in golang.org/x/crypto/acme, retrying")
	if d > 10*time.Second {
		return 10 * time.Second
	}
	return d
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package terror

import (
	"fmt"
	"testing"

	"github.com/juju/errors"
	. "github.com/pingcap/check"
)

func TestT(t *testing.T) {
	TestingT(t)
}

var _ = Suite(&testTErrorSuite{})

type testTErrorSuite struct {
}

func (s *testTErrorSuite) TestTError(c *C) {
	c.Assert(ClassParser.String(), Not(Equals), "")
	c.Assert(ClassOptimizer.String(), Not(Equals), "")
	c.Assert(ClassKV.String(), Not(Equals), "")
	c.Assert(ClassServer.String(), Not(Equals), "")

	parserErr := ClassParser.New(ErrCode(1), "error 1")
	c.Assert(parserErr.Error(), Not(Equals), "")
	c.Assert(ClassParser.EqualClass(parserErr), IsTrue)
	c.Assert(ClassParser.NotEqualClass(parserErr), IsFalse)

	c.Assert(ClassOptimizer.EqualClass(parserErr), IsFalse)
	optimizerErr := ClassOptimizer.New(ErrCode(2), "abc")
	c.Assert(ClassOptimizer.EqualClass(errors.New("abc")), IsFalse)
	c.Assert(ClassOptimizer.EqualClass(nil), IsFalse)
	c.Assert(optimizerErr.Equal(optimizerErr.Gen("def")), IsTrue)
	c.Assert(optimizerErr.Equal(nil), IsFalse)
	c.Assert(optimizerErr.Equal(errors.New("abc")), IsFalse)
}

var predefinedErr = ClassExecutor.New(ErrCode(123), "predefiend error")

func example() error {
	return predefinedErr.Gen("error message:%s", "abc")
}

func (s *testTErrorSuite) TestExample(c *C) {
	err := example()
	fmt.Println(errors.ErrorStack(err))
}

func (s *testTErrorSuite) TestErrorEqual(c *C) {
	e1 := errors.New("test error")
	c.Assert(e1, NotNil)

	e2 := errors.Trace(e1)
	c.Assert(e2, NotNil)

	e3 := errors.Trace(e2)
	c.Assert(e3, NotNil)

	c.Assert(errors.Cause(e2), Equals, e1)
	c.Assert(errors.Cause(e3), Equals, e1)
	c.Assert(errors.Cause(e2), Equals, errors.Cause(e3))

	e4 := errors.New("test error")
	c.Assert(errors.Cause(e4), Not(Equals), e1)

	e5 := errors.Errorf("test error")
	c.Assert(errors.Cause(e5), Not(Equals), e1)

	c.Assert(ErrorEqual(e1, e2), IsTrue)
	c.Assert(ErrorEqual(e1, e3), IsTrue)
	c.Assert(ErrorEqual(e1, e4), IsTrue)
	c.Assert(ErrorEqual(e1, e5), IsTrue)

	var e6 error

	c.Assert(ErrorEqual(nil, nil), IsTrue)
	c.Assert(ErrorNotEqual(e1, e6), IsTrue)
	code1 := ErrCode(1)
	code2 := ErrCode(2)
	te1 := ClassParser.New(code1, "abc")
	te2 := ClassParser.New(code1, "def")
	te3 := ClassKV.New(code1, "abc")
	te4 := ClassKV.New(code2, "abc")
	c.Assert(ErrorEqual(te1, te2), IsTrue)
	c.Assert(ErrorEqual(te1, te3), IsFalse)
	c.Assert(ErrorEqual(te3, te4), IsFalse)
}
<commit_msg>terror: improve test.<commit_after>// Copyright 2015 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package terror

import (
	"testing"

	"github.com/juju/errors"
	. "github.com/pingcap/check"
	"strings"
)

func TestT(t *testing.T) {
	TestingT(t)
}

var _ = Suite(&testTErrorSuite{})

type testTErrorSuite struct {
}

func (s *testTErrorSuite) TestTError(c *C) {
	c.Assert(ClassParser.String(), Not(Equals), "")
	c.Assert(ClassOptimizer.String(), Not(Equals), "")
	c.Assert(ClassKV.String(), Not(Equals), "")
	c.Assert(ClassServer.String(), Not(Equals), "")

	parserErr := ClassParser.New(ErrCode(1), "error 1")
	c.Assert(parserErr.Error(), Not(Equals), "")
	c.Assert(ClassParser.EqualClass(parserErr), IsTrue)
	c.Assert(ClassParser.NotEqualClass(parserErr), IsFalse)

	c.Assert(ClassOptimizer.EqualClass(parserErr), IsFalse)
	optimizerErr := ClassOptimizer.New(ErrCode(2), "abc")
	c.Assert(ClassOptimizer.EqualClass(errors.New("abc")), IsFalse)
	c.Assert(ClassOptimizer.EqualClass(nil), IsFalse)
	c.Assert(optimizerErr.Equal(optimizerErr.Gen("def")), IsTrue)
	c.Assert(optimizerErr.Equal(nil), IsFalse)
	c.Assert(optimizerErr.Equal(errors.New("abc")), IsFalse)
}

var predefinedErr = ClassExecutor.New(ErrCode(123), "predefiend error")

func example() error {
	err := call()
	return errors.Trace(err)
}

func call() error {
	return predefinedErr.Gen("error message:%s", "abc")
}

func (s *testTErrorSuite) TestTraceAndLocation(c *C) {
	err := example()
	stack := errors.ErrorStack(err)
	lines := strings.Split(stack, "\n")
	c.Assert(len(lines), Equals, 2)
	for _, v := range lines {
		c.Assert(strings.Contains(v, "terror_test.go"), IsTrue)
	}
}

func (s *testTErrorSuite) TestErrorEqual(c *C) {
	e1 := errors.New("test error")
	c.Assert(e1, NotNil)

	e2 := errors.Trace(e1)
	c.Assert(e2, NotNil)

	e3 := errors.Trace(e2)
	c.Assert(e3, NotNil)

	c.Assert(errors.Cause(e2), Equals, e1)
	c.Assert(errors.Cause(e3), Equals, e1)
	c.Assert(errors.Cause(e2), Equals, errors.Cause(e3))

	e4 := errors.New("test error")
	c.Assert(errors.Cause(e4), Not(Equals), e1)

	e5 := errors.Errorf("test error")
	c.Assert(errors.Cause(e5), Not(Equals), e1)

	c.Assert(ErrorEqual(e1, e2), IsTrue)
	c.Assert(ErrorEqual(e1, e3), IsTrue)
	c.Assert(ErrorEqual(e1, e4), IsTrue)
	c.Assert(ErrorEqual(e1, e5), IsTrue)

	var e6 error

	c.Assert(ErrorEqual(nil, nil), IsTrue)
	c.Assert(ErrorNotEqual(e1, e6), IsTrue)
	code1 := ErrCode(1)
	code2 := ErrCode(2)
	te1 := ClassParser.New(code1, "abc")
	te2 := ClassParser.New(code1, "def")
	te3 := ClassKV.New(code1, "abc")
	te4 := ClassKV.New(code2, "abc")
	c.Assert(ErrorEqual(te1, te2), IsTrue)
	c.Assert(ErrorEqual(te1, te3), IsFalse)
	c.Assert(ErrorEqual(te3, te4), IsFalse)
}
<|endoftext|>


<commit_before>package cluster

import (
	"github.com/hashicorp/go-msgpack/codec"

	"github.com/smancke/guble/protocol"

	"errors"
	"unsafe"
)

type messageType int

var (
	mh codec.MsgpackHandle
	h  = &mh // or mh to use msgpack
)

const (
	NEXT_ID_RESPONSE messageType = iota

	NEXT_ID_REQUEST

	// Guble protocol.Message
	MESSAGE

	STRING_BODY_MESSAGE
)

type message struct {
	NodeID int
	Type   messageType
	Body   []byte
}

func (cmsg *message) encode() ([]byte, error) {
	logger.WithField("clusterMessage", cmsg).Debug("encode")
	encodedBytes := make([]byte, cmsg.len()+5)
	encoder := codec.NewEncoderBytes(&encodedBytes, h)
	err := encoder.Encode(cmsg)
	if err != nil {
		logger.WithField("err", err).Error("Encoding failed")
		return nil, err
	}
	return encodedBytes, nil
}

func (cmsg *message) len() int {
	return int(unsafe.Sizeof(cmsg.Type)) + int(unsafe.Sizeof(cmsg.NodeID)) + len(cmsg.Body)
}

func decode(msgBytes []byte) (*message, error) {
	var cmsg message
	logger.WithField("clusterMessageBytes", string(msgBytes)).Debug("decode")

	decoder := codec.NewDecoderBytes(msgBytes, h)
	err := decoder.Decode(&cmsg)
	if err != nil {
		logger.WithField("err", err).Error("Decoding failed")
		return nil, err
	}
	return &cmsg, nil
}

// ParseMessage parses a message, sent from the server to the client.
// The parsed messages can have one of the types: *Message or *NotificationMessage or *NextID
func ParseMessage(cmsg *message) (interface{}, error) {

	switch cmsg.Type {
	case NEXT_ID_REQUEST:

		response, err := DecodeNextID(cmsg.Body)
		if err != nil {
			logger.WithField("err", err).Error("Decoding of NextId Message failed")
			return nil, err
		}
		return response, nil
	case MESSAGE:
		response, err := protocol.ParseMessage(cmsg.Body)
		if err != nil {
			logger.WithField("err", err).Error("Decoding of protocol.Message failed")
			return nil, err
		}
		return response, nil
	default:
		logger.Error("Unknown cluster message type")
		return nil, errors.New("Unkown message type")
	}

}
<commit_msg>refactoring in codec<commit_after>package cluster

import (
	"github.com/hashicorp/go-msgpack/codec"

	"github.com/smancke/guble/protocol"

	"errors"
	"unsafe"
)

type messageType int

var (
	mh codec.MsgpackHandle
	h  = &mh // or mh to use msgpack
)

const (
	NEXT_ID_RESPONSE messageType = iota

	NEXT_ID_REQUEST

	// Guble protocol.Message
	MESSAGE

	STRING_BODY_MESSAGE
)

type message struct {
	NodeID int
	Type   messageType
	Body   []byte
}

func (cmsg *message) encode() ([]byte, error) {
	logger.WithField("clusterMessage", cmsg).Debug("encode")
	encodedBytes := make([]byte, cmsg.len()+5)
	encoder := codec.NewEncoderBytes(&encodedBytes, h)
	err := encoder.Encode(cmsg)
	if err != nil {
		logger.WithField("err", err).Error("Encoding failed")
		return nil, err
	}
	return encodedBytes, nil
}

func (cmsg *message) len() int {
	return int(unsafe.Sizeof(cmsg.Type)) + int(unsafe.Sizeof(cmsg.NodeID)) + len(cmsg.Body)
}

func decode(msgBytes []byte) (*message, error) {
	var cmsg message
	logger.WithField("clusterMessageBytes", string(msgBytes)).Debug("decode")

	decoder := codec.NewDecoderBytes(msgBytes, h)
	err := decoder.Decode(&cmsg)
	if err != nil {
		logger.WithField("err", err).Error("Decoding failed")
		return nil, err
	}
	return &cmsg, nil
}

// ParseMessage parses a message, sent from the server to the client.
// The parsed messages can have one of the types: *Message or *NextID
func ParseMessage(cmsg *message) (interface{}, error) {
	switch cmsg.Type {
	case NEXT_ID_REQUEST:
		response, err := DecodeNextID(cmsg.Body)
		if err != nil {
			logger.WithField("err", err).Error("Decoding of NextId Message failed")
			return nil, err
		}
		return response, nil
	case MESSAGE:
		response, err := protocol.ParseMessage(cmsg.Body)
		if err != nil {
			logger.WithField("err", err).Error("Decoding of protocol.Message failed")
			return nil, err
		}
		return response, nil
	default:
		errorMessage := "Unknown cluster message type"
		logger.Error(errorMessage)
		return nil, errors.New(errorMessage)
	}
}
<|endoftext|>