<commit_before>package swarm

import (
	"context"
	"sync"

	addrutil "github.com/libp2p/go-addr-util"
	iconn "github.com/libp2p/go-libp2p-interface-conn"
	peer "github.com/libp2p/go-libp2p-peer"
	ma "github.com/multiformats/go-multiaddr"
)

type dialResult struct {
	Conn iconn.Conn
	Addr ma.Multiaddr
	Err  error
}

type dialJob struct {
	addr    ma.Multiaddr
	peer    peer.ID
	ctx     context.Context
	resp    chan dialResult
	success bool
}

func (dj *dialJob) cancelled() bool {
	select {
	case <-dj.ctx.Done():
		return true
	default:
		return false
	}
}

type dialLimiter struct {
	rllock      sync.Mutex
	fdConsuming int
	fdLimit     int
	waitingOnFd []*dialJob

	dialFunc func(context.Context, peer.ID, ma.Multiaddr) (iconn.Conn, error)

	activePerPeer      map[peer.ID]int
	perPeerLimit       int
	waitingOnPeerLimit map[peer.ID][]*dialJob
}

type dialfunc func(context.Context, peer.ID, ma.Multiaddr) (iconn.Conn, error)

func newDialLimiter(df dialfunc) *dialLimiter {
	return newDialLimiterWithParams(df, concurrentFdDials, defaultPerPeerRateLimit)
}

func newDialLimiterWithParams(df dialfunc, fdLimit, perPeerLimit int) *dialLimiter {
	return &dialLimiter{
		fdLimit:            fdLimit,
		perPeerLimit:       perPeerLimit,
		waitingOnPeerLimit: make(map[peer.ID][]*dialJob),
		activePerPeer:      make(map[peer.ID]int),
		dialFunc:           df,
	}
}

func (dl *dialLimiter) finishedDial(dj *dialJob) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()

	if addrutil.IsFDCostlyTransport(dj.addr) {
		dl.fdConsuming--

		if len(dl.waitingOnFd) > 0 {
			next := dl.waitingOnFd[0]
			dl.waitingOnFd[0] = nil // clear out memory
			dl.waitingOnFd = dl.waitingOnFd[1:]
			if len(dl.waitingOnFd) == 0 {
				dl.waitingOnFd = nil // clear out memory
			}
			dl.fdConsuming++

			go dl.executeDial(next)
		}
	}

	// release tokens in reverse order than we take them
	dl.activePerPeer[dj.peer]--
	if dl.activePerPeer[dj.peer] == 0 {
		delete(dl.activePerPeer, dj.peer)
	}

	waitlist := dl.waitingOnPeerLimit[dj.peer]
	if !dj.success && len(waitlist) > 0 {
		next := waitlist[0]

		if len(waitlist) == 1 {
			delete(dl.waitingOnPeerLimit, dj.peer)
		} else {
			waitlist[0] = nil // clear out memory
			dl.waitingOnPeerLimit[dj.peer] = waitlist[1:]
		}
		dl.activePerPeer[dj.peer]++ // just kidding, we still want this token

		if addrutil.IsFDCostlyTransport(next.addr) {
			if dl.fdConsuming >= dl.fdLimit {
				dl.waitingOnFd = append(dl.waitingOnFd, next)
				return
			}

			// take token
			dl.fdConsuming++
		}

		// can kick this off right here, dials in this list already
		// have the other tokens needed
		go dl.executeDial(next)
	}
}

// AddDialJob tries to take the needed tokens for starting the given dial job.
// If it acquires all needed tokens, it immediately starts the dial, otherwise
// it will put it on the waitlist for the requested token.
func (dl *dialLimiter) AddDialJob(dj *dialJob) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()

	if dl.activePerPeer[dj.peer] >= dl.perPeerLimit {
		wlist := dl.waitingOnPeerLimit[dj.peer]
		dl.waitingOnPeerLimit[dj.peer] = append(wlist, dj)
		return
	}
	dl.activePerPeer[dj.peer]++

	if addrutil.IsFDCostlyTransport(dj.addr) {
		if dl.fdConsuming >= dl.fdLimit {
			dl.waitingOnFd = append(dl.waitingOnFd, dj)
			return
		}

		// take token
		dl.fdConsuming++
	}

	// take second needed token and start dial!
	go dl.executeDial(dj)
}

func (dl *dialLimiter) clearAllPeerDials(p peer.ID) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()
	delete(dl.waitingOnPeerLimit, p)
	// NB: the waitingOnFd list doesnt need to be cleaned out here, we will
	// remove them as we encounter them because they are 'cancelled' at this
	// point
}

// executeDial calls the dialFunc, and reports the result through the response
// channel when finished. Once the response is sent it also releases all tokens
// it held during the dial.
func (dl *dialLimiter) executeDial(j *dialJob) {
	defer dl.finishedDial(j)
	if j.cancelled() {
		return
	}

	con, err := dl.dialFunc(j.ctx, j.peer, j.addr)
	select {
	case j.resp <- dialResult{Conn: con, Addr: j.addr, Err: err}:
	case <-j.ctx.Done():
	}
}
<commit_msg>don't leak connections when canceling dials<commit_after>package swarm

import (
	"context"
	"sync"

	addrutil "github.com/libp2p/go-addr-util"
	iconn "github.com/libp2p/go-libp2p-interface-conn"
	peer "github.com/libp2p/go-libp2p-peer"
	ma "github.com/multiformats/go-multiaddr"
)

type dialResult struct {
	Conn iconn.Conn
	Addr ma.Multiaddr
	Err  error
}

type dialJob struct {
	addr    ma.Multiaddr
	peer    peer.ID
	ctx     context.Context
	resp    chan dialResult
	success bool
}

func (dj *dialJob) cancelled() bool {
	select {
	case <-dj.ctx.Done():
		return true
	default:
		return false
	}
}

type dialLimiter struct {
	rllock      sync.Mutex
	fdConsuming int
	fdLimit     int
	waitingOnFd []*dialJob

	dialFunc func(context.Context, peer.ID, ma.Multiaddr) (iconn.Conn, error)

	activePerPeer      map[peer.ID]int
	perPeerLimit       int
	waitingOnPeerLimit map[peer.ID][]*dialJob
}

type dialfunc func(context.Context, peer.ID, ma.Multiaddr) (iconn.Conn, error)

func newDialLimiter(df dialfunc) *dialLimiter {
	return newDialLimiterWithParams(df, concurrentFdDials, defaultPerPeerRateLimit)
}

func newDialLimiterWithParams(df dialfunc, fdLimit, perPeerLimit int) *dialLimiter {
	return &dialLimiter{
		fdLimit:            fdLimit,
		perPeerLimit:       perPeerLimit,
		waitingOnPeerLimit: make(map[peer.ID][]*dialJob),
		activePerPeer:      make(map[peer.ID]int),
		dialFunc:           df,
	}
}

func (dl *dialLimiter) finishedDial(dj *dialJob) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()

	if addrutil.IsFDCostlyTransport(dj.addr) {
		dl.fdConsuming--

		if len(dl.waitingOnFd) > 0 {
			next := dl.waitingOnFd[0]
			dl.waitingOnFd[0] = nil // clear out memory
			dl.waitingOnFd = dl.waitingOnFd[1:]
			if len(dl.waitingOnFd) == 0 {
				dl.waitingOnFd = nil // clear out memory
			}
			dl.fdConsuming++

			go dl.executeDial(next)
		}
	}

	// release tokens in reverse order than we take them
	dl.activePerPeer[dj.peer]--
	if dl.activePerPeer[dj.peer] == 0 {
		delete(dl.activePerPeer, dj.peer)
	}

	waitlist := dl.waitingOnPeerLimit[dj.peer]
	if !dj.success && len(waitlist) > 0 {
		next := waitlist[0]

		if len(waitlist) == 1 {
			delete(dl.waitingOnPeerLimit, dj.peer)
		} else {
			waitlist[0] = nil // clear out memory
			dl.waitingOnPeerLimit[dj.peer] = waitlist[1:]
		}
		dl.activePerPeer[dj.peer]++ // just kidding, we still want this token

		if addrutil.IsFDCostlyTransport(next.addr) {
			if dl.fdConsuming >= dl.fdLimit {
				dl.waitingOnFd = append(dl.waitingOnFd, next)
				return
			}

			// take token
			dl.fdConsuming++
		}

		// can kick this off right here, dials in this list already
		// have the other tokens needed
		go dl.executeDial(next)
	}
}

// AddDialJob tries to take the needed tokens for starting the given dial job.
// If it acquires all needed tokens, it immediately starts the dial, otherwise
// it will put it on the waitlist for the requested token.
func (dl *dialLimiter) AddDialJob(dj *dialJob) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()

	if dl.activePerPeer[dj.peer] >= dl.perPeerLimit {
		wlist := dl.waitingOnPeerLimit[dj.peer]
		dl.waitingOnPeerLimit[dj.peer] = append(wlist, dj)
		return
	}
	dl.activePerPeer[dj.peer]++

	if addrutil.IsFDCostlyTransport(dj.addr) {
		if dl.fdConsuming >= dl.fdLimit {
			dl.waitingOnFd = append(dl.waitingOnFd, dj)
			return
		}

		// take token
		dl.fdConsuming++
	}

	// take second needed token and start dial!
	go dl.executeDial(dj)
}

