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

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "17.0+"          // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.17.0-dev"    // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<commit_msg>Kubernetes version v0.17.1<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "17.1"           // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.17.1"        // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<|endoftext|>


<commit_before>/*
Copyright 2014 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 version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "8.0"            // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.8.0"         // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<commit_msg>Kubernetes version v0.8.0-dev<commit_after>/*
Copyright 2014 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 version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "8.0+"           // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.8.0-dev"     // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<|endoftext|>


<commit_before>package test

import (
	"context"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"testing"
	"time"

	yaml "gopkg.in/yaml.v2"

	"github.com/jacksontj/promxy/config"
	"github.com/jacksontj/promxy/proxystorage"
	"github.com/prometheus/common/route"
	"github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/promql"
	"github.com/prometheus/prometheus/storage"
	"github.com/prometheus/prometheus/util/testutil"
	"github.com/prometheus/prometheus/web/api/v1"
	"github.com/sirupsen/logrus"
)

const rawPSConfig = `
promxy:
  http_client:
    tls_config:
      insecure_skip_verify: true
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
`

const rawPSRemoteReadConfig = `
promxy:
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
      remote_read: true
      http_client:
        tls_config:
          insecure_skip_verify: true
`

const rawDoublePSConfig = `
promxy:
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
      labels:
        az: a
      http_client:
        tls_config:
          insecure_skip_verify: true
    - static_configs:
        - targets:
          - localhost:8084
      labels:
        az: b
      http_client:
        tls_config:
          insecure_skip_verify: true
`

func getProxyStorage(cfg string) *proxystorage.ProxyStorage {
	ps, err := proxystorage.NewProxyStorage()
	if err != nil {
		logrus.Fatalf("Error creating proxy: %v", err)
	}

	// Create promxy in front of it
	pstorageConfig := &proxyconfig.Config{}
	if err := yaml.Unmarshal([]byte(cfg), &pstorageConfig); err != nil {
		panic(err)
	}
	if err := ps.ApplyConfig(pstorageConfig); err != nil {
		logrus.Fatalf("Unable to apply config: %v", err)
	}
	return ps
}

func startAPIForTest(test *promql.Test, listen string) (*http.Server, chan struct{}) {
	// Start up API server for engine
	cfgFunc := func() config.Config { return config.DefaultConfig }
	// Return 503 until ready (for us there isn't much startup, so this might not need to be implemented
	readyFunc := func(f http.HandlerFunc) http.HandlerFunc { return f }

	api := v1.NewAPI(
		promql.NewEngine(nil, nil, 20, 10*time.Minute),
		test.Storage(),
		nil,
		nil,
		cfgFunc,
		nil,
		readyFunc,
		nil,
		true,
	)

	apiRouter := route.New()
	api.Register(apiRouter.WithPrefix("/api/v1"))

	startChan := make(chan struct{})
	stopChan := make(chan struct{})
	srv := &http.Server{Addr: listen, Handler: apiRouter}

	go func() {
		defer close(stopChan)
		close(startChan)
		srv.ListenAndServe()
	}()

	<-startChan

	return srv, stopChan
}

func TestUpstreamEvaluations(t *testing.T) {
	files, err := filepath.Glob("../vendor/github.com/prometheus/prometheus/promql/testdata/*.test")
	if err != nil {
		t.Fatal(err)
	}
	for i, psConfig := range []string{rawPSConfig, rawPSRemoteReadConfig} {
		for _, fn := range files {

			// Upstream prom is using a StaleNan to determine if a given timeseries has gone
			// NaN -- the problem being that for range vectors they filter out all "stale" samples
			// meaning that it isn't possible to get a "raw" dump of data through the v1 API
			// The only option that exists in reality is the "remote read" API -- which suffers
			// from the same memory-balooning problems that the HTTP+JSON API originally had.
			// It has **less** of a problem (its 2x memory instead of 14x) so it is a viable option.
			// NOTE: Skipped only when promxy isn't configured to use the remote_read API
			if psConfig == rawPSConfig && strings.Contains(fn, "staleness.test") {
				continue
			}
			t.Run(strconv.Itoa(i)+fn, func(t *testing.T) {
				test, err := newTestFromFile(t, fn)
				if err != nil {
					t.Errorf("error creating test for %s: %s", fn, err)
				}

				// Create API for the storage engine
				srv, stopChan := startAPIForTest(test, ":8083")

				ps := getProxyStorage(psConfig)
				lStorage := &LayeredStorage{ps, test.Storage()}
				// Replace the test storage with the promxy one
				test.SetStorage(lStorage)
				test.QueryEngine().NodeReplacer = ps.NodeReplacer

				err = test.Run()
				if err != nil {
					t.Errorf("error running test %s: %s", fn, err)
				}
				test.Close()

				// stop server
				ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
				srv.Shutdown(ctx)
				<-stopChan
			})
		}
	}
}

func TestEvaluations(t *testing.T) {
	files, err := filepath.Glob("testdata/*.test")
	if err != nil {
		t.Fatal(err)
	}
	for _, fn := range files {
		t.Run(fn, func(t *testing.T) {
			test, err := newTestFromFile(t, fn)
			if err != nil {
				t.Errorf("error creating test for %s: %s", fn, err)
			}

			// Create API for the storage engine
			srv, stopChan := startAPIForTest(test, ":8083")
			srv2, stopChan2 := startAPIForTest(test, ":8084")

			ps := getProxyStorage(rawDoublePSConfig)
			lStorage := &LayeredStorage{ps, test.Storage()}
			// Replace the test storage with the promxy one
			test.SetStorage(lStorage)
			test.QueryEngine().NodeReplacer = ps.NodeReplacer

			err = test.Run()
			if err != nil {
				t.Errorf("error running test %s: %s", fn, err)
			}

			test.Close()

			// stop server
			ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
			srv.Shutdown(ctx)
			srv2.Shutdown(ctx)

			<-stopChan
			<-stopChan2
		})
	}
}

func newTestFromFile(t testutil.T, filename string) (*promql.Test, error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return promql.NewTest(t, string(content))
}

// Create a wrapper for the storage that will proxy reads but not writes

type LayeredStorage struct {
	proxyStorage storage.Storage
	baseStorage  storage.Storage
}

func (p *LayeredStorage) Querier(ctx context.Context, mint, maxt int64) (storage.Querier, error) {
	return p.proxyStorage.Querier(ctx, mint, maxt)
}
func (p *LayeredStorage) StartTime() (int64, error) {
	return p.baseStorage.StartTime()
}

func (p *LayeredStorage) Appender() (storage.Appender, error) {
	return p.baseStorage.Appender()
}
func (p *LayeredStorage) Close() error {
	return p.baseStorage.Close()
}
<commit_msg>Cleanup golint complaints<commit_after>package test

import (
	"context"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"testing"
	"time"

	yaml "gopkg.in/yaml.v2"

	"github.com/jacksontj/promxy/config"
	"github.com/jacksontj/promxy/proxystorage"
	"github.com/prometheus/common/route"
	"github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/promql"
	"github.com/prometheus/prometheus/storage"
	"github.com/prometheus/prometheus/util/testutil"
	"github.com/prometheus/prometheus/web/api/v1"
	"github.com/sirupsen/logrus"
)

const rawPSConfig = `
promxy:
  http_client:
    tls_config:
      insecure_skip_verify: true
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
`

const rawPSRemoteReadConfig = `
promxy:
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
      remote_read: true
      http_client:
        tls_config:
          insecure_skip_verify: true
`

const rawDoublePSConfig = `
promxy:
  server_groups:
    - static_configs:
        - targets:
          - localhost:8083
      labels:
        az: a
      http_client:
        tls_config:
          insecure_skip_verify: true
    - static_configs:
        - targets:
          - localhost:8084
      labels:
        az: b
      http_client:
        tls_config:
          insecure_skip_verify: true
`

func getProxyStorage(cfg string) *proxystorage.ProxyStorage {
	ps, err := proxystorage.NewProxyStorage()
	if err != nil {
		logrus.Fatalf("Error creating proxy: %v", err)
	}

	// Create promxy in front of it
	pstorageConfig := &proxyconfig.Config{}
	if err := yaml.Unmarshal([]byte(cfg), &pstorageConfig); err != nil {
		panic(err)
	}
	if err := ps.ApplyConfig(pstorageConfig); err != nil {
		logrus.Fatalf("Unable to apply config: %v", err)
	}
	return ps
}

func startAPIForTest(test *promql.Test, listen string) (*http.Server, chan struct{}) {
	// Start up API server for engine
	cfgFunc := func() config.Config { return config.DefaultConfig }
	// Return 503 until ready (for us there isn't much startup, so this might not need to be implemented
	readyFunc := func(f http.HandlerFunc) http.HandlerFunc { return f }

	api := v1.NewAPI(
		promql.NewEngine(nil, nil, 20, 10*time.Minute),
		test.Storage(),
		nil,
		nil,
		cfgFunc,
		nil,
		readyFunc,
		nil,
		true,
	)

	apiRouter := route.New()
	api.Register(apiRouter.WithPrefix("/api/v1"))

	startChan := make(chan struct{})
	stopChan := make(chan struct{})
	srv := &http.Server{Addr: listen, Handler: apiRouter}

	go func() {
		defer close(stopChan)
		close(startChan)
		srv.ListenAndServe()
	}()

	<-startChan

	return srv, stopChan
}

func TestUpstreamEvaluations(t *testing.T) {
	files, err := filepath.Glob("../vendor/github.com/prometheus/prometheus/promql/testdata/*.test")
	if err != nil {
		t.Fatal(err)
	}
	for i, psConfig := range []string{rawPSConfig, rawPSRemoteReadConfig} {
		for _, fn := range files {

			// Upstream prom is using a StaleNan to determine if a given timeseries has gone
			// NaN -- the problem being that for range vectors they filter out all "stale" samples
			// meaning that it isn't possible to get a "raw" dump of data through the v1 API
			// The only option that exists in reality is the "remote read" API -- which suffers
			// from the same memory-balooning problems that the HTTP+JSON API originally had.
			// It has **less** of a problem (its 2x memory instead of 14x) so it is a viable option.
			// NOTE: Skipped only when promxy isn't configured to use the remote_read API
			if psConfig == rawPSConfig && strings.Contains(fn, "staleness.test") {
				continue
			}
			t.Run(strconv.Itoa(i)+fn, func(t *testing.T) {
				test, err := newTestFromFile(t, fn)
				if err != nil {
					t.Errorf("error creating test for %s: %s", fn, err)
				}

				// Create API for the storage engine
				srv, stopChan := startAPIForTest(test, ":8083")

				ps := getProxyStorage(psConfig)
				lStorage := &LayeredStorage{ps, test.Storage()}
				// Replace the test storage with the promxy one
				test.SetStorage(lStorage)
				test.QueryEngine().NodeReplacer = ps.NodeReplacer

				err = test.Run()
				if err != nil {
					t.Errorf("error running test %s: %s", fn, err)
				}
				test.Close()

				// stop server
				ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
				defer cancel()
				srv.Shutdown(ctx)
				<-stopChan
			})
		}
	}
}

func TestEvaluations(t *testing.T) {
	files, err := filepath.Glob("testdata/*.test")
	if err != nil {
		t.Fatal(err)
	}
	for _, fn := range files {
		t.Run(fn, func(t *testing.T) {
			test, err := newTestFromFile(t, fn)
			if err != nil {
				t.Errorf("error creating test for %s: %s", fn, err)
			}

			// Create API for the storage engine
			srv, stopChan := startAPIForTest(test, ":8083")
			srv2, stopChan2 := startAPIForTest(test, ":8084")

			ps := getProxyStorage(rawDoublePSConfig)
			lStorage := &LayeredStorage{ps, test.Storage()}
			// Replace the test storage with the promxy one
			test.SetStorage(lStorage)
			test.QueryEngine().NodeReplacer = ps.NodeReplacer

			err = test.Run()
			if err != nil {
				t.Errorf("error running test %s: %s", fn, err)
			}

			test.Close()

			// stop server
			ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
			defer cancel()
			srv.Shutdown(ctx)
			srv2.Shutdown(ctx)

			<-stopChan
			<-stopChan2
		})
	}
}

func newTestFromFile(t testutil.T, filename string) (*promql.Test, error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return promql.NewTest(t, string(content))
}

// Create a wrapper for the storage that will proxy reads but not writes

type LayeredStorage struct {
	proxyStorage storage.Storage
	baseStorage  storage.Storage
}

func (p *LayeredStorage) Querier(ctx context.Context, mint, maxt int64) (storage.Querier, error) {
	return p.proxyStorage.Querier(ctx, mint, maxt)
}
func (p *LayeredStorage) StartTime() (int64, error) {
	return p.baseStorage.StartTime()
}

func (p *LayeredStorage) Appender() (storage.Appender, error) {
	return p.baseStorage.Appender()
}
func (p *LayeredStorage) Close() error {
	return p.baseStorage.Close()
}
<|endoftext|>


<commit_before>package plugin

import (
	"log"
	"github.com/emersion/go-kdeconnect/protocol"
	"github.com/emersion/go-kdeconnect/network"
)

const TelephonyType protocol.PackageType = "kdeconnect.telephony"

type TelephonyEventName string
const (
	TelephonyRinging TelephonyEventName = "ringing"
	TelephonyTalking = "talking"
	TelephonyMissedCall = "missedCall"
	TelephonySms = "sms"
)

type TelephonyAction string
const (
	TelephonyMute TelephonyAction = "mute"
)

type TelephonyBody struct {
	Event TelephonyEventName `json:"event",omitempty`
	PhoneNumber string `json:"phoneNumber,omitempty"`
	ContactName string `json:"contactName,omitempty"`

	MessageBody string `json:"messageBody,omitempty"`

	isCancel string `json:"isCancel,omitempty"` // It is a string but must be a bool
	IsCancel bool `json:"-"`

	Action TelephonyAction `json:"action,omitempty"`
}

type TelephonyEvent struct {
	Event
	TelephonyBody
}

type Telephony struct {
	Incoming chan *TelephonyEvent
}

func (p *Telephony) GetDisplayName() string {
	return "Telephony"
}

func (p *Telephony) GetSupportedPackages() map[protocol.PackageType]BodyFactory {
	return map[protocol.PackageType]BodyFactory{
		TelephonyType: func() interface{} { return &TelephonyBody{} },
	}
}

func (p *Telephony) Handle(device *network.Device, pkg *protocol.Package) bool {
	if pkg.Type != TelephonyType {
		return false
	}

	event := &TelephonyEvent{TelephonyBody: *pkg.Body.(*TelephonyBody)}
	event.Device = device

	// Workaround because isCancel is sent as a string, not a bool
	if event.isCancel != "" {
		event.IsCancel = true
	}

	select {
	case p.Incoming <- event:
	default:
	}

	return true
}

func (p *Telephony) SendAction(device *network.Device, action TelephonyAction) error {
	return device.Send(TelephonyType, &TelephonyBody{Action: action})
}

func NewTelephony() *Telephony {
	return &Telephony{
		Incoming: make(chan *TelephonyEvent),
	}
}
<commit_msg>Removes unnecessary import<commit_after>package plugin

import (
	"github.com/emersion/go-kdeconnect/protocol"
	"github.com/emersion/go-kdeconnect/network"
)

const TelephonyType protocol.PackageType = "kdeconnect.telephony"

type TelephonyEventName string
const (
	TelephonyRinging TelephonyEventName = "ringing"
	TelephonyTalking = "talking"
	TelephonyMissedCall = "missedCall"
	TelephonySms = "sms"
)

type TelephonyAction string
const (
	TelephonyMute TelephonyAction = "mute"
)

type TelephonyBody struct {
	Event TelephonyEventName `json:"event",omitempty`
	PhoneNumber string `json:"phoneNumber,omitempty"`
	ContactName string `json:"contactName,omitempty"`

	MessageBody string `json:"messageBody,omitempty"`

	isCancel string `json:"isCancel,omitempty"` // It is a string but must be a bool
	IsCancel bool `json:"-"`

	Action TelephonyAction `json:"action,omitempty"`
}

type TelephonyEvent struct {
	Event
	TelephonyBody
}

type Telephony struct {
	Incoming chan *TelephonyEvent
}

func (p *Telephony) GetDisplayName() string {
	return "Telephony"
}

func (p *Telephony) GetSupportedPackages() map[protocol.PackageType]BodyFactory {
	return map[protocol.PackageType]BodyFactory{
		TelephonyType: func() interface{} { return &TelephonyBody{} },
	}
}

func (p *Telephony) Handle(device *network.Device, pkg *protocol.Package) bool {
	if pkg.Type != TelephonyType {
		return false
	}

	event := &TelephonyEvent{TelephonyBody: *pkg.Body.(*TelephonyBody)}
	event.Device = device

	// Workaround because isCancel is sent as a string, not a bool
	if event.isCancel != "" {
		event.IsCancel = true
	}

	select {
	case p.Incoming <- event:
	default:
	}

	return true
}

func (p *Telephony) SendAction(device *network.Device, action TelephonyAction) error {
	return device.Send(TelephonyType, &TelephonyBody{Action: action})
}

func NewTelephony() *Telephony {
	return &Telephony{
		Incoming: make(chan *TelephonyEvent),
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the concurrency primitive functions.

package golisp

import (
	"fmt"
	"runtime"
	"strings"
	"time"
	"unsafe"
)

type Process struct {
	Env           *SymbolTableFrame
	Code          *Data
	Wake          chan bool
	Abort         chan bool
	Restart       chan bool
	ScheduleTimer *time.Timer
}

func RegisterConcurrencyPrimitives() {
	MakePrimitiveFunction("fork", "1", ForkImpl)
	MakePrimitiveFunction("proc-sleep", "2", ProcSleepImpl)
	MakePrimitiveFunction("wake", "1", WakeImpl)
	MakePrimitiveFunction("schedule", "2", ScheduleImpl)
	MakePrimitiveFunction("reset-timeout", "1", ResetTimeoutImpl)
	MakePrimitiveFunction("abandon", "1", AbandonImpl)
}

func ForkImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f := Car(args)

	if !FunctionP(f) {
		err = ProcessError(fmt.Sprintf("fork expected a function, but received %v.", f), env)
		return
	}

	if FunctionValue(f).RequiredArgCount != 1 {
		err = ProcessError(fmt.Sprintf("fork expected a function with arity of 1, but it was %d.", FunctionValue(f).RequiredArgCount), env)
		return
	}

	proc := &Process{Env: env, Code: f, Wake: make(chan bool, 1), Abort: make(chan bool, 1), Restart: make(chan bool, 1)}
	procObj := ObjectWithTypeAndValue("Process", unsafe.Pointer(proc))

	go func() {
		callWithPanicProtection(func() {
			_, forkedErr := FunctionValue(f).ApplyWithoutEval(InternalMakeList(procObj), env)
			if forkedErr != nil {
				fmt.Println(forkedErr)
			}
		}, "fork")
	}()

	return procObj, nil
}

func ProcSleepImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("proc-sleep expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))

	millis := Cadr(args)
	if !IntegerP(millis) {
		err = ProcessError(fmt.Sprintf("proc-sleep expected an integer as a delay, but received %v.", millis), env)
		return
	}

	woken := false
	select {
	case <-proc.Wake:
		woken = true
	case <-time.After(time.Duration(IntegerValue(millis)) * time.Millisecond):
	}

	return BooleanWithValue(woken), nil
}

func WakeImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("wake expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	proc.Wake <- true
	return StringWithValue("OK"), nil
}

func ScheduleImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	millis := Car(args)
	if !IntegerP(millis) {
		err = ProcessError(fmt.Sprintf("schedule expected an integer as a delay, but received %v.", millis), env)
		return
	}
	f := Cadr(args)

	if !FunctionP(f) {
		err = ProcessError(fmt.Sprintf("schedule expected a function, but received %v.", f), env)
		return
	}

	if FunctionValue(f).RequiredArgCount != 1 {
		err = ProcessError(fmt.Sprintf("schedule expected a function with arity of 1, but it was %d.", FunctionValue(f).RequiredArgCount), env)
		return
	}

	proc := &Process{
		Env:           env,
		Code:          f,
		Wake:          make(chan bool, 1),
		Abort:         make(chan bool, 1),
		Restart:       make(chan bool, 1),
		ScheduleTimer: time.NewTimer(time.Duration(IntegerValue(millis)) * time.Millisecond)}
	procObj := ObjectWithTypeAndValue("Process", unsafe.Pointer(proc))

	aborted := false
	go func() {
		callWithPanicProtection(func() {
		Loop:
			for {
				select {
				case <-proc.Abort:
					aborted = true
					break Loop
				case <-proc.Restart:
					proc.ScheduleTimer.Reset(time.Duration(IntegerValue(millis)) * time.Millisecond)
				case <-proc.ScheduleTimer.C:
					_, err = FunctionValue(f).ApplyWithoutEval(InternalMakeList(procObj), env)
					break Loop
				}
			}
		}, "schedule")
	}()

	return procObj, nil

}

func AbandonImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("adandon expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	proc.Abort <- true
	return StringWithValue("OK"), nil
}

func ResetTimeoutImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("restart expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	var str string
	select {
	case proc.Restart <- true:
		str = "OK"
	default:
		str = "task was already completed or abandoned"
	}
	return StringWithValue(str), nil
}

func callWithPanicProtection(f func(), prefix string) {
	defer func() {
		if recovered := recover(); recovered != nil {
			stackBuf := make([]byte, 10000)
			stackBuf = stackBuf[:runtime.Stack(stackBuf, false)]
			stack := strings.Split(string(stackBuf), "\n")
			for i := 0; i < 7; i++ {
				fmt.Println(stack[i])
			}
		}
	}()

	f()
}
<commit_msg>initial implementation of "join" for forked tasks<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the concurrency primitive functions.

package golisp

import (
	"fmt"
	"runtime"
	"strings"
	"time"
	"unsafe"
)

type Process struct {
	Env           *SymbolTableFrame
	Code          *Data
	Wake          chan bool
	Abort         chan bool
	Restart       chan bool
	ReturnValue   chan *Data
	Joined        bool
	ScheduleTimer *time.Timer
}

func RegisterConcurrencyPrimitives() {
	MakePrimitiveFunction("fork", "1", ForkImpl)
	MakePrimitiveFunction("proc-sleep", "2", ProcSleepImpl)
	MakePrimitiveFunction("wake", "1", WakeImpl)
	MakePrimitiveFunction("schedule", "2", ScheduleImpl)
	MakePrimitiveFunction("reset-timeout", "1", ResetTimeoutImpl)
	MakePrimitiveFunction("abandon", "1", AbandonImpl)
	MakePrimitiveFunction("join", "1", JoinImpl)
}

func ForkImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	f := Car(args)

	if !FunctionP(f) {
		err = ProcessError(fmt.Sprintf("fork expected a function, but received %v.", f), env)
		return
	}

	if FunctionValue(f).RequiredArgCount != 1 {
		err = ProcessError(fmt.Sprintf("fork expected a function with arity of 1, but it was %d.", FunctionValue(f).RequiredArgCount), env)
		return
	}

	proc := &Process{Env: env, Code: f, Wake: make(chan bool, 1), Abort: make(chan bool, 1), Restart: make(chan bool, 1), ReturnValue: make(chan *Data, 1)}
	procObj := ObjectWithTypeAndValue("Process", unsafe.Pointer(proc))

	go func() {
		var returnValue *Data = nil
		defer func() {
			proc.ReturnValue <- returnValue
		}()

		callWithPanicProtection(func() {
			var forkedErr error
			returnValue, forkedErr = FunctionValue(f).ApplyWithoutEval(InternalMakeList(procObj), env)
			if forkedErr != nil {
				fmt.Println(forkedErr)
			}
		}, "fork")
	}()

	return procObj, nil
}

func ProcSleepImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("proc-sleep expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))

	millis := Cadr(args)
	if !IntegerP(millis) {
		err = ProcessError(fmt.Sprintf("proc-sleep expected an integer as a delay, but received %v.", millis), env)
		return
	}

	woken := false
	select {
	case <-proc.Wake:
		woken = true
	case <-time.After(time.Duration(IntegerValue(millis)) * time.Millisecond):
	}

	return BooleanWithValue(woken), nil
}

func WakeImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("wake expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	proc.Wake <- true
	return StringWithValue("OK"), nil
}

func ScheduleImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	millis := Car(args)
	if !IntegerP(millis) {
		err = ProcessError(fmt.Sprintf("schedule expected an integer as a delay, but received %v.", millis), env)
		return
	}
	f := Cadr(args)

	if !FunctionP(f) {
		err = ProcessError(fmt.Sprintf("schedule expected a function, but received %v.", f), env)
		return
	}

	if FunctionValue(f).RequiredArgCount != 1 {
		err = ProcessError(fmt.Sprintf("schedule expected a function with arity of 1, but it was %d.", FunctionValue(f).RequiredArgCount), env)
		return
	}

	proc := &Process{
		Env:           env,
		Code:          f,
		Wake:          make(chan bool, 1),
		Abort:         make(chan bool, 1),
		Restart:       make(chan bool, 1),
		ScheduleTimer: time.NewTimer(time.Duration(IntegerValue(millis)) * time.Millisecond)}
	procObj := ObjectWithTypeAndValue("Process", unsafe.Pointer(proc))

	aborted := false
	go func() {
		callWithPanicProtection(func() {
		Loop:
			for {
				select {
				case <-proc.Abort:
					aborted = true
					break Loop
				case <-proc.Restart:
					proc.ScheduleTimer.Reset(time.Duration(IntegerValue(millis)) * time.Millisecond)
				case <-proc.ScheduleTimer.C:
					_, err = FunctionValue(f).ApplyWithoutEval(InternalMakeList(procObj), env)
					break Loop
				}
			}
		}, "schedule")
	}()

	return procObj, nil

}

func AbandonImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("adandon expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	proc.Abort <- true
	return StringWithValue("OK"), nil
}

func ResetTimeoutImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("restart expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}

	proc := (*Process)(ObjectValue(procObj))
	var str string
	select {
	case proc.Restart <- true:
		str = "OK"
	default:
		str = "task was already completed or abandoned"
	}
	return StringWithValue(str), nil
}

func JoinImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	procObj := Car(args)

	if !ObjectP(procObj) || ObjectType(procObj) != "Process" {
		err = ProcessError(fmt.Sprintf("join expects a Process object expected but received %s.", ObjectType(procObj)), env)
		return
	}
	proc := (*Process)(ObjectValue(procObj))

	if !proc.Joined {
		proc.Joined = true
		return <-proc.ReturnValue, nil
	} else {
		return nil, ProcessError("tried to run join on a task twice", env)
	}
}

func callWithPanicProtection(f func(), prefix string) {
	defer func() {
		if recovered := recover(); recovered != nil {
			stackBuf := make([]byte, 10000)
			stackBuf = stackBuf[:runtime.Stack(stackBuf, false)]
			stack := strings.Split(string(stackBuf), "\n")
			for i := 0; i < 7; i++ {
				fmt.Println(stack[i])
			}
		}
	}()

	f()
}
<|endoftext|>


<commit_before><commit_msg>renamed measurement<commit_after><|endoftext|>


<commit_before>// Copyright 2017 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 x509util

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"strconv"

	"github.com/google/certificate-transparency-go/x509"
	"github.com/google/certificate-transparency-go/x509/pkix"
)

func revocationReasonToString(reason x509.RevocationReasonCode) string {
	switch reason {
	case x509.Unspecified:
		return "Unspecified"
	case x509.KeyCompromise:
		return "Key Compromise"
	case x509.CACompromise:
		return "CA Compromise"
	case x509.AffiliationChanged:
		return "Affiliation Changed"
	case x509.Superseded:
		return "Superseded"
	case x509.CessationOfOperation:
		return "Cessation Of Operation"
	case x509.CertificateHold:
		return "Certificate Hold"
	case x509.RemoveFromCRL:
		return "Remove From CRL"
	case x509.PrivilegeWithdrawn:
		return "Privilege Withdrawn"
	case x509.AACompromise:
		return "AA Compromise"
	default:
		return strconv.Itoa(int(reason))
	}
}

// CRLToString generates a string describing the given certificate revocation list.
// The output roughly resembles that from openssl crl -text.
func CRLToString(crl *x509.CertificateList) string {
	var result bytes.Buffer
	var showCritical = func(critical bool) {
		if critical {
			result.WriteString(" critical")
		}
		result.WriteString("\n")
	}
	result.WriteString("Certificate Revocation List (CRL):\n")
	result.WriteString(fmt.Sprintf("        Version: %d (%#x)\n", crl.TBSCertList.Version+1, crl.TBSCertList.Version))
	result.WriteString(fmt.Sprintf("    Signature Algorithm: %v\n", x509.SignatureAlgorithmFromAI(crl.TBSCertList.Signature)))
	var issuer pkix.Name
	issuer.FillFromRDNSequence(&crl.TBSCertList.Issuer)
	result.WriteString(fmt.Sprintf("        Issuer: %v\n", NameToString(issuer)))
	result.WriteString(fmt.Sprintf("        Last Update: %v\n", crl.TBSCertList.ThisUpdate))
	result.WriteString(fmt.Sprintf("        Next Update: %v\n", crl.TBSCertList.NextUpdate))

	if len(crl.TBSCertList.Extensions) > 0 {
		result.WriteString("        CRL extensions:\n")
	}

	count, critical := OIDInExtensions(x509.OIDExtensionAuthorityKeyId, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Authority Key Identifier:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                keyid:%v\n", hex.EncodeToString(crl.TBSCertList.AuthorityKeyID)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionIssuerAltName, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Issuer Alt Name:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&crl.TBSCertList.IssuerAltNames)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionCRLNumber, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 CRLNumber:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %d\n", crl.TBSCertList.CRLNumber))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionDeltaCRLIndicator, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Delta CRL Indicator:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %d\n", crl.TBSCertList.BaseCRLNumber))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionIssuingDistributionPoint, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Issuing Distribution Point:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&crl.TBSCertList.IssuingDPFullNames)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionFreshestCRL, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Freshest CRL:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                Full Name:\n"))
		var buf bytes.Buffer
		for _, pt := range crl.TBSCertList.FreshestCRLDistributionPoint {
			commaAppend(&buf, "URI:"+pt)
		}
		result.WriteString(fmt.Sprintf("                    %v\n", buf.String()))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionAuthorityInfoAccess, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            Authority Information Access:"))
		showCritical(critical)
		var issuerBuf bytes.Buffer
		for _, issuer := range crl.TBSCertList.IssuingCertificateURL {
			commaAppend(&issuerBuf, "URI:"+issuer)
		}
		if issuerBuf.Len() > 0 {
			result.WriteString(fmt.Sprintf("                CA Issuers - %v\n", issuerBuf.String()))
		}
		var ocspBuf bytes.Buffer
		for _, ocsp := range crl.TBSCertList.OCSPServer {
			commaAppend(&ocspBuf, "URI:"+ocsp)
		}
		if ocspBuf.Len() > 0 {
			result.WriteString(fmt.Sprintf("                OCSP - %v\n", ocspBuf.String()))
		}
		// TODO(drysdale): Display other GeneralName types
	}

	result.WriteString("\n")
	result.WriteString("Revoked Certificates:\n")
	for _, c := range crl.TBSCertList.RevokedCertificates {
		result.WriteString(fmt.Sprintf("    Serial Number: %d (%#[1]x)\n", c.SerialNumber))
		result.WriteString(fmt.Sprintf("        Revocation Date : %v\n", c.RevocationTime))
		count, critical = OIDInExtensions(x509.OIDExtensionCRLReasons, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("            X509v3 CRL Reason Code:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", revocationReasonToString(c.RevocationReason)))
		}
		count, critical = OIDInExtensions(x509.OIDExtensionInvalidityDate, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("        Invalidity Date:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", c.InvalidityDate))
		}
		count, critical = OIDInExtensions(x509.OIDExtensionCertificateIssuer, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("        Issuer:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&c.Issuer)))
		}
	}
	result.WriteString(fmt.Sprintf("    Signature Algorithm: %v\n", x509.SignatureAlgorithmFromAI(crl.SignatureAlgorithm)))
	appendHexData(&result, crl.SignatureValue.Bytes, 18, "         ")
	result.WriteString("\n")

	return result.String()
}
<commit_msg>x509util: export RevocationReasonToString<commit_after>// Copyright 2017 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 x509util

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"strconv"

	"github.com/google/certificate-transparency-go/x509"
	"github.com/google/certificate-transparency-go/x509/pkix"
)

// RevocationReasonToString generates a string describing a revocation reason code.
func RevocationReasonToString(reason x509.RevocationReasonCode) string {
	switch reason {
	case x509.Unspecified:
		return "Unspecified"
	case x509.KeyCompromise:
		return "Key Compromise"
	case x509.CACompromise:
		return "CA Compromise"
	case x509.AffiliationChanged:
		return "Affiliation Changed"
	case x509.Superseded:
		return "Superseded"
	case x509.CessationOfOperation:
		return "Cessation Of Operation"
	case x509.CertificateHold:
		return "Certificate Hold"
	case x509.RemoveFromCRL:
		return "Remove From CRL"
	case x509.PrivilegeWithdrawn:
		return "Privilege Withdrawn"
	case x509.AACompromise:
		return "AA Compromise"
	default:
		return strconv.Itoa(int(reason))
	}
}

// CRLToString generates a string describing the given certificate revocation list.
// The output roughly resembles that from openssl crl -text.
func CRLToString(crl *x509.CertificateList) string {
	var result bytes.Buffer
	var showCritical = func(critical bool) {
		if critical {
			result.WriteString(" critical")
		}
		result.WriteString("\n")
	}
	result.WriteString("Certificate Revocation List (CRL):\n")
	result.WriteString(fmt.Sprintf("        Version: %d (%#x)\n", crl.TBSCertList.Version+1, crl.TBSCertList.Version))
	result.WriteString(fmt.Sprintf("    Signature Algorithm: %v\n", x509.SignatureAlgorithmFromAI(crl.TBSCertList.Signature)))
	var issuer pkix.Name
	issuer.FillFromRDNSequence(&crl.TBSCertList.Issuer)
	result.WriteString(fmt.Sprintf("        Issuer: %v\n", NameToString(issuer)))
	result.WriteString(fmt.Sprintf("        Last Update: %v\n", crl.TBSCertList.ThisUpdate))
	result.WriteString(fmt.Sprintf("        Next Update: %v\n", crl.TBSCertList.NextUpdate))

	if len(crl.TBSCertList.Extensions) > 0 {
		result.WriteString("        CRL extensions:\n")
	}

	count, critical := OIDInExtensions(x509.OIDExtensionAuthorityKeyId, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Authority Key Identifier:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                keyid:%v\n", hex.EncodeToString(crl.TBSCertList.AuthorityKeyID)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionIssuerAltName, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Issuer Alt Name:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&crl.TBSCertList.IssuerAltNames)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionCRLNumber, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 CRLNumber:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %d\n", crl.TBSCertList.CRLNumber))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionDeltaCRLIndicator, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Delta CRL Indicator:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %d\n", crl.TBSCertList.BaseCRLNumber))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionIssuingDistributionPoint, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Issuing Distribution Point:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&crl.TBSCertList.IssuingDPFullNames)))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionFreshestCRL, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            X509v3 Freshest CRL:"))
		showCritical(critical)
		result.WriteString(fmt.Sprintf("                Full Name:\n"))
		var buf bytes.Buffer
		for _, pt := range crl.TBSCertList.FreshestCRLDistributionPoint {
			commaAppend(&buf, "URI:"+pt)
		}
		result.WriteString(fmt.Sprintf("                    %v\n", buf.String()))
	}
	count, critical = OIDInExtensions(x509.OIDExtensionAuthorityInfoAccess, crl.TBSCertList.Extensions)
	if count > 0 {
		result.WriteString(fmt.Sprintf("            Authority Information Access:"))
		showCritical(critical)
		var issuerBuf bytes.Buffer
		for _, issuer := range crl.TBSCertList.IssuingCertificateURL {
			commaAppend(&issuerBuf, "URI:"+issuer)
		}
		if issuerBuf.Len() > 0 {
			result.WriteString(fmt.Sprintf("                CA Issuers - %v\n", issuerBuf.String()))
		}
		var ocspBuf bytes.Buffer
		for _, ocsp := range crl.TBSCertList.OCSPServer {
			commaAppend(&ocspBuf, "URI:"+ocsp)
		}
		if ocspBuf.Len() > 0 {
			result.WriteString(fmt.Sprintf("                OCSP - %v\n", ocspBuf.String()))
		}
		// TODO(drysdale): Display other GeneralName types
	}

	result.WriteString("\n")
	result.WriteString("Revoked Certificates:\n")
	for _, c := range crl.TBSCertList.RevokedCertificates {
		result.WriteString(fmt.Sprintf("    Serial Number: %d (%#[1]x)\n", c.SerialNumber))
		result.WriteString(fmt.Sprintf("        Revocation Date : %v\n", c.RevocationTime))
		count, critical = OIDInExtensions(x509.OIDExtensionCRLReasons, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("            X509v3 CRL Reason Code:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", RevocationReasonToString(c.RevocationReason)))
		}
		count, critical = OIDInExtensions(x509.OIDExtensionInvalidityDate, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("        Invalidity Date:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", c.InvalidityDate))
		}
		count, critical = OIDInExtensions(x509.OIDExtensionCertificateIssuer, c.Extensions)
		if count > 0 {
			result.WriteString(fmt.Sprintf("        Issuer:"))
			showCritical(critical)
			result.WriteString(fmt.Sprintf("                %s\n", GeneralNamesToString(&c.Issuer)))
		}
	}
	result.WriteString(fmt.Sprintf("    Signature Algorithm: %v\n", x509.SignatureAlgorithmFromAI(crl.SignatureAlgorithm)))
	appendHexData(&result, crl.SignatureValue.Bytes, 18, "         ")
	result.WriteString("\n")

	return result.String()
}
<|endoftext|>


<commit_before>package app

import (
	"github.com/jgraham909/revmgo"
	"github.com/revel/revel"
)

func init() {
	revel.OnAppStart(revmgo.AppInit)
	// Filters is the default set of global filters.
	revel.Filters = []revel.Filter{
		revel.PanicFilter,             // Recover from panics and display an error page instead.
		revel.RouterFilter,            // Use the routing table to select the right Action
		revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
		revel.ParamsFilter,            // Parse parameters into Controller.Params.
		revel.SessionFilter,           // Restore and write the session cookie.
		revel.FlashFilter,             // Restore and write the flash cookie.
		revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
		revel.I18nFilter,              // Resolve the requested language
		revel.InterceptorFilter,       // Run interceptors around the action.
		revel.ActionInvoker,           // Invoke the action.
	}
}
<commit_msg>Test of pulling key values from revmgo on init<commit_after>package app

import (
	"github.com/jgraham909/revmgo"
	"github.com/revel/revel"
)

func init() {
	revel.OnAppStart(revmgo.AppInit)
	// Filters is the default set of global filters.
	revel.Filters = []revel.Filter{
		revel.PanicFilter,             // Recover from panics and display an error page instead.
		revel.RouterFilter,            // Use the routing table to select the right Action
		revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
		revel.ParamsFilter,            // Parse parameters into Controller.Params.
		revel.SessionFilter,           // Restore and write the session cookie.
		revel.FlashFilter,             // Restore and write the flash cookie.
		revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
		revel.I18nFilter,              // Resolve the requested language
		revel.InterceptorFilter,       // Run interceptors around the action.
		revel.ActionInvoker,           // Invoke the action.
	}

	revel.OnAppStart(func() {

		var keyValues []map[string]string

		db := revmgo.Session.DB("test")
		col := db.C("config")
		query := col.Find(nil)

		err := query.All(&keyValues)

		if err != nil {
			revel.ERROR.Printf("%v", err)
		} else if keyValues != nil {
			for key, value := range keyValues {
				revel.INFO.Printf("%s: %s", key, value)
			}
		} else {
			revel.INFO.Printf("No keys found")
		}

	})
}
<|endoftext|>


<commit_before>package database

import (
	"context"
	"strings"

	"github.com/grafana/grafana/pkg/services/accesscontrol"
	"github.com/grafana/grafana/pkg/services/sqlstore"
)

const (
	globalOrgID = 0
)

func ProvideService(sqlStore *sqlstore.SQLStore) *AccessControlStore {
	return &AccessControlStore{sqlStore}
}

type AccessControlStore struct {
	sql *sqlstore.SQLStore
}

func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query accesscontrol.GetUserPermissionsQuery) ([]*accesscontrol.Permission, error) {
	result := make([]*accesscontrol.Permission, 0)
	err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
		filter, params := userRolesFilter(query.OrgID, query.UserID, query.Roles)

		// TODO: optimize this
		q := `SELECT
			permission.id,
			permission.role_id,
			permission.action,
			permission.scope,
			permission.updated,
			permission.created
			FROM permission
			INNER JOIN role ON role.id = permission.role_id
		` + filter

		if query.Actions != nil {
			q += " AND permission.action IN("
			if len(query.Actions) > 0 {
				q += "?" + strings.Repeat(",?", len(query.Actions)-1)
			}
			q += ")"
			for _, a := range query.Actions {
				params = append(params, a)
			}
		}

		if err := sess.SQL(q, params...).Find(&result); err != nil {
			return err
		}

		return nil
	})

	return result, err
}

func userRolesFilter(orgID, userID int64, roles []string) (string, []interface{}) {
	q := `
	WHERE role.id IN (
		SELECT ur.role_id
		FROM user_role AS ur
		WHERE ur.user_id = ?
		AND (ur.org_id = ? OR ur.org_id = ?)
		UNION
		SELECT tr.role_id FROM team_role as tr
		INNER JOIN team_member as tm ON tm.team_id = tr.team_id
		WHERE tm.user_id = ? AND tr.org_id = ?
	`
	params := []interface{}{userID, orgID, globalOrgID, userID, orgID}

	if len(roles) != 0 {
		q += `
			UNION
			SELECT br.role_id FROM builtin_role AS br
			WHERE role IN (? ` + strings.Repeat(", ?", len(roles)-1) + `)
		`
		for _, role := range roles {
			params = append(params, role)
		}

		q += `AND (br.org_id = ? OR br.org_id = ?)`
		params = append(params, orgID, globalOrgID)
	}

	q += `)`

	return q, params
}

func deletePermissions(sess *sqlstore.DBSession, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	rawSQL := "DELETE FROM permission WHERE id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
	args := make([]interface{}, 0, len(ids)+1)
	args = append(args, rawSQL)
	for _, id := range ids {
		args = append(args, id)
	}

	_, err := sess.Exec(args...)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>sort user permissions by scope (#48928)<commit_after>package database

import (
	"context"
	"strings"

	"github.com/grafana/grafana/pkg/services/accesscontrol"
	"github.com/grafana/grafana/pkg/services/sqlstore"
)

const (
	globalOrgID = 0
)

func ProvideService(sqlStore *sqlstore.SQLStore) *AccessControlStore {
	return &AccessControlStore{sqlStore}
}

type AccessControlStore struct {
	sql *sqlstore.SQLStore
}

func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query accesscontrol.GetUserPermissionsQuery) ([]*accesscontrol.Permission, error) {
	result := make([]*accesscontrol.Permission, 0)
	err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
		filter, params := userRolesFilter(query.OrgID, query.UserID, query.Roles)

		// TODO: optimize this
		q := `SELECT
			permission.id,
			permission.role_id,
			permission.action,
			permission.scope,
			permission.updated,
			permission.created
			FROM permission
			INNER JOIN role ON role.id = permission.role_id
		` + filter

		if query.Actions != nil {
			q += " AND permission.action IN("
			if len(query.Actions) > 0 {
				q += "?" + strings.Repeat(",?", len(query.Actions)-1)
			}
			q += ")"
			for _, a := range query.Actions {
				params = append(params, a)
			}
		}

		q += `
			ORDER BY permission.scope
		`

		if err := sess.SQL(q, params...).Find(&result); err != nil {
			return err
		}

		return nil
	})

	return result, err
}

func userRolesFilter(orgID, userID int64, roles []string) (string, []interface{}) {
	q := `
	WHERE role.id IN (
		SELECT ur.role_id
		FROM user_role AS ur
		WHERE ur.user_id = ?
		AND (ur.org_id = ? OR ur.org_id = ?)
		UNION
		SELECT tr.role_id FROM team_role as tr
		INNER JOIN team_member as tm ON tm.team_id = tr.team_id
		WHERE tm.user_id = ? AND tr.org_id = ?
	`
	params := []interface{}{userID, orgID, globalOrgID, userID, orgID}

	if len(roles) != 0 {
		q += `
			UNION
			SELECT br.role_id FROM builtin_role AS br
			WHERE role IN (? ` + strings.Repeat(", ?", len(roles)-1) + `)
		`
		for _, role := range roles {
			params = append(params, role)
		}

		q += `AND (br.org_id = ? OR br.org_id = ?)`
		params = append(params, orgID, globalOrgID)
	}

	q += `)`

	return q, params
}

func deletePermissions(sess *sqlstore.DBSession, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	rawSQL := "DELETE FROM permission WHERE id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
	args := make([]interface{}, 0, len(ids)+1)
	args = append(args, rawSQL)
	for _, id := range ids {
		args = append(args, id)
	}

	_, err := sess.Exec(args...)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before><commit_msg>fixed aws mapping of nat gateway<commit_after><|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package drain

import (
	"fmt"

	corev1 "k8s.io/api/core/v1"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
)

// This file contains default implementations of how to
// drain/cordon/uncordon nodes.  These functions may be called
// directly, or their functionality copied into your own code, for
// example if you want different output behaviour.

// RunNodeDrain shows the canonical way to drain a node.
// You should first cordon the node, e.g. using RunCordonOrUncordon
func RunNodeDrain(drainer *Helper, nodeName string) error {
	// TODO(justinsb): Ensure we have adequate e2e coverage of this function in library consumers
	list, errs := drainer.GetPodsForDeletion(nodeName)
	if errs != nil {
		return utilerrors.NewAggregate(errs)
	}
	if warnings := list.Warnings(); warnings != "" {
		fmt.Fprintf(drainer.ErrOut, "WARNING: %s\n", warnings)
	}

	if err := drainer.DeleteOrEvictPods(list.Pods()); err != nil {
		// Maybe warn about non-deleted pods here
		return err
	}
	return nil
}

// RunCordonOrUncordon demonstrates the canonical way to cordon or uncordon a Node
func RunCordonOrUncordon(drainer *Helper, node *corev1.Node, desired bool) error {
	// TODO(justinsb): Ensure we have adequate e2e coverage of this function in library consumers
	c := NewCordonHelper(node)

	if updateRequired := c.UpdateIfRequired(desired); !updateRequired {
		// Already done
		return nil
	}

	err, patchErr := c.PatchOrReplaceWithContext(drainer.Ctx, drainer.Client, false)
	if err != nil {
		if patchErr != nil {
			return fmt.Errorf("cordon error: %s; merge patch error: %s", err.Error(), patchErr.Error())
		}
		return fmt.Errorf("cordon error: %s", err.Error())
	}

	return nil
}
<commit_msg>wrap error from RunCordonOrUncordon<commit_after>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package drain

import (
	"fmt"

	corev1 "k8s.io/api/core/v1"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
)

// This file contains default implementations of how to
// drain/cordon/uncordon nodes.  These functions may be called
// directly, or their functionality copied into your own code, for
// example if you want different output behaviour.

// RunNodeDrain shows the canonical way to drain a node.
// You should first cordon the node, e.g. using RunCordonOrUncordon
func RunNodeDrain(drainer *Helper, nodeName string) error {
	// TODO(justinsb): Ensure we have adequate e2e coverage of this function in library consumers
	list, errs := drainer.GetPodsForDeletion(nodeName)
	if errs != nil {
		return utilerrors.NewAggregate(errs)
	}
	if warnings := list.Warnings(); warnings != "" {
		fmt.Fprintf(drainer.ErrOut, "WARNING: %s\n", warnings)
	}

	if err := drainer.DeleteOrEvictPods(list.Pods()); err != nil {
		// Maybe warn about non-deleted pods here
		return err
	}
	return nil
}

// RunCordonOrUncordon demonstrates the canonical way to cordon or uncordon a Node
func RunCordonOrUncordon(drainer *Helper, node *corev1.Node, desired bool) error {
	// TODO(justinsb): Ensure we have adequate e2e coverage of this function in library consumers
	c := NewCordonHelper(node)

	if updateRequired := c.UpdateIfRequired(desired); !updateRequired {
		// Already done
		return nil
	}

	err, patchErr := c.PatchOrReplaceWithContext(drainer.Ctx, drainer.Client, false)
	if err != nil {
		if patchErr != nil {
			return fmt.Errorf("cordon error: %s; merge patch error: %w", err.Error(), patchErr)
		}
		return fmt.Errorf("cordon error: %w", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package protocol

import (
	"crypto/ecdsa"
	"encoding/hex"

	"github.com/status-im/status-go/eth-node/crypto"
	"github.com/status-im/status-go/eth-node/types"
	"github.com/status-im/status-go/images"
	"github.com/status-im/status-go/protocol/identity/alias"
	"github.com/status-im/status-go/protocol/identity/identicon"
)

const (
	contactBlocked         = ":contact/blocked"
	contactAdded           = ":contact/added"
	contactRequestReceived = ":contact/request-received"
)

// ContactDeviceInfo is a struct containing information about a particular device owned by a contact
type ContactDeviceInfo struct {
	// The installation id of the device
	InstallationID string `json:"id"`
	// Timestamp represents the last time we received this info
	Timestamp int64 `json:"timestamp"`
	// FCMToken is to be used for push notifications
	FCMToken string `json:"fcmToken"`
}

// Contact has information about a "Contact". A contact is not necessarily one
// that we added or added us, that's based on SystemTags.
type Contact struct {
	// ID of the contact. It's a hex-encoded public key (prefixed with 0x).
	ID string `json:"id"`
	// Ethereum address of the contact
	Address string `json:"address,omitempty"`
	// ENS name of contact
	Name string `json:"name,omitempty"`
	// EnsVerified whether we verified the name of the contact
	ENSVerified bool `json:"ensVerified"`
	// EnsVerifiedAt the time we last verified the name
	ENSVerifiedAt uint64 `json:"ensVerifiedAt"`
	// LastENSClockValue is the last clock value of when we
	// received an ENS name for the user
	LastENSClockValue uint64 `json:"lastENSClockValue"`
	// ENSVerificationRetries is how many times we retried the ENS
	ENSVerificationRetries uint64 `json:"ensVerificationRetries"`
	// Generated username name of the contact
	Alias string `json:"alias,omitempty"`
	// Identicon generated from public key
	Identicon string `json:"identicon"`
	// LastUpdated is the last time we received an update from the contact
	// updates should be discarded if last updated is less than the one stored
	LastUpdated uint64 `json:"lastUpdated"`
	// SystemTags contains information about whether we blocked/added/have been
	// added.
	SystemTags []string `json:"systemTags"`

	DeviceInfo    []ContactDeviceInfo `json:"deviceInfo"`
	TributeToTalk string              `json:"tributeToTalk,omitempty"`
	LocalNickname string              `json:"localNickname,omitempty"`

	Images map[string]images.IdentityImage `json:"images"`
}

func (c Contact) PublicKey() (*ecdsa.PublicKey, error) {
	b, err := types.DecodeHex(c.ID)
	if err != nil {
		return nil, err
	}
	return crypto.UnmarshalPubkey(b)
}

func (c Contact) IsAdded() bool {
	return existsInStringSlice(c.SystemTags, contactAdded)
}

func (c Contact) HasBeenAdded() bool {
	return existsInStringSlice(c.SystemTags, contactRequestReceived)
}

func (c Contact) IsBlocked() bool {
	return existsInStringSlice(c.SystemTags, contactBlocked)
}

func (c *Contact) ResetENSVerification(clock uint64, name string) {
	c.ENSVerifiedAt = 0
	c.ENSVerified = false
	c.ENSVerificationRetries = 0
	c.LastENSClockValue = clock
	c.Name = name
}

// existsInStringSlice checks if a string is in a set.
func existsInStringSlice(set []string, find string) bool {
	for _, s := range set {
		if s == find {
			return true
		}
	}
	return false
}

func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
	id := "0x" + hex.EncodeToString(crypto.FromECDSAPub(publicKey))

	identicon, err := identicon.GenerateBase64(id)
	if err != nil {
		return nil, err
	}

	contact := &Contact{
		ID:        id,
		Alias:     alias.GenerateFromPublicKey(publicKey),
		Identicon: identicon,
	}

	return contact, nil
}

// HasCustomFields returns whether the the contact has any field that is valuable
// to the client other than the computed name/image
func (c Contact) HasCustomFields() bool {
	return c.IsAdded() || c.HasBeenAdded() || c.IsBlocked() || c.ENSVerified || c.LocalNickname != ""
}

func contactIDFromPublicKey(key *ecdsa.PublicKey) string {
	return types.EncodeHex(crypto.FromECDSAPub(key))

}
<commit_msg>Add images field to HasCustomFields<commit_after>package protocol

import (
	"crypto/ecdsa"
	"encoding/hex"

	"github.com/status-im/status-go/eth-node/crypto"
	"github.com/status-im/status-go/eth-node/types"
	"github.com/status-im/status-go/images"
	"github.com/status-im/status-go/protocol/identity/alias"
	"github.com/status-im/status-go/protocol/identity/identicon"
)

const (
	contactBlocked         = ":contact/blocked"
	contactAdded           = ":contact/added"
	contactRequestReceived = ":contact/request-received"
)

// ContactDeviceInfo is a struct containing information about a particular device owned by a contact
type ContactDeviceInfo struct {
	// The installation id of the device
	InstallationID string `json:"id"`
	// Timestamp represents the last time we received this info
	Timestamp int64 `json:"timestamp"`
	// FCMToken is to be used for push notifications
	FCMToken string `json:"fcmToken"`
}

// Contact has information about a "Contact". A contact is not necessarily one
// that we added or added us, that's based on SystemTags.
type Contact struct {
	// ID of the contact. It's a hex-encoded public key (prefixed with 0x).
	ID string `json:"id"`
	// Ethereum address of the contact
	Address string `json:"address,omitempty"`
	// ENS name of contact
	Name string `json:"name,omitempty"`
	// EnsVerified whether we verified the name of the contact
	ENSVerified bool `json:"ensVerified"`
	// EnsVerifiedAt the time we last verified the name
	ENSVerifiedAt uint64 `json:"ensVerifiedAt"`
	// LastENSClockValue is the last clock value of when we
	// received an ENS name for the user
	LastENSClockValue uint64 `json:"lastENSClockValue"`
	// ENSVerificationRetries is how many times we retried the ENS
	ENSVerificationRetries uint64 `json:"ensVerificationRetries"`
	// Generated username name of the contact
	Alias string `json:"alias,omitempty"`
	// Identicon generated from public key
	Identicon string `json:"identicon"`
	// LastUpdated is the last time we received an update from the contact
	// updates should be discarded if last updated is less than the one stored
	LastUpdated uint64 `json:"lastUpdated"`
	// SystemTags contains information about whether we blocked/added/have been
	// added.
	SystemTags []string `json:"systemTags"`

	DeviceInfo    []ContactDeviceInfo `json:"deviceInfo"`
	TributeToTalk string              `json:"tributeToTalk,omitempty"`
	LocalNickname string              `json:"localNickname,omitempty"`

	Images map[string]images.IdentityImage `json:"images"`
}

func (c Contact) PublicKey() (*ecdsa.PublicKey, error) {
	b, err := types.DecodeHex(c.ID)
	if err != nil {
		return nil, err
	}
	return crypto.UnmarshalPubkey(b)
}

func (c Contact) IsAdded() bool {
	return existsInStringSlice(c.SystemTags, contactAdded)
}

func (c Contact) HasBeenAdded() bool {
	return existsInStringSlice(c.SystemTags, contactRequestReceived)
}

func (c Contact) IsBlocked() bool {
	return existsInStringSlice(c.SystemTags, contactBlocked)
}

func (c *Contact) ResetENSVerification(clock uint64, name string) {
	c.ENSVerifiedAt = 0
	c.ENSVerified = false
	c.ENSVerificationRetries = 0
	c.LastENSClockValue = clock
	c.Name = name
}

// existsInStringSlice checks if a string is in a set.
func existsInStringSlice(set []string, find string) bool {
	for _, s := range set {
		if s == find {
			return true
		}
	}
	return false
}

func buildContact(publicKey *ecdsa.PublicKey) (*Contact, error) {
	id := "0x" + hex.EncodeToString(crypto.FromECDSAPub(publicKey))

	identicon, err := identicon.GenerateBase64(id)
	if err != nil {
		return nil, err
	}

	contact := &Contact{
		ID:        id,
		Alias:     alias.GenerateFromPublicKey(publicKey),
		Identicon: identicon,
	}

	return contact, nil
}

// HasCustomFields returns whether the the contact has any field that is valuable
// to the client other than the computed name/image
func (c Contact) HasCustomFields() bool {
	return c.IsAdded() || c.HasBeenAdded() || c.IsBlocked() || c.ENSVerified || c.LocalNickname != "" || len(c.Images) != 0
}

func contactIDFromPublicKey(key *ecdsa.PublicKey) string {
	return types.EncodeHex(crypto.FromECDSAPub(key))

}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package provider

import (
	"fmt"
	"net"
	"strconv"
	"time"

	"github.com/miekg/dns"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"

	"github.com/kubernetes-incubator/external-dns/endpoint"
	"github.com/kubernetes-incubator/external-dns/plan"
)

// rfc2136 provider type
type rfc2136Provider struct {
	nameserver    string
	zoneName      string
	tsigKeyName   string
	tsigSecret    string
	tsigSecretAlg string
	insecure      bool
	axfr          bool

	// only consider hosted zones managing domains ending in this suffix
	domainFilter DomainFilter
	dryRun       bool
	actions      rfc1236Actions
}

var (
	// Map of supported TSIG algorithms
	tsigAlgs = map[string]string{
		"hmac-md5":    dns.HmacMD5,
		"hmac-sha1":   dns.HmacSHA1,
		"hmac-sha256": dns.HmacSHA256,
		"hmac-sha512": dns.HmacSHA512,
	}
)

type rfc1236Actions interface {
	SendMessage(msg *dns.Msg) error
	IncomeTransfer(m *dns.Msg, a string) (env chan *dns.Envelope, err error)
}

// NewRfc2136Provider is a factory function for OpenStack rfc2136 providers
func NewRfc2136Provider(host string, port int, zoneName string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter DomainFilter, dryRun bool, actions rfc1236Actions) (Provider, error) {
	secretAlgChecked, ok := tsigAlgs[secretAlg]
	if !ok {
		return nil, errors.Errorf("%s is not supported TSIG algorithm", secretAlg)
	}

	r := &rfc2136Provider{
		nameserver:   net.JoinHostPort(host, strconv.Itoa(port)),
		zoneName:     dns.Fqdn(zoneName),
		insecure:     insecure,
		domainFilter: domainFilter,
		dryRun:       dryRun,
		axfr:         axfr,
	}
	if actions != nil {
		r.actions = actions
	} else {
		r.actions = r
	}

	if !insecure {
		r.tsigKeyName = dns.Fqdn(keyName)
		r.tsigSecret = secret
		r.tsigSecretAlg = secretAlgChecked
	}

	log.Infof("Configured RFC2136 with zone '%s' and nameserver '%s'", r.zoneName, r.nameserver)
	return r, nil
}

// Records returns the list of records.
func (r rfc2136Provider) Records() ([]*endpoint.Endpoint, error) {
	rrs, err := r.List()
	if err != nil {
		return nil, err
	}

	var eps []*endpoint.Endpoint

OuterLoop:
	for _, rr := range rrs {
		log.Debugf("Record=%s", rr)

		if rr.Header().Class != dns.ClassINET {
			continue
		}

		rrFqdn := rr.Header().Name
		rrTTL := endpoint.TTL(rr.Header().Ttl)
		var rrType string
		var rrValues []string
		switch rr.Header().Rrtype {
		case dns.TypeCNAME:
			rrValues = []string{rr.(*dns.CNAME).Target}
			rrType = "CNAME"
		case dns.TypeA:
			rrValues = []string{rr.(*dns.A).A.String()}
			rrType = "A"
		case dns.TypeAAAA:
			rrValues = []string{rr.(*dns.AAAA).AAAA.String()}
			rrType = "AAAA"
		case dns.TypeTXT:
			rrValues = (rr.(*dns.TXT).Txt)
			rrType = "TXT"
		default:
			continue // Unhandled record type
		}

		for idx, existingEndpoint := range eps {
			if existingEndpoint.DNSName == rrFqdn && existingEndpoint.RecordType == rrType {
				eps[idx].Targets = append(eps[idx].Targets, rrValues...)
				continue OuterLoop
			}
		}

		ep := endpoint.NewEndpointWithTTL(
			rrFqdn,
			rrType,
			rrTTL,
			rrValues...,
		)

		eps = append(eps, ep)
	}

	return eps, nil
}

func (r rfc2136Provider) IncomeTransfer(m *dns.Msg, a string) (env chan *dns.Envelope, err error) {
	t := new(dns.Transfer)
	if !r.insecure {
		t.TsigSecret = map[string]string{r.tsigKeyName: r.tsigSecret}
	}

	return t.In(m, r.nameserver)
}

func (r rfc2136Provider) List() ([]dns.RR, error) {
	if !r.axfr {
		log.Info("axfr is disabled")
		return make([]dns.RR, 0), nil
	}

	log.Debugf("Fetching records for '%s'", r.zoneName)

	m := new(dns.Msg)
	m.SetAxfr(r.zoneName)
	if !r.insecure {
		m.SetTsig(r.tsigKeyName, r.tsigSecretAlg, 300, time.Now().Unix())
	}

	env, err := r.actions.IncomeTransfer(m, r.nameserver)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch records via AXFR: %v", err)
	}

	records := make([]dns.RR, 0)
	for e := range env {
		if e.Error != nil {
			if e.Error == dns.ErrSoa {
				log.Error("AXFR error: unexpected response received from the server")
			} else {
				log.Errorf("AXFR error: %v", e.Error)
			}
			continue
		}
		records = append(records, e.RR...)
	}

	return records, nil
}

// ApplyChanges applies a given set of changes in a given zone.
func (r rfc2136Provider) ApplyChanges(changes *plan.Changes) error {
	log.Debugf("ApplyChanges")

	for _, ep := range changes.Create {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.AddRecord(ep)
	}
	for _, ep := range changes.UpdateNew {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.UpdateRecord(ep)
	}
	for _, ep := range changes.Delete {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.RemoveRecord(ep)
	}

	return nil
}

func (r rfc2136Provider) UpdateRecord(ep *endpoint.Endpoint) error {
	err := r.RemoveRecord(ep)
	if err != nil {
		return err
	}

	return r.AddRecord(ep)
}

func (r rfc2136Provider) AddRecord(ep *endpoint.Endpoint) error {
	log.Debugf("AddRecord.ep=%s", ep)

	newRR := fmt.Sprintf("%s %d %s %s", ep.DNSName, ep.RecordTTL, ep.RecordType, ep.Targets)
	log.Debugf("Adding RR: %s", newRR)

	rr, err := dns.NewRR(newRR)
	if err != nil {
		return fmt.Errorf("failed to build RR: %v", err)
	}

	rrs := make([]dns.RR, 1)
	rrs[0] = rr

	m := new(dns.Msg)
	m.SetUpdate(r.zoneName)
	m.Insert(rrs)

	err = r.actions.SendMessage(m)
	if err != nil {
		return fmt.Errorf("RFC2136 query failed: %v", err)
	}

	return nil
}

func (r rfc2136Provider) RemoveRecord(ep *endpoint.Endpoint) error {
	log.Debugf("RemoveRecord.ep=%s", ep)

	newRR := fmt.Sprintf("%s 0 %s 0.0.0.0", ep.DNSName, ep.RecordType)
	log.Debugf("Adding RR: %s", newRR)

	rr, err := dns.NewRR(newRR)
	if err != nil {
		return fmt.Errorf("failed to build RR: %v", err)
	}

	rrs := make([]dns.RR, 1)
	rrs[0] = rr

	m := new(dns.Msg)
	m.SetUpdate(r.zoneName)
	m.RemoveRRset(rrs)

	err = r.actions.SendMessage(m)
	if err != nil {
		return fmt.Errorf("RFC2136 query failed: %v", err)
	}

	return nil
}

func (r rfc2136Provider) SendMessage(msg *dns.Msg) error {
	if !r.dryRun {
		log.Debugf("SendMessage")
	} else {
		log.Debugf("SendMessage.skipped")
		return nil
	}

	c := new(dns.Client)
	c.SingleInflight = true

	if !r.insecure {
		c.TsigSecret = map[string]string{r.tsigKeyName: r.tsigSecret}
		msg.SetTsig(r.tsigKeyName, r.tsigSecretAlg, 300, time.Now().Unix())
	}

	resp, _, err := c.Exchange(msg, r.nameserver)
	if err != nil {
		log.Infof("error in dns.Client.Exchange: %s", err)
		return err
	}
	if resp != nil && resp.Rcode != dns.RcodeSuccess {
		log.Infof("Bad dns.Client.Exchange response: %s", resp)
		return fmt.Errorf("bad return code: %s", dns.RcodeToString[resp.Rcode])
	}

	log.Debugf("SendMessage.success")
	return nil
}
<commit_msg>Small style fix after code review<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package provider

import (
	"fmt"
	"net"
	"strconv"
	"time"

	"github.com/miekg/dns"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"

	"github.com/kubernetes-incubator/external-dns/endpoint"
	"github.com/kubernetes-incubator/external-dns/plan"
)

// rfc2136 provider type
type rfc2136Provider struct {
	nameserver    string
	zoneName      string
	tsigKeyName   string
	tsigSecret    string
	tsigSecretAlg string
	insecure      bool
	axfr          bool

	// only consider hosted zones managing domains ending in this suffix
	domainFilter DomainFilter
	dryRun       bool
	actions      rfc1236Actions
}

var (
	// Map of supported TSIG algorithms
	tsigAlgs = map[string]string{
		"hmac-md5":    dns.HmacMD5,
		"hmac-sha1":   dns.HmacSHA1,
		"hmac-sha256": dns.HmacSHA256,
		"hmac-sha512": dns.HmacSHA512,
	}
)

type rfc1236Actions interface {
	SendMessage(msg *dns.Msg) error
	IncomeTransfer(m *dns.Msg, a string) (env chan *dns.Envelope, err error)
}

// NewRfc2136Provider is a factory function for OpenStack rfc2136 providers
func NewRfc2136Provider(host string, port int, zoneName string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter DomainFilter, dryRun bool, actions rfc1236Actions) (Provider, error) {
	secretAlgChecked, ok := tsigAlgs[secretAlg]
	if !ok {
		return nil, errors.Errorf("%s is not supported TSIG algorithm", secretAlg)
	}

	r := &rfc2136Provider{
		nameserver:   net.JoinHostPort(host, strconv.Itoa(port)),
		zoneName:     dns.Fqdn(zoneName),
		insecure:     insecure,
		domainFilter: domainFilter,
		dryRun:       dryRun,
		axfr:         axfr,
	}
	if actions != nil {
		r.actions = actions
	} else {
		r.actions = r
	}

	if !insecure {
		r.tsigKeyName = dns.Fqdn(keyName)
		r.tsigSecret = secret
		r.tsigSecretAlg = secretAlgChecked
	}

	log.Infof("Configured RFC2136 with zone '%s' and nameserver '%s'", r.zoneName, r.nameserver)
	return r, nil
}

// Records returns the list of records.
func (r rfc2136Provider) Records() ([]*endpoint.Endpoint, error) {
	rrs, err := r.List()
	if err != nil {
		return nil, err
	}

	var eps []*endpoint.Endpoint

OuterLoop:
	for _, rr := range rrs {
		log.Debugf("Record=%s", rr)

		if rr.Header().Class != dns.ClassINET {
			continue
		}

		rrFqdn := rr.Header().Name
		rrTTL := endpoint.TTL(rr.Header().Ttl)
		var rrType string
		var rrValues []string
		switch rr.Header().Rrtype {
		case dns.TypeCNAME:
			rrValues = []string{rr.(*dns.CNAME).Target}
			rrType = "CNAME"
		case dns.TypeA:
			rrValues = []string{rr.(*dns.A).A.String()}
			rrType = "A"
		case dns.TypeAAAA:
			rrValues = []string{rr.(*dns.AAAA).AAAA.String()}
			rrType = "AAAA"
		case dns.TypeTXT:
			rrValues = (rr.(*dns.TXT).Txt)
			rrType = "TXT"
		default:
			continue // Unhandled record type
		}

		for idx, existingEndpoint := range eps {
			if existingEndpoint.DNSName == rrFqdn && existingEndpoint.RecordType == rrType {
				eps[idx].Targets = append(eps[idx].Targets, rrValues...)
				continue OuterLoop
			}
		}

		ep := endpoint.NewEndpointWithTTL(
			rrFqdn,
			rrType,
			rrTTL,
			rrValues...,
		)

		eps = append(eps, ep)
	}

	return eps, nil
}

func (r rfc2136Provider) IncomeTransfer(m *dns.Msg, a string) (env chan *dns.Envelope, err error) {
	t := new(dns.Transfer)
	if !r.insecure {
		t.TsigSecret = map[string]string{r.tsigKeyName: r.tsigSecret}
	}

	return t.In(m, r.nameserver)
}

func (r rfc2136Provider) List() ([]dns.RR, error) {
	if !r.axfr {
		log.Info("axfr is disabled")
		return make([]dns.RR, 0), nil
	}

	log.Debugf("Fetching records for '%s'", r.zoneName)

	m := new(dns.Msg)
	m.SetAxfr(r.zoneName)
	if !r.insecure {
		m.SetTsig(r.tsigKeyName, r.tsigSecretAlg, 300, time.Now().Unix())
	}

	env, err := r.actions.IncomeTransfer(m, r.nameserver)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch records via AXFR: %v", err)
	}

	records := make([]dns.RR, 0)
	for e := range env {
		if e.Error != nil {
			if e.Error == dns.ErrSoa {
				log.Error("AXFR error: unexpected response received from the server")
			} else {
				log.Errorf("AXFR error: %v", e.Error)
			}
			continue
		}
		records = append(records, e.RR...)
	}

	return records, nil
}

// ApplyChanges applies a given set of changes in a given zone.
func (r rfc2136Provider) ApplyChanges(changes *plan.Changes) error {
	log.Debugf("ApplyChanges")

	for _, ep := range changes.Create {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.AddRecord(ep)
	}
	for _, ep := range changes.UpdateNew {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.UpdateRecord(ep)
	}
	for _, ep := range changes.Delete {

		if !r.domainFilter.Match(ep.DNSName) {
			log.Debugf("Skipping record %s because it was filtered out by the specified --domain-filter", ep.DNSName)
			continue
		}

		r.RemoveRecord(ep)
	}

	return nil
}

func (r rfc2136Provider) UpdateRecord(ep *endpoint.Endpoint) error {
	err := r.RemoveRecord(ep)
	if err != nil {
		return err
	}

	return r.AddRecord(ep)
}

func (r rfc2136Provider) AddRecord(ep *endpoint.Endpoint) error {
	log.Debugf("AddRecord.ep=%s", ep)

	newRR := fmt.Sprintf("%s %d %s %s", ep.DNSName, ep.RecordTTL, ep.RecordType, ep.Targets)
	log.Debugf("Adding RR: %s", newRR)

	rr, err := dns.NewRR(newRR)
	if err != nil {
		return fmt.Errorf("failed to build RR: %v", err)
	}

	rrs := make([]dns.RR, 1)
	rrs[0] = rr

	m := new(dns.Msg)
	m.SetUpdate(r.zoneName)
	m.Insert(rrs)

	err = r.actions.SendMessage(m)
	if err != nil {
		return fmt.Errorf("RFC2136 query failed: %v", err)
	}

	return nil
}

func (r rfc2136Provider) RemoveRecord(ep *endpoint.Endpoint) error {
	log.Debugf("RemoveRecord.ep=%s", ep)

	newRR := fmt.Sprintf("%s 0 %s 0.0.0.0", ep.DNSName, ep.RecordType)
	log.Debugf("Adding RR: %s", newRR)

	rr, err := dns.NewRR(newRR)
	if err != nil {
		return fmt.Errorf("failed to build RR: %v", err)
	}

	rrs := make([]dns.RR, 1)
	rrs[0] = rr

	m := new(dns.Msg)
	m.SetUpdate(r.zoneName)
	m.RemoveRRset(rrs)

	err = r.actions.SendMessage(m)
	if err != nil {
		return fmt.Errorf("RFC2136 query failed: %v", err)
	}

	return nil
}

func (r rfc2136Provider) SendMessage(msg *dns.Msg) error {
	if r.dryRun {
		log.Debugf("SendMessage.skipped")
	}
	log.Debugf("SendMessage")

	c := new(dns.Client)
	c.SingleInflight = true

	if !r.insecure {
		c.TsigSecret = map[string]string{r.tsigKeyName: r.tsigSecret}
		msg.SetTsig(r.tsigKeyName, r.tsigSecretAlg, 300, time.Now().Unix())
	}

	resp, _, err := c.Exchange(msg, r.nameserver)
	if err != nil {
		log.Infof("error in dns.Client.Exchange: %s", err)
		return err
	}
	if resp != nil && resp.Rcode != dns.RcodeSuccess {
		log.Infof("Bad dns.Client.Exchange response: %s", resp)
		return fmt.Errorf("bad return code: %s", dns.RcodeToString[resp.Rcode])
	}

	log.Debugf("SendMessage.success")
	return nil
}
<|endoftext|>