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

// nolint:errcheck
package k8sclient

import (
	"log"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws/awsutil"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes/fake"
)

var podArray = []interface{}{
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "bc5f5839-f62e-44b9-a79e-af250d92dcb1",
			Name:      "kube-proxy-csm88",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-csm88",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "75ab40d2-552a-4c05-82c9-0ddcb3008657",
			Name:      "coredns-7554568866-26jdf",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/coredns-7554568866-26jdf",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "b0280963-d68a-4096-ac56-4ecfbaee37f6",
			Name:      "aws-node-wf7jj",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/aws-node-wf7jj",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "eb09849f-b3f6-4c2c-ba4a-3e2c6eaf24f4",
			Name:      "cloudwatch-agent-rnjfp",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-rnjfp",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "11d078c2-6fed-49c3-83a8-b94915a6451f",
			Name:      "guestbook-qbdv8",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-qbdv8",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "52a76177-8431-400c-95b2-109f9b28b3b1",
			Name:      "kube-proxy-v5l9h",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-v5l9h",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "bb003966-4134-4ebf-9be3-dfb1741a1499",
			Name:      "redis-slave-mdjsj",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/redis-slave-mdjsj",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "440854dd-73e8-4616-b21a-3a63831d27e3",
			Name:      "guestbook-qjqnz",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-qjqnz",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "b79e85a1-1fc8-439c-b3a5-bd854ed29e10",
			Name:      "kube-proxy-h5tsv",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-h5tsv",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "f9ecca30-f5de-4809-9b63-79dc8369a0a6",
			Name:      "cloudwatch-agent-ksd26",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-ksd26",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "cfc496eb-2e5e-490e-9547-f0fe5399c219",
			Name:      "aws-node-pqxp2",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/aws-node-pqxp2",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "20d46c94-5341-429d-af0c-55d97314db7b",
			Name:      "cloudwatch-agent-2x7p4",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-2x7p4",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "885c6c56-da31-4a63-b823-eed50172193d",
			Name:      "guestbook-92wmq",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-92wmq",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
}

func TestPodClient_NamespaceToRunningPodNum(t *testing.T) {
	setOption := podSyncCheckerOption(&mockReflectorSyncChecker{})

	fakeClientSet := fake.NewSimpleClientset()
	client := newPodClient(fakeClientSet, zap.NewNop(), setOption)
	client.store.Replace(podArray, "")
	client.refresh()

	expectedMap := map[string]int{
		"kube-system": 6,
		"default":     7,
	}
	resultMap := client.NamespaceToRunningPodNum()
	log.Printf("NamespaceToRunningPodNum (len=%v): %v", len(resultMap), awsutil.Prettify(resultMap))
	assert.True(t, reflect.DeepEqual(resultMap, expectedMap))
	client.shutdown()
	assert.True(t, client.stopped)
}

func TestTransformFuncPod(t *testing.T) {
	info, err := transformFuncPod(nil)
	assert.Nil(t, info)
	assert.NotNil(t, err)
}
<commit_msg>[internal/k8s/k8sclient] Skip flaky TestPodClient_NamespaceToRunningP… (#11079)<commit_after>// Copyright  OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// nolint:errcheck
package k8sclient

import (
	"log"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws/awsutil"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes/fake"
)

var podArray = []interface{}{
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "bc5f5839-f62e-44b9-a79e-af250d92dcb1",
			Name:      "kube-proxy-csm88",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-csm88",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "75ab40d2-552a-4c05-82c9-0ddcb3008657",
			Name:      "coredns-7554568866-26jdf",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/coredns-7554568866-26jdf",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "b0280963-d68a-4096-ac56-4ecfbaee37f6",
			Name:      "aws-node-wf7jj",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/aws-node-wf7jj",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "eb09849f-b3f6-4c2c-ba4a-3e2c6eaf24f4",
			Name:      "cloudwatch-agent-rnjfp",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-rnjfp",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "11d078c2-6fed-49c3-83a8-b94915a6451f",
			Name:      "guestbook-qbdv8",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-qbdv8",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "52a76177-8431-400c-95b2-109f9b28b3b1",
			Name:      "kube-proxy-v5l9h",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-v5l9h",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "bb003966-4134-4ebf-9be3-dfb1741a1499",
			Name:      "redis-slave-mdjsj",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/redis-slave-mdjsj",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "440854dd-73e8-4616-b21a-3a63831d27e3",
			Name:      "guestbook-qjqnz",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-qjqnz",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "b79e85a1-1fc8-439c-b3a5-bd854ed29e10",
			Name:      "kube-proxy-h5tsv",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/kube-proxy-h5tsv",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "f9ecca30-f5de-4809-9b63-79dc8369a0a6",
			Name:      "cloudwatch-agent-ksd26",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-ksd26",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "cfc496eb-2e5e-490e-9547-f0fe5399c219",
			Name:      "aws-node-pqxp2",
			Namespace: "kube-system",
			SelfLink:  "/api/v1/namespaces/kube-system/pods/aws-node-pqxp2",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "20d46c94-5341-429d-af0c-55d97314db7b",
			Name:      "cloudwatch-agent-2x7p4",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/cloudwatch-agent-2x7p4",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
	&v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			UID:       "885c6c56-da31-4a63-b823-eed50172193d",
			Name:      "guestbook-92wmq",
			Namespace: "default",
			SelfLink:  "/api/v1/namespaces/default/pods/guestbook-92wmq",
		},
		Status: v1.PodStatus{
			Phase: "Running",
		},
	},
}

// workaround to avoid "unused" lint errors which test is skipped
var skip = func(t *testing.T, why string) {
	t.Skip(why)
}

func TestPodClient_NamespaceToRunningPodNum(t *testing.T) {
	skip(t, "Flaky test - See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/11078")
	setOption := podSyncCheckerOption(&mockReflectorSyncChecker{})

	fakeClientSet := fake.NewSimpleClientset()
	client := newPodClient(fakeClientSet, zap.NewNop(), setOption)
	client.store.Replace(podArray, "")
	client.refresh()

	expectedMap := map[string]int{
		"kube-system": 6,
		"default":     7,
	}
	resultMap := client.NamespaceToRunningPodNum()
	log.Printf("NamespaceToRunningPodNum (len=%v): %v", len(resultMap), awsutil.Prettify(resultMap))
	assert.True(t, reflect.DeepEqual(resultMap, expectedMap))
	client.shutdown()
	assert.True(t, client.stopped)
}

func TestTransformFuncPod(t *testing.T) {
	info, err := transformFuncPod(nil)
	assert.Nil(t, info)
	assert.NotNil(t, err)
}
<|endoftext|>


<commit_before>// Copyright 2022 Google Inc. 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 storage

import (
	"context"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

func init() { RegisterTestSuite(&BucketHandleTest{}) }

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithGeneration() {
	// Modify the default object with different content
	updatedContent := "Some Modification"
	defaultObj := GetTestFakeStorageObject()
	defaultObj.Generation = 2
	defaultObj.Content = []byte(updatedContent)
	CreateObject(t.fakeStorageServer, defaultObj)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(updatedContent)),
			},
			Generation: 2,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(updatedContent))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), updatedContent)
}
<commit_msg>Adding the test for valid/invalid generation<commit_after>// Copyright 2022 Google Inc. 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 storage

import (
	"context"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

func init() { RegisterTestSuite(&BucketHandleTest{}) }

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithValidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: TestObjectGeneration,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithInvalidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: 222, // other than TestObjectGeneration, doesn't exist.
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}
<|endoftext|>


<commit_before>package device