func (dl *dialLimiter) clearAllPeerDials(p peer.ID) {
	dl.rllock.Lock()
	defer dl.rllock.Unlock()
	delete(dl.waitingOnPeerLimit, p)
	// NB: the waitingOnFd list doesnt need to be cleaned out here, we will
	// remove them as we encounter them because they are 'cancelled' at this
	// point
}

// executeDial calls the dialFunc, and reports the result through the response
// channel when finished. Once the response is sent it also releases all tokens
// it held during the dial.
func (dl *dialLimiter) executeDial(j *dialJob) {
	defer dl.finishedDial(j)
	if j.cancelled() {
		return
	}

	con, err := dl.dialFunc(j.ctx, j.peer, j.addr)
	select {
	case j.resp <- dialResult{Conn: con, Addr: j.addr, Err: err}:
	case <-j.ctx.Done():
		if err == nil {
			con.Close()
		}
	}
}
<|endoftext|>


<commit_before>package oauth

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

	"github.com/ViBiOh/dashboard/fetch"
)

const accessTokenURL = `https://github.com/login/oauth/access_token?`

var (
	stateSalt    string
	clientID     string
	clientSecret string
	redirectURL  string
)

// Init retrieve env variables
func Init() {
	stateSalt = os.Getenv(`OAUTH_STATE_SALT`)
	redirectURL = os.Getenv(`OAUTH_REDIRECT_URL`)
	clientID = os.Getenv(`GITHUB_OAUTH_CLIENT_ID`)
	stateSalt = os.Getenv(`GITHUB_OAUTH_CLIENT_SECRET`)
}

func getAccessToken(code string) ([]byte, error) {
	url := accessTokenURL + `client_id=` + clientID + `&client_secret=` + clientSecret + `&code=` + code
	result, err := fetch.Post(url)
	if err != nil {
		return nil, fmt.Errorf(`Error while requesting access token %s: %v`, url, err)
	}

	return result, nil
}

// Handler for Docker request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	accessToken, err := getAccessToken(r.URL.Query().Get(`code`))
	if err != nil {
		log.Printf(`Error while getting access token: %v`, err)
		http.Redirect(w, r, OAUTH_REDIRECT_URL + `/login`, http.StatusTemporaryRedirect)
		return
	}

	log.Printf(`Access token is %s`, accessToken)
	http.Redirect(w, r, OAUTH_REDIRECT_URL, http.StatusTemporaryRedirect)
}
<commit_msg>Update oauth.go<commit_after>package oauth

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

	"github.com/ViBiOh/dashboard/fetch"
)

const accessTokenURL = `https://github.com/login/oauth/access_token?`

var (
	stateSalt    string
	clientID     string
	clientSecret string
	redirectURL  string
)

// Init retrieve env variables
func Init() {
	stateSalt = os.Getenv(`OAUTH_STATE_SALT`)
	redirectURL = os.Getenv(`OAUTH_REDIRECT_URL`)
	clientID = os.Getenv(`GITHUB_OAUTH_CLIENT_ID`)
	stateSalt = os.Getenv(`GITHUB_OAUTH_CLIENT_SECRET`)
}

func getAccessToken(code string) ([]byte, error) {
	url := accessTokenURL + `client_id=` + clientID + `&client_secret=` + clientSecret + `&code=` + code
	result, err := fetch.Post(url)
	if err != nil {
		return nil, fmt.Errorf(`Error while requesting access token %s: %v`, url, err)
	}

	return result, nil
}

// Handler for Docker request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	accessToken, err := getAccessToken(r.URL.Query().Get(`code`))
	if err != nil {
		log.Printf(`Error while getting access token: %v`, err)
		http.Redirect(w, r, redirectURL + `/login`, http.StatusTemporaryRedirect)
		return
	}

	log.Printf(`Access token is %s`, accessToken)
	http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"net/http"

	"github.com/lmbarros/sbxs_go_rand/randutil"
)

func handleGimmeAName(w http.ResponseWriter, r *http.Request) {
	nouns := [...][2]string{
		{"Galpão", "M"},
		{"Fogo", "M"},
		{"Churrasco", "M"},
		{"Braseiro", "M"},
		{"Chama", "F"},
		{"Brasa", "F"},
		{"Estância", "F"},
		{"Estrela", "F"},
		{"Tradição", "F"},
	}

	adjectivesM := [...]string{
		"Gaúcho",
		"do Sul",
		"Crioulo",
		"do Rio Grande",
		"Nativo",
		"Nativista",
		"da Fronteira",
		"Gauchesco",
		"Gaudério",
		"Farrapo",
	}

	adjectivesF := [...]string{
		"Gaúcha",
		"do Sul",
		"Crioula",
		"do Rio Grande",
		"Nativa",
		"Nativista",
		"da Fronteira",
		"Gauchesca",
		"Gaudéria",
	}

	i := rand.Intn(len(nouns))
	noun := nouns[i][0]

	var adjective string

	if nouns[i][1] == "M" {
		adjective = adjectivesM[rand.Intn(len(adjectivesM))]
	} else {
		adjective = adjectivesF[rand.Intn(len(adjectivesF))]
	}

	fmt.Fprintf(w, "%s %s", noun, adjective)
}

func handleEverythingElse(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Please access /gimmeaname to get a churrascaria name.")
}

func main() {
	rand.Seed(randutil.GoodSeed())

	http.HandleFunc("/gimmeaname", handleGimmeAName)
	http.HandleFunc("/", handleEverythingElse)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>One more adjective :-)<commit_after>package main

import (
	"fmt"
	"math/rand"
	"net/http"

	"github.com/lmbarros/sbxs_go_rand/randutil"
)

func handleGimmeAName(w http.ResponseWriter, r *http.Request) {
	nouns := [...][2]string{
		{"Galpão", "M"},
		{"Fogo", "M"},
		{"Churrasco", "M"},
		{"Braseiro", "M"},
		{"Chama", "F"},
		{"Brasa", "F"},
		{"Estância", "F"},
		{"Estrela", "F"},
		{"Tradição", "F"},
	}

	adjectivesM := [...]string{
		"Gaúcho",
		"do Sul",
		"Crioulo",
		"do Rio Grande",
		"Nativo",
		"Nativista",
		"da Fronteira",
		"Gauchesco",
		"Gaudério",
		"Farrapo",
		"da Amizade",
	}

	adjectivesF := [...]string{
		"Gaúcha",
		"do Sul",
		"Crioula",
		"do Rio Grande",
		"Nativa",
		"Nativista",
		"da Fronteira",
		"Gauchesca",
		"Gaudéria",
		"da Amizade",
	}

	i := rand.Intn(len(nouns))
	noun := nouns[i][0]

	var adjective string

	if nouns[i][1] == "M" {
		adjective = adjectivesM[rand.Intn(len(adjectivesM))]
	} else {
		adjective = adjectivesF[rand.Intn(len(adjectivesF))]
	}

	fmt.Fprintf(w, "%s %s", noun, adjective)
}

func handleEverythingElse(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Please access /gimmeaname to get a churrascaria name.")
}

