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

// Package https provides a helper for starting an HTTPS server.
package https

import (
	"crypto/tls"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"path/filepath"

	"golang.org/x/crypto/acme/autocert"
	gContext "golang.org/x/net/context"
	"google.golang.org/api/option"

	"cloud.google.com/go/compute/metadata"
	"cloud.google.com/go/storage"

	"upspin.io/access"
	"upspin.io/errors"
	"upspin.io/flags"
	"upspin.io/log"
)

// Options permits the configuration of TLS certificates for servers running
// outside GCE. The default is the self-signed certificate in
// upspin.io/transport/auth/testdata.
type Options struct {
	// LetsEncryptCache specifies the cache file for Let's Encrypt.
	// If non-empty, enables Let's Encrypt certificates for this server.
	LetsEncryptCache string

	// CertFile and KeyFile specifies the TLS certificates to use.
	// It has no effect if LetsEncryptCache is non-empty.
	CertFile string
	KeyFile  string
}

var defaultOptions = &Options{
	CertFile: filepath.Join(os.Getenv("GOPATH"), "/src/upspin.io/transport/auth/testdata/cert.pem"),
	KeyFile:  filepath.Join(os.Getenv("GOPATH"), "/src/upspin.io/transport/auth/testdata/key.pem"),
}

func (opt *Options) applyDefaults() {
	if opt.CertFile == "" {
		opt.CertFile = defaultOptions.CertFile
	}
	if opt.KeyFile == "" {
		opt.KeyFile = defaultOptions.KeyFile
	}
}

// ListenAndServe serves the http.DefaultServeMux by HTTPS (and HTTP,
// redirecting to HTTPS), storing SSL credentials in the Google Cloud Storage
// buckets letsencrypt*.
//
// If the server is running outside GCE, instead an HTTPS server is started on
// the address specified by addr using the certificate details specified by opt.
//
// The given channel, if any, is closed when the TCP listener has succeeded.
// It may be used to signal that the server is ready to start serving requests.
func ListenAndServe(ready chan<- struct{}, serverName, addr string, opt *Options) {
	if opt == nil {
		opt = defaultOptions
	} else {
		opt.applyDefaults()
	}
	var config *tls.Config
	var m autocert.Manager
	m.Prompt = autocert.AcceptTOS
	// TODO(ehg) How do I capture the --domain flags from deploy?
	// m.HostPolicy = autocert.HostWhitelist("dir.upspin.io")

	if metadata.OnGCE() {
		addr = ":443"
		log.Info.Printf("https: serving HTTPS on GCE %q using Let's Encrypt certificates", addr)
		const key = "letsencrypt-bucket"
		bucket, err := metadata.InstanceAttributeValue(key)
		if err != nil {
			log.Fatalf("https: couldn't read %q metadata value: %v", key, err)
		}
		cache, err := newAutocertCache(bucket, serverName)
		if err != nil {
			log.Fatalf("https: couldn't set up letsencrypt cache: %v", err)
		}
		m.Cache = cache
		config = &tls.Config{GetCertificate: m.GetCertificate}
	} else if file := opt.LetsEncryptCache; file != "" {
		log.Info.Printf("https: serving HTTPS on %q using Let's Encrypt certificates", addr)
		m.Cache = autocert.DirCache(file)
		config = &tls.Config{GetCertificate: m.GetCertificate}
	} else {
		log.Info.Printf("https: not on GCE; serving HTTPS on %q using provided certificates", addr)
		if opt.CertFile == defaultOptions.CertFile || opt.KeyFile == defaultOptions.KeyFile {
			log.Error.Print("https: WARNING: using self-signed test certificates.")
		}
		var err error
		config, err = newDefaultTLSConfig(opt.CertFile, opt.KeyFile)
		if err != nil {
			log.Fatalf("https: setting up TLS config: %v", err)
		}
	}
	server := &http.Server{
		// ReadTimeout:  15 * time.Second,
		// WriteTimeout: 15 * time.Second,
		// IdleTimeout:  60 * time.Second,
		TLSConfig: config,
	}
	// TODO(adg): enable HTTP/2 once it's fast enough
	//err := http2.ConfigureServer(server, nil)
	//if err != nil {
	//	log.Fatalf("https: %v", err)
	//}

	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("https: %v", err)
	}
	if ready != nil {
		close(ready)
	}
	err = server.Serve(tls.NewListener(ln, config))
	log.Fatalf("https: %v", err)
}

// ListenAndServeFromFlags is the same as ListenAndServe, but it determines the
// listen address and Options from command-line flags in the flags package.
func ListenAndServeFromFlags(ready chan<- struct{}, serverName string) {
	ListenAndServe(ready, serverName, flags.HTTPSAddr, &Options{
		LetsEncryptCache: flags.LetsEncryptCache,
		CertFile:         flags.TLSCertFile,
		KeyFile:          flags.TLSKeyFile,
	})
}

// newDefaultTLSConfig creates a new TLS config based on the certificate files given.
func newDefaultTLSConfig(certFile string, certKeyFile string) (*tls.Config, error) {
	const op = "cloud/https.newDefaultTLSConfig"
	certReadable, err := isReadableFile(certFile)
	if err != nil {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("SSL certificate in %q: %q", certFile, err))
	}
	if !certReadable {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("certificate file %q not readable", certFile))
	}
	keyReadable, err := isReadableFile(certKeyFile)
	if err != nil {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("SSL key in %q: %v", certKeyFile, err))
	}
	if !keyReadable {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("certificate key file %q not readable", certKeyFile))
	}

	cert, err := tls.LoadX509KeyPair(certFile, certKeyFile)
	if err != nil {
		return nil, errors.E(op, err)
	}

	tlsConfig := &tls.Config{
		CipherSuites: []uint16{
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
		},
		MinVersion:               tls.VersionTLS12,
		PreferServerCipherSuites: true, // Use our choice, not the client's choice
		CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
		Certificates:             []tls.Certificate{cert},
	}
	tlsConfig.BuildNameToCertificate()
	return tlsConfig, nil
}

// isReadableFile reports whether the file exists and is readable.
// If the error is non-nil, it means there might be a file or directory
// with that name but we cannot read it.
func isReadableFile(path string) (bool, error) {
	// Is it stattable and is it a plain file?
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil // Item does not exist.
		}
		return false, err // Item is problematic.
	}
	if info.IsDir() {
		return false, errors.Str("is directory")
	}
	// Is it readable?
	fd, err := os.Open(path)
	if err != nil {
		return false, access.ErrPermissionDenied
	}
	fd.Close()
	return true, nil // Item exists and is readable.
}

// autocertCache implements autocert.Cache.
type autocertCache struct {
	b      *storage.BucketHandle
	server string
}

func newAutocertCache(bucket, prefix string) (cache autocertCache, err error) {
	ctx := gContext.Background()
	client, err := storage.NewClient(ctx, option.WithScopes(storage.ScopeFullControl))
	if err != nil {
		return
	}
	cache.b = client.Bucket(bucket)
	cache.server = prefix + "-"
	return
}

func (cache autocertCache) Get(ctx gContext.Context, name string) ([]byte, error) {
	r, err := cache.b.Object(cache.server + name).NewReader(ctx)
	if err == storage.ErrObjectNotExist {
		return nil, autocert.ErrCacheMiss
	}
	if err != nil {
		return nil, err
	}
	defer r.Close()
	return ioutil.ReadAll(r)
}

func (cache autocertCache) Put(ctx gContext.Context, name string, data []byte) error {
	// TODO(ehg) Do we need to add contentType="text/plain; charset=utf-8"?
	w := cache.b.Object(cache.server + name).NewWriter(ctx)
	_, err := w.Write(data)
	if err != nil {
		log.Printf("https: writing letsencrypt cache: %s %v", name, err)
	}
	if err := w.Close(); err != nil {
		log.Printf("https: writing letsencrypt cache: %s %v", name, err)
	}
	return err
}

func (cache autocertCache) Delete(ctx gContext.Context, name string) error {
	return cache.b.Object(cache.server + name).Delete(ctx)
}
<commit_msg>cloud/https: Add Go 1.8 cipher suites.<commit_after>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package https provides a helper for starting an HTTPS server.
package https

import (
	"crypto/tls"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"path/filepath"

	"golang.org/x/crypto/acme/autocert"
	gContext "golang.org/x/net/context"
	"google.golang.org/api/option"

	"cloud.google.com/go/compute/metadata"
	"cloud.google.com/go/storage"

	"upspin.io/access"
	"upspin.io/errors"
	"upspin.io/flags"
	"upspin.io/log"
)

// Options permits the configuration of TLS certificates for servers running
// outside GCE. The default is the self-signed certificate in
// upspin.io/transport/auth/testdata.
type Options struct {
	// LetsEncryptCache specifies the cache file for Let's Encrypt.
	// If non-empty, enables Let's Encrypt certificates for this server.
	LetsEncryptCache string

	// CertFile and KeyFile specifies the TLS certificates to use.
	// It has no effect if LetsEncryptCache is non-empty.
	CertFile string
	KeyFile  string
}

var defaultOptions = &Options{
	CertFile: filepath.Join(os.Getenv("GOPATH"), "/src/upspin.io/transport/auth/testdata/cert.pem"),
	KeyFile:  filepath.Join(os.Getenv("GOPATH"), "/src/upspin.io/transport/auth/testdata/key.pem"),
}