import (
	"encoding/json"
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestParseConvey(t *testing.T) {
	assert := assert.New(t)
	testData := []struct {
		value        string
		expectsError bool
		expectedJSON string
	}{
		{
			"this is not valid",
			true,
			"",
		},
		{
			"eyJmb28iOiAiYmFyIn0=",
			false,
			`{"foo": "bar"}`,
		},
		{
			"eyJkZXZpY2UiOiAiMTIzIiwgImF0dHJpYnV0ZXMiOiB7InZhbHVlIjogMTIzLCAiY29ubmVjdGVkIjogdHJ1ZSwgIm5hbWUiOiAiZm9vYmFyIn19",
			false,
			`{"device": "123", "attributes": {"value": 123, "connected": true, "name": "foobar"}}`,
		},
	}

	for _, record := range testData {
		t.Logf("%v", record)
		convey, err := ParseConvey(record.value)
		assert.Equal(record.expectsError, convey == nil)
		assert.Equal(record.expectsError, err != nil)

		if convey != nil {
			assert.Equal(record.value, convey.Encoded())
			assert.NotEmpty(convey.String())
			t.Logf(convey.String())

			actualJSON, err := json.Marshal(convey)
			if assert.Nil(err, fmt.Sprintf("%s", err)) {
				assert.NotEmpty(actualJSON)
				assert.JSONEq(record.expectedJSON, string(actualJSON))
			}
		}
	}
}
<commit_msg>Moved convey test data outside tests so it can be shared<commit_after>package device

import (
	"encoding/json"
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

var conveyTestData = []struct {
	encoded      string
	decoded      map[string]interface{}
	valid        bool
	expectedJSON string
}{
	{
		"this is not valid",
		nil,
		false,
		"",
	},
	{
		"eyJmb28iOiAiYmFyIn0=",
		map[string]interface{}{"foo": "bar"},
		true,
		`{"foo": "bar"}`,
	},
	{
		"eyJkZXZpY2UiOiAiMTIzIiwgImF0dHJpYnV0ZXMiOiB7InZhbHVlIjogMTIzLCAiY29ubmVjdGVkIjogdHJ1ZSwgIm5hbWUiOiAiZm9vYmFyIn19",
		map[string]interface{}{"device": "123", "attributes": map[string]interface{}{"value": 123, "connected": true, "name": "foobar"}},
		true,
		`{"device": "123", "attributes": {"value": 123, "connected": true, "name": "foobar"}}`,
	},
}

func TestNewConvey(t *testing.T) {
}

func TestParseConvey(t *testing.T) {
	assert := assert.New(t)

	for _, record := range conveyTestData {
		t.Logf("%v", record)
		convey, err := ParseConvey(record.encoded)
		assert.Equal(record.valid, convey != nil)
		assert.Equal(record.valid, err == nil)

		if convey != nil {
			assert.Equal(record.encoded, convey.Encoded())
			assert.NotEmpty(convey.String())
			t.Logf(convey.String())

			actualJSON, err := json.Marshal(convey)
			if assert.Nil(err, fmt.Sprintf("%s", err)) {
				assert.NotEmpty(actualJSON)
				assert.JSONEq(record.expectedJSON, string(actualJSON))
			}
		}
	}
}
<|endoftext|>


<commit_before>// Package weather provides commands to a bot.
package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	"encoding/json"
	"net/http"

	"github.com/weirdtales/senor-rosado/slack"
)

// partial struct for a google map api hit - so gross.
type weatherLocation struct {
	Results []struct {
		FormattedAddress string `json:"formatted_address"`
		Geometry         struct {
			Location struct {
				Lat float64 `json:"lat"`
				Lng float64 `json:"lng"`
			} `json:"location"`
		} `json:"geometry"`
		Status string `json:"status"`
	} `json:"results"`
}

// partial struct for a darksky api hit - so pretty.
type weatherInfo struct {
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Timezone  string  `json:"timezone"`
	Currently struct {
		Time                int64   `json:"time"`
		Summary             string  `json:"summary"`
		Icon                string  `json:"icon"`
		Temperature         float64 `json:"temperature"`
		ApparentTemperature float64 `json:"apparentTemperature"`
		DewPoint            float64 `json:"dewPoint"`
		Humidity            float64 `json:"humidity"`
		WindSpeed           float64 `json:"windSpeed"`
		Visibility          float64 `json:"visibility"`
		CloudCover          float64 `json:"cloudCover"`
		Pressure            float64 `json:"pressure"`
		Ozone               float64 `json:"ozone"`
	} `json:"currently"`
	Daily struct {
		Summary string `json:"summary"`
	} `json:"daily"`
	Hourly struct {
		Summary string `json:"summary"`
	} `json:"hourly"`

	GoogleName string // use the google maps FormattedAddress value - it's good
}

var httpClient = &http.Client{Timeout: 10 * time.Second}

// Register ...
func Register() (r string, h string) {
	r = `^weather .+`
	h = "`weather stalins tomb` get a weather report for a place"
	return
}

// Respond reports the current forecast for a location.
func Respond(m slack.Message, c slack.Conn, matches []string) {
	// TODO needs to be cached for a minute or so
	reply := getReply(m)
	reply.Channel = m.Channel
	c.Send(m, reply)
}

// eats a slack.Message and returns a slack.Reply with some text set.
func getReply(m slack.Message) (r slack.Reply) {
	token := os.Getenv("DARKSKY_TOKEN")
	if token == "" {
		r.Text = "I got no DARKSKY_TOKEN token in my env. Sort it."
		return
	}

	if m.Subcommand == "" {
		r.Text = "Specify a location, then I can help."
		return
	}

	loc, err := getLocation(strings.Replace(m.Tail, " ", ",", -1))
	if err != nil {
		r.Text = fmt.Sprintf("Problem getting location: %s", err)
		return
	}

	w, err := getWeather(token, loc)
	if err != nil {
		r.Text = fmt.Sprintf("Problem getting weather: %s", err)
		return
	}

	report := "*%s* :point_right: %s, %.1f°C. %s %s"
	r.Text = fmt.Sprintf(report, w.GoogleName, w.Currently.Summary, w.Currently.Temperature, w.Hourly.Summary, w.Daily.Summary)
	return
}

// returns a weatherLocation struct from google maps api.
func getLocation(q string) (loc weatherLocation, err error) {
	url := "http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false"
	url = fmt.Sprintf(url, q) // TODO does `q` need to be sanitized?

	err = getJSON(url, &loc)
	if err != nil {
		return
	}

	if len(loc.Results) < 1 {
		err = fmt.Errorf("google maps failed to convert the query into a location")
	}
	return
}

// returns a weatherInfo struct from darksky.
func getWeather(token string, loc weatherLocation) (w weatherInfo, err error) {
	w.GoogleName = loc.Results[0].FormattedAddress
	url := "https://api.darksky.net/forecast/%s/%f,%f?units=si"
	url = fmt.Sprintf(url, token, loc.Results[0].Geometry.Location.Lat, loc.Results[0].Geometry.Location.Lng)

	err = getJSON(url, &w)
	if err != nil {
		return
	}

	if w.Timezone == "" {
		err = fmt.Errorf("darksky doesn't have weather data for the location")
	}
	return
}

// pointless scaffolding.
func getJSON(url string, target interface{}) error {
	r, err := httpClient.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if r.StatusCode != 200 {
		err = fmt.Errorf("ERR non-200 response from \"%d\"", r.StatusCode)
		return err
	}

	return json.NewDecoder(r.Body).Decode(target)
}
<commit_msg>cleanup<commit_after>// Package weather provides commands to a bot.
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/weirdtales/senor-rosado/slack"
)

// partial struct for a google map api hit - so gross.
type weatherLocation struct {
	Results []struct {
		FormattedAddress string `json:"formatted_address"`
		Geometry         struct {
			Location struct {
				Lat float64 `json:"lat"`
				Lng float64 `json:"lng"`
			} `json:"location"`
		} `json:"geometry"`
		Status string `json:"status"`
	} `json:"results"`
}

// partial struct for a darksky api hit - so pretty.
type weatherInfo struct {
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Timezone  string  `json:"timezone"`
	Currently struct {
		Time                int64   `json:"time"`
		Summary             string  `json:"summary"`
		Icon                string  `json:"icon"`
		Temperature         float64 `json:"temperature"`
		ApparentTemperature float64 `json:"apparentTemperature"`
		DewPoint            float64 `json:"dewPoint"`
		Humidity            float64 `json:"humidity"`
		WindSpeed           float64 `json:"windSpeed"`
		Visibility          float64 `json:"visibility"`
		CloudCover          float64 `json:"cloudCover"`
		Pressure            float64 `json:"pressure"`
		Ozone               float64 `json:"ozone"`
	} `json:"currently"`
	Daily struct {
		Summary string `json:"summary"`
	} `json:"daily"`
	Hourly struct {
		Summary string `json:"summary"`
	} `json:"hourly"`

	GoogleName string // use the google maps FormattedAddress value - it's good
}

// Register ...
func Register() (r string, h string) {
	r = `^weather .+`
	h = "`weather stalins tomb` get a weather report for a place"
	return
}

// Respond reports the current forecast for a location.
func Respond(m slack.Message, c slack.Conn, matches []string) {
	// TODO needs to be cached for a minute or so
	reply := getReply(m)
	reply.Channel = m.Channel
	c.Send(m, reply)
}

// eats a slack.Message and returns a slack.Reply with some text set.
func getReply(m slack.Message) (r slack.Reply) {
	token := os.Getenv("DARKSKY_TOKEN")
	if token == "" {
		r.Text = "I got no DARKSKY_TOKEN token in my env. Sort it."
		return
	}

	if m.Subcommand == "" {
		r.Text = "Specify a location, then I can help."
		return
	}

	loc, err := getLocation(strings.Replace(m.Tail, " ", ",", -1))
	if err != nil {
		r.Text = fmt.Sprintf("Problem getting location: %s", err)
		return
	}

	w, err := getWeather(token, loc)
	if err != nil {
		r.Text = fmt.Sprintf("Problem getting weather: %s", err)
		return
	}

	report := "*%s* :point_right: %s, %.1f°C. %s %s"
	r.Text = fmt.Sprintf(report, w.GoogleName, w.Currently.Summary, w.Currently.Temperature, w.Hourly.Summary, w.Daily.Summary)
	return
}

// returns a weatherLocation struct from google maps api.
func getLocation(q string) (loc weatherLocation, err error) {
	url := "http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false"
	url = fmt.Sprintf(url, q) // TODO does `q` need to be sanitized?

	if err = slack.getJSON(url, &loc); err != nil {
		return
	}

	if len(loc.Results) < 1 {
		err = fmt.Errorf("google maps failed to convert the query into a location")
	}
	return
}

// returns a weatherInfo struct from darksky.
func getWeather(token string, loc weatherLocation) (w weatherInfo, err error) {
	w.GoogleName = loc.Results[0].FormattedAddress
	url := "https://api.darksky.net/forecast/%s/%f,%f?units=si"
	url = fmt.Sprintf(url, token, loc.Results[0].Geometry.Location.Lat, loc.Results[0].Geometry.Location.Lng)

	err = slack.getJSON(url, &w)
	if err != nil {
		return
	}

	// TODO brittle?
	if w.Timezone == "" {
		err = fmt.Errorf("darksky doesn't have weather data for the location")
	}
	return
}
<|endoftext|>


<commit_before>package payment