func main() {
	rand.Seed(randutil.GoodSeed())

	http.HandleFunc("/gimmeaname", handleGimmeAName)
	http.HandleFunc("/", handleEverythingElse)

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>// Copyright 2015 CloudAwan LLC
//
// 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 glusterfs

import (
	"bufio"
	"bytes"
	"errors"
	"github.com/cloudawan/cloudone/utility/configuration"
	"github.com/cloudawan/cloudone_utility/logger"
	"github.com/cloudawan/cloudone_utility/sshclient"
	"strconv"
	"strings"
	"time"
)

func CreateGlusterfsVolumeControl() (*GlusterfsVolumeControl, error) {
	var ok bool

	glusterfsHostSlice, ok := configuration.LocalConfiguration.GetStringSlice("glusterfsHost")
	if ok == false {
		log.Error("Can't load glusterfsClusterIPSlice")
		return nil, errors.New("Can't load glusterfsClusterIPSlice")
	}

	glusterfsPath, ok := configuration.LocalConfiguration.GetString("glusterfsPath")
	if ok == false {
		log.Error("Can't load glusterfsPath")
		return nil, errors.New("Can't load glusterfsPath")
	}

	glusterfsSSHTimeoutInSecond, ok := configuration.LocalConfiguration.GetInt("glusterfsSSHTimeoutInSecond")
	if ok == false {
		log.Error("Can't load glusterfsSSHTimeoutInSecond")
		return nil, errors.New("Can't load glusterfsSSHTimeoutInSecond")
	}

	glusterfsSSHHostSlice, ok := configuration.LocalConfiguration.GetStringSlice("glusterfsSSHHost")
	if ok == false {
		log.Error("Can't load glusterfsSSHHost")
		return nil, errors.New("Can't load glusterfsSSHHost")
	}

	glusterfsSSHPort, ok := configuration.LocalConfiguration.GetInt("glusterfsSSHPort")
	if ok == false {
		log.Error("Can't load glusterfsSSHPort")
		return nil, errors.New("Can't load glusterfsSSHPort")
	}

	glusterfsSSHUser, ok := configuration.LocalConfiguration.GetString("glusterfsSSHUser")
	if ok == false {
		log.Error("Can't load glusterfsSSHUser")
		return nil, errors.New("Can't load glusterfsSSHUser")
	}

	glusterfsSSHPassword, ok := configuration.LocalConfiguration.GetString("glusterfsSSHPassword")
	if ok == false {
		log.Error("Can't load glusterfsSSHPassword")
		return nil, errors.New("Can't load glusterfsSSHPassword")
	}

	glusterfsVolumeControl := &GlusterfsVolumeControl{
		glusterfsHostSlice,
		glusterfsPath,
		glusterfsSSHTimeoutInSecond,
		glusterfsSSHHostSlice,
		glusterfsSSHPort,
		glusterfsSSHUser,
		glusterfsSSHPassword,
	}

	return glusterfsVolumeControl, nil
}

type GlusterfsVolume struct {
	VolumeName     string
	Type           string
	VolumeID       string
	Status         string
	NumberOfBricks string
	TransportType  string
	Bricks         []string
	Size           int
}

type GlusterfsVolumeControl struct {
	GlusterfsClusterHostSlice   []string
	GlusterfsPath               string
	GlusterfsSSHTimeoutInSecond int
	GlusterfsSSHHostSlice       []string
	GlusterfsSSHPort            int
	GlusterfsSSHUser            string
	GlusterfsSSHPassword        string
}

func parseVolumeInfo(text string) (returnedGlusterfsVolumeSlice []GlusterfsVolume, returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("parseVolumeInfo Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedGlusterfsVolumeSlice = nil
			returnedError = err.(error)
		}
	}()

	glusterfsVolumeSlice := make([]GlusterfsVolume, 0)

	scanner := bufio.NewScanner(bytes.NewBufferString(text))
	var glusterfsVolume *GlusterfsVolume = nil
	for scanner.Scan() {
		line := scanner.Text()
		if line == " " {
			if glusterfsVolume != nil {
				glusterfsVolumeSlice = append(glusterfsVolumeSlice, *glusterfsVolume)
			}
			glusterfsVolume = &GlusterfsVolume{}
		} else if strings.HasPrefix(line, "Volume Name: ") {
			glusterfsVolume.VolumeName = line[len("Volume Name: "):]
		} else if strings.HasPrefix(line, "Type: ") {
			glusterfsVolume.Type = line[len("Type: "):]
		} else if strings.HasPrefix(line, "Volume ID: ") {
			glusterfsVolume.VolumeID = line[len("Volume ID: "):]
		} else if strings.HasPrefix(line, "Status: ") {
			glusterfsVolume.Status = line[len("Status: "):]
		} else if strings.HasPrefix(line, "Number of Bricks: ") {
			glusterfsVolume.NumberOfBricks = line[len("Number of Bricks: "):]
			var err error
			glusterfsVolume.Size, err = strconv.Atoi(strings.TrimSpace(strings.Split(line, "=")[1]))
			if err != nil {
				log.Error("Parse brick error %s", err)
				return nil, err
			}
		} else if strings.HasPrefix(line, "Transport-type: ") {
			glusterfsVolume.TransportType = line[len("Transport-type: "):]
		} else if line == "Bricks:" {
			brickSlice := make([]string, 0)
			for i := 0; i < glusterfsVolume.Size; i++ {
				scanner.Scan()
				brickSlice = append(brickSlice, scanner.Text())
			}
			glusterfsVolume.Bricks = brickSlice
		} else {
			// Ignore unexpected data
		}
	}
	if glusterfsVolume != nil {
		glusterfsVolumeSlice = append(glusterfsVolumeSlice, *glusterfsVolume)
	}
	if err := scanner.Err(); err != nil {
		log.Error("Scanner error %s", err)
		return nil, err
	}
	return glusterfsVolumeSlice, nil
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) getAvailableHost() (*string, error) {
	for _, host := range glusterfsVolumeControl.GlusterfsClusterHostSlice {
		_, err := sshclient.InteractiveSSH(
			time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
			host,
			glusterfsVolumeControl.GlusterfsSSHPort,
			glusterfsVolumeControl.GlusterfsSSHUser,
			glusterfsVolumeControl.GlusterfsSSHPassword,
			nil,
			nil)
		if err == nil {
			return &host, nil
		}
	}

	return nil, errors.New("No available host")
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) GetAllVolume() ([]GlusterfsVolume, error) {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return nil, err
	}

	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, "sudo gluster volume info\n")

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = "cloud4win\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	glusterfsVolumeSlice, err := parseVolumeInfo(resultSlice[0])
	if err != nil {
		log.Error("Parse volume info error %s", err)
		return nil, err
	} else {
		return glusterfsVolumeSlice, nil
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) CreateVolume(name string,
	stripe int, replica int, transport string, hostSlice []string) error {
	if stripe == 0 {
		if replica != len(hostSlice) {
			return errors.New("Replica amount is not the same as ip amount")
		}
	} else if replica == 0 {
		if stripe != len(hostSlice) {
			return errors.New("Stripe amount is not the same as ip amount")
		}
	} else {
		if stripe*replica != len(hostSlice) {
			return errors.New("Replica * Stripe amount is not the same as ip amount")
		}
	}

	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume create ")
	commandBuffer.WriteString(name)

	if stripe > 0 {
		commandBuffer.WriteString(" stripe ")
		commandBuffer.WriteString(strconv.Itoa(stripe))
	}
	if replica > 0 {
		commandBuffer.WriteString(" replica ")
		commandBuffer.WriteString(strconv.Itoa(replica))
	}
	commandBuffer.WriteString(" transport ")
	commandBuffer.WriteString(transport)
	for _, ip := range hostSlice {
		path := " " + ip + ":" + glusterfsVolumeControl.GlusterfsPath + "/" + name
		commandBuffer.WriteString(path)
	}
	commandBuffer.WriteString(" force\n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to create volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) StartVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume start ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to start volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) StopVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume stop ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to stop volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) DeleteVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume delete ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to delete volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}
<commit_msg>Glusterfs info parsing<commit_after>// Copyright 2015 CloudAwan LLC
//
// 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 glusterfs

import (
	"bufio"
	"bytes"
	"errors"
	"github.com/cloudawan/cloudone/utility/configuration"
	"github.com/cloudawan/cloudone_utility/logger"
	"github.com/cloudawan/cloudone_utility/sshclient"
	"strconv"
	"strings"
	"time"
)

func CreateGlusterfsVolumeControl() (*GlusterfsVolumeControl, error) {
	var ok bool

	glusterfsHostSlice, ok := configuration.LocalConfiguration.GetStringSlice("glusterfsHost")
	if ok == false {
		log.Error("Can't load glusterfsClusterIPSlice")
		return nil, errors.New("Can't load glusterfsClusterIPSlice")
	}

	glusterfsPath, ok := configuration.LocalConfiguration.GetString("glusterfsPath")
	if ok == false {
		log.Error("Can't load glusterfsPath")
		return nil, errors.New("Can't load glusterfsPath")
	}

	glusterfsSSHTimeoutInSecond, ok := configuration.LocalConfiguration.GetInt("glusterfsSSHTimeoutInSecond")
	if ok == false {
		log.Error("Can't load glusterfsSSHTimeoutInSecond")
		return nil, errors.New("Can't load glusterfsSSHTimeoutInSecond")
	}

	glusterfsSSHHostSlice, ok := configuration.LocalConfiguration.GetStringSlice("glusterfsSSHHost")
	if ok == false {
		log.Error("Can't load glusterfsSSHHost")
		return nil, errors.New("Can't load glusterfsSSHHost")
	}

	glusterfsSSHPort, ok := configuration.LocalConfiguration.GetInt("glusterfsSSHPort")
	if ok == false {
		log.Error("Can't load glusterfsSSHPort")
		return nil, errors.New("Can't load glusterfsSSHPort")
	}

	glusterfsSSHUser, ok := configuration.LocalConfiguration.GetString("glusterfsSSHUser")
	if ok == false {
		log.Error("Can't load glusterfsSSHUser")
		return nil, errors.New("Can't load glusterfsSSHUser")
	}

	glusterfsSSHPassword, ok := configuration.LocalConfiguration.GetString("glusterfsSSHPassword")
	if ok == false {
		log.Error("Can't load glusterfsSSHPassword")
		return nil, errors.New("Can't load glusterfsSSHPassword")
	}

	glusterfsVolumeControl := &GlusterfsVolumeControl{
		glusterfsHostSlice,
		glusterfsPath,
		glusterfsSSHTimeoutInSecond,
		glusterfsSSHHostSlice,
		glusterfsSSHPort,
		glusterfsSSHUser,
		glusterfsSSHPassword,
	}

	return glusterfsVolumeControl, nil
}

type GlusterfsVolume struct {
	VolumeName     string
	Type           string
	VolumeID       string
	Status         string
	NumberOfBricks string
	TransportType  string
	Bricks         []string
	Size           int
}

type GlusterfsVolumeControl struct {
	GlusterfsClusterHostSlice   []string
	GlusterfsPath               string
	GlusterfsSSHTimeoutInSecond int
	GlusterfsSSHHostSlice       []string
	GlusterfsSSHPort            int
	GlusterfsSSHUser            string
	GlusterfsSSHPassword        string
}

func parseSize(field string) (returnedSize int, returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("Parse size error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedSize = -1
			returnedError = err.(error)
		}
	}()

	var value string
	if strings.Contains(field, "=") {
		value = strings.Split(field, "=")[1]
	} else {
		value = field
	}

	size, err := strconv.Atoi(strings.TrimSpace(value))

	if err != nil {
		log.Error("Parse size error %s", err)
		return -1, err
	} else {
		return size, nil
	}
}

func parseVolumeInfo(text string) (returnedGlusterfsVolumeSlice []GlusterfsVolume, returnedError error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("parseVolumeInfo Error: %s", err)
			log.Error(logger.GetStackTrace(4096, false))
			returnedGlusterfsVolumeSlice = nil
			returnedError = err.(error)
		}
	}()

	glusterfsVolumeSlice := make([]GlusterfsVolume, 0)

	scanner := bufio.NewScanner(bytes.NewBufferString(text))
	var glusterfsVolume *GlusterfsVolume = nil
	for scanner.Scan() {
		line := scanner.Text()
		if line == " " {
			if glusterfsVolume != nil {
				glusterfsVolumeSlice = append(glusterfsVolumeSlice, *glusterfsVolume)
			}
			glusterfsVolume = &GlusterfsVolume{}
		} else if strings.HasPrefix(line, "Volume Name: ") {
			glusterfsVolume.VolumeName = line[len("Volume Name: "):]
		} else if strings.HasPrefix(line, "Type: ") {
			glusterfsVolume.Type = line[len("Type: "):]
		} else if strings.HasPrefix(line, "Volume ID: ") {
			glusterfsVolume.VolumeID = line[len("Volume ID: "):]
		} else if strings.HasPrefix(line, "Status: ") {
			glusterfsVolume.Status = line[len("Status: "):]
		} else if strings.HasPrefix(line, "Number of Bricks: ") {
			glusterfsVolume.NumberOfBricks = line[len("Number of Bricks: "):]
			glusterfsVolume.Size, _ = parseSize(glusterfsVolume.NumberOfBricks)
		} else if strings.HasPrefix(line, "Transport-type: ") {
			glusterfsVolume.TransportType = line[len("Transport-type: "):]
		} else if line == "Bricks:" {
			brickSlice := make([]string, 0)
			for i := 0; i < glusterfsVolume.Size; i++ {
				scanner.Scan()
				brickSlice = append(brickSlice, scanner.Text())
			}
			glusterfsVolume.Bricks = brickSlice
		} else {
			// Ignore unexpected data
		}
	}
	if glusterfsVolume != nil {
		glusterfsVolumeSlice = append(glusterfsVolumeSlice, *glusterfsVolume)
	}
	if err := scanner.Err(); err != nil {
		log.Error("Scanner error %s", err)
		return nil, err
	}
	return glusterfsVolumeSlice, nil
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) getAvailableHost() (*string, error) {
	for _, host := range glusterfsVolumeControl.GlusterfsClusterHostSlice {
		_, err := sshclient.InteractiveSSH(
			time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
			host,
			glusterfsVolumeControl.GlusterfsSSHPort,
			glusterfsVolumeControl.GlusterfsSSHUser,
			glusterfsVolumeControl.GlusterfsSSHPassword,
			nil,
			nil)
		if err == nil {
			return &host, nil
		}
	}

	return nil, errors.New("No available host")
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) GetAllVolume() ([]GlusterfsVolume, error) {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return nil, err
	}

	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, "sudo gluster volume info\n")

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = "cloud4win\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	glusterfsVolumeSlice, err := parseVolumeInfo(resultSlice[0])
	if err != nil {
		log.Error("Parse volume info error %s", err)
		return nil, err
	} else {
		return glusterfsVolumeSlice, nil
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) CreateVolume(name string,
	stripe int, replica int, transport string, hostSlice []string) error {
	if stripe == 0 {
		if replica != len(hostSlice) {
			return errors.New("Replica amount is not the same as ip amount")
		}
	} else if replica == 0 {
		if stripe != len(hostSlice) {
			return errors.New("Stripe amount is not the same as ip amount")
		}
	} else {
		if stripe*replica != len(hostSlice) {
			return errors.New("Replica * Stripe amount is not the same as ip amount")
		}
	}

	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume create ")
	commandBuffer.WriteString(name)

	if stripe > 0 {
		commandBuffer.WriteString(" stripe ")
		commandBuffer.WriteString(strconv.Itoa(stripe))
	}
	if replica > 0 {
		commandBuffer.WriteString(" replica ")
		commandBuffer.WriteString(strconv.Itoa(replica))
	}
	commandBuffer.WriteString(" transport ")
	commandBuffer.WriteString(transport)
	for _, ip := range hostSlice {
		path := " " + ip + ":" + glusterfsVolumeControl.GlusterfsPath + "/" + name
		commandBuffer.WriteString(path)
	}
	commandBuffer.WriteString(" force\n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to create volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) StartVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume start ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to start volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) StopVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume stop ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to stop volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}

func (glusterfsVolumeControl *GlusterfsVolumeControl) DeleteVolume(name string) error {
	host, err := glusterfsVolumeControl.getAvailableHost()
	if err != nil {
		return err
	}

	commandBuffer := bytes.Buffer{}
	commandBuffer.WriteString("sudo gluster --mode=script volume delete ")
	commandBuffer.WriteString(name)
	commandBuffer.WriteString(" \n")
	commandSlice := make([]string, 0)
	commandSlice = append(commandSlice, commandBuffer.String())

	interactiveMap := make(map[string]string)
	interactiveMap["[sudo]"] = glusterfsVolumeControl.GlusterfsSSHPassword + "\n"

	resultSlice, err := sshclient.InteractiveSSH(
		time.Duration(glusterfsVolumeControl.GlusterfsSSHTimeoutInSecond)*time.Second,
		*host,
		glusterfsVolumeControl.GlusterfsSSHPort,
		glusterfsVolumeControl.GlusterfsSSHUser,
		glusterfsVolumeControl.GlusterfsSSHPassword,
		commandSlice,
		interactiveMap)

	if err != nil {
		log.Error("Create volume error %s resultSlice %s", err, resultSlice)
		return err
	} else {
		if strings.Contains(resultSlice[0], "success") {
			return nil
		} else {
			log.Debug("Issue command: " + commandBuffer.String())
			log.Error("Fail to delete volume with error: " + resultSlice[0])
			return errors.New(resultSlice[0])
		}
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

// add sweeper to delete known test subnets
func init() {
	resource.AddTestSweepers("aws_subnet", &resource.Sweeper{
		Name: "aws_subnet",
		F:    testSweepSubnets,
		Dependencies: []string{
			"aws_batch_compute_environment",
			"aws_elb",
		},
	})
}

func testSweepSubnets(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).ec2conn

	req := &ec2.DescribeSubnetsInput{
		Filters: []*ec2.Filter{
			{
				Name: aws.String("tag-value"),
				Values: []*string{
					aws.String("tf-acc-*"),
				},
			},
		},
	}
	resp, err := conn.DescribeSubnets(req)
	if err != nil {
		return fmt.Errorf("Error describing subnets: %s", err)
	}

	if len(resp.Subnets) == 0 {
		log.Print("[DEBUG] No aws subnets to sweep")
		return nil
	}

	for _, subnet := range resp.Subnets {
		// delete the subnet
		_, err := conn.DeleteSubnet(&ec2.DeleteSubnetInput{
			SubnetId: subnet.SubnetId,
		})
		if err != nil {
			return fmt.Errorf(
				"Error deleting Subnet (%s): %s",
				*subnet.SubnetId, err)
		}
	}

	return nil
}

func TestAccAWSSubnet_basic(t *testing.T) {
	var v ec2.Subnet

	testCheck := func(*terraform.State) error {
		if *v.CidrBlock != "10.1.1.0/24" {
			return fmt.Errorf("bad cidr: %s", *v.CidrBlock)
		}

		if *v.MapPublicIpOnLaunch != true {
			return fmt.Errorf("bad MapPublicIpOnLaunch: %t", *v.MapPublicIpOnLaunch)
		}

		return nil
	}

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &v),
					testCheck,
				),
			},
		},
	})
}