func (opt *Options) applyDefaults() {
	if opt.CertFile == "" {
		opt.CertFile = defaultOptions.CertFile
	}
	if opt.KeyFile == "" {
		opt.KeyFile = defaultOptions.KeyFile
	}
}

// ListenAndServe serves the http.DefaultServeMux by HTTPS (and HTTP,
// redirecting to HTTPS), storing SSL credentials in the Google Cloud Storage
// buckets letsencrypt*.
//
// If the server is running outside GCE, instead an HTTPS server is started on
// the address specified by addr using the certificate details specified by opt.
//
// The given channel, if any, is closed when the TCP listener has succeeded.
// It may be used to signal that the server is ready to start serving requests.
func ListenAndServe(ready chan<- struct{}, serverName, addr string, opt *Options) {
	if opt == nil {
		opt = defaultOptions
	} else {
		opt.applyDefaults()
	}
	var config *tls.Config
	var m autocert.Manager
	m.Prompt = autocert.AcceptTOS
	// TODO(ehg) How do I capture the --domain flags from deploy?
	// m.HostPolicy = autocert.HostWhitelist("dir.upspin.io")

	if metadata.OnGCE() {
		addr = ":443"
		log.Info.Printf("https: serving HTTPS on GCE %q using Let's Encrypt certificates", addr)
		const key = "letsencrypt-bucket"
		bucket, err := metadata.InstanceAttributeValue(key)
		if err != nil {
			log.Fatalf("https: couldn't read %q metadata value: %v", key, err)
		}
		cache, err := newAutocertCache(bucket, serverName)
		if err != nil {
			log.Fatalf("https: couldn't set up letsencrypt cache: %v", err)
		}
		m.Cache = cache
		config = &tls.Config{GetCertificate: m.GetCertificate}
	} else if file := opt.LetsEncryptCache; file != "" {
		log.Info.Printf("https: serving HTTPS on %q using Let's Encrypt certificates", addr)
		m.Cache = autocert.DirCache(file)
		config = &tls.Config{GetCertificate: m.GetCertificate}
	} else {
		log.Info.Printf("https: not on GCE; serving HTTPS on %q using provided certificates", addr)
		if opt.CertFile == defaultOptions.CertFile || opt.KeyFile == defaultOptions.KeyFile {
			log.Error.Print("https: WARNING: using self-signed test certificates.")
		}
		var err error
		config, err = newDefaultTLSConfig(opt.CertFile, opt.KeyFile)
		if err != nil {
			log.Fatalf("https: setting up TLS config: %v", err)
		}
	}
	server := &http.Server{
		// ReadTimeout:  15 * time.Second,
		// WriteTimeout: 15 * time.Second,
		// IdleTimeout:  60 * time.Second,
		TLSConfig: config,
	}
	// TODO(adg): enable HTTP/2 once it's fast enough
	//err := http2.ConfigureServer(server, nil)
	//if err != nil {
	//	log.Fatalf("https: %v", err)
	//}

	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("https: %v", err)
	}
	if ready != nil {
		close(ready)
	}
	err = server.Serve(tls.NewListener(ln, config))
	log.Fatalf("https: %v", err)
}

// ListenAndServeFromFlags is the same as ListenAndServe, but it determines the
// listen address and Options from command-line flags in the flags package.
func ListenAndServeFromFlags(ready chan<- struct{}, serverName string) {
	ListenAndServe(ready, serverName, flags.HTTPSAddr, &Options{
		LetsEncryptCache: flags.LetsEncryptCache,
		CertFile:         flags.TLSCertFile,
		KeyFile:          flags.TLSKeyFile,
	})
}

// newDefaultTLSConfig creates a new TLS config based on the certificate files given.
func newDefaultTLSConfig(certFile string, certKeyFile string) (*tls.Config, error) {
	const op = "cloud/https.newDefaultTLSConfig"
	certReadable, err := isReadableFile(certFile)
	if err != nil {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("SSL certificate in %q: %q", certFile, err))
	}
	if !certReadable {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("certificate file %q not readable", certFile))
	}
	keyReadable, err := isReadableFile(certKeyFile)
	if err != nil {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("SSL key in %q: %v", certKeyFile, err))
	}
	if !keyReadable {
		return nil, errors.E(op, errors.Invalid, errors.Errorf("certificate key file %q not readable", certKeyFile))
	}

	cert, err := tls.LoadX509KeyPair(certFile, certKeyFile)
	if err != nil {
		return nil, errors.E(op, err)
	}

	tlsConfig := &tls.Config{
		CipherSuites: []uint16{
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
		},
		MinVersion:               tls.VersionTLS12,
		PreferServerCipherSuites: true, // Use our choice, not the client's choice
		CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256, tls.X25519},
		Certificates:             []tls.Certificate{cert},
	}
	tlsConfig.BuildNameToCertificate()
	return tlsConfig, nil
}

// isReadableFile reports whether the file exists and is readable.
// If the error is non-nil, it means there might be a file or directory
// with that name but we cannot read it.
func isReadableFile(path string) (bool, error) {
	// Is it stattable and is it a plain file?
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil // Item does not exist.
		}
		return false, err // Item is problematic.
	}
	if info.IsDir() {
		return false, errors.Str("is directory")
	}
	// Is it readable?
	fd, err := os.Open(path)
	if err != nil {
		return false, access.ErrPermissionDenied
	}
	fd.Close()
	return true, nil // Item exists and is readable.
}

// autocertCache implements autocert.Cache.
type autocertCache struct {
	b      *storage.BucketHandle
	server string
}

func newAutocertCache(bucket, prefix string) (cache autocertCache, err error) {
	ctx := gContext.Background()
	client, err := storage.NewClient(ctx, option.WithScopes(storage.ScopeFullControl))
	if err != nil {
		return
	}
	cache.b = client.Bucket(bucket)
	cache.server = prefix + "-"
	return
}

func (cache autocertCache) Get(ctx gContext.Context, name string) ([]byte, error) {
	r, err := cache.b.Object(cache.server + name).NewReader(ctx)
	if err == storage.ErrObjectNotExist {
		return nil, autocert.ErrCacheMiss
	}
	if err != nil {
		return nil, err
	}
	defer r.Close()
	return ioutil.ReadAll(r)
}

func (cache autocertCache) Put(ctx gContext.Context, name string, data []byte) error {
	// TODO(ehg) Do we need to add contentType="text/plain; charset=utf-8"?
	w := cache.b.Object(cache.server + name).NewWriter(ctx)
	_, err := w.Write(data)
	if err != nil {
		log.Printf("https: writing letsencrypt cache: %s %v", name, err)
	}
	if err := w.Close(); err != nil {
		log.Printf("https: writing letsencrypt cache: %s %v", name, err)
	}
	return err
}

func (cache autocertCache) Delete(ctx gContext.Context, name string) error {
	return cache.b.Object(cache.server + name).Delete(ctx)
}
<|endoftext|>


<commit_before>package logging

import (
	smoke ".."
	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Loggregator:", func() {
	var testConfig = smoke.GetConfig()
	var useExistingApp = (testConfig.LoggingApp != "")
	var appName string

	Describe("cf logs", func() {
		BeforeEach(func() {
			appName = testConfig.LoggingApp
			if !useExistingApp {
				appName = generator.RandomName()
				Expect(cf.Cf("push", appName, "-p", SIMPLE_RUBY_APP_BITS_PATH).Wait(CF_PUSH_TIMEOUT_IN_SECONDS)).To(Exit(0))
			}
		})

		AfterEach(func() {
			if testConfig.Cleanup && !useExistingApp {
				Expect(cf.Cf("delete", appName, "-f", "-r").Wait(CF_TIMEOUT_IN_SECONDS)).To(Exit(0))
			}
		})

		It("can see app messages in the logs", func() {
			Eventually(func() *Session {
				appLogsSession := cf.Cf("logs", "--recent", appName)
				Expect(appLogsSession.Wait(CF_TIMEOUT_IN_SECONDS)).To(Exit(0))
				return appLogsSession
			}, CF_TIMEOUT_IN_SECONDS*5).Should(Say(`\[App/0\]`))
		})
	})
})
<commit_msg>Change test to match APP or App to support Diego or DEAs<commit_after>package logging

import (
	smoke ".."
	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Loggregator:", func() {
	var testConfig = smoke.GetConfig()
	var useExistingApp = (testConfig.LoggingApp != "")
	var appName string

	Describe("cf logs", func() {
		BeforeEach(func() {
			appName = testConfig.LoggingApp
			if !useExistingApp {
				appName = generator.RandomName()
				Expect(cf.Cf("push", appName, "-p", SIMPLE_RUBY_APP_BITS_PATH).Wait(CF_PUSH_TIMEOUT_IN_SECONDS)).To(Exit(0))
			}
		})

		AfterEach(func() {
			if testConfig.Cleanup && !useExistingApp {
				Expect(cf.Cf("delete", appName, "-f", "-r").Wait(CF_TIMEOUT_IN_SECONDS)).To(Exit(0))
			}
		})

		It("can see app messages in the logs", func() {
			Eventually(func() *Session {
				appLogsSession := cf.Cf("logs", "--recent", appName)
				Expect(appLogsSession.Wait(CF_TIMEOUT_IN_SECONDS)).To(Exit(0))
				return appLogsSession
			}, CF_TIMEOUT_IN_SECONDS*5).Should(Say(`\[(App|APP)/0\]`))
		})
	})
})
<|endoftext|>