import (
	"encoding/json"
	"errors"
	"fmt"
	"socialapi/workers/helper"
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"
	"socialapi/workers/payment/paypal"
	"socialapi/workers/payment/stripe"
	"time"

	"github.com/koding/kite"
)

var (
	ProviderNotFound       = errors.New("provider not found")
	ProviderNotImplemented = errors.New("provider not implemented")

	WorkerName    = "socialapi-payment"
	WorkerVersion = "1.0.0"

	Log = helper.CreateLogger(WorkerName, false)

	KiteClient *kite.Client
)

//----------------------------------------------------------
// SubscribeRequest
//----------------------------------------------------------

type SubscribeRequest struct {
	AccountId, Token, Email           string
	Provider, PlanTitle, PlanInterval string
}

func (s *SubscribeRequest) Do() (interface{}, error) {
	var err error

	switch s.Provider {
	case "stripe":
		err = stripe.Subscribe(
			s.Token, s.AccountId, s.Email, s.PlanTitle, s.PlanInterval,
		)
	case "paypal":
		err = paypal.SubscribeWithPlan(s.Token, s.AccountId, s.PlanTitle, s.PlanInterval)
	default:
		err = ProviderNotFound
	}

	if err != nil {
		Log.Error(
			"Subscribing account: %s to plan: %s failed. %s",
			s.AccountId, s.PlanTitle, err,
		)
	}

	return nil, err
}

//----------------------------------------------------------
// AccountRequest
//----------------------------------------------------------

type AccountRequest struct {
	AccountId string
}

type SubscriptionsResponse struct {
	AccountId          string    `json:"accountId"`
	PlanTitle          string    `json:"planTitle"`
	PlanInterval       string    `json:"planInterval"`
	State              string    `json:"state"`
	Provider           string    `json:"provider"`
	CurrentPeriodStart time.Time `json:"currentPeriodStart"`
	CurrentPeriodEnd   time.Time `json:"currentPeriodEnd"`
}

// Subscriptions return given `account_id` subscription if it exists.
// In case of no customer, or no subscriptions or no plan found, it
// returns the default plan as subscription.
func (a *AccountRequest) Subscriptions() (*SubscriptionsResponse, error) {
	if a.AccountId == "" {
		return nil, paymenterrors.ErrAccountIdIsNotSet
	}

	defaultResp := &SubscriptionsResponse{
		AccountId:    a.AccountId,
		PlanTitle:    "free",
		PlanInterval: "month",
		State:        "active",
		Provider:     "koding",
	}

	customer, err := stripe.FindCustomerByOldId(a.AccountId)
	if err != nil {
		return defaultResp, nil
	}

	subscriptions, err := stripe.FindCustomerSubscriptions(customer)
	if err != nil {
		return defaultResp, nil
	}

	if len(subscriptions) == 0 {
		return defaultResp, nil
	}

	currentSubscription := subscriptions[0]

	// cancel implies user took the action after satisfying provider limits,
	// therefore we return `free` plan for them
	if currentSubscription.State == paymentmodels.SubscriptionStateCanceled {
		return defaultResp, nil
	}

	plan := &paymentmodels.Plan{}
	err = plan.ById(currentSubscription.PlanId)
	if err != nil {
		return defaultResp, nil
	}

	resp := &SubscriptionsResponse{
		AccountId:          a.AccountId,
		PlanTitle:          plan.Title,
		PlanInterval:       plan.Interval,
		CurrentPeriodStart: currentSubscription.CurrentPeriodStart,
		CurrentPeriodEnd:   currentSubscription.CurrentPeriodEnd,
		State:              currentSubscription.State,
		Provider:           currentSubscription.Provider,
	}

	return resp, nil
}

func (a *AccountRequest) Invoices() ([]*stripe.StripeInvoiceResponse, error) {
	invoices, err := stripe.FindInvoicesForCustomer(a.AccountId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		Log.Error("Fetching invoices for account: %s failed. %s", a.AccountId, err)
	}

	return invoices, err
}

func (a *AccountRequest) CreditCard() (*stripe.CreditCardResponse, error) {
	resp, err := stripe.GetCreditCard(a.AccountId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		Log.Error("Fetching cc for account: %s failed. %s", a.AccountId, err)
	}

	return resp, err
}

func (a *AccountRequest) Delete() (interface{}, error) {
	err := stripe.DeleteCustomer(a.AccountId)
	if err != nil {
		Log.Error("Deleting account: %s failed. %s", a.AccountId, err)
	}

	return nil, err
}

func (a *AccountRequest) ActiveUsernames() ([]string, error) {
	customer := paymentmodels.NewCustomer()
	customers, err := customer.ByActiveSubscription()
	if err != nil {
		return nil, err
	}

	usernames := []string{}
	for _, customer := range customers {
		usernames = append(usernames, customer.Username)
	}

	return usernames, nil
}

//----------------------------------------------------------
// UpdateCreditCard
//----------------------------------------------------------

type UpdateCreditCardRequest struct {
	AccountId, Provider, Token string
}

func (u *UpdateCreditCardRequest) Do() (interface{}, error) {
	switch u.Provider {
	case "stripe":
		err := stripe.UpdateCreditCard(u.AccountId, u.Token)
		if err != nil {
			Log.Error("Updating cc for account: %s failed. %s", u.AccountId, err)
		}

		return nil, err
	case "paypal":
		return nil, ProviderNotImplemented
	default:
		return nil, ProviderNotFound
	}
}

//----------------------------------------------------------
// StripeWebhook
//----------------------------------------------------------

type StripeWebhook struct {
	Name     string `json:"type"`
	Created  int    `json:"created"`
	Livemode bool   `json:"livemode"`
	Id       string `json:"id"`
	Data     struct {
		Object interface{} `json:"object"`
	} `json:"data"`
}

func (s *StripeWebhook) Do() (interface{}, error) {
	var err error

	if !s.Livemode {
		Log.Error("Received test Stripe webhook: %v", s)
		return nil, nil
	}

	raw, err := json.Marshal(s.Data.Object)
	if err != nil {
		Log.Error("Error marshalling Stripe webhook '%v' : %v", s, err)
		return nil, err
	}

	switch s.Name {
	case "customer.subscription.deleted":
		err = stripe.SubscriptionDeletedWebhook(raw)
		if err != nil {
			return nil, err
		}

		subsObj, ok := s.Data.Object.(map[string]interface{})
		if !ok {
			return nil, errUnmarshalFailed(s.Data.Object)
		}

		customerId, ok := subsObj["customer"].(string)
		if !ok {
			return nil, errUnmarshalFailed(s.Data.Object)
		}

		err = stopMachinesForUser(customerId)
	case "invoice.created":
		err = stripe.InvoiceCreatedWebhook(raw)
	case "customer.deleted":
		err = stripe.CustomerDeletedWebhook(raw)
	}

	if err != nil {
		Log.Error("Error handling Stripe webhook '%v' : %v", s, err)
	}

	return nil, err
}

//----------------------------------------------------------
// Paypal
//----------------------------------------------------------

type PaypalRequest struct {
	Token     string `json:"token"`
	AccountId string `json:"accountId"`
}

func (p *PaypalRequest) Success() (interface{}, error) {
	return nil, paypal.Subscribe(p.Token, p.AccountId)
}

func (p *PaypalRequest) Cancel() (interface{}, error) {
	return nil, nil
}

type PaypalGetTokenRequest struct {
	PlanTitle    string `json:"planTitle"`
	PlanInterval string `json:"planInterval"`
}

func (p *PaypalGetTokenRequest) Do() (interface{}, error) {
	return paypal.GetToken(p.PlanTitle, p.PlanInterval)
}

//----------------------------------------------------------
// Webhook
//----------------------------------------------------------

type PaypalWebhook struct {
	TransactionType string `json:"txn_type"`
	Status          string `json:"payment_status"`
	PayerId         string `json:"payer_id"`
}

var PaypalActionExpire = "cancel"

var PaypalStatusActionMap = map[string]string{
	"Denied":   PaypalActionExpire,
	"Expired":  PaypalActionExpire,
	"Failed":   PaypalActionExpire,
	"Reversed": PaypalActionExpire,
	"Voided":   PaypalActionExpire,
}

var PaypalTransactionActionMap = map[string]string{
	"recurring_payment_profile_cancel": PaypalActionExpire,
}

func (p *PaypalWebhook) Do() (interface{}, error) {
	action, ok := PaypalStatusActionMap[p.Status]
	if !ok {
		action, ok = PaypalTransactionActionMap[p.TransactionType]
		if !ok {
			return nil, nil
		}
	}

	var err error

	switch action {
	case PaypalActionExpire:
		err = paypal.ExpireSubscription(p.PayerId)
		if err != nil {
			return nil, err
		}

		err = stopMachinesForUser(p.PayerId)
	}

	return nil, err
}

func isUsernameEmpty(username string) bool {
	return username == ""
}

func errUsernameEmpty(customerId string) error {
	return fmt.Errorf(
		"stopping machine for paypal customer: %s failed since username is empty",
		customerId,
	)
}

func errUnmarshalFailed(data interface{}) error {
	return fmt.Errorf("unmarshalling webhook failed: %v", data)
}
<commit_msg>payments: don't return username if it's empty<commit_after>package payment

import (
	"encoding/json"
	"errors"
	"fmt"
	"socialapi/workers/helper"
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"
	"socialapi/workers/payment/paypal"
	"socialapi/workers/payment/stripe"
	"time"

	"github.com/koding/kite"
)