func TestAccAWSSubnet_ipv6(t *testing.T) {
	var before, after ec2.Subnet

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfigIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &before),
					testAccCheckAwsSubnetIpv6BeforeUpdate(t, &before),
				),
			},
			{
				Config: testAccSubnetConfigIpv6UpdateAssignIpv6OnCreation,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &after),
					testAccCheckAwsSubnetIpv6AfterUpdate(t, &after),
				),
			},
			{
				Config: testAccSubnetConfigIpv6UpdateIpv6Cidr,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &after),

					testAccCheckAwsSubnetNotRecreated(t, &before, &after),
				),
			},
		},
	})
}

func TestAccAWSSubnet_enableIpv6(t *testing.T) {
	var subnet ec2.Subnet

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfigPreIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &subnet),
				),
			},
			{
				Config: testAccSubnetConfigIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &subnet),
				),
			},
		},
	})
}

func testAccCheckAwsSubnetIpv6BeforeUpdate(t *testing.T, subnet *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if subnet.Ipv6CidrBlockAssociationSet == nil {
			return fmt.Errorf("Expected IPV6 CIDR Block Association")
		}

		if *subnet.AssignIpv6AddressOnCreation != true {
			return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *subnet.AssignIpv6AddressOnCreation)
		}

		return nil
	}
}