<commit_before>package oauth2

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestNewTokenResponse(t *testing.T) {
	res := NewTokenResponse("foo", "bar", 1)
	assert.Equal(t, "foo", res.TokenType)
	assert.Equal(t, "bar", res.AccessToken)
	assert.Equal(t, 1, res.ExpiresIn)
	assert.Equal(t, map[string]string{
		"token_type":   "foo",
		"access_token": "bar",
		"expires_in":   "1",
	}, res.Map())
}

func TestTokenResponseMap(t *testing.T) {
	res := NewTokenResponse("foo", "bar", 1)
	res.RefreshToken = "baz"
	res.Scope = Scope([]string{"qux"})
	res.State = "quuz"

	assert.Equal(t, map[string]string{
		"token_type":    "foo",
		"access_token":  "bar",
		"expires_in":    "1",
		"refresh_token": "baz",
		"scope":         "qux",
		"state":         "quuz",
	}, res.Map())
}

func TestWriteTokenResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewTokenResponse("foo", "bar", 1)

	err := WriteTokenResponse(rec, res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.JSONEq(t, `{
		"token_type": "foo",
		"access_token": "bar",
		"expires_in": 1
	}`, rec.Body.String())
}

func TestRedirectTokenResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewTokenResponse("foo", "bar", 1)

	err := RedirectTokenResponse(rec, "http://example.com?baz=qux", res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusFound, rec.Code)
	assert.Equal(t, "http://example.com?baz=qux#access_token=bar&expires_in=1&token_type=foo", rec.HeaderMap.Get("Location"))
}

func TestNewAuthorizationCodeResponse(t *testing.T) {
	res := NewCodeResponse("foo")
	assert.Equal(t, "foo", res.Code)
	assert.Equal(t, map[string]string{
		"code": "foo",
	}, res.Map())
}

func TestAuthorizationCodeResponseMap(t *testing.T) {
	res := NewCodeResponse("foo")
	res.State = "bar"

	assert.Equal(t, map[string]string{
		"code":  "foo",
		"state": "bar",
	}, res.Map())
}

func TestRedirectAuthorizationCodeResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewCodeResponse("foo")

	err := RedirectCodeResponse(rec, "http://example.com?bar=baz", res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusFound, rec.Code)
	assert.Equal(t, "http://example.com?bar=baz&code=foo", rec.HeaderMap.Get("Location"))
}
<commit_msg>reflect changes<commit_after>package oauth2

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestNewTokenResponse(t *testing.T) {
	res := NewTokenResponse("foo", "bar", 1)
	assert.Equal(t, "foo", res.TokenType)
	assert.Equal(t, "bar", res.AccessToken)
	assert.Equal(t, 1, res.ExpiresIn)
	assert.Equal(t, map[string]string{
		"token_type":   "foo",
		"access_token": "bar",
		"expires_in":   "1",
	}, res.Map())
}

func TestTokenResponseMap(t *testing.T) {
	res := NewTokenResponse("foo", "bar", 1)
	res.RefreshToken = "baz"
	res.Scope = Scope([]string{"qux"})
	res.State = "quuz"

	assert.Equal(t, map[string]string{
		"token_type":    "foo",
		"access_token":  "bar",
		"expires_in":    "1",
		"refresh_token": "baz",
		"scope":         "qux",
		"state":         "quuz",
	}, res.Map())
}

func TestWriteTokenResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewTokenResponse("foo", "bar", 1)

	err := WriteTokenResponse(rec, res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.JSONEq(t, `{
		"token_type": "foo",
		"access_token": "bar",
		"expires_in": 1
	}`, rec.Body.String())
}

func TestRedirectTokenResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewTokenResponse("foo", "bar", 1)

	err := RedirectTokenResponse(rec, "http://example.com?baz=qux", res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusFound, rec.Code)
	assert.Equal(t, "http://example.com?baz=qux#access_token=bar&expires_in=1&token_type=foo", rec.HeaderMap.Get("Location"))
}

func TestNewCodeResponse(t *testing.T) {
	res := NewCodeResponse("foo")
	assert.Equal(t, "foo", res.Code)
	assert.Equal(t, map[string]string{
		"code": "foo",
	}, res.Map())
}

func TestCodeResponseMap(t *testing.T) {
	res := NewCodeResponse("foo")
	res.State = "bar"

	assert.Equal(t, map[string]string{
		"code":  "foo",
		"state": "bar",
	}, res.Map())
}

func TestRedirectCodeResponse(t *testing.T) {
	rec := httptest.NewRecorder()
	res := NewCodeResponse("foo")

	err := RedirectCodeResponse(rec, "http://example.com?bar=baz", res)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusFound, rec.Code)
	assert.Equal(t, "http://example.com?bar=baz&code=foo", rec.HeaderMap.Get("Location"))
}
<|endoftext|>


<commit_before>package build

import (
	"fmt"
	"io/ioutil"
	"neon/util"
	"path/filepath"
	"strings"
)

type Repository interface {
	GetResource(path string) ([]byte, error)
}

type LocalRepository struct {
	Root string
}

func NewLocalRepository() Repository {
	root := util.ExpandUserHome("~/.neon")
	repository := LocalRepository{
		Root: root,
	}
	return repository
}

func (repo LocalRepository) GetResource(path string) ([]byte, error) {
	group, version, artifact, err := SplitRepositoryPath(path)
	if err != nil {
		return nil, err
	}
	file := filepath.Join(repo.Root, group, version, artifact)
	resource, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, fmt.Errorf("loading resource '%s': %v", file, err)
	}
	return resource, nil
}

func SplitRepositoryPath(path string) (string, string, string, error) {
	if IsRepositoryPath(path) {
		parts := strings.Split(path[1:], "/")
		if len(parts) < 2 || len(parts) > 3 {
			return "", "", "", fmt.Errorf("Bad Neon path '%s'", path)
		}
		if len(parts) == 2 {
			parts = []string{parts[0], "latest", parts[1]}
		}
		return parts[0], parts[1], parts[2], nil
	} else {
		return "", "", "", fmt.Errorf("'%s' is not a repository path", path)
	}
}

func IsRepositoryPath(path string) bool {
	return strings.HasPrefix(path, ":")
}
<commit_msg>Changed neon path separator to :<commit_after>package build

import (
	"fmt"
	"io/ioutil"
	"neon/util"
	"path/filepath"
	"strings"
)

type Repository interface {
	GetResource(path string) ([]byte, error)
}

type LocalRepository struct {
	Root string
}

func NewLocalRepository() Repository {
	root := util.ExpandUserHome("~/.neon")
	repository := LocalRepository{
		Root: root,
	}
	return repository
}

func (repo LocalRepository) GetResource(path string) ([]byte, error) {
	group, version, artifact, err := SplitRepositoryPath(path)
	if err != nil {
		return nil, err
	}
	file := filepath.Join(repo.Root, group, version, artifact)
	resource, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, fmt.Errorf("loading resource '%s': %v", file, err)
	}
	return resource, nil
}

func SplitRepositoryPath(path string) (string, string, string, error) {
	if IsRepositoryPath(path) {
		parts := strings.Split(path[1:], ":")
		if len(parts) < 2 || len(parts) > 3 {
			return "", "", "", fmt.Errorf("Bad Neon path '%s'", path)
		}
		if len(parts) == 2 {
			parts = []string{parts[0], "latest", parts[1]}
		}
		return parts[0], parts[1], parts[2], nil
	} else {
		return "", "", "", fmt.Errorf("'%s' is not a repository path", path)
	}
}

func IsRepositoryPath(path string) bool {
	return strings.HasPrefix(path, ":")
}
<|endoftext|>


<commit_before>package rest

import (
	"net/http"

	"github.com/leanovate/microtools/routing"
)

type Resource interface {
	Self() Link
	Get(request *http.Request) (interface{}, error)
	Patch(request *http.Request) (interface{}, error)
	Update(request *http.Request) (interface{}, error)
	Delete(request *http.Request) (interface{}, error)

	SubResources(name string) (Resources, error)
}

type ResourceBase struct{}