var (
	ProviderNotFound       = errors.New("provider not found")
	ProviderNotImplemented = errors.New("provider not implemented")

	WorkerName    = "socialapi-payment"
	WorkerVersion = "1.0.0"

	Log = helper.CreateLogger(WorkerName, false)

	KiteClient *kite.Client
)

//----------------------------------------------------------
// SubscribeRequest
//----------------------------------------------------------

type SubscribeRequest struct {
	AccountId, Token, Email           string
	Provider, PlanTitle, PlanInterval string
}

func (s *SubscribeRequest) Do() (interface{}, error) {
	var err error

	switch s.Provider {
	case "stripe":
		err = stripe.Subscribe(
			s.Token, s.AccountId, s.Email, s.PlanTitle, s.PlanInterval,
		)
	case "paypal":
		err = paypal.SubscribeWithPlan(s.Token, s.AccountId, s.PlanTitle, s.PlanInterval)
	default:
		err = ProviderNotFound
	}

	if err != nil {
		Log.Error(
			"Subscribing account: %s to plan: %s failed. %s",
			s.AccountId, s.PlanTitle, err,
		)
	}

	return nil, err
}

//----------------------------------------------------------
// AccountRequest
//----------------------------------------------------------

type AccountRequest struct {
	AccountId string
}

type SubscriptionsResponse struct {
	AccountId          string    `json:"accountId"`
	PlanTitle          string    `json:"planTitle"`
	PlanInterval       string    `json:"planInterval"`
	State              string    `json:"state"`
	Provider           string    `json:"provider"`
	CurrentPeriodStart time.Time `json:"currentPeriodStart"`
	CurrentPeriodEnd   time.Time `json:"currentPeriodEnd"`
}

// Subscriptions return given `account_id` subscription if it exists.
// In case of no customer, or no subscriptions or no plan found, it
// returns the default plan as subscription.
func (a *AccountRequest) Subscriptions() (*SubscriptionsResponse, error) {
	if a.AccountId == "" {
		return nil, paymenterrors.ErrAccountIdIsNotSet
	}

	defaultResp := &SubscriptionsResponse{
		AccountId:    a.AccountId,
		PlanTitle:    "free",
		PlanInterval: "month",
		State:        "active",
		Provider:     "koding",
	}

	customer, err := stripe.FindCustomerByOldId(a.AccountId)
	if err != nil {
		return defaultResp, nil
	}

	subscriptions, err := stripe.FindCustomerSubscriptions(customer)
	if err != nil {
		return defaultResp, nil
	}

	if len(subscriptions) == 0 {
		return defaultResp, nil
	}

	currentSubscription := subscriptions[0]

	// cancel implies user took the action after satisfying provider limits,
	// therefore we return `free` plan for them
	if currentSubscription.State == paymentmodels.SubscriptionStateCanceled {
		return defaultResp, nil
	}

	plan := &paymentmodels.Plan{}
	err = plan.ById(currentSubscription.PlanId)
	if err != nil {
		return defaultResp, nil
	}

	resp := &SubscriptionsResponse{
		AccountId:          a.AccountId,
		PlanTitle:          plan.Title,
		PlanInterval:       plan.Interval,
		CurrentPeriodStart: currentSubscription.CurrentPeriodStart,
		CurrentPeriodEnd:   currentSubscription.CurrentPeriodEnd,
		State:              currentSubscription.State,
		Provider:           currentSubscription.Provider,
	}

	return resp, nil
}

func (a *AccountRequest) Invoices() ([]*stripe.StripeInvoiceResponse, error) {
	invoices, err := stripe.FindInvoicesForCustomer(a.AccountId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		Log.Error("Fetching invoices for account: %s failed. %s", a.AccountId, err)
	}

	return invoices, err
}

func (a *AccountRequest) CreditCard() (*stripe.CreditCardResponse, error) {
	resp, err := stripe.GetCreditCard(a.AccountId)
	if err != nil && err != paymenterrors.ErrCustomerNotFound {
		Log.Error("Fetching cc for account: %s failed. %s", a.AccountId, err)
	}

	return resp, err
}

func (a *AccountRequest) Delete() (interface{}, error) {
	err := stripe.DeleteCustomer(a.AccountId)
	if err != nil {
		Log.Error("Deleting account: %s failed. %s", a.AccountId, err)
	}

	return nil, err
}

func (a *AccountRequest) ActiveUsernames() ([]string, error) {
	customer := paymentmodels.NewCustomer()
	customers, err := customer.ByActiveSubscription()
	if err != nil {
		return nil, err
	}

	usernames := []string{}
	for _, customer := range customers {
		if customer.Username != "" {
			usernames = append(usernames, customer.Username)
		}
	}

	return usernames, nil
}

//----------------------------------------------------------
// UpdateCreditCard
//----------------------------------------------------------

type UpdateCreditCardRequest struct {
	AccountId, Provider, Token string
}

func (u *UpdateCreditCardRequest) Do() (interface{}, error) {
	switch u.Provider {
	case "stripe":
		err := stripe.UpdateCreditCard(u.AccountId, u.Token)
		if err != nil {
			Log.Error("Updating cc for account: %s failed. %s", u.AccountId, err)
		}

		return nil, err
	case "paypal":
		return nil, ProviderNotImplemented
	default:
		return nil, ProviderNotFound
	}
}

//----------------------------------------------------------
// StripeWebhook
//----------------------------------------------------------

type StripeWebhook struct {
	Name     string `json:"type"`
	Created  int    `json:"created"`
	Livemode bool   `json:"livemode"`
	Id       string `json:"id"`
	Data     struct {
		Object interface{} `json:"object"`
	} `json:"data"`
}

func (s *StripeWebhook) Do() (interface{}, error) {
	var err error

	if !s.Livemode {
		Log.Error("Received test Stripe webhook: %v", s)
		return nil, nil
	}

	raw, err := json.Marshal(s.Data.Object)
	if err != nil {
		Log.Error("Error marshalling Stripe webhook '%v' : %v", s, err)
		return nil, err
	}

	switch s.Name {
	case "customer.subscription.deleted":
		err = stripe.SubscriptionDeletedWebhook(raw)
		if err != nil {
			return nil, err
		}

		subsObj, ok := s.Data.Object.(map[string]interface{})
		if !ok {
			return nil, errUnmarshalFailed(s.Data.Object)
		}

		customerId, ok := subsObj["customer"].(string)
		if !ok {
			return nil, errUnmarshalFailed(s.Data.Object)
		}

		err = stopMachinesForUser(customerId)
	case "invoice.created":
		err = stripe.InvoiceCreatedWebhook(raw)
	case "customer.deleted":
		err = stripe.CustomerDeletedWebhook(raw)
	}

	if err != nil {
		Log.Error("Error handling Stripe webhook '%v' : %v", s, err)
	}

	return nil, err
}

//----------------------------------------------------------
// Paypal
//----------------------------------------------------------

type PaypalRequest struct {
	Token     string `json:"token"`
	AccountId string `json:"accountId"`
}

func (p *PaypalRequest) Success() (interface{}, error) {
	return nil, paypal.Subscribe(p.Token, p.AccountId)
}

func (p *PaypalRequest) Cancel() (interface{}, error) {
	return nil, nil
}

type PaypalGetTokenRequest struct {
	PlanTitle    string `json:"planTitle"`
	PlanInterval string `json:"planInterval"`
}

func (p *PaypalGetTokenRequest) Do() (interface{}, error) {
	return paypal.GetToken(p.PlanTitle, p.PlanInterval)
}

//----------------------------------------------------------
// Webhook
//----------------------------------------------------------

type PaypalWebhook struct {
	TransactionType string `json:"txn_type"`
	Status          string `json:"payment_status"`
	PayerId         string `json:"payer_id"`
}

var PaypalActionExpire = "cancel"

var PaypalStatusActionMap = map[string]string{
	"Denied":   PaypalActionExpire,
	"Expired":  PaypalActionExpire,
	"Failed":   PaypalActionExpire,
	"Reversed": PaypalActionExpire,
	"Voided":   PaypalActionExpire,
}

var PaypalTransactionActionMap = map[string]string{
	"recurring_payment_profile_cancel": PaypalActionExpire,
}

func (p *PaypalWebhook) Do() (interface{}, error) {
	action, ok := PaypalStatusActionMap[p.Status]
	if !ok {
		action, ok = PaypalTransactionActionMap[p.TransactionType]
		if !ok {
			return nil, nil
		}
	}

	var err error

	switch action {
	case PaypalActionExpire:
		err = paypal.ExpireSubscription(p.PayerId)
		if err != nil {
			return nil, err
		}

		err = stopMachinesForUser(p.PayerId)
	}

	return nil, err
}

func isUsernameEmpty(username string) bool {
	return username == ""
}

func errUsernameEmpty(customerId string) error {
	return fmt.Errorf(
		"stopping machine for paypal customer: %s failed since username is empty",
		customerId,
	)
}

func errUnmarshalFailed(data interface{}) error {
	return fmt.Errorf("unmarshalling webhook failed: %v", data)
}
<|endoftext|>


<commit_before>//Package ts3sqlib provides a simple interface for the TeamSpeak3 ServerQuery.
package ts3sqlib

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"sync"
)

const (
	stdPort string = ":10011"
)

var (
	//StdoutLogger is the standard logger that prints to stdout.
	StdoutLogger = log.New(os.Stdout, "", log.LstdFlags)
	//StderrLogger is the standard logger that prints to stderr.
	StderrLogger = log.New(os.Stderr, "", log.LstdFlags)
)