func testAccCheckAwsSubnetIpv6AfterUpdate(t *testing.T, subnet *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *subnet.AssignIpv6AddressOnCreation != false {
			return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *subnet.AssignIpv6AddressOnCreation)
		}

		return nil
	}
}

func testAccCheckAwsSubnetNotRecreated(t *testing.T,
	before, after *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *before.SubnetId != *after.SubnetId {
			t.Fatalf("Expected SubnetIDs not to change, but both got before: %s and after: %s", *before.SubnetId, *after.SubnetId)
		}
		return nil
	}
}

func testAccCheckSubnetDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_subnet" {
			continue
		}

		// Try to find the resource
		resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsInput{
			SubnetIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err == nil {
			if len(resp.Subnets) > 0 {
				return fmt.Errorf("still exist.")
			}

			return nil
		}

		// Verify the error is what we want
		ec2err, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if ec2err.Code() != "InvalidSubnetID.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckSubnetExists(n string, v *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsInput{
			SubnetIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return err
		}
		if len(resp.Subnets) == 0 {
			return fmt.Errorf("Subnet not found")
		}

		*v = *resp.Subnets[0]

		return nil
	}
}

const testAccSubnetConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
	tags {
		Name = "terraform-testacc-subnet"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.1.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	map_public_ip_on_launch = true
	tags {
		Name = "tf-acc-subnet"
	}
}
`

const testAccSubnetConfigPreIpv6 = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	map_public_ip_on_launch = true
	tags {
		Name = "tf-acc-subnet-ipv6"
	}
}
`

const testAccSubnetConfigIpv6 = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = true
	tags {
		Name = "tf-acc-subnet-ipv6"
	}
}
`

const testAccSubnetConfigIpv6UpdateAssignIpv6OnCreation = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-assign-ipv6-on-creation"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = false
	tags {
		Name = "tf-acc-subnet-assign-ipv6-on-creation"
	}
}
`

const testAccSubnetConfigIpv6UpdateIpv6Cidr = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6-update-cidr"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 3)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = false
	tags {
		Name = "tf-acc-subnet-ipv6-update-cidr"
	}
}
`
<commit_msg>tests/resource/aws_subnet: Add sweeper dependencies<commit_after>package aws

import (
	"fmt"
	"log"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

// add sweeper to delete known test subnets
func init() {
	resource.AddTestSweepers("aws_subnet", &resource.Sweeper{
		Name: "aws_subnet",
		F:    testSweepSubnets,
		// When implemented, these should be moved to aws_network_interface
		// and aws_network_interface set as dependency here.
		Dependencies: []string{
			"aws_autoscaling_group",
			"aws_batch_compute_environment",
			"aws_beanstalk_environment",
			"aws_db_instance",
			"aws_elasticsearch_domain",
			"aws_elb",
			"aws_lambda_function",
			"aws_mq_broker",
			"aws_redshift_cluster",
		},
	})
}

func testSweepSubnets(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).ec2conn

	req := &ec2.DescribeSubnetsInput{
		Filters: []*ec2.Filter{
			{
				Name: aws.String("tag-value"),
				Values: []*string{
					aws.String("tf-acc-*"),
				},
			},
		},
	}
	resp, err := conn.DescribeSubnets(req)
	if err != nil {
		return fmt.Errorf("Error describing subnets: %s", err)
	}

	if len(resp.Subnets) == 0 {
		log.Print("[DEBUG] No aws subnets to sweep")
		return nil
	}

	for _, subnet := range resp.Subnets {
		// delete the subnet
		_, err := conn.DeleteSubnet(&ec2.DeleteSubnetInput{
			SubnetId: subnet.SubnetId,
		})
		if err != nil {
			return fmt.Errorf(
				"Error deleting Subnet (%s): %s",
				*subnet.SubnetId, err)
		}
	}

	return nil
}

func TestAccAWSSubnet_basic(t *testing.T) {
	var v ec2.Subnet

	testCheck := func(*terraform.State) error {
		if *v.CidrBlock != "10.1.1.0/24" {
			return fmt.Errorf("bad cidr: %s", *v.CidrBlock)
		}

		if *v.MapPublicIpOnLaunch != true {
			return fmt.Errorf("bad MapPublicIpOnLaunch: %t", *v.MapPublicIpOnLaunch)
		}

		return nil
	}

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &v),
					testCheck,
				),
			},
		},
	})
}

func TestAccAWSSubnet_ipv6(t *testing.T) {
	var before, after ec2.Subnet

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfigIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &before),
					testAccCheckAwsSubnetIpv6BeforeUpdate(t, &before),
				),
			},
			{
				Config: testAccSubnetConfigIpv6UpdateAssignIpv6OnCreation,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &after),
					testAccCheckAwsSubnetIpv6AfterUpdate(t, &after),
				),
			},
			{
				Config: testAccSubnetConfigIpv6UpdateIpv6Cidr,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &after),

					testAccCheckAwsSubnetNotRecreated(t, &before, &after),
				),
			},
		},
	})
}

func TestAccAWSSubnet_enableIpv6(t *testing.T) {
	var subnet ec2.Subnet

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_subnet.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckSubnetDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccSubnetConfigPreIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &subnet),
				),
			},
			{
				Config: testAccSubnetConfigIpv6,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckSubnetExists(
						"aws_subnet.foo", &subnet),
				),
			},
		},
	})
}

func testAccCheckAwsSubnetIpv6BeforeUpdate(t *testing.T, subnet *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if subnet.Ipv6CidrBlockAssociationSet == nil {
			return fmt.Errorf("Expected IPV6 CIDR Block Association")
		}

		if *subnet.AssignIpv6AddressOnCreation != true {
			return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *subnet.AssignIpv6AddressOnCreation)
		}

		return nil
	}
}

func testAccCheckAwsSubnetIpv6AfterUpdate(t *testing.T, subnet *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *subnet.AssignIpv6AddressOnCreation != false {
			return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *subnet.AssignIpv6AddressOnCreation)
		}

		return nil
	}
}

func testAccCheckAwsSubnetNotRecreated(t *testing.T,
	before, after *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if *before.SubnetId != *after.SubnetId {
			t.Fatalf("Expected SubnetIDs not to change, but both got before: %s and after: %s", *before.SubnetId, *after.SubnetId)
		}
		return nil
	}
}

func testAccCheckSubnetDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_subnet" {
			continue
		}

		// Try to find the resource
		resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsInput{
			SubnetIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err == nil {
			if len(resp.Subnets) > 0 {
				return fmt.Errorf("still exist.")
			}

			return nil
		}

		// Verify the error is what we want
		ec2err, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if ec2err.Code() != "InvalidSubnetID.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckSubnetExists(n string, v *ec2.Subnet) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsInput{
			SubnetIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return err
		}
		if len(resp.Subnets) == 0 {
			return fmt.Errorf("Subnet not found")
		}

		*v = *resp.Subnets[0]

		return nil
	}
}

const testAccSubnetConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
	tags {
		Name = "terraform-testacc-subnet"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.1.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	map_public_ip_on_launch = true
	tags {
		Name = "tf-acc-subnet"
	}
}
`

const testAccSubnetConfigPreIpv6 = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	map_public_ip_on_launch = true
	tags {
		Name = "tf-acc-subnet-ipv6"
	}
}
`

const testAccSubnetConfigIpv6 = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = true
	tags {
		Name = "tf-acc-subnet-ipv6"
	}
}
`