func (ResourceBase) Get(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Patch(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Update(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Delete(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) SubResources(name string) (Resources, error) {
	return nil, NotFound
}

func ResourceMatcher(resource Resource) routing.Matcher {
	return routing.Sequence(
		routing.StringPart(func(name string) routing.Matcher {
			subResources, err := resource.SubResources(name)
			if err != nil {
				return HttpErrorMatcher(WrapError(err))
			}
			return ResourcesMatcher("", subResources)
		}),
		routing.EndSeq(
			routing.GET(restHandler(resource.Get)),
			routing.PUT(restHandler(resource.Update)),
			routing.PATCH(restHandler(resource.Patch)),
			routing.DELETE(restHandler(resource.Delete)),
			HttpErrorMatcher(MethodNotAllowed),
		),
	)
}
<commit_msg>More flexible subresources<commit_after>package rest

import (
	"net/http"

	"github.com/leanovate/microtools/routing"
)

type Resource interface {
	Self() Link
	Get(request *http.Request) (interface{}, error)
	Patch(request *http.Request) (interface{}, error)
	Update(request *http.Request) (interface{}, error)
	Delete(request *http.Request) (interface{}, error)

	SubResource(name string) (routing.Matcher, error)
}

type ResourceBase struct{}

func (ResourceBase) Get(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Patch(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Update(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) Delete(request *http.Request) (interface{}, error) {
	return nil, MethodNotAllowed
}

func (ResourceBase) SubResource(name string) (routing.Matcher, error) {
	return nil, NotFound
}

func ResourceMatcher(resource Resource) routing.Matcher {
	return routing.Sequence(
		routing.StringPart(func(name string) routing.Matcher {
			subResource, err := resource.SubResource(name)
			if err != nil {
				return HttpErrorMatcher(WrapError(err))
			}
			return subResource
		}),
		routing.EndSeq(
			routing.GET(restHandler(resource.Get)),
			routing.PUT(restHandler(resource.Update)),
			routing.PATCH(restHandler(resource.Patch)),
			routing.DELETE(restHandler(resource.Delete)),
			HttpErrorMatcher(MethodNotAllowed),
		),
	)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"

	"github.com/oracle/oci-go-sdk/v39/common"
	oci_mysql "github.com/oracle/oci-go-sdk/v39/mysql"

	"github.com/terraform-providers/terraform-provider-oci/httpreplay"
)

var (
	mysqlConfigurationSingularDataSourceRepresentation = map[string]interface{}{
		"configuration_id": Representation{repType: Required, create: `${var.MysqlConfigurationOCID[var.region]}`},
	}

	mysqlConfigurationDataSourceRepresentation = map[string]interface{}{
		"compartment_id":   Representation{repType: Required, create: `${var.compartment_id}`},
		"configuration_id": Representation{repType: Optional, create: `${var.MysqlConfigurationOCID[var.region]}`},
		"display_name":     Representation{repType: Optional, create: `VM.Standard.E2.2.Built-in`},
		"shape_name":       Representation{repType: Optional, create: `VM.Standard.E2.2`},
		"state":            Representation{repType: Optional, create: `ACTIVE`},
		"type":             Representation{repType: Optional, create: []string{`DEFAULT`}},
	}

	MysqlConfigurationResourceConfig = MysqlConfigurationIdVariable
)

func TestMysqlMysqlConfigurationResource_basic(t *testing.T) {
	httpreplay.SetScenario("TestMysqlMysqlConfigurationResource_basic")
	defer httpreplay.SaveScenario()

	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getEnvSettingWithBlankDefault("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	datasourceName := "data.oci_mysql_mysql_configurations.test_mysql_configurations"
	singularDatasourceName := "data.oci_mysql_mysql_configuration.test_mysql_configuration"

	saveConfigContent("", "", "", t)

	resource.Test(t, resource.TestCase{
		PreCheck: func() { testAccPreCheck(t) },
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify datasource
			{
				Config: config +
					generateDataSourceFromRepresentationMap("oci_mysql_mysql_configurations", "test_mysql_configurations", Required, Create, mysqlConfigurationDataSourceRepresentation) +
					compartmentIdVariableStr + MysqlConfigurationResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(datasourceName, "compartment_id", compartmentId),

					resource.TestCheckResourceAttrSet(datasourceName, "configurations.#"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.id"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.shape_name"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.state"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.time_created"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.type"),
				),
			},
			// verify singular datasource
			{
				Config: config +
					generateDataSourceFromRepresentationMap("oci_mysql_mysql_configuration", "test_mysql_configuration", Required, Create, mysqlConfigurationSingularDataSourceRepresentation) +
					compartmentIdVariableStr + MysqlConfigurationResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(singularDatasourceName, "configuration_id"),

					resource.TestCheckResourceAttr(singularDatasourceName, "defined_tags.%", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "description", "Default Standalone configuration for the VM.Standard.E2.2 MySQL Shape"),
					resource.TestCheckResourceAttr(singularDatasourceName, "display_name", "VM.Standard.E2.2.Standalone"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "state"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "time_created"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "type"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.#", "1"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.autocommit", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.completion_type", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.connect_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.cte_max_recursion_depth", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.default_authentication_plugin", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.foreign_key_checks", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.generated_random_password_length", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.group_replication_consistency", "EVENTUAL"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.information_schema_stats_expiry", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_buffer_pool_instances", "4"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_buffer_pool_size", "10200547328"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_enable_stopword", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_max_token_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_min_token_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_num_word_optimize", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_result_cache_limit", "33554432"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_server_stopword_table", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_lock_wait_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_max_purge_lag", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_max_purge_lag_delay", "300000"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.local_infile", "true"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mandatory_roles", "public"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_connections", "1000"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_execution_time", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_prepared_stmt_count", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysql_firewall_mode", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_connect_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_deflate_default_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_deflate_max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_document_id_unique_prefix", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_enable_hello_notice", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_idle_worker_thread_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_interactive_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_lz4default_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_lz4max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_max_allowed_packet", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_min_worker_threads", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_read_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_wait_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_write_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_zstd_max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.parser_max_mem_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.query_alloc_block_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.query_prealloc_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_mode", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_require_primary_key", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_warnings", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.transaction_isolation", ""),
				),
			},
		},
	})
}

func init() {
	if DependencyGraph == nil {
		initDependencyGraph()
	}
	if !inSweeperExcludeList("MysqlMysqlConfiguration") {
		resource.AddTestSweepers("MysqlMysqlConfiguration", &resource.Sweeper{
			Name:         "MysqlMysqlConfiguration",
			Dependencies: DependencyGraph["mysqlConfiguration"],
			F:            sweepMysqlMysqlConfigurationResource,
		})
	}
}

func sweepMysqlMysqlConfigurationResource(compartment string) error {
	mysqlaasClient := GetTestClients(&schema.ResourceData{}).mysqlaasClient()
	mysqlConfigurationIds, err := getMysqlConfigurationIds(compartment)
	if err != nil {
		return err
	}
	for _, mysqlConfigurationId := range mysqlConfigurationIds {
		if ok := SweeperDefaultResourceId[mysqlConfigurationId]; !ok {
			deleteConfigurationRequest := oci_mysql.DeleteConfigurationRequest{}
			deleteConfigurationRequest.ConfigurationId = &mysqlConfigurationId

			deleteConfigurationRequest.RequestMetadata.RetryPolicy = getRetryPolicy(true, "mysql")
			_, error := mysqlaasClient.DeleteConfiguration(context.Background(), deleteConfigurationRequest)
			if error != nil {
				fmt.Printf("Error deleting MysqlConfiguration %s %s, It is possible that the resource is already deleted. Please verify manually \n", mysqlConfigurationId, error)
				continue
			}
			waitTillCondition(testAccProvider, &mysqlConfigurationId, mysqlConfigurationSweepWaitCondition, time.Duration(3*time.Minute),
				mysqlConfigurationSweepResponseFetchOperation, "mysql", true)
		}
	}
	return nil
}

func getMysqlConfigurationIds(compartment string) ([]string, error) {
	ids := getResourceIdsToSweep(compartment, "MysqlConfigurationId")
	if ids != nil {
		return ids, nil
	}
	var resourceIds []string
	compartmentId := compartment
	mysqlaasClient := GetTestClients(&schema.ResourceData{}).mysqlaasClient()

	listConfigurationsRequest := oci_mysql.ListConfigurationsRequest{}
	listConfigurationsRequest.CompartmentId = &compartmentId
	listConfigurationsRequest.LifecycleState = oci_mysql.ConfigurationLifecycleStateActive
	listConfigurationsResponse, err := mysqlaasClient.ListConfigurations(context.Background(), listConfigurationsRequest)

	if err != nil {
		return resourceIds, fmt.Errorf("Error getting MysqlConfiguration list for compartment id : %s , %s \n", compartmentId, err)
	}
	for _, mysqlConfiguration := range listConfigurationsResponse.Items {
		id := *mysqlConfiguration.Id
		resourceIds = append(resourceIds, id)
		addResourceIdToSweeperResourceIdMap(compartmentId, "MysqlConfigurationId", id)
	}
	return resourceIds, nil
}

func mysqlConfigurationSweepWaitCondition(response common.OCIOperationResponse) bool {
	// Only stop if the resource is available beyond 3 mins. As there could be an issue for the sweeper to delete the resource and manual intervention required.
	if mysqlConfigurationResponse, ok := response.Response.(oci_mysql.GetConfigurationResponse); ok {
		return mysqlConfigurationResponse.LifecycleState != oci_mysql.ConfigurationLifecycleStateDeleted
	}
	return false
}

func mysqlConfigurationSweepResponseFetchOperation(client *OracleClients, resourceId *string, retryPolicy *common.RetryPolicy) error {
	_, err := client.mysqlaasClient().GetConfiguration(context.Background(), oci_mysql.GetConfigurationRequest{RequestMetadata: common.RequestMetadata{
		RetryPolicy: retryPolicy,
	},
	})
	return err
}
<commit_msg>fix TestMysqlMysqlConfigurationResource_basic test failure<commit_after>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"

	"github.com/oracle/oci-go-sdk/v39/common"
	oci_mysql "github.com/oracle/oci-go-sdk/v39/mysql"

	"github.com/terraform-providers/terraform-provider-oci/httpreplay"
)

var (
	mysqlConfigurationSingularDataSourceRepresentation = map[string]interface{}{
		"configuration_id": Representation{repType: Required, create: `${var.MysqlConfigurationOCID[var.region]}`},
	}

	mysqlConfigurationDataSourceRepresentation = map[string]interface{}{
		"compartment_id":   Representation{repType: Required, create: `${var.compartment_id}`},
		"configuration_id": Representation{repType: Optional, create: `${var.MysqlConfigurationOCID[var.region]}`},
		"display_name":     Representation{repType: Optional, create: `VM.Standard.E2.2.Built-in`},
		"shape_name":       Representation{repType: Optional, create: `VM.Standard.E2.2`},
		"state":            Representation{repType: Optional, create: `ACTIVE`},
		"type":             Representation{repType: Optional, create: []string{`DEFAULT`}},
	}

	MysqlConfigurationResourceConfig = MysqlConfigurationIdVariable
)

func TestMysqlMysqlConfigurationResource_basic(t *testing.T) {
	httpreplay.SetScenario("TestMysqlMysqlConfigurationResource_basic")
	defer httpreplay.SaveScenario()

	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getEnvSettingWithBlankDefault("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	datasourceName := "data.oci_mysql_mysql_configurations.test_mysql_configurations"
	singularDatasourceName := "data.oci_mysql_mysql_configuration.test_mysql_configuration"

	saveConfigContent("", "", "", t)

	resource.Test(t, resource.TestCase{
		PreCheck: func() { testAccPreCheck(t) },
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify datasource
			{
				Config: config +
					generateDataSourceFromRepresentationMap("oci_mysql_mysql_configurations", "test_mysql_configurations", Required, Create, mysqlConfigurationDataSourceRepresentation) +
					compartmentIdVariableStr + MysqlConfigurationResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(datasourceName, "compartment_id", compartmentId),

					resource.TestCheckResourceAttrSet(datasourceName, "configurations.#"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.id"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.shape_name"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.state"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.time_created"),
					resource.TestCheckResourceAttrSet(datasourceName, "configurations.0.type"),
				),
			},
			// verify singular datasource
			{
				Config: config +
					generateDataSourceFromRepresentationMap("oci_mysql_mysql_configuration", "test_mysql_configuration", Required, Create, mysqlConfigurationSingularDataSourceRepresentation) +
					compartmentIdVariableStr + MysqlConfigurationResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(singularDatasourceName, "configuration_id"),

					resource.TestCheckResourceAttr(singularDatasourceName, "defined_tags.%", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "description", "Default Standalone configuration for the VM.Standard.E2.2 MySQL Shape"),
					resource.TestCheckResourceAttr(singularDatasourceName, "display_name", "VM.Standard.E2.2.Standalone"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "state"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "time_created"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "type"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.#", "1"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.autocommit", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.completion_type", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.connect_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.cte_max_recursion_depth", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.default_authentication_plugin", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.foreign_key_checks", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.generated_random_password_length", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.group_replication_consistency", "BEFORE_ON_PRIMARY_FAILOVER"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.information_schema_stats_expiry", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_buffer_pool_instances", "4"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_buffer_pool_size", "10200547328"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_enable_stopword", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_max_token_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_min_token_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_num_word_optimize", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_result_cache_limit", "33554432"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_ft_server_stopword_table", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_lock_wait_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_max_purge_lag", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.innodb_max_purge_lag_delay", "300000"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.local_infile", "true"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mandatory_roles", "public"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_connections", "1000"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_execution_time", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.max_prepared_stmt_count", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysql_firewall_mode", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_connect_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_deflate_default_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_deflate_max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_document_id_unique_prefix", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_enable_hello_notice", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_idle_worker_thread_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_interactive_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_lz4default_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_lz4max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_max_allowed_packet", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_min_worker_threads", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_read_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_wait_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_write_timeout", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.mysqlx_zstd_max_client_compression_level", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.parser_max_mem_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.query_alloc_block_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.query_prealloc_size", "0"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_mode", ""),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_require_primary_key", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.sql_warnings", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "variables.0.transaction_isolation", ""),
				),
			},
		},
	})
}

func init() {
	if DependencyGraph == nil {
		initDependencyGraph()
	}
	if !inSweeperExcludeList("MysqlMysqlConfiguration") {
		resource.AddTestSweepers("MysqlMysqlConfiguration", &resource.Sweeper{
			Name:         "MysqlMysqlConfiguration",
			Dependencies: DependencyGraph["mysqlConfiguration"],
			F:            sweepMysqlMysqlConfigurationResource,
		})
	}
}

func sweepMysqlMysqlConfigurationResource(compartment string) error {
	mysqlaasClient := GetTestClients(&schema.ResourceData{}).mysqlaasClient()
	mysqlConfigurationIds, err := getMysqlConfigurationIds(compartment)
	if err != nil {
		return err
	}
	for _, mysqlConfigurationId := range mysqlConfigurationIds {
		if ok := SweeperDefaultResourceId[mysqlConfigurationId]; !ok {
			deleteConfigurationRequest := oci_mysql.DeleteConfigurationRequest{}
			deleteConfigurationRequest.ConfigurationId = &mysqlConfigurationId

			deleteConfigurationRequest.RequestMetadata.RetryPolicy = getRetryPolicy(true, "mysql")
			_, error := mysqlaasClient.DeleteConfiguration(context.Background(), deleteConfigurationRequest)
			if error != nil {
				fmt.Printf("Error deleting MysqlConfiguration %s %s, It is possible that the resource is already deleted. Please verify manually \n", mysqlConfigurationId, error)
				continue
			}
			waitTillCondition(testAccProvider, &mysqlConfigurationId, mysqlConfigurationSweepWaitCondition, time.Duration(3*time.Minute),
				mysqlConfigurationSweepResponseFetchOperation, "mysql", true)
		}
	}
	return nil
}

func getMysqlConfigurationIds(compartment string) ([]string, error) {
	ids := getResourceIdsToSweep(compartment, "MysqlConfigurationId")
	if ids != nil {
		return ids, nil
	}
	var resourceIds []string
	compartmentId := compartment
	mysqlaasClient := GetTestClients(&schema.ResourceData{}).mysqlaasClient()

	listConfigurationsRequest := oci_mysql.ListConfigurationsRequest{}
	listConfigurationsRequest.CompartmentId = &compartmentId
	listConfigurationsRequest.LifecycleState = oci_mysql.ConfigurationLifecycleStateActive
	listConfigurationsResponse, err := mysqlaasClient.ListConfigurations(context.Background(), listConfigurationsRequest)

	if err != nil {
		return resourceIds, fmt.Errorf("Error getting MysqlConfiguration list for compartment id : %s , %s \n", compartmentId, err)
	}
	for _, mysqlConfiguration := range listConfigurationsResponse.Items {
		id := *mysqlConfiguration.Id
		resourceIds = append(resourceIds, id)
		addResourceIdToSweeperResourceIdMap(compartmentId, "MysqlConfigurationId", id)
	}
	return resourceIds, nil
}

func mysqlConfigurationSweepWaitCondition(response common.OCIOperationResponse) bool {
	// Only stop if the resource is available beyond 3 mins. As there could be an issue for the sweeper to delete the resource and manual intervention required.
	if mysqlConfigurationResponse, ok := response.Response.(oci_mysql.GetConfigurationResponse); ok {
		return mysqlConfigurationResponse.LifecycleState != oci_mysql.ConfigurationLifecycleStateDeleted
	}
	return false
}

func mysqlConfigurationSweepResponseFetchOperation(client *OracleClients, resourceId *string, retryPolicy *common.RetryPolicy) error {
	_, err := client.mysqlaasClient().GetConfiguration(context.Background(), oci_mysql.GetConfigurationRequest{RequestMetadata: common.RequestMetadata{
		RetryPolicy: retryPolicy,
	},
	})
	return err
}
<|endoftext|>


<commit_before>package rtfdoc

import "fmt"

// AddParagraph return new instance of Paragraph
func (doc *Document) AddParagraph() *Paragraph {
	p := Paragraph{
		align:   AlignCenter,
		indent:  "\\fl360",
		content: nil,
		generalSettings: generalSettings{
			colorTable: doc.colorTable,
			fontColor:  doc.fontColor,
		},
		allowedWidth: doc.maxWidth,
	}
	p.updateMaxWidth()
	doc.content = append(doc.content, &p)
	return &p
}

func (par *Paragraph) updateMaxWidth() *Paragraph {
	par.maxWidth = par.allowedWidth
	return par
}

func (par Paragraph) compose() string {
	indentStr := fmt.Sprintf("\\fi%d \\li%d \\ri%d",
		par.indentFirstLine,
		par.indentLeftIndent,
		par.indentRightIndent)
	res := fmt.Sprintf("\n{\\par \\pard %s \\q%s", indentStr, par.align)
	if par.isTable {
		res += "\\intbl"
	}

	for _, c := range par.content {
		res += c.compose()
	}
	// res += "\n\\par}"
	return res
}

// SetIndentFirstLine function sets first line indent in twips
func (par *Paragraph) SetIndentFirstLine(value int) *Paragraph {
	par.indentFirstLine = value
	return par
}

// SetIndentRight function sets right indent in twips
func (par *Paragraph) SetIndentRight(value int) *Paragraph {
	par.indentRightIndent = value
	return par
}

// SetIndentLeft function sets left indent in twips
func (par *Paragraph) SetIndentLeft(value int) *Paragraph {
	par.indentLeftIndent = value
	return par
}

// SetAlign sets Paragraph align (c/center, l/left, r/right, j/justify)
func (par *Paragraph) SetAlign(align string) *Paragraph {
	for _, i := range []string{
		AlignCenter,
		AlignLeft,
		AlignRight,
		AlignJustify,
		AlignDistribute,
	} {
		if i == align {
			par.align = i
		}
	}

	return par
}
<commit_msg>par befor pard fix test #3<commit_after>package rtfdoc

import "fmt"

// AddParagraph return new instance of Paragraph
func (doc *Document) AddParagraph() *Paragraph {
	p := Paragraph{
		align:   AlignCenter,
		indent:  "\\fl360",
		content: nil,
		generalSettings: generalSettings{
			colorTable: doc.colorTable,
			fontColor:  doc.fontColor,
		},
		allowedWidth: doc.maxWidth,
	}
	p.updateMaxWidth()
	doc.content = append(doc.content, &p)
	return &p
}

func (par *Paragraph) updateMaxWidth() *Paragraph {
	par.maxWidth = par.allowedWidth
	return par
}

func (par Paragraph) compose() string {
	indentStr := fmt.Sprintf("\\fi%d \\li%d \\ri%d",
		par.indentFirstLine,
		par.indentLeftIndent,
		par.indentRightIndent)
	res := fmt.Sprintf("\n{\\pard %s \\q%s", indentStr, par.align)
	if par.isTable {
		res += "\\intbl"
	}

	for _, c := range par.content {
		res += c.compose()
	}
	// res += "\n\\par}"
	return res
}

// SetIndentFirstLine function sets first line indent in twips
func (par *Paragraph) SetIndentFirstLine(value int) *Paragraph {
	par.indentFirstLine = value
	return par
}

// SetIndentRight function sets right indent in twips
func (par *Paragraph) SetIndentRight(value int) *Paragraph {
	par.indentRightIndent = value
	return par
}

// SetIndentLeft function sets left indent in twips
func (par *Paragraph) SetIndentLeft(value int) *Paragraph {
	par.indentLeftIndent = value
	return par
}

// SetAlign sets Paragraph align (c/center, l/left, r/right, j/justify)
func (par *Paragraph) SetAlign(align string) *Paragraph {
	for _, i := range []string{
		AlignCenter,
		AlignLeft,
		AlignRight,
		AlignJustify,
		AlignDistribute,
	} {
		if i == align {
			par.align = i
		}
	}

	return par
}
<|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 docker

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

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

	K8sVersion "k8s.io/apimachinery/pkg/util/version"
	"k8s.io/kubeadm/kinder/pkg/constants"
	kindnodes "sigs.k8s.io/kind/pkg/cluster/nodes"
	kindCRI "sigs.k8s.io/kind/pkg/container/cri"
	kinddocker "sigs.k8s.io/kind/pkg/container/docker"
	kindexec "sigs.k8s.io/kind/pkg/exec"
)

// CreateControlPlaneNode creates a kind(er) contol-plane node that uses docker runtime internally
func CreateControlPlaneNode(name, image, clusterLabel, listenAddress string, port int32, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping) error {
	// gets a random host port for the API server
	if port == 0 {
		p, err := getPort()
		if err != nil {
			return errors.Wrap(err, "failed to get port for API server")
		}
		port = p
	}

	// add api server port mapping
	portMappingsWithAPIServer := append(portMappings, kindCRI.PortMapping{
		ListenAddress: listenAddress,
		HostPort:      port,
		ContainerPort: constants.APIServerPort,
	})
	return createNode(
		name, image, clusterLabel, constants.ControlPlaneNodeRoleValue, mounts, portMappingsWithAPIServer,
		// publish selected port for the API server
		"--expose", fmt.Sprintf("%d", port),
	)
}

// CreateWorkerNode creates a kind(er) worker node node that uses the docker runtime internally
func CreateWorkerNode(name, image, clusterLabel string, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping) error {
	return createNode(name, image, clusterLabel, constants.WorkerNodeRoleValue, mounts, portMappings)
}

// helper used to get a free TCP port for the API server
func getPort() (int32, error) {
	dummyListener, err := net.Listen("tcp", ":0")
	if err != nil {
		return 0, err
	}
	defer dummyListener.Close()
	port := dummyListener.Addr().(*net.TCPAddr).Port
	return int32(port), nil
}

// createNode `docker run`s the node image, note that due to
// images/node/entrypoint being the entrypoint, this container will
// effectively be paused until we call actuallyStartNode(...)
func createNode(name, image, clusterLabel, role string, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping, extraArgs ...string) error {
	runArgs := []string{
		"-d", // run the container detached
		"-t", // allocate a tty for entrypoint logs
		// running containers in a container requires privileged
		// NOTE: we could try to replicate this with --cap-add, and use less
		// privileges, but this flag also changes some mounts that are necessary
		// including some ones docker would otherwise do by default.
		// for now this is what we want. in the future we may revisit this.
		"--privileged",
		"--security-opt", "seccomp=unconfined", // also ignore seccomp
		"--tmpfs", "/tmp", // various things depend on working /tmp
		"--tmpfs", "/run", // systemd wants a writable /run
		// some k8s things want /lib/modules
		"-v", "/lib/modules:/lib/modules:ro",
		"--hostname", name, // make hostname match container name
		"--name", name, // ... and set the container name
		// label the node with the cluster ID
		"--label", clusterLabel,
		// label the node with the role ID
		"--label", fmt.Sprintf("%s=%s", constants.NodeRoleKey, role),
		// explicitly set the entrypoint
		"--entrypoint=/usr/local/bin/entrypoint",
	}

	// pass proxy environment variables to be used by node's docker deamon
	proxyDetails, err := getProxyDetails()
	if err != nil || proxyDetails == nil {
		return errors.Wrap(err, "proxy setup error")
	}
	for key, val := range proxyDetails.Envs {
		runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", key, val))
	}

	// adds node specific args
	runArgs = append(runArgs, extraArgs...)

	if kinddocker.UsernsRemap() {
		// We need this argument in order to make this command work
		// in systems that have userns-remap enabled on the docker daemon
		runArgs = append(runArgs, "--userns=host")
	}

	err = kinddocker.Run(
		image,
		kinddocker.WithRunArgs(runArgs...),
		kinddocker.WithContainerArgs(
			// explicitly pass the entrypoint argument
			"/sbin/init",
		),
		kinddocker.WithMounts(mounts),
		kinddocker.WithPortMappings(portMappings),
	)
	if err != nil {
		return err
	}

	handle := kindnodes.FromName(name)

	// Deletes the machine-id embedded in the node image and regenerate a new one.
	// This is necessary because both kubelet and other components like weave net
	// use machine-id internally to distinguish nodes.
	if err := handle.Command("rm", "-f", "/etc/machine-id").Run(); err != nil {
		return errors.Wrap(err, "machine-id-setup error")
	}

	if err := handle.Command("systemd-machine-id-setup").Run(); err != nil {
		return errors.Wrap(err, "machine-id-setup error")
	}

	// we need to change a few mounts once we have the container
	// we'd do this ahead of time if we could, but --privileged implies things
	// that don't seem to be configurable, and we need that flag
	if err := fixMounts(handle); err != nil {
		return err
	}

	// signal the node container entrypoint to continue booting into systemd
	if err := signalStart(handle); err != nil {
		return err
	}

	// wait for docker to be ready
	if !waitForDocker(handle, time.Now().Add(time.Second*30)) {
		return errors.Errorf("timed out waiting for docker to be ready on node %s", handle.Name())
	}

	// load the docker image artifacts into the docker daemon
	loadImages(handle)

	return nil
}

// proxyDetails contains proxy settings discovered on the host
type proxyDetails struct {
	Envs map[string]string
	// future proxy details here
}

const (
	// Docker default bridge network is named "bridge" (https://docs.docker.com/network/bridge/#use-the-default-bridge-network)
	defaultNetwork = "bridge"
	httpProxy      = "HTTP_PROXY"
	httpsProxy     = "HTTPS_PROXY"
	noProxy        = "NO_PROXY"
)

// getProxyDetails returns a struct with the host environment proxy settings
// that should be passed to the nodes
func getProxyDetails() (*proxyDetails, error) {
	var proxyEnvs = []string{httpProxy, httpsProxy, noProxy}
	var val string
	var details proxyDetails
	details.Envs = make(map[string]string)

	proxySupport := false

	for _, name := range proxyEnvs {
		val = os.Getenv(name)
		if val != "" {
			proxySupport = true
			details.Envs[name] = val
			details.Envs[strings.ToLower(name)] = val
		} else {
			val = os.Getenv(strings.ToLower(name))
			if val != "" {
				proxySupport = true
				details.Envs[name] = val
				details.Envs[strings.ToLower(name)] = val
			}
		}
	}

	// Specifically add the docker network subnets to NO_PROXY if we are using proxies
	if proxySupport {
		subnets, err := getSubnets(defaultNetwork)
		if err != nil {
			return nil, err
		}
		noProxyList := strings.Join(append(subnets, details.Envs[noProxy]), ",")
		details.Envs[noProxy] = noProxyList
		details.Envs[strings.ToLower(noProxy)] = noProxyList
	}

	return &details, nil
}

// getSubnets returns a slice of subnets for a specified network
func getSubnets(networkName string) ([]string, error) {
	format := `{{range (index (index . "IPAM") "Config")}}{{index . "Subnet"}} {{end}}`
	lines, err := kinddocker.NetworkInspect([]string{networkName}, format)
	if err != nil {
		return nil, err
	}
	return strings.Split(lines[0], " "), nil
}

// fixMounts will correct mounts in the node container to meet the right
// sharing and permissions for systemd and Docker / Kubernetes
func fixMounts(n *kindnodes.Node) error {
	// Check if userns-remap is enabled
	if kinddocker.UsernsRemap() {
		// The binary /bin/mount should be owned by root:root in order to execute
		// the following mount commands
		if err := n.Command("chown", "root:root", "/bin/mount").Run(); err != nil {
			return err
		}
		// The binary /bin/mount should have the setuid bit
		if err := n.Command("chmod", "-s", "/bin/mount").Run(); err != nil {
			return err
		}
	}

	// systemd-in-a-container should have read only /sys
	// https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
	// however, we need other things from `docker run --privileged` ...
	// and this flag also happens to make /sys rw, amongst other things
	if err := n.Command("mount", "-o", "remount,ro", "/sys").Run(); err != nil {
		return err
	}
	// kubernetes needs shared mount propagation
	if err := n.Command("mount", "--make-shared", "/").Run(); err != nil {
		return err
	}
	if err := n.Command("mount", "--make-shared", "/run").Run(); err != nil {
		return err
	}
	if err := n.Command("mount", "--make-shared", "/var/lib/docker").Run(); err != nil {
		return err
	}
	return nil
}

// signalStart sends SIGUSR1 to the node, which signals our entrypoint to boot
// see images/node/entrypoint
func signalStart(n *kindnodes.Node) error {
	return kinddocker.Kill("SIGUSR1", n.Name())
}

// waitForDocker waits for Docker to be ready on the node
// it returns true on success, and false on a timeout
func waitForDocker(n *kindnodes.Node, until time.Time) bool {
	return tryUntil(until, func() bool {
		cmd := n.Command("systemctl", "is-active", "docker")
		out, err := kindexec.CombinedOutputLines(cmd)
		if err != nil {
			return false
		}
		return len(out) == 1 && out[0] == "active"
	})
}

// helper that calls `try()`` in a loop until the deadline `until`
// has passed or `try()`returns true, returns wether try ever returned true
func tryUntil(until time.Time, try func() bool) bool {
	for until.After(time.Now()) {
		if try() {
			return true
		}
	}
	return false
}

// loadImages loads image tarballs stored on the node into docker on the node
func loadImages(n *kindnodes.Node) {
	// load images cached on the node into docker
	if err := n.Command(
		"/bin/bash", "-c",
		// use xargs to load images in parallel
		`find /kind/images -name *.tar -print0 | xargs -0 -n 1 -P $(nproc) docker load -i`,
	).Run(); err != nil {
		log.Warningf("Failed to preload docker images: %v", err)
		return
	}

	// if this fails, we don't care yet, but try to get the kubernetes version
	// and see if we can skip retagging for amd64
	// if this fails, we can just assume some unknown version and re-tag
	// in a future release of kind, we can probably drop v1.11 support
	// and remove the logic below this comment entirely
	if rawVersion, err := n.KubeVersion(); err == nil {
		if ver, err := K8sVersion.ParseGeneric(rawVersion); err == nil {
			if !ver.LessThan(K8sVersion.MustParseSemantic("v1.12.0")) {
				return
			}
		}
	}

	// for older releases, we need the images to have the arch in their name
	// bazel built images were missing these, newer releases do not use them
	// for any builds ...
	// retag images that are missing -amd64 as image:tag -> image-amd64:tag
	if err := n.Command(
		"/bin/bash", "-c",
		`docker images --format='{{.Repository}}:{{.Tag}}' | grep -v amd64 | xargs -L 1 -I '{}' /bin/bash -c 'docker tag "{}" "$(echo "{}" | sed s/:/-amd64:/)"'`,
	).Run(); err != nil {
		log.Warningf("Failed to re-tag docker images: %v", err)
	}
}
<commit_msg>fir typo "deamon" -> "daemon"<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 docker

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

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

	K8sVersion "k8s.io/apimachinery/pkg/util/version"
	"k8s.io/kubeadm/kinder/pkg/constants"
	kindnodes "sigs.k8s.io/kind/pkg/cluster/nodes"
	kindCRI "sigs.k8s.io/kind/pkg/container/cri"
	kinddocker "sigs.k8s.io/kind/pkg/container/docker"
	kindexec "sigs.k8s.io/kind/pkg/exec"
)

// CreateControlPlaneNode creates a kind(er) contol-plane node that uses docker runtime internally
func CreateControlPlaneNode(name, image, clusterLabel, listenAddress string, port int32, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping) error {
	// gets a random host port for the API server
	if port == 0 {
		p, err := getPort()
		if err != nil {
			return errors.Wrap(err, "failed to get port for API server")
		}
		port = p
	}

	// add api server port mapping
	portMappingsWithAPIServer := append(portMappings, kindCRI.PortMapping{
		ListenAddress: listenAddress,
		HostPort:      port,
		ContainerPort: constants.APIServerPort,
	})
	return createNode(
		name, image, clusterLabel, constants.ControlPlaneNodeRoleValue, mounts, portMappingsWithAPIServer,
		// publish selected port for the API server
		"--expose", fmt.Sprintf("%d", port),
	)
}

// CreateWorkerNode creates a kind(er) worker node node that uses the docker runtime internally
func CreateWorkerNode(name, image, clusterLabel string, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping) error {
	return createNode(name, image, clusterLabel, constants.WorkerNodeRoleValue, mounts, portMappings)
}

// helper used to get a free TCP port for the API server
func getPort() (int32, error) {
	dummyListener, err := net.Listen("tcp", ":0")
	if err != nil {
		return 0, err
	}
	defer dummyListener.Close()
	port := dummyListener.Addr().(*net.TCPAddr).Port
	return int32(port), nil
}

// createNode `docker run`s the node image, note that due to
// images/node/entrypoint being the entrypoint, this container will
// effectively be paused until we call actuallyStartNode(...)
func createNode(name, image, clusterLabel, role string, mounts []kindCRI.Mount, portMappings []kindCRI.PortMapping, extraArgs ...string) error {
	runArgs := []string{
		"-d", // run the container detached
		"-t", // allocate a tty for entrypoint logs
		// running containers in a container requires privileged
		// NOTE: we could try to replicate this with --cap-add, and use less
		// privileges, but this flag also changes some mounts that are necessary
		// including some ones docker would otherwise do by default.
		// for now this is what we want. in the future we may revisit this.
		"--privileged",
		"--security-opt", "seccomp=unconfined", // also ignore seccomp
		"--tmpfs", "/tmp", // various things depend on working /tmp
		"--tmpfs", "/run", // systemd wants a writable /run
		// some k8s things want /lib/modules
		"-v", "/lib/modules:/lib/modules:ro",
		"--hostname", name, // make hostname match container name
		"--name", name, // ... and set the container name
		// label the node with the cluster ID
		"--label", clusterLabel,
		// label the node with the role ID
		"--label", fmt.Sprintf("%s=%s", constants.NodeRoleKey, role),
		// explicitly set the entrypoint
		"--entrypoint=/usr/local/bin/entrypoint",
	}

	// pass proxy environment variables to be used by node's docker daemon
	proxyDetails, err := getProxyDetails()
	if err != nil || proxyDetails == nil {
		return errors.Wrap(err, "proxy setup error")
	}
	for key, val := range proxyDetails.Envs {
		runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", key, val))
	}

	// adds node specific args
	runArgs = append(runArgs, extraArgs...)

	if kinddocker.UsernsRemap() {
		// We need this argument in order to make this command work
		// in systems that have userns-remap enabled on the docker daemon
		runArgs = append(runArgs, "--userns=host")
	}

	err = kinddocker.Run(
		image,
		kinddocker.WithRunArgs(runArgs...),
		kinddocker.WithContainerArgs(
			// explicitly pass the entrypoint argument
			"/sbin/init",
		),
		kinddocker.WithMounts(mounts),
		kinddocker.WithPortMappings(portMappings),
	)
	if err != nil {
		return err
	}

	handle := kindnodes.FromName(name)

	// Deletes the machine-id embedded in the node image and regenerate a new one.
	// This is necessary because both kubelet and other components like weave net
	// use machine-id internally to distinguish nodes.
	if err := handle.Command("rm", "-f", "/etc/machine-id").Run(); err != nil {
		return errors.Wrap(err, "machine-id-setup error")
	}

	if err := handle.Command("systemd-machine-id-setup").Run(); err != nil {
		return errors.Wrap(err, "machine-id-setup error")
	}

	// we need to change a few mounts once we have the container
	// we'd do this ahead of time if we could, but --privileged implies things
	// that don't seem to be configurable, and we need that flag
	if err := fixMounts(handle); err != nil {
		return err
	}

	// signal the node container entrypoint to continue booting into systemd
	if err := signalStart(handle); err != nil {
		return err
	}

	// wait for docker to be ready
	if !waitForDocker(handle, time.Now().Add(time.Second*30)) {
		return errors.Errorf("timed out waiting for docker to be ready on node %s", handle.Name())
	}

	// load the docker image artifacts into the docker daemon
	loadImages(handle)

	return nil
}

// proxyDetails contains proxy settings discovered on the host
type proxyDetails struct {
	Envs map[string]string
	// future proxy details here
}

const (
	// Docker default bridge network is named "bridge" (https://docs.docker.com/network/bridge/#use-the-default-bridge-network)
	defaultNetwork = "bridge"
	httpProxy      = "HTTP_PROXY"
	httpsProxy     = "HTTPS_PROXY"
	noProxy        = "NO_PROXY"
)

// getProxyDetails returns a struct with the host environment proxy settings
// that should be passed to the nodes
func getProxyDetails() (*proxyDetails, error) {
	var proxyEnvs = []string{httpProxy, httpsProxy, noProxy}
	var val string
	var details proxyDetails
	details.Envs = make(map[string]string)

	proxySupport := false

	for _, name := range proxyEnvs {
		val = os.Getenv(name)
		if val != "" {
			proxySupport = true
			details.Envs[name] = val
			details.Envs[strings.ToLower(name)] = val
		} else {
			val = os.Getenv(strings.ToLower(name))
			if val != "" {
				proxySupport = true
				details.Envs[name] = val
				details.Envs[strings.ToLower(name)] = val
			}
		}
	}

	// Specifically add the docker network subnets to NO_PROXY if we are using proxies
	if proxySupport {
		subnets, err := getSubnets(defaultNetwork)
		if err != nil {
			return nil, err
		}
		noProxyList := strings.Join(append(subnets, details.Envs[noProxy]), ",")
		details.Envs[noProxy] = noProxyList
		details.Envs[strings.ToLower(noProxy)] = noProxyList
	}

	return &details, nil
}

// getSubnets returns a slice of subnets for a specified network
func getSubnets(networkName string) ([]string, error) {
	format := `{{range (index (index . "IPAM") "Config")}}{{index . "Subnet"}} {{end}}`
	lines, err := kinddocker.NetworkInspect([]string{networkName}, format)
	if err != nil {
		return nil, err
	}
	return strings.Split(lines[0], " "), nil
}

// fixMounts will correct mounts in the node container to meet the right
// sharing and permissions for systemd and Docker / Kubernetes
func fixMounts(n *kindnodes.Node) error {
	// Check if userns-remap is enabled
	if kinddocker.UsernsRemap() {
		// The binary /bin/mount should be owned by root:root in order to execute
		// the following mount commands
		if err := n.Command("chown", "root:root", "/bin/mount").Run(); err != nil {
			return err
		}
		// The binary /bin/mount should have the setuid bit
		if err := n.Command("chmod", "-s", "/bin/mount").Run(); err != nil {
			return err
		}
	}

	// systemd-in-a-container should have read only /sys
	// https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
	// however, we need other things from `docker run --privileged` ...
	// and this flag also happens to make /sys rw, amongst other things
	if err := n.Command("mount", "-o", "remount,ro", "/sys").Run(); err != nil {
		return err
	}
	// kubernetes needs shared mount propagation
	if err := n.Command("mount", "--make-shared", "/").Run(); err != nil {
		return err
	}
	if err := n.Command("mount", "--make-shared", "/run").Run(); err != nil {
		return err
	}
	if err := n.Command("mount", "--make-shared", "/var/lib/docker").Run(); err != nil {
		return err
	}
	return nil
}

// signalStart sends SIGUSR1 to the node, which signals our entrypoint to boot
// see images/node/entrypoint
func signalStart(n *kindnodes.Node) error {
	return kinddocker.Kill("SIGUSR1", n.Name())
}

// waitForDocker waits for Docker to be ready on the node
// it returns true on success, and false on a timeout
func waitForDocker(n *kindnodes.Node, until time.Time) bool {
	return tryUntil(until, func() bool {
		cmd := n.Command("systemctl", "is-active", "docker")
		out, err := kindexec.CombinedOutputLines(cmd)
		if err != nil {
			return false
		}
		return len(out) == 1 && out[0] == "active"
	})
}

// helper that calls `try()`` in a loop until the deadline `until`
// has passed or `try()`returns true, returns wether try ever returned true
func tryUntil(until time.Time, try func() bool) bool {
	for until.After(time.Now()) {
		if try() {
			return true
		}
	}
	return false
}

// loadImages loads image tarballs stored on the node into docker on the node
func loadImages(n *kindnodes.Node) {
	// load images cached on the node into docker
	if err := n.Command(
		"/bin/bash", "-c",
		// use xargs to load images in parallel
		`find /kind/images -name *.tar -print0 | xargs -0 -n 1 -P $(nproc) docker load -i`,
	).Run(); err != nil {
		log.Warningf("Failed to preload docker images: %v", err)
		return
	}

	// if this fails, we don't care yet, but try to get the kubernetes version
	// and see if we can skip retagging for amd64
	// if this fails, we can just assume some unknown version and re-tag
	// in a future release of kind, we can probably drop v1.11 support
	// and remove the logic below this comment entirely
	if rawVersion, err := n.KubeVersion(); err == nil {
		if ver, err := K8sVersion.ParseGeneric(rawVersion); err == nil {
			if !ver.LessThan(K8sVersion.MustParseSemantic("v1.12.0")) {
				return
			}
		}
	}

	// for older releases, we need the images to have the arch in their name
	// bazel built images were missing these, newer releases do not use them
	// for any builds ...
	// retag images that are missing -amd64 as image:tag -> image-amd64:tag
	if err := n.Command(
		"/bin/bash", "-c",
		`docker images --format='{{.Repository}}:{{.Tag}}' | grep -v amd64 | xargs -L 1 -I '{}' /bin/bash -c 'docker tag "{}" "$(echo "{}" | sed s/:/-amd64:/)"'`,
	).Run(); err != nil {
		log.Warningf("Failed to re-tag docker images: %v", err)
	}
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"github.com/prataprc/collatejson"
	"strconv"
	"unicode/utf8"
)

var options struct {
	floatText  string
	intText    string
	stringText string
}

func argParse() {
	//flag.BoolVar(&options.ast, "ast", false, "Show the ast of production")
	//flag.IntVar(&options.seed, "s", seed, "Seed value")
	//flag.IntVar(&options.count, "n", 1, "Generate n combinations")
	//flag.StringVar(&options.outfile, "o", "-", "Specify an output file")
	flag.StringVar(&options.floatText, "f", "", "encode floating point number")
	flag.StringVar(&options.intText, "i", "", "encode integer number")
	flag.StringVar(&options.stringText, "s", "", "encode string")
	flag.Parse()
}

func main() {
	argParse()
	if options.floatText != "" {
		encodeFloat(options.floatText)
	} else if options.intText != "" {
		encodeInt(options.intText)
	} else {
		s, i := options.stringText, 0
		for {
			r, c := utf8.DecodeRune([]byte(s[i:]))
			i += c
			fmt.Println(r, c)
			if len(s[i:]) == 0 {
				break
			}
		}
	}
}

func encodeFloat(text string) {
	if f, err := strconv.ParseFloat(text, 64); err != nil {
		panic(err)
	} else {
		ftext := []byte(strconv.FormatFloat(f, 'e', -1, 64))
		fmt.Printf("Encoding %v: %v\n", f, string(collatejson.EncodeFloat(ftext)))
	}
}

func encodeInt(text string) {
	fmt.Println(string(collatejson.EncodeInt([]byte(text))))
}
<commit_msg>experiment with unicode collation.<commit_after>//  Copyright (c) 2013 Couchbase, Inc.
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
//  except in compliance with the License. You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//  Unless required by applicable law or agreed to in writing, software distributed under the
//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
//  either express or implied. See the License for the specific language governing permissions
//  and limitations under the License.

package main

import (
	"code.google.com/p/go.text/collate"
	"code.google.com/p/go.text/language"
	"code.google.com/p/go.text/unicode/norm"
	"flag"
	"fmt"
	"github.com/prataprc/collatejson"
	"strconv"
	"unicode/utf8"
)

var options struct {
	floatText  string
	intText    string
	stringText string
}

func argParse() {
	//flag.BoolVar(&options.ast, "ast", false, "Show the ast of production")
	//flag.IntVar(&options.seed, "s", seed, "Seed value")
	//flag.IntVar(&options.count, "n", 1, "Generate n combinations")
	//flag.StringVar(&options.outfile, "o", "-", "Specify an output file")
	flag.StringVar(&options.floatText, "f", "", "encode floating point number")
	flag.StringVar(&options.intText, "i", "", "encode integer number")
	flag.StringVar(&options.stringText, "s", "", "encode string")
	flag.Parse()
}

func main() {
	argParse()
	if options.floatText != "" {
		encodeFloat(options.floatText)
	} else if options.intText != "" {
		encodeInt(options.intText)
	} else {
		fmt.Println("composed:", []byte(options.stringText))
		b := norm.NFKD.Bytes([]byte(options.stringText))
		fmt.Println("decomposed:", b)
		cl := collate.New(language.De)
		buf := &collate.Buffer{}
		rawkey := cl.Key(buf, b)
		fmt.Println("rawkey:", rawkey)

		s, i := string(b), 0
		for {
			r, c := utf8.DecodeRune([]byte(s[i:]))
			i += c
			fmt.Printf("%c %v %v\n", r, r, c)
			if len(s[i:]) == 0 {
				break
			}
		}
	}
}

func encodeFloat(text string) {
	if f, err := strconv.ParseFloat(text, 64); err != nil {
		panic(err)
	} else {
		ftext := []byte(strconv.FormatFloat(f, 'e', -1, 64))
		fmt.Printf("Encoding %v: %v\n", f, string(collatejson.EncodeFloat(ftext)))
	}
}

func encodeInt(text string) {
	fmt.Println(string(collatejson.EncodeInt([]byte(text))))
}
<|endoftext|>