//SqConn contains the connection to a ts3 server.
type SqConn struct {
	conn       net.Conn
	logger     *log.Logger
	sendMutex  *sync.Mutex
	receiving  bool
	recvNotify chan string
	recvChan   chan string
	closed     chan bool
	//WelcomeMsg contains the welcome message from the ts3 server
	WelcomeMsg string
}

//Dial creates a new SqConn and connects to the ts3 server with the given
//address and returns a pointer to it and an error.
//If the logger is nil, then the standard logger is used.
func Dial(address string, logger *log.Logger) (conn *SqConn, err error) {
	conn = nil

	if !strings.Contains(address, ":") {
		address += stdPort
	}

	connection, err := net.Dial("tcp", address)
	if err != nil {
		return
	}

	conn = &SqConn{
		conn:       connection,
		logger:     logger,
		sendMutex:  &sync.Mutex{},
		receiving:  true,
		recvNotify: make(chan string),
		recvChan:   make(chan string),
		closed:     make(chan bool),
		WelcomeMsg: "",
	}

	go conn.recv() //goroutine that splits the incoming messages into notify
	//and normal messages.

	if !strings.Contains(<-conn.recvChan, "TS3") {
		conn = nil
		err = fmt.Errorf("no connection to a ts3-server-query")
		return
	}

	conn.WelcomeMsg = <-conn.recvChan

	return
}

func (c *SqConn) recv() {
	var err error
	line := ""
	scan := bufio.NewScanner(c.conn)

	for c.receiving {
		//read line
		if !scan.Scan() {
			if err = scan.Err(); err != nil && c.logger != nil {
				c.logger.Print(err)
			}
			c.receiving = false
			c.closed <- true
			break
		}

		line = scan.Text()
		line = strings.Replace(line, string([]byte{13}), "", -1)

		if err = scan.Err(); err != nil {
			if c.logger != nil {
				c.logger.Print(err)
			}
			continue
		}

		//decide if its notify or not and put it to the correct channel
		if strings.HasPrefix(line, "notify") {
			c.recvNotify <- line
		} else {
			c.recvChan <- line
		}
	}
}

//RecvNotify returns a notify message or blocks until one arrives.
func (c *SqConn) RecvNotify() (answer string, err error) {
	answer = ""
	err = nil

	answer = <-c.recvNotify
	return
}

//Close closes the connection to the ts3 server.
func (c *SqConn) Close() {
	c.receiving = false
	c.conn.Close()
}

//IsClosed checks if the connection is closed
func (c *SqConn) IsClosed() bool {
	return !c.receiving
}

//Send sends a message to the server and returns the answer and an error.
func (c *SqConn) Send(msg string) (answer string, err error) {
	if c == nil {
		fmt.Errorf("nil pointer error")
		return
	}

	c.sendMutex.Lock()
	defer c.sendMutex.Unlock()

	//msg must have a newline at the end
	if !strings.HasSuffix(msg, "\n") {
		msg += "\n"
	}

	if !c.receiving {
		answer = ""
		err = fmt.Errorf("connection closed")
		return
	}

	if c.logger != nil {
		c.logger.Print("send: ", msg)
	}

	answer = ""

	_, err = c.conn.Write([]byte(msg)) //If the return value is smaller than
	if err != nil {                    //the length of msg, it's an error.
		return
	}

	line := ""
	err = nil

	for !isError(line) && c.receiving {
		select {
		case line = <-c.recvChan:
			if isError(line) {
				err = toError(line)
				break
			}

			answer += line + "\n"

		case <-c.closed:
			break
		}
	}

	if err == nil {
		err = NewError(-1, "connection closed", "")
	}

	if MsgEndError.Equals(err) {
		err = nil
	}

	//logging
	if c.logger != nil {
		if answer != "" && answer != "\n" {
			c.logger.Println(answer)
		}
		if err != nil {
			c.logger.Println(err)
		}
	}

	return
}
<commit_msg>first try for notify channels<commit_after>//Package ts3sqlib provides a simple interface for the TeamSpeak3 ServerQuery.
package ts3sqlib

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"sync"
)

const (
	stdPort string = ":10011"
)

var (
	//StdoutLogger is the standard logger that prints to stdout.
	StdoutLogger = log.New(os.Stdout, "", log.LstdFlags)
	//StderrLogger is the standard logger that prints to stderr.
	StderrLogger = log.New(os.Stderr, "", log.LstdFlags)
)

//SqConn contains the connection to a ts3 server.
type SqConn struct {
	conn           net.Conn
	logger         *log.Logger
	sendMutex      *sync.Mutex
	receiving      bool
	recvNotify     chan string
	notifyChannels []chan string
	recvChan       chan string
	closed         chan bool
	//WelcomeMsg contains the welcome message from the ts3 server
	WelcomeMsg string
}

//Dial creates a new SqConn and connects to the ts3 server with the given
//address and returns a pointer to it and an error.
//If the logger is nil, then the standard logger is used.
func Dial(address string, logger *log.Logger) (conn *SqConn, err error) {
	conn = nil

	if !strings.Contains(address, ":") {
		address += stdPort
	}

	connection, err := net.Dial("tcp", address)
	if err != nil {
		return
	}

	conn = &SqConn{
		conn:           connection,
		logger:         logger,
		sendMutex:      &sync.Mutex{},
		receiving:      true,
		recvNotify:     make(chan string),
		notifyChannels: make([]chan string, 0),
		recvChan:       make(chan string),
		closed:         make(chan bool),
		WelcomeMsg:     "",
	}

	go conn.recv() //goroutine that splits the incoming messages into notify
	//and normal messages.

	if !strings.Contains(<-conn.recvChan, "TS3") {
		conn = nil
		err = fmt.Errorf("no connection to a ts3-server-query")
		return
	}

	conn.WelcomeMsg = <-conn.recvChan

	return
}

func (c *SqConn) recv() {
	var err error
	line := ""
	scan := bufio.NewScanner(c.conn)

	for c.receiving {
		//read line
		if !scan.Scan() {
			if err = scan.Err(); err != nil && c.logger != nil {
				c.logger.Print(err)
			}
			c.receiving = false
			c.closed <- true
			break
		}

		line = scan.Text()
		line = strings.Replace(line, string([]byte{13}), "", -1)

		if err = scan.Err(); err != nil {
			if c.logger != nil {
				c.logger.Print(err)
			}
			continue
		}

		//decide if its notify or not and put it to the correct channel
		if strings.HasPrefix(line, "notify") {
			c.recvNotify <- line
			//send to notifyChannels
			for _, nc := range c.notifyChannels {
				nc <- line
			}
		} else {
			c.recvChan <- line
		}
	}
}

//RecvNotify returns a notify message or blocks until one arrives.
func (c *SqConn) RecvNotify() (answer string, err error) {
	answer = ""
	err = nil

	answer = <-c.recvNotify
	return
}

func (c *SqConn) Notify() <-chan string {
	s := make(chan string)
	//adding s to notify channels
	c.notifyChannels = append(c.notifyChannels, s)

	return s
}

//Close closes the connection to the ts3 server.
func (c *SqConn) Close() {
	c.receiving = false
	c.conn.Close()
}

//IsClosed checks if the connection is closed
func (c *SqConn) IsClosed() bool {
	return !c.receiving
}

//Send sends a message to the server and returns the answer and an error.
func (c *SqConn) Send(msg string) (answer string, err error) {
	if c == nil {
		fmt.Errorf("nil pointer error")
		return
	}

	c.sendMutex.Lock()
	defer c.sendMutex.Unlock()

	//msg must have a newline at the end
	if !strings.HasSuffix(msg, "\n") {
		msg += "\n"
	}

	if !c.receiving {
		answer = ""
		err = fmt.Errorf("connection closed")
		return
	}

	if c.logger != nil {
		c.logger.Print("send: ", msg)
	}

	answer = ""

	_, err = c.conn.Write([]byte(msg)) //If the return value is smaller than
	if err != nil {                    //the length of msg, it's an error.
		return
	}

	line := ""
	err = nil

	for !isError(line) && c.receiving {
		select {
		case line = <-c.recvChan:
			if isError(line) {
				err = toError(line)
				break
			}

			answer += line + "\n"

		case <-c.closed:
			break
		}
	}

	if err == nil {
		err = NewError(-1, "connection closed", "")
	}

	if MsgEndError.Equals(err) {
		err = nil
	}

	//logging
	if c.logger != nil {
		if answer != "" && answer != "\n" {
			c.logger.Println(answer)
		}
		if err != nil {
			c.logger.Println(err)
		}
	}

	return
}
<|endoftext|>


<commit_before>// +build V7

package ui

import (
	"fmt"
)

// Translates warnings and outputs them to ui.Err.
// Prints each warning with a trailing newline.
func (ui *UI) DisplayWarnings(warnings []string) {
	for _, warning := range warnings {
		fmt.Fprintf(ui.Err, "%s\n", ui.TranslateText(warning))
	}
}

// DisplayWarning translates the warning, substitutes in templateValues, and
// outputs to ui.Err. Only the first map in templateValues is used.
// This command has one fewer newline than DisplayWarning. Use it before an OK message in V7.
func (ui *UI) DisplayWarning(template string, templateValues ...map[string]interface{}) {
	fmt.Fprintf(ui.Err, "%s\n", ui.TranslateText(template, templateValues...))
}
<commit_msg>Sort methods in ui_v7 alphabetically<commit_after>// +build V7

package ui

import (
	"fmt"
)