const testAccSubnetConfigIpv6UpdateAssignIpv6OnCreation = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-assign-ipv6-on-creation"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = false
	tags {
		Name = "tf-acc-subnet-assign-ipv6-on-creation"
	}
}
`

const testAccSubnetConfigIpv6UpdateIpv6Cidr = `
resource "aws_vpc" "foo" {
	cidr_block = "10.10.0.0/16"
	assign_generated_ipv6_cidr_block = true
	tags {
		Name = "terraform-testacc-subnet-ipv6-update-cidr"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.10.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 3)}"
	map_public_ip_on_launch = true
	assign_ipv6_address_on_creation = false
	tags {
		Name = "tf-acc-subnet-ipv6-update-cidr"
	}
}
`
<|endoftext|>


<commit_before>// Copyright (c) 2014 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.

// +build leveldb

package cbft

import (
	_ "github.com/blevesearch/bleve/index/store/leveldb"
)
<commit_msg>changes for blevex/leveldb<commit_after>// Copyright (c) 2014 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.

// +build leveldb

package cbft

import (
	_ "github.com/blevesearch/blevex/leveldb"
)
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sagemaker"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix = "terraform-testacc-"

func TestAccAWSSagemakerNotebookInstance_basic(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),
					testAccCheckAWSSagemakerNotebookInstanceName(&notebook, notebookName),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "name", notebookName),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_update(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "instance_type", "ml.t2.medium"),
				),
			},

			{
				Config: testAccAWSSagemakerNotebookInstanceUpdateConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "instance_type", "ml.m4.xlarge"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_tags(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceTagsConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "foo", "bar"),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "name", notebookName),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.%", "1"),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.foo", "bar"),
				),
			},

			{
				Config: testAccAWSSagemakerNotebookInstanceTagsUpdateConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "foo", ""),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "bar", "baz"),

					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.%", "1"),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.bar", "baz"),
				),
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_disappears(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),
					testAccCheckAWSSagemakerNotebookInstanceDisappears(&notebook),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSagemakerNotebookInstanceDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_sagemaker_notebook_instance" {
			continue
		}

		describeNotebookInput := &sagemaker.DescribeNotebookInstanceInput{
			NotebookInstanceName: aws.String(rs.Primary.ID),
		}
		notebookInstance, err := conn.DescribeNotebookInstance(describeNotebookInput)
		if err != nil {
			return nil
		}

		if *notebookInstance.NotebookInstanceName == rs.Primary.ID {
			return fmt.Errorf("sagemaker notebook instance %q still exists", rs.Primary.ID)
		}
	}

	return nil
}

func testAccCheckAWSSagemakerNotebookInstanceExists(n string, notebook *sagemaker.DescribeNotebookInstanceOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No sagmaker Notebook Instance ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn
		opts := &sagemaker.DescribeNotebookInstanceInput{
			NotebookInstanceName: aws.String(rs.Primary.ID),
		}
		resp, err := conn.DescribeNotebookInstance(opts)
		if err != nil {
			return err
		}

		*notebook = *resp

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceDisappears(instance *sagemaker.DescribeNotebookInstanceOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

		if *instance.NotebookInstanceStatus != sagemaker.NotebookInstanceStatusFailed && *instance.NotebookInstanceStatus != sagemaker.NotebookInstanceStatusStopped {
			if err := stopSagemakerNotebookInstance(conn, *instance.NotebookInstanceName); err != nil {
				return err
			}
		}

		deleteOpts := &sagemaker.DeleteNotebookInstanceInput{
			NotebookInstanceName: instance.NotebookInstanceName,
		}

		if _, err := conn.DeleteNotebookInstance(deleteOpts); err != nil {
			return fmt.Errorf("error trying to delete sagemaker notebook instance (%s): %s", aws.StringValue(instance.NotebookInstanceName), err)
		}

		stateConf := &resource.StateChangeConf{
			Pending: []string{
				sagemaker.NotebookInstanceStatusDeleting,
			},
			Target:  []string{""},
			Refresh: sagemakerNotebookInstanceStateRefreshFunc(conn, *instance.NotebookInstanceName),
			Timeout: 10 * time.Minute,
		}
		_, err := stateConf.WaitForState()
		if err != nil {
			return fmt.Errorf("error waiting for sagemaker notebook instance (%s) to delete: %s", aws.StringValue(instance.NotebookInstanceName), err)
		}

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceName(notebook *sagemaker.DescribeNotebookInstanceOutput, expected string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		notebookName := notebook.NotebookInstanceName
		if *notebookName != expected {
			return fmt.Errorf("Bad Notebook Instance name: %s", *notebook.NotebookInstanceName)
		}

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceTags(notebook *sagemaker.DescribeNotebookInstanceOutput, key string, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

		ts, err := conn.ListTags(&sagemaker.ListTagsInput{
			ResourceArn: notebook.NotebookInstanceArn,
		})
		if err != nil {
			return fmt.Errorf("Error listing tags: %s", err)
		}

		m := tagsToMapSagemaker(ts.Tags)
		v, ok := m[key]
		if value != "" && !ok {
			return fmt.Errorf("Missing tag: %s", key)
		} else if value == "" && ok {
			return fmt.Errorf("Extra tag: %s", key)
		}
		if value == "" {
			return nil
		}

		if v != value {
			return fmt.Errorf("%s: bad value: %s", key, v)
		}

		return nil
	}
}

func testAccAWSSagemakerNotebookInstanceConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceUpdateConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.m4.xlarge"
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceTagsConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
	tags = {
		foo = "bar"
	}
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceTagsUpdateConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
	tags = {
		bar = "baz"
	}
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}
<commit_msg>tests/resource/aws_sagemaker_notebook_instance: Implement acceptance test for lifecycle_config_name argument<commit_after>package aws

import (
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sagemaker"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix = "terraform-testacc-"

func TestAccAWSSagemakerNotebookInstance_basic(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),
					testAccCheckAWSSagemakerNotebookInstanceName(&notebook, notebookName),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "name", notebookName),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_update(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "instance_type", "ml.t2.medium"),
				),
			},

			{
				Config: testAccAWSSagemakerNotebookInstanceUpdateConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "instance_type", "ml.m4.xlarge"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_LifecycleConfigName(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	rName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	resourceName := "aws_sagemaker_notebook_instance.test"
	sagemakerLifecycleConfigResourceName := "aws_sagemaker_notebook_instance_lifecycle_configuration.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfigLifecycleConfigName(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),
					resource.TestCheckResourceAttrPair(resourceName, "lifecycle_config_name", sagemakerLifecycleConfigResourceName, "name"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_tags(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceTagsConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "foo", "bar"),

					resource.TestCheckResourceAttr(
						"aws_sagemaker_notebook_instance.foo", "name", notebookName),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.%", "1"),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.foo", "bar"),
				),
			},

			{
				Config: testAccAWSSagemakerNotebookInstanceTagsUpdateConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists("aws_sagemaker_notebook_instance.foo", &notebook),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "foo", ""),
					testAccCheckAWSSagemakerNotebookInstanceTags(&notebook, "bar", "baz"),

					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.%", "1"),
					resource.TestCheckResourceAttr("aws_sagemaker_notebook_instance.foo", "tags.bar", "baz"),
				),
			},
		},
	})
}

func TestAccAWSSagemakerNotebookInstance_disappears(t *testing.T) {
	var notebook sagemaker.DescribeNotebookInstanceOutput
	notebookName := resource.PrefixedUniqueId(sagemakerTestAccSagemakerNotebookInstanceResourceNamePrefix)
	var resourceName = "aws_sagemaker_notebook_instance.foo"
	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerNotebookInstanceConfig(notebookName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, &notebook),
					testAccCheckAWSSagemakerNotebookInstanceDisappears(&notebook),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSagemakerNotebookInstanceDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_sagemaker_notebook_instance" {
			continue
		}

		describeNotebookInput := &sagemaker.DescribeNotebookInstanceInput{
			NotebookInstanceName: aws.String(rs.Primary.ID),
		}
		notebookInstance, err := conn.DescribeNotebookInstance(describeNotebookInput)
		if err != nil {
			return nil
		}

		if *notebookInstance.NotebookInstanceName == rs.Primary.ID {
			return fmt.Errorf("sagemaker notebook instance %q still exists", rs.Primary.ID)
		}
	}

	return nil
}

func testAccCheckAWSSagemakerNotebookInstanceExists(n string, notebook *sagemaker.DescribeNotebookInstanceOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No sagmaker Notebook Instance ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn
		opts := &sagemaker.DescribeNotebookInstanceInput{
			NotebookInstanceName: aws.String(rs.Primary.ID),
		}
		resp, err := conn.DescribeNotebookInstance(opts)
		if err != nil {
			return err
		}

		*notebook = *resp

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceDisappears(instance *sagemaker.DescribeNotebookInstanceOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

		if *instance.NotebookInstanceStatus != sagemaker.NotebookInstanceStatusFailed && *instance.NotebookInstanceStatus != sagemaker.NotebookInstanceStatusStopped {
			if err := stopSagemakerNotebookInstance(conn, *instance.NotebookInstanceName); err != nil {
				return err
			}
		}

		deleteOpts := &sagemaker.DeleteNotebookInstanceInput{
			NotebookInstanceName: instance.NotebookInstanceName,
		}

		if _, err := conn.DeleteNotebookInstance(deleteOpts); err != nil {
			return fmt.Errorf("error trying to delete sagemaker notebook instance (%s): %s", aws.StringValue(instance.NotebookInstanceName), err)
		}

		stateConf := &resource.StateChangeConf{
			Pending: []string{
				sagemaker.NotebookInstanceStatusDeleting,
			},
			Target:  []string{""},
			Refresh: sagemakerNotebookInstanceStateRefreshFunc(conn, *instance.NotebookInstanceName),
			Timeout: 10 * time.Minute,
		}
		_, err := stateConf.WaitForState()
		if err != nil {
			return fmt.Errorf("error waiting for sagemaker notebook instance (%s) to delete: %s", aws.StringValue(instance.NotebookInstanceName), err)
		}

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceName(notebook *sagemaker.DescribeNotebookInstanceOutput, expected string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		notebookName := notebook.NotebookInstanceName
		if *notebookName != expected {
			return fmt.Errorf("Bad Notebook Instance name: %s", *notebook.NotebookInstanceName)
		}

		return nil
	}
}

func testAccCheckAWSSagemakerNotebookInstanceTags(notebook *sagemaker.DescribeNotebookInstanceOutput, key string, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

		ts, err := conn.ListTags(&sagemaker.ListTagsInput{
			ResourceArn: notebook.NotebookInstanceArn,
		})
		if err != nil {
			return fmt.Errorf("Error listing tags: %s", err)
		}

		m := tagsToMapSagemaker(ts.Tags)
		v, ok := m[key]
		if value != "" && !ok {
			return fmt.Errorf("Missing tag: %s", key)
		} else if value == "" && ok {
			return fmt.Errorf("Extra tag: %s", key)
		}
		if value == "" {
			return nil
		}

		if v != value {
			return fmt.Errorf("%s: bad value: %s", key, v)
		}

		return nil
	}
}

func testAccAWSSagemakerNotebookInstanceConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceUpdateConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.m4.xlarge"
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceConfigLifecycleConfigName(rName string) string {
	return fmt.Sprintf(`
data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = [ "sts:AssumeRole" ]
    principals {
      identifiers = ["sagemaker.amazonaws.com"]
      type        = "Service"
    }
  }
}

resource "aws_iam_role" "test" {
  assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
  name               = %[1]q
  path               = "/"
}

resource "aws_sagemaker_notebook_instance_lifecycle_configuration" "test" {
  name = %[1]q
}

resource "aws_sagemaker_notebook_instance" "test" {
  instance_type         = "ml.t2.medium"
  lifecycle_config_name = "${aws_sagemaker_notebook_instance_lifecycle_configuration.test.name}"
  name                  = %[1]q
  role_arn              = "${aws_iam_role.test.arn}"
}
`, rName)
}

func testAccAWSSagemakerNotebookInstanceTagsConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
	tags = {
		foo = "bar"
	}
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}

func testAccAWSSagemakerNotebookInstanceTagsUpdateConfig(notebookName string) string {
	return fmt.Sprintf(`
resource "aws_sagemaker_notebook_instance" "foo" {
	name = "%s"
	role_arn = "${aws_iam_role.foo.arn}"
	instance_type = "ml.t2.medium"
	tags = {
		bar = "baz"
	}
}

resource "aws_iam_role" "foo" {
	name = "%s"
	path = "/"
	assume_role_policy = "${data.aws_iam_policy_document.assume_role.json}"
}

data "aws_iam_policy_document" "assume_role" {
	statement {
		actions = [ "sts:AssumeRole" ]
		principals {
			type = "Service"
			identifiers = [ "sagemaker.amazonaws.com" ]
		}
	}
}
`, notebookName, notebookName)
}
<|endoftext|>


<commit_before>package oauth

import (
	"log"
	"net/http"
	"os"

	"github.com/ViBiOh/dashboard/fetch"
)

const accessTokenURL = `https://github.com/login/oauth/access_token`

var stateSalt string

func Init() {
	stateSalt = os.Getenv(`OAUTH_STATE_SALT`)
}

// Handler for Docker request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Printf(`Path = %s`, r.URL.Path)
}
<commit_msg>Update oauth.go<commit_after>package oauth

import (
	"log"
	"net/http"
	"os"
)

const accessTokenURL = `https://github.com/login/oauth/access_token`

var stateSalt string

func Init() {
	stateSalt = os.Getenv(`OAUTH_STATE_SALT`)
}

// Handler for Docker request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Printf(`Path = %s`, r.URL.Path)
}
<|endoftext|>


<commit_before>package dht

// func TestFindPeersNear(t *testing.T) {
// 	peer1 := net.Peer{ID: "a1", Addresses: []string{"127.0.0.1:8889"}}
// 	peer2 := net.Peer{ID: "a2", Addresses: []string{"127.0.0.1:8890"}}
// 	peer3 := net.Peer{ID: "a3", Addresses: []string{"127.0.0.1:8891"}}
// 	peer4 := net.Peer{ID: "a4", Addresses: []string{"127.0.0.1:8821"}}
// 	peer5 := net.Peer{ID: "a5", Addresses: []string{"127.0.0.1:8841"}}
// 	peer6 := net.Peer{ID: "a6", Addresses: []string{"127.0.0.1:8861"}}

// 	rt := NewSimpleRoutingTable()
// 	rt.Add(peer2)
// 	rt.Add(peer3)
// 	rt.Add(peer4)
// 	rt.Add(peer5)
// 	rt.Add(peer6)

// 	nnet, _ := net.NewTCPNetwork(&peer1)

// 	node, _ := NewDHTNode([]net.Peer{peer2}, peer1, rt, nnet)
// 	peers, err := node.findPeersNear(peer6.ID, 3)
// 	if err != nil {
// 		fmt.Println(err)
// 		t.Fail()
// 	}

// 	if len(peers) == 0 {
// 		t.Fail()
// 	}

// 	if peers[0].ID != peer6.ID {
// 		t.Fail()
// 	}
// }
<commit_msg>Remove unit tests<commit_after><|endoftext|>