// DisplayWarning translates the warning, substitutes in templateValues, and
// outputs to ui.Err. Only the first map in templateValues is used.
// This command has one fewer newline than DisplayWarning. Use it before an OK message in V7.
func (ui *UI) DisplayWarning(template string, templateValues ...map[string]interface{}) {
	fmt.Fprintf(ui.Err, "%s\n", ui.TranslateText(template, templateValues...))
}

// Translates warnings and outputs them to ui.Err.
// Prints each warning with a trailing newline.
func (ui *UI) DisplayWarnings(warnings []string) {
	for _, warning := range warnings {
		fmt.Fprintf(ui.Err, "%s\n", ui.TranslateText(warning))
	}
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"time"

	// "k8s.io/api/core/v1"

	// "k8s.io/api/extensions/v1beta1"

	"github.com/keel-hq/keel/internal/k8s"
	"github.com/keel-hq/keel/types"
	"github.com/keel-hq/keel/util/image"

	"github.com/keel-hq/keel/util/version"

	log "github.com/sirupsen/logrus"
)

// func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updated v1beta1.Deployment, shouldUpdateDeployment bool, err error) {
func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, resource *k8s.GenericResource) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
	updatePlan = &UpdatePlan{}

	eventRepoRef, err := image.Parse(repo.Name)
	if err != nil {
		return
	}

	labels := resource.GetLabels()

	log.WithFields(log.Fields{
		"labels":    labels,
		"name":      resource.Name,
		"namespace": resource.Namespace,
		"kind":      resource.Kind(),
		"policy":    policy,
	}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking resource...")

	shouldUpdateDeployment = false

	for idx, c := range resource.Containers() {
		containerImageRef, err := image.Parse(c.Image)
		if err != nil {
			log.WithFields(log.Fields{
				"error":      err,
				"image_name": c.Image,
			}).Error("provider.kubernetes: failed to parse image name")
			continue
		}

		log.WithFields(log.Fields{
			"name":              resource.Name,
			"namespace":         resource.Namespace,
			"parsed_image_name": containerImageRef.Remote(),
			"kind":              resource.Kind(),
			"target_image_name": repo.Name,
			"target_tag":        repo.Tag,
			"policy":            policy,
			"image":             c.Image,
		}).Info("provider.kubernetes: checking image")

		if containerImageRef.Repository() != eventRepoRef.Repository() {
			log.WithFields(log.Fields{
				"parsed_image_name": containerImageRef.Remote(),
				"target_image_name": repo.Name,
			}).Info("provider.kubernetes: images do not match, ignoring")
			continue
		}

		// if policy is force, don't bother with version checking
		// same with `latest` images, update them to versioned ones
		if policy == types.PolicyTypeForce || containerImageRef.Tag() == "latest" {
			if containerImageRef.Registry() == image.DefaultRegistryHostname {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
			} else {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
			}
			shouldUpdateDeployment = true
			setUpdateTime(resource)

			log.WithFields(log.Fields{
				"parsed_image":     containerImageRef.Remote(),
				"raw_image_name":   c.Image,
				"target_image":     repo.Name,
				"target_image_tag": repo.Tag,
				"policy":           policy,
			}).Info("provider.kubernetes: impacted deployment container found")

			updatePlan.CurrentVersion = containerImageRef.Tag()
			updatePlan.NewVersion = newVersion.Original
			updatePlan.Resource = resource

			// success, moving to next container
			continue
		}

		currentVersion, err := version.GetVersionFromImageName(c.Image)
		if err != nil {
			log.WithFields(log.Fields{
				"error":               err,
				"container_image":     c.Image,
				"container_image_tag": containerImageRef.Tag(),
				"keel_policy":         policy,
			}).Error("provider.kubernetes: failed to get image version, is it tagged as semver?")
			continue
		}

		log.WithFields(log.Fields{
			"labels":          labels,
			"name":            resource.Name,
			"namespace":       resource.Namespace,
			"image":           c.Image,
			"current_version": currentVersion.String(),
			"policy":          policy,
		}).Info("provider.kubernetes: current image version")

		shouldUpdateContainer, err := version.ShouldUpdate(currentVersion, newVersion, policy)
		if err != nil {
			log.WithFields(log.Fields{
				"error":           err,
				"new_version":     newVersion.String(),
				"current_version": currentVersion.String(),
				"keel_policy":     policy,
			}).Error("provider.kubernetes: got error while checking whether deployment should be updated")
			continue
		}

		log.WithFields(log.Fields{
			"labels":          labels,
			"name":            resource.Name,
			"namespace":       resource.Namespace,
			"image":           c.Image,
			"current_version": currentVersion.String(),
			"new_version":     newVersion.String(),
			"policy":          policy,
			"should_update":   shouldUpdateContainer,
		}).Info("provider.kubernetes: checked version, deciding whether to update")

		if shouldUpdateContainer {
			if containerImageRef.Registry() == image.DefaultRegistryHostname {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
			} else {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
			}
			// marking this deployment for update
			shouldUpdateDeployment = true

			setUpdateTime(resource)

			updatePlan.CurrentVersion = currentVersion.Original
			updatePlan.NewVersion = newVersion.Original
			updatePlan.Resource = resource

			log.WithFields(log.Fields{
				"parsed_image":     containerImageRef.Remote(),
				"raw_image_name":   c.Image,
				"target_image":     repo.Name,
				"target_image_tag": repo.Tag,
				"policy":           policy,
			}).Info("provider.kubernetes: impacted deployment container found")
		}
	}

	return updatePlan, shouldUpdateDeployment, nil
}

func setUpdateTime(resource *k8s.GenericResource) {
	specAnnotations := resource.GetSpecAnnotations()
	specAnnotations[types.KeelUpdateTimeAnnotation] = time.Now().String()
	resource.SetSpecAnnotations(specAnnotations)
}
<commit_msg>use image.Parse(repo.String()) in checkVersionedDeployment<commit_after>package kubernetes

import (
	"fmt"
	"time"

	// "k8s.io/api/core/v1"

	// "k8s.io/api/extensions/v1beta1"

	"github.com/keel-hq/keel/internal/k8s"
	"github.com/keel-hq/keel/types"
	"github.com/keel-hq/keel/util/image"

	"github.com/keel-hq/keel/util/version"

	log "github.com/sirupsen/logrus"
)

// func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updated v1beta1.Deployment, shouldUpdateDeployment bool, err error) {
func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, resource *k8s.GenericResource) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
	updatePlan = &UpdatePlan{}

	eventRepoRef, err := image.Parse(repo.String())
	if err != nil {
		return
	}

	labels := resource.GetLabels()

	log.WithFields(log.Fields{
		"labels":    labels,
		"name":      resource.Name,
		"namespace": resource.Namespace,
		"kind":      resource.Kind(),
		"policy":    policy,
	}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking resource...")

	shouldUpdateDeployment = false

	for idx, c := range resource.Containers() {
		containerImageRef, err := image.Parse(c.Image)
		if err != nil {
			log.WithFields(log.Fields{
				"error":      err,
				"image_name": c.Image,
			}).Error("provider.kubernetes: failed to parse image name")
			continue
		}

		log.WithFields(log.Fields{
			"name":              resource.Name,
			"namespace":         resource.Namespace,
			"parsed_image_name": containerImageRef.Remote(),
			"kind":              resource.Kind(),
			"target_image_name": repo.Name,
			"target_tag":        repo.Tag,
			"policy":            policy,
			"image":             c.Image,
		}).Info("provider.kubernetes: checking image")

		if containerImageRef.Repository() != eventRepoRef.Repository() {
			log.WithFields(log.Fields{
				"parsed_image_name": containerImageRef.Remote(),
				"target_image_name": repo.Name,
			}).Info("provider.kubernetes: images do not match, ignoring")
			continue
		}

		// if policy is force, don't bother with version checking
		// same with `latest` images, update them to versioned ones
		if policy == types.PolicyTypeForce || containerImageRef.Tag() == "latest" {
			if containerImageRef.Registry() == image.DefaultRegistryHostname {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
			} else {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
			}
			shouldUpdateDeployment = true
			setUpdateTime(resource)

			log.WithFields(log.Fields{
				"parsed_image":     containerImageRef.Remote(),
				"raw_image_name":   c.Image,
				"target_image":     repo.Name,
				"target_image_tag": repo.Tag,
				"policy":           policy,
			}).Info("provider.kubernetes: impacted deployment container found")

			updatePlan.CurrentVersion = containerImageRef.Tag()
			updatePlan.NewVersion = newVersion.Original
			updatePlan.Resource = resource

			// success, moving to next container
			continue
		}

		currentVersion, err := version.GetVersionFromImageName(c.Image)
		if err != nil {
			log.WithFields(log.Fields{
				"error":               err,
				"container_image":     c.Image,
				"container_image_tag": containerImageRef.Tag(),
				"keel_policy":         policy,
			}).Error("provider.kubernetes: failed to get image version, is it tagged as semver?")
			continue
		}

		log.WithFields(log.Fields{
			"labels":          labels,
			"name":            resource.Name,
			"namespace":       resource.Namespace,
			"image":           c.Image,
			"current_version": currentVersion.String(),
			"policy":          policy,
		}).Info("provider.kubernetes: current image version")

		shouldUpdateContainer, err := version.ShouldUpdate(currentVersion, newVersion, policy)
		if err != nil {
			log.WithFields(log.Fields{
				"error":           err,
				"new_version":     newVersion.String(),
				"current_version": currentVersion.String(),
				"keel_policy":     policy,
			}).Error("provider.kubernetes: got error while checking whether deployment should be updated")
			continue
		}

		log.WithFields(log.Fields{
			"labels":          labels,
			"name":            resource.Name,
			"namespace":       resource.Namespace,
			"image":           c.Image,
			"current_version": currentVersion.String(),
			"new_version":     newVersion.String(),
			"policy":          policy,
			"should_update":   shouldUpdateContainer,
		}).Info("provider.kubernetes: checked version, deciding whether to update")

		if shouldUpdateContainer {
			if containerImageRef.Registry() == image.DefaultRegistryHostname {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
			} else {
				resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
			}
			// marking this deployment for update
			shouldUpdateDeployment = true

			setUpdateTime(resource)

			updatePlan.CurrentVersion = currentVersion.Original
			updatePlan.NewVersion = newVersion.Original
			updatePlan.Resource = resource

			log.WithFields(log.Fields{
				"parsed_image":     containerImageRef.Remote(),
				"raw_image_name":   c.Image,
				"target_image":     repo.Name,
				"target_image_tag": repo.Tag,
				"policy":           policy,
			}).Info("provider.kubernetes: impacted deployment container found")
		}
	}

	return updatePlan, shouldUpdateDeployment, nil
}