<commit_before>/*
Copyright 2019 The xridge kubestone contributors.

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

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

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

package iperf3

import (
	"context"

	"github.com/go-logr/logr"
	ctrl "sigs.k8s.io/controller-runtime"

	"github.com/xridge/kubestone/pkg/k8s"

	perfv1alpha1 "github.com/xridge/kubestone/api/v1alpha1"
)

// Reconciler provides fields from manager to reconciler
type Reconciler struct {
	K8S k8s.Access
	Log logr.Logger
}

// +kubebuilder:rbac:groups=perf.kubestone.xridge.io,resources=iperf3s,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=perf.kubestone.xridge.io,resources=iperf3s/status,verbs=get;update;patch

// Reconcile Iperf3 Job Requests
func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()

	var cr perfv1alpha1.Iperf3
	if err := r.K8S.Client.Get(ctx, req.NamespacedName, &cr); err != nil {
		return ctrl.Result{}, k8s.IgnoreNotFound(err)
	}

	// Run to one completion
	if cr.Status.Completed {
		return ctrl.Result{}, nil
	}

	cr.Status.Running = true
	if err := r.K8S.Client.Status().Update(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.K8S.CreateWithReference(ctx, newServerDeployment(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.K8S.CreateWithReference(ctx, newServerService(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	serverReady, err := r.serverDeploymentReady(&cr)
	if err != nil {
		return ctrl.Result{}, err
	}
	if !serverReady {
		// Wait for deployment to be ready
		return ctrl.Result{Requeue: true}, nil
	}

	if err := r.K8S.CreateWithReference(ctx, newClientPod(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	clientPodFinished, err := r.clientPodFinished(&cr)
	if err != nil {
		return ctrl.Result{}, err
	}
	if !clientPodFinished {
		// Wait for the client pod to be completed
		return ctrl.Result{Requeue: true}, nil
	}

	if err := r.deleteServerService(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.deleteServerDeployment(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	cr.Status.Running = false
	cr.Status.Completed = true
	if err := r.K8S.Client.Status().Update(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	return ctrl.Result{}, nil
}

// SetupWithManager registers the Iperf3Reconciler with the provided manager
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&perfv1alpha1.Iperf3{}).
		Complete(r)
}
<commit_msg>WiP: More docs to iperf3 reconciler<commit_after>/*
Copyright 2019 The xridge kubestone contributors.

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

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

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

package iperf3

import (
	"context"

	"github.com/go-logr/logr"
	ctrl "sigs.k8s.io/controller-runtime"

	"github.com/xridge/kubestone/pkg/k8s"

	perfv1alpha1 "github.com/xridge/kubestone/api/v1alpha1"
)

// Reconciler provides fields from manager to reconciler
type Reconciler struct {
	K8S k8s.Access
	Log logr.Logger
}

// +kubebuilder:rbac:groups=perf.kubestone.xridge.io,resources=iperf3s,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=perf.kubestone.xridge.io,resources=iperf3s/status,verbs=get;update;patch

// Reconcile Iperf3 Benchmark Requests by creating:
//   - iperf3 server deployment
//   - iperf3 server service
//   - iperf3 client pod
// The creation of iperf3 client pod is postponed until the server
// deployment completes. Once the iperf3 client pod is completed,
// the server deployment and service objects are removed from k8s.
func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()

	var cr perfv1alpha1.Iperf3
	if err := r.K8S.Client.Get(ctx, req.NamespacedName, &cr); err != nil {
		return ctrl.Result{}, k8s.IgnoreNotFound(err)
	}

	// Run to one completion
	if cr.Status.Completed {
		return ctrl.Result{}, nil
	}

	cr.Status.Running = true
	if err := r.K8S.Client.Status().Update(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.K8S.CreateWithReference(ctx, newServerDeployment(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.K8S.CreateWithReference(ctx, newServerService(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	serverReady, err := r.serverDeploymentReady(&cr)
	if err != nil {
		return ctrl.Result{}, err
	}
	if !serverReady {
		// Wait for deployment to be ready
		return ctrl.Result{Requeue: true}, nil
	}

	if err := r.K8S.CreateWithReference(ctx, newClientPod(&cr), &cr); err != nil {
		return ctrl.Result{}, err
	}

	clientPodFinished, err := r.clientPodFinished(&cr)
	if err != nil {
		return ctrl.Result{}, err
	}
	if !clientPodFinished {
		// Wait for the client pod to be completed
		return ctrl.Result{Requeue: true}, nil
	}

	if err := r.deleteServerService(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	if err := r.deleteServerDeployment(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	cr.Status.Running = false
	cr.Status.Completed = true
	if err := r.K8S.Client.Status().Update(ctx, &cr); err != nil {
		return ctrl.Result{}, err
	}

	return ctrl.Result{}, nil
}

// SetupWithManager registers the Iperf3Reconciler with the provided manager
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&perfv1alpha1.Iperf3{}).
		Complete(r)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 cloudprovider

import (
	"time"

	"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
	apiv1 "k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// CloudProvider contains configuration info and functions for interacting with
// cloud provider (GCE, AWS, etc).
type CloudProvider interface {
	// Name returns name of the cloud provider.
	Name() string

	// NodeGroups returns all node groups configured for this cloud provider.
	NodeGroups() []NodeGroup

	// NodeGroupForNode returns the node group for the given node, nil if the node
	// should not be processed by cluster autoscaler, or non-nil error if such
	// occurred.
	NodeGroupForNode(*apiv1.Node) (NodeGroup, error)

	// Pricing returns pricing model for this cloud provider or error if not available.
	Pricing() (PricingModel, errors.AutoscalerError)
}

// ErrNotImplemented is returned if a method is not implemented.
var ErrNotImplemented errors.AutoscalerError = errors.NewAutoscalerError(errors.InternalError, "Not implemented")

// NodeGroup contains configuration info and functions to control a set
// of nodes that have the same capacity and set of labels.
type NodeGroup interface {
	// MaxSize returns maximum size of the node group.
	MaxSize() int

	// MinSize returns minimum size of the node group.
	MinSize() int

	// TargetSize returns the current target size of the node group. It is possible that the
	// number of nodes in Kubernetes is different at the moment but should be equal
	// to Size() once everything stabilizes (new nodes finish startup and registration or
	// removed nodes are deleted completely)
	TargetSize() (int, error)

	// IncreaseSize increases the size of the node group. To delete a node you need
	// to explicitly name it and use DeleteNode. This function should wait until
	// node group size is updated.
	IncreaseSize(delta int) error

	// DeleteNodes deletes nodes from this node group. Error is returned either on
	// failure or if the given node doesn't belong to this node group. This function
	// should wait until node group size is updated.
	DeleteNodes([]*apiv1.Node) error

	// DecreaseTargetSize decreases the target size of the node group. This function
	// doesn't permit to delete any existing node and can be used only to reduce the
	// request for new nodes that have not been yet fulfilled. Delta should be negative.
	// It is assumed that cloud provider will not delete the existing nodes if the size
	// when there is an option to just decrease the target.
	DecreaseTargetSize(delta int) error

	// Id returns an unique identifier of the node group.
	Id() string

	// Debug returns a string containing all information regarding this node group.
	Debug() string

	// Nodes returns a list of all nodes that belong to this node group.
	Nodes() ([]string, error)

	// TemplateNodeInfo returns a schedulercache.NodeInfo structure of an empty
	// (as if just started) node. This will be used in scale-up simulations to
	// predict what would a new node look like if a node group was expanded. The returned
	// NodeInfo is expected to have a fully populated Node object, with all of the labels,
	// capacity and allocatable information as well as all pods that are started on
	// the node by default, using manifest (most likely only kube-proxy).
	TemplateNodeInfo() (*schedulercache.NodeInfo, error)
}

// PricingModel contains information about the node price and how it changes in time.
type PricingModel interface {
	// NodePrice returns a price of running the given node for a given period of time.
	// All prices returned by the structure should be in the same currency.
	NodePrice(node *apiv1.Node, startTime time.Time, endTime time.Time) (float64, error)

	// PodePrice returns a theoretical minimum priece of running a pod for a given
	// period of time on a perfectly matching machine.
	PodPrice(pod *apiv1.Pod, startTime time.Time, endTime time.Time) (float64, error)
}
<commit_msg>Fix comment in cloud_provider.go<commit_after>/*
Copyright 2016 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 cloudprovider

import (
	"time"

	"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
	apiv1 "k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// CloudProvider contains configuration info and functions for interacting with
// cloud provider (GCE, AWS, etc).
type CloudProvider interface {
	// Name returns name of the cloud provider.
	Name() string

	// NodeGroups returns all node groups configured for this cloud provider.
	NodeGroups() []NodeGroup

	// NodeGroupForNode returns the node group for the given node, nil if the node
	// should not be processed by cluster autoscaler, or non-nil error if such
	// occurred.
	NodeGroupForNode(*apiv1.Node) (NodeGroup, error)

	// Pricing returns pricing model for this cloud provider or error if not available.
	Pricing() (PricingModel, errors.AutoscalerError)
}

// ErrNotImplemented is returned if a method is not implemented.
var ErrNotImplemented errors.AutoscalerError = errors.NewAutoscalerError(errors.InternalError, "Not implemented")

// NodeGroup contains configuration info and functions to control a set
// of nodes that have the same capacity and set of labels.
type NodeGroup interface {
	// MaxSize returns maximum size of the node group.
	MaxSize() int

	// MinSize returns minimum size of the node group.
	MinSize() int

	// TargetSize returns the current target size of the node group. It is possible that the
	// number of nodes in Kubernetes is different at the moment but should be equal
	// to Size() once everything stabilizes (new nodes finish startup and registration or
	// removed nodes are deleted completely)
	TargetSize() (int, error)

	// IncreaseSize increases the size of the node group. To delete a node you need
	// to explicitly name it and use DeleteNode. This function should wait until
	// node group size is updated.
	IncreaseSize(delta int) error

	// DeleteNodes deletes nodes from this node group. Error is returned either on
	// failure or if the given node doesn't belong to this node group. This function
	// should wait until node group size is updated.
	DeleteNodes([]*apiv1.Node) error

	// DecreaseTargetSize decreases the target size of the node group. This function
	// doesn't permit to delete any existing node and can be used only to reduce the
	// request for new nodes that have not been yet fulfilled. Delta should be negative.
	// It is assumed that cloud provider will not delete the existing nodes when there
	// is an option to just decrease the target.
	DecreaseTargetSize(delta int) error

	// Id returns an unique identifier of the node group.
	Id() string

	// Debug returns a string containing all information regarding this node group.
	Debug() string

	// Nodes returns a list of all nodes that belong to this node group.
	Nodes() ([]string, error)

	// TemplateNodeInfo returns a schedulercache.NodeInfo structure of an empty
	// (as if just started) node. This will be used in scale-up simulations to
	// predict what would a new node look like if a node group was expanded. The returned
	// NodeInfo is expected to have a fully populated Node object, with all of the labels,
	// capacity and allocatable information as well as all pods that are started on
	// the node by default, using manifest (most likely only kube-proxy).
	TemplateNodeInfo() (*schedulercache.NodeInfo, error)
}

// PricingModel contains information about the node price and how it changes in time.
type PricingModel interface {
	// NodePrice returns a price of running the given node for a given period of time.
	// All prices returned by the structure should be in the same currency.
	NodePrice(node *apiv1.Node, startTime time.Time, endTime time.Time) (float64, error)

	// PodePrice returns a theoretical minimum priece of running a pod for a given
	// period of time on a perfectly matching machine.
	PodPrice(pod *apiv1.Pod, startTime time.Time, endTime time.Time) (float64, error)
}
<|endoftext|>