func setUpdateTime(resource *k8s.GenericResource) {
	specAnnotations := resource.GetSpecAnnotations()
	specAnnotations[types.KeelUpdateTimeAnnotation] = time.Now().String()
	resource.SetSpecAnnotations(specAnnotations)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
)

func main() {

	addr := net.UDPAddr{Port: 8125, IP: net.ParseIP("127.0.0.1")}
	conn, err := net.ListenUDP("udp", &addr)
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	buf := make([]byte, 1024)
	for {
		if n, _, err := conn.ReadFromUDP(buf); err == nil {
			fmt.Println(string(buf[0:n]))
		} else {
			fmt.Println("Error: ", err)
		}
	}
}
<commit_msg>renamed echostats.go function from main for CircleCI.<commit_after>package main

import (
	"fmt"
	"net"
)

func stats() {

	addr := net.UDPAddr{Port: 8125, IP: net.ParseIP("127.0.0.1")}
	conn, err := net.ListenUDP("udp", &addr)
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	buf := make([]byte, 1024)
	for {
		if n, _, err := conn.ReadFromUDP(buf); err == nil {
			fmt.Println(string(buf[0:n]))
		} else {
			fmt.Println("Error: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"syscall"
)

import (
	"github.com/VividCortex/godaemon"
	_ "github.com/influxdb/influxdb/models"
)

const (
	LOG_FILE = "nfs.log"
)

func parseArgs(daemonize *bool, port *string) {
	flag.BoolVar(daemonize, "d", false, "daemonize")
	flag.StringVar(port, "p", "8086", "port")
	flag.Parse()
}

func main() {
	var logfile *os.File
	var err error
	var port string

	daemonize := true
	if godaemon.Stage() == godaemon.StageParent {
		parseArgs(&daemonize, &port)

		if daemonize {
			logfile, err = os.OpenFile(LOG_FILE, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				fmt.Println("[ERROR] error opening log file:", err)
				os.Exit(1)
			}

			err = syscall.Flock(int(logfile.Fd()), syscall.LOCK_EX)
			if err != nil {
				fmt.Println("[ERROR] error acquiring lock to log file:", err)
				os.Exit(1)
			}
		}
	}

	if daemonize {
		_, _, err = godaemon.MakeDaemon(&godaemon.DaemonAttr{Files: []**os.File{&logfile}})
		if err != nil {
			fmt.Println("[ERROR] error daemonizing:", err)
			os.Exit(1)
		}

		defer logfile.Close()
		log.SetOutput(logfile)
		parseArgs(&daemonize, &port)
	}

	log.SetFlags(log.LstdFlags)
	log.Println("#################### BEGIN OF LOG ##########################")

	// listening to incoming connections
	conn, err := net.Listen("tcp", ":"+port)
	if err != nil {
		log.Fatalln("[ERROR] listening:", err)
	}
	defer conn.Close()
	log.Println("[_INFO] listening on", port)

	for {
		client, err := conn.Accept()
		if err != nil {
			log.Println("[_WARN] error accepting: ", err.Error())
			continue
		}
		log.Printf("[_INFO] Received request from %s\n", client.RemoteAddr())

		reader := bufio.NewReader(client)
		line, isPrefix, err := reader.ReadLine()
		for err == nil && !isPrefix {
			log.Println(string(line))
			line, isPrefix, err = reader.ReadLine()
		}
		if isPrefix {
			log.Println("buffer size is too small!")
		} else {
			log.Println(err)
		}
	}
}
<commit_msg>nfs : listening to line protocol using http<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"syscall"
)

import (
	"github.com/VividCortex/godaemon"
	_ "github.com/influxdb/influxdb/models"
)

const (
	LOG_FILE = "nfs.log"
)

func writeHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNoContent)
}

func defaultHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("[WARN] unexpected request:", r)
	w.WriteHeader(http.StatusNoContent)
}

func parseArgs(daemonize *bool, port *string) {
	flag.BoolVar(daemonize, "d", false, "daemonize")
	flag.StringVar(port, "p", "8086", "port")
	flag.Parse()
}

func main() {
	var logfile *os.File
	var err error
	var port string

	daemonize := true
	if godaemon.Stage() == godaemon.StageParent {
		parseArgs(&daemonize, &port)

		if daemonize {
			logfile, err = os.OpenFile(LOG_FILE, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				fmt.Println("[ERROR] error opening log file:", err)
				os.Exit(1)
			}

			err = syscall.Flock(int(logfile.Fd()), syscall.LOCK_EX)
			if err != nil {
				fmt.Println("[ERROR] error acquiring lock to log file:", err)
				os.Exit(1)
			}
		}
	}

	if daemonize {
		_, _, err = godaemon.MakeDaemon(&godaemon.DaemonAttr{Files: []**os.File{&logfile}})
		if err != nil {
			fmt.Println("[ERROR] error daemonizing:", err)
			os.Exit(1)
		}

		defer logfile.Close()
		log.SetOutput(logfile)
		parseArgs(&daemonize, &port)
	}

	log.SetFlags(log.LstdFlags)
	log.Println("#################### BEGIN OF LOG ##########################")
	http.HandleFunc("/", defaultHandler)
	http.HandleFunc("/write", writeHandler)
	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>package utils

import (
	"log"
	"net/http"

	. "github.com/julienschmidt/httprouter"
)

type HttpError struct {
	Error   error
	Message string
	Code    int
}

type ErrHandler func(http.ResponseWriter, *http.Request, Params) *HttpError

// ErrWrap processes errors in the query.
// Logging the queries.
// If the url has parameters of success or failure,
// in case of redirect performs on them
// depending on the result of the request.
// Parameters are passed in the request url, for example:
// 	http://localhost:8000/login?success=http://google.com&failure=http://ya.ru
func ErrWrap(eh ErrHandler) Handle {
	return Handle(func(w http.ResponseWriter, r *http.Request, p Params) {
		if e := eh(w, r, p); e != nil {
			log.Printf("\033[7m\033[1m\tError: %v Message: %v Code: %v\033[0m", e.Error, e.Message, e.Code)

			if failureURL := r.URL.Query().Get("failure"); failureURL != "" {
				http.Redirect(w, r, failureURL, 301)
			} else {
				http.Error(w, e.Message, e.Code)
			}
		} else {
			log.Printf("\033[7m\033[1m\tSuccessfully.\033[0m")

			if successURL := r.URL.Query().Get("success"); successURL != "" {
				http.Redirect(w, r, successURL, 301)
			}
		}
	})
}
<commit_msg>Change logging style, added telegram error report.<commit_after>package utils

import (
	"log"
	"net/http"

	. "github.com/julienschmidt/httprouter"
)

type HttpError struct {
	Error   error
	Message string
	Code    int
}

type ErrHandler func(http.ResponseWriter, *http.Request, Params) *HttpError

// ErrWrap processes errors in the query.
// Logging the queries.
// If the url has parameters of success or failure,
// in case of redirect performs on them
// depending on the result of the request.
// Parameters are passed in the request url, for example:
// 	http://localhost:8000/login?success=http://google.com&failure=http://ya.ru
func ErrWrap(eh ErrHandler) Handle {
	return Handle(func(writer http.ResponseWriter, request *http.Request, params Params) {
		if e := eh(writer, request, params); e != nil {
			log.Printf("\033[7m\033[1m\t ✗ Error: %v Message: %v Code: %v\033[0m",
				e.Error, e.Message, e.Code)

			go telegramReport(ErrorReport{
				Error: *e,
				Params: params,
				Request: *request,
			})

			if failureURL := request.URL.Query().Get("failure"); failureURL != "" {
				http.Redirect(writer, request, failureURL, 301)
			} else {
				http.Error(writer, e.Message, e.Code)
			}
		} else {
			log.Printf("\033[7m\033[1m\t ✓ Successfully.\033[0m")

			if successURL := request.URL.Query().Get("success"); successURL != "" {
				http.Redirect(writer, request, successURL, 301)
			}
		}
	})
}
<|endoftext|>


<commit_before>// Package stream provides WDTE functions for manipulating streams of
// data.
package stream

import "github.com/DeedleFake/wdte"

// A Stream is a type of function that can yield successive values.
type Stream interface {
	wdte.Func

	// Next returns the next value and true, or an undefined value and
	// false if the stream is empty.
	Next(frame wdte.Frame) (wdte.Func, bool)
}

// A NextFunc wraps a Go function, making it possible to use it as a
// Stream. When called as a WDTE function, the function simply returns itself.
type NextFunc func(frame wdte.Frame) (wdte.Func, bool)

func (n NextFunc) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return n
}

func (n NextFunc) Equals(other wdte.Func) bool {
	panic("Not implemented.")
}

func (n NextFunc) Next(frame wdte.Frame) (wdte.Func, bool) {
	return n(frame)
}

// An array is a Stream that iterates over an array.
type array struct {
	a wdte.Array
	i int
}

// New returns a new stream. If given one argument and that argument
// is an array, it iterates over the values of the array. If given
// more than one argument or the first argument is not an array, it
// iterates over its arguments.
func New(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(New)

	case 1:
		if a1, ok := args[0].Call(frame).(wdte.Array); ok {
			frame = frame.WithID("new")
			return &array{a: a1}
		}
	}

	frame = frame.WithID("new")
	return &array{a: args}
}

func (a *array) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return a
}

func (a *array) Equals(other wdte.Func) bool {
	panic("Not implemented.")
}

func (a *array) Next(frame wdte.Frame) (wdte.Func, bool) {
	if a.i >= len(a.a) {
		return nil, false
	}

	r := a.a[a.i]
	a.i++
	return r, true
}

// An rng (range) is a stream that yields successive numbers.
type rng struct {
	// i is the next number to return.
	i wdte.Number

	// m is the number to stop at, exclusive.
	m wdte.Number

	// s is the amount to increment every time Next() is called.
	s wdte.Number
}

// Range returns a stream that yields successive numbers. If given a
// single argument, the range yielded is [0, args[0]). If given two
// arguments, the range is [args[0], args[1]). If given three
// arguments, the range is the same as with two arguments, but the
// step in between numbers yielded is the third argument, rather than
// 1.
func Range(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	if len(args) == 0 {
		return wdte.GoFunc(Range)
	}

	frame = frame.WithID("range")

	switch len(args) {
	case 1:
		return &rng{
			m: args[0].Call(frame).(wdte.Number),
			s: 1,
		}

	case 2:
		return &rng{
			i: args[0].Call(frame).(wdte.Number),
			m: args[1].Call(frame).(wdte.Number),
			s: 1,
		}
	}

	return &rng{
		i: args[0].Call(frame).(wdte.Number),
		m: args[1].Call(frame).(wdte.Number),
		s: args[2].Call(frame).(wdte.Number),
	}
}

func (r *rng) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return r
}

func (r *rng) Equals(other wdte.Func) bool {
	panic("Not implemented.")
}

func (r *rng) Next(frame wdte.Frame) (wdte.Func, bool) {
	if r.i >= r.m {
		return nil, false
	}

	n := r.i
	r.i += r.s
	return n, true
}

// A mapper is a function that creates Stream wrappers that call a
// function on each value yielded by the underlying Stream, returning
// the result.
type mapper struct {
	m wdte.Func
}

// Map returns a function that takes a Stream and wraps the Stream in
// a new Stream that calls the function originally given to Map on
// each element before passing it on.
//
// Wow, that sound horrible. It's not too bad, though. It works like
// this. Call Map with some function `f` and get a new function. Then,
// call that returned function on a Stream to get a new Stream that
// calls `f` on each element when Next is called.
func Map(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Map)
	}

	return &mapper{m: args[0].Call(frame)}
}

func (m *mapper) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 1:
		if a, ok := args[0].Call(frame).(Stream); ok {
			return NextFunc(func(frame wdte.Frame) (wdte.Func, bool) {
				n, ok := a.Next(frame)
				if !ok {
					return nil, false
				}

				frame = frame.WithID("map")
				return m.m.Call(frame, n), true
			})
		}
	}

	return m
}

func (m *mapper) Equals(other wdte.Func) bool {
	panic("Not implemented.")
}

// Collect converts a Stream into an array.
func Collect(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Collect)
	}

	frame = frame.WithID("collect")

	a, ok := args[0].Call(frame).(Stream)
	if !ok {
		return args[0]
	}

	r := wdte.Array{}
	for {
		n, ok := a.Next(frame)
		if !ok {
			break
		}
		if _, ok := n.(error); ok {
			return n
		}

		r = append(r, n.Call(frame))
	}

	return r
}

// Module returns a module for easy importing into an actual script.
// The imported functions have the same names as the functions in this
// package, except that the first letter is lowercase.
func Module() *wdte.Module {
	return &wdte.Module{
		Funcs: map[wdte.ID]wdte.Func{
			"new":     wdte.GoFunc(New),
			"range":   wdte.GoFunc(Range),
			"map":     wdte.GoFunc(Map),
			"collect": wdte.GoFunc(Collect),
		},
	}
}
<commit_msg>std/stream: Remove unused and unimplemented Equals() methods.<commit_after>// Package stream provides WDTE functions for manipulating streams of
// data.
package stream

import "github.com/DeedleFake/wdte"

// A Stream is a type of function that can yield successive values.
type Stream interface {
	wdte.Func

	// Next returns the next value and true, or an undefined value and
	// false if the stream is empty.
	Next(frame wdte.Frame) (wdte.Func, bool)
}

// A NextFunc wraps a Go function, making it possible to use it as a
// Stream. When called as a WDTE function, the function simply returns itself.
type NextFunc func(frame wdte.Frame) (wdte.Func, bool)

func (n NextFunc) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return n
}

func (n NextFunc) Next(frame wdte.Frame) (wdte.Func, bool) {
	return n(frame)
}

// An array is a Stream that iterates over an array.
type array struct {
	a wdte.Array
	i int
}

// New returns a new stream. If given one argument and that argument
// is an array, it iterates over the values of the array. If given
// more than one argument or the first argument is not an array, it
// iterates over its arguments.
func New(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(New)

	case 1:
		if a1, ok := args[0].Call(frame).(wdte.Array); ok {
			frame = frame.WithID("new")
			return &array{a: a1}
		}
	}

	frame = frame.WithID("new")
	return &array{a: args}
}

func (a *array) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return a
}

func (a *array) Next(frame wdte.Frame) (wdte.Func, bool) {
	if a.i >= len(a.a) {
		return nil, false
	}

	r := a.a[a.i]
	a.i++
	return r, true
}

// An rng (range) is a stream that yields successive numbers.
type rng struct {
	// i is the next number to return.
	i wdte.Number

	// m is the number to stop at, exclusive.
	m wdte.Number

	// s is the amount to increment every time Next() is called.
	s wdte.Number
}

// Range returns a stream that yields successive numbers. If given a
// single argument, the range yielded is [0, args[0]). If given two
// arguments, the range is [args[0], args[1]). If given three
// arguments, the range is the same as with two arguments, but the
// step in between numbers yielded is the third argument, rather than
// 1.
func Range(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	if len(args) == 0 {
		return wdte.GoFunc(Range)
	}

	frame = frame.WithID("range")

	switch len(args) {
	case 1:
		return &rng{
			m: args[0].Call(frame).(wdte.Number),
			s: 1,
		}

	case 2:
		return &rng{
			i: args[0].Call(frame).(wdte.Number),
			m: args[1].Call(frame).(wdte.Number),
			s: 1,
		}
	}

	return &rng{
		i: args[0].Call(frame).(wdte.Number),
		m: args[1].Call(frame).(wdte.Number),
		s: args[2].Call(frame).(wdte.Number),
	}
}

func (r *rng) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	return r
}

func (r *rng) Next(frame wdte.Frame) (wdte.Func, bool) {
	if r.i >= r.m {
		return nil, false
	}

	n := r.i
	r.i += r.s
	return n, true
}

// A mapper is a function that creates Stream wrappers that call a
// function on each value yielded by the underlying Stream, returning
// the result.
type mapper struct {
	m wdte.Func
}

// Map returns a function that takes a Stream and wraps the Stream in
// a new Stream that calls the function originally given to Map on
// each element before passing it on.
//
// Wow, that sound horrible. It's not too bad, though. It works like
// this. Call Map with some function `f` and get a new function. Then,
// call that returned function on a Stream to get a new Stream that
// calls `f` on each element when Next is called.
func Map(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Map)
	}

	return &mapper{m: args[0].Call(frame)}
}

func (m *mapper) Call(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 1:
		if a, ok := args[0].Call(frame).(Stream); ok {
			return NextFunc(func(frame wdte.Frame) (wdte.Func, bool) {
				n, ok := a.Next(frame)
				if !ok {
					return nil, false
				}

				frame = frame.WithID("map")
				return m.m.Call(frame, n), true
			})
		}
	}

	return m
}

// Collect converts a Stream into an array.
func Collect(frame wdte.Frame, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Collect)
	}

	frame = frame.WithID("collect")

	a, ok := args[0].Call(frame).(Stream)
	if !ok {
		return args[0]
	}

	r := wdte.Array{}
	for {
		n, ok := a.Next(frame)
		if !ok {
			break
		}
		if _, ok := n.(error); ok {
			return n
		}

		r = append(r, n.Call(frame))
	}

	return r
}

// Module returns a module for easy importing into an actual script.
// The imported functions have the same names as the functions in this
// package, except that the first letter is lowercase.
func Module() *wdte.Module {
	return &wdte.Module{
		Funcs: map[wdte.ID]wdte.Func{
			"new":     wdte.GoFunc(New),
			"range":   wdte.GoFunc(Range),
			"map":     wdte.GoFunc(Map),
			"collect": wdte.GoFunc(Collect),
		},
	}
}
<|endoftext|>