<commit_before>package controllers

import (
	"net/http"
	"strings"
	"time"

	"fmt"
	"github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
	"github.com/steffen25/golang.zone/app"
	"github.com/steffen25/golang.zone/models"
	"github.com/steffen25/golang.zone/repositories"
	"github.com/steffen25/golang.zone/services"
	"log"
	"strconv"
)

type PostController struct {
	*app.App
	repositories.PostRepository
}

type PostPaginator struct {
	Total        int         `json:"total"`
	PerPage      int         `json:"perPage"`
	CurrentPage  int         `json:"currentPage"`
	LastPage     int         `json:"lastPage"`
	From         int         `json:"from"`
	To           int         `json:"to"`
	FirstPageUrl string      `json:"firstPageUrl"`
	LastPageUrl  string      `json:"lastPageUrl"`
	NextPageUrl  *string     `json:"nextPageUrl"`
	PrevPageUrl  *string     `json:"prevPageUrl"`
	Data         interface{} `json:"data"`
}

func NewPostController(a *app.App, pr repositories.PostRepository) *PostController {
	return &PostController{a, pr}
}

func (pc *PostController) GetAll(w http.ResponseWriter, r *http.Request) {
	total, _ := pc.PostRepository.GetTotalPostCount()
	page := r.URL.Query().Get("page")
	log.Println("page: ", page)
	pageInt, err := strconv.Atoi(page)
	if err != nil {
		pageInt = 1
	}
	perPage := r.URL.Query().Get("perpage")
	log.Println("perpage: ", perPage)
	perPageInt, err := strconv.Atoi(perPage)
	if err != nil || perPageInt < 1 || perPageInt > 100 {
		perPageInt = 10
	}
	offset := (pageInt - 1) * perPageInt
	log.Println("offset: ", offset)
	to := pageInt * perPageInt
	from := offset + 1
	totalPages := (total-1)/perPageInt + 1
	//totalCount := int(float64(total) / float64(perPageInt))
	// $prevPage = ($page + $totalPages - 2) % $totalPages + 1;
	//nextPage := pageInt%totalPages + 1
	//prevPage := (pageInt+totalPages-2)%totalPages + 1
	// $previous_offset = (($currentPage - 1) - 1) * $items_per_page;
	// (currentPage-1 // Should be greater or equal to 0) * limit
	prevPage := pageInt - 1
	log.Println("prevPage: ", prevPage)
	firstPageUrl := fmt.Sprintf(r.URL.Scheme+r.Host+r.URL.Path+"?page=%d", 1)
	lastPageString := fmt.Sprintf(r.URL.Scheme+r.Host+r.URL.Path+"?page=%d", totalPages)
	var prevPageUrl string
	var nextPageUrl string
	if prevPage > 0 && prevPage < totalPages {
		prevPageUrl = fmt.Sprintf(r.URL.Scheme+r.Host+r.URL.Path+"?page=%d", prevPage)
	}
	nextPage := pageInt + 1
	if nextPage <= totalPages {
		nextPageUrl = fmt.Sprintf(r.URL.Scheme+r.Host+r.URL.Path+"?page=%d", nextPage)
	}
	//prevPageString := fmt.Sprintf(r.URL.Path+"?page=%d", prevPage)
	posts, err := pc.PostRepository.Paginate(perPageInt, offset)
	if err != nil {
		NewAPIError(&APIError{false, "Could not fetch posts", http.StatusBadRequest}, w)
		return
	}

	if len(posts) == 0 {
		NewAPIResponse(&APIResponse{Success: false, Message: "Could not find posts", Data: posts}, w, http.StatusNotFound)
		return
	}

	postPaginator := PostPaginator{
		total,
		perPageInt,
		pageInt,
		totalPages,
		from,
		to,
		firstPageUrl,
		lastPageString,
		&nextPageUrl,
		&prevPageUrl,
		posts,
	}

	NewAPIResponse(&APIResponse{Success: true, Data: postPaginator}, w, http.StatusOK)
}

func (pc *PostController) GetById(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}
	post, err := pc.PostRepository.FindById(id)
	if err != nil {
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Data: post}, w, http.StatusOK)
}

func (pc *PostController) GetBySlug(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	slug := vars["slug"]
	post, err := pc.PostRepository.FindBySlug(slug)
	if err != nil {
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Data: post}, w, http.StatusOK)
}

func (pc *PostController) Create(w http.ResponseWriter, r *http.Request) {
	uid, err := services.UserIdFromContext(r.Context())
	if err != nil {
		NewAPIError(&APIError{false, "Something went wrong", http.StatusInternalServerError}, w)
		return
	}

	j, err := GetJSON(r.Body)
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}

	title, err := j.GetString("title")
	if err != nil {
		NewAPIError(&APIError{false, "Title is required", http.StatusBadRequest}, w)
		return
	}

	body, err := j.GetString("body")
	if err != nil {
		NewAPIError(&APIError{false, "Content is required", http.StatusBadRequest}, w)
		return
	}

	post := &models.Post{
		Title:     title,
		Slug:      generateSlug(title),
		Body:      body,
		CreatedAt: time.Now(),
		UserID:    uid,
	}

	err = pc.PostRepository.Create(post)
	if err != nil {
		NewAPIError(&APIError{false, "Could not create post", http.StatusBadRequest}, w)
		return
	}

	defer r.Body.Close()
	NewAPIResponse(&APIResponse{Success: true, Message: "Post created"}, w, http.StatusOK)
}

func (pc *PostController) Update(w http.ResponseWriter, r *http.Request) {
	uid, err := services.UserIdFromContext(r.Context())
	if err != nil {
		NewAPIError(&APIError{false, "Something went wrong", http.StatusInternalServerError}, w)
		return
	}
	vars := mux.Vars(r)
	postId, err := strconv.Atoi(vars["id"])
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}
	post, err := pc.PostRepository.FindById(postId)
	if err != nil {
		// post was not found
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	j, err := GetJSON(r.Body)
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}

	title, err := j.GetString("title")
	if err != nil {
		NewAPIError(&APIError{false, "Title is required", http.StatusBadRequest}, w)
		return
	}

	body, err := j.GetString("body")
	if err != nil {
		NewAPIError(&APIError{false, "Content is required", http.StatusBadRequest}, w)
		return
	}
	if len(strings.Fields(title)) < 2 {
		NewAPIError(&APIError{false, "Title is too short", http.StatusBadRequest}, w)
		return
	}

	if len(strings.Fields(body)) < 5 {
		NewAPIError(&APIError{false, "Body is too short", http.StatusBadRequest}, w)
		return
	}
	post.UserID = uid
	post.UpdatedAt = mysql.NullTime{Time: time.Now(), Valid: true}
	post.Title = title
	post.Body = body
	post.Slug = generateSlug(title)
	err = pc.PostRepository.Update(post)
	if err != nil {
		NewAPIError(&APIError{false, "Could not update post", http.StatusBadRequest}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Message: "Post updated"}, w, http.StatusOK)
}
<commit_msg>Fixed http scheme temp solution<commit_after>package controllers

import (
	"net/http"
	"strings"
	"time"

	"fmt"
	"github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
	"github.com/steffen25/golang.zone/app"
	"github.com/steffen25/golang.zone/models"
	"github.com/steffen25/golang.zone/repositories"
	"github.com/steffen25/golang.zone/services"
	"log"
	"strconv"
)

type PostController struct {
	*app.App
	repositories.PostRepository
}

type PostPaginator struct {
	Total        int         `json:"total"`
	PerPage      int         `json:"perPage"`
	CurrentPage  int         `json:"currentPage"`
	LastPage     int         `json:"lastPage"`
	From         int         `json:"from"`
	To           int         `json:"to"`
	FirstPageUrl string      `json:"firstPageUrl"`
	LastPageUrl  string      `json:"lastPageUrl"`
	NextPageUrl  *string     `json:"nextPageUrl"`
	PrevPageUrl  *string     `json:"prevPageUrl"`
	Data         interface{} `json:"data"`
}

func NewPostController(a *app.App, pr repositories.PostRepository) *PostController {
	return &PostController{a, pr}
}

func (pc *PostController) GetAll(w http.ResponseWriter, r *http.Request) {
	httpScheme := "https://"
	total, _ := pc.PostRepository.GetTotalPostCount()
	page := r.URL.Query().Get("page")
	log.Println("page: ", page)
	pageInt, err := strconv.Atoi(page)
	if err != nil {
		pageInt = 1
	}
	perPage := r.URL.Query().Get("perpage")
	log.Println("perpage: ", perPage)
	perPageInt, err := strconv.Atoi(perPage)
	if err != nil || perPageInt < 1 || perPageInt > 100 {
		perPageInt = 10
	}
	offset := (pageInt - 1) * perPageInt
	log.Println("offset: ", offset)
	to := pageInt * perPageInt
	if to > total {
		to = total
	}
	from := offset + 1
	totalPages := (total-1)/perPageInt + 1
	//totalCount := int(float64(total) / float64(perPageInt))
	// $prevPage = ($page + $totalPages - 2) % $totalPages + 1;
	//nextPage := pageInt%totalPages + 1
	//prevPage := (pageInt+totalPages-2)%totalPages + 1
	// $previous_offset = (($currentPage - 1) - 1) * $items_per_page;
	// (currentPage-1 // Should be greater or equal to 0) * limit
	prevPage := pageInt - 1
	log.Println("prevPage: ", prevPage)
	firstPageUrl := fmt.Sprintf(httpScheme+r.Host+r.URL.Path+"?page=%d", 1)
	lastPageString := fmt.Sprintf(httpScheme+r.Host+r.URL.Path+"?page=%d", totalPages)
	var prevPageUrl string
	var nextPageUrl string
	if prevPage > 0 && prevPage < totalPages {
		prevPageUrl = fmt.Sprintf(httpScheme+r.Host+r.URL.Path+"?page=%d", prevPage)
	}
	nextPage := pageInt + 1
	if nextPage <= totalPages {
		nextPageUrl = fmt.Sprintf(httpScheme+r.Host+r.URL.Path+"?page=%d", nextPage)
	}
	//prevPageString := fmt.Sprintf(r.URL.Path+"?page=%d", prevPage)
	posts, err := pc.PostRepository.Paginate(perPageInt, offset)
	if err != nil {
		NewAPIError(&APIError{false, "Could not fetch posts", http.StatusBadRequest}, w)
		return
	}

	if len(posts) == 0 {
		NewAPIResponse(&APIResponse{Success: false, Message: "Could not find posts", Data: posts}, w, http.StatusNotFound)
		return
	}

	postPaginator := PostPaginator{
		total,
		perPageInt,
		pageInt,
		totalPages,
		from,
		to,
		firstPageUrl,
		lastPageString,
		&nextPageUrl,
		&prevPageUrl,
		posts,
	}

	NewAPIResponse(&APIResponse{Success: true, Data: postPaginator}, w, http.StatusOK)
}

func (pc *PostController) GetById(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}
	post, err := pc.PostRepository.FindById(id)
	if err != nil {
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Data: post}, w, http.StatusOK)
}

func (pc *PostController) GetBySlug(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	slug := vars["slug"]
	post, err := pc.PostRepository.FindBySlug(slug)
	if err != nil {
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Data: post}, w, http.StatusOK)
}

func (pc *PostController) Create(w http.ResponseWriter, r *http.Request) {
	uid, err := services.UserIdFromContext(r.Context())
	if err != nil {
		NewAPIError(&APIError{false, "Something went wrong", http.StatusInternalServerError}, w)
		return
	}

	j, err := GetJSON(r.Body)
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}

	title, err := j.GetString("title")
	if err != nil {
		NewAPIError(&APIError{false, "Title is required", http.StatusBadRequest}, w)
		return
	}

	body, err := j.GetString("body")
	if err != nil {
		NewAPIError(&APIError{false, "Content is required", http.StatusBadRequest}, w)
		return
	}

	post := &models.Post{
		Title:     title,
		Slug:      generateSlug(title),
		Body:      body,
		CreatedAt: time.Now(),
		UserID:    uid,
	}

	err = pc.PostRepository.Create(post)
	if err != nil {
		NewAPIError(&APIError{false, "Could not create post", http.StatusBadRequest}, w)
		return
	}

	defer r.Body.Close()
	NewAPIResponse(&APIResponse{Success: true, Message: "Post created"}, w, http.StatusOK)
}

func (pc *PostController) Update(w http.ResponseWriter, r *http.Request) {
	uid, err := services.UserIdFromContext(r.Context())
	if err != nil {
		NewAPIError(&APIError{false, "Something went wrong", http.StatusInternalServerError}, w)
		return
	}
	vars := mux.Vars(r)
	postId, err := strconv.Atoi(vars["id"])
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}
	post, err := pc.PostRepository.FindById(postId)
	if err != nil {
		// post was not found
		NewAPIError(&APIError{false, "Could not find post", http.StatusNotFound}, w)
		return
	}

	j, err := GetJSON(r.Body)
	if err != nil {
		NewAPIError(&APIError{false, "Invalid request", http.StatusBadRequest}, w)
		return
	}

	title, err := j.GetString("title")
	if err != nil {
		NewAPIError(&APIError{false, "Title is required", http.StatusBadRequest}, w)
		return
	}

	body, err := j.GetString("body")
	if err != nil {
		NewAPIError(&APIError{false, "Content is required", http.StatusBadRequest}, w)
		return
	}
	if len(strings.Fields(title)) < 2 {
		NewAPIError(&APIError{false, "Title is too short", http.StatusBadRequest}, w)
		return
	}

	if len(strings.Fields(body)) < 5 {
		NewAPIError(&APIError{false, "Body is too short", http.StatusBadRequest}, w)
		return
	}
	post.UserID = uid
	post.UpdatedAt = mysql.NullTime{Time: time.Now(), Valid: true}
	post.Title = title
	post.Body = body
	post.Slug = generateSlug(title)
	err = pc.PostRepository.Update(post)
	if err != nil {
		NewAPIError(&APIError{false, "Could not update post", http.StatusBadRequest}, w)
		return
	}

	NewAPIResponse(&APIResponse{Success: true, Message: "Post updated"}, w, http.StatusOK)
}
<|endoftext|>


<commit_before>package logging

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

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

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

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

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

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

<commit_msg>Delete route when deleting logging app<commit_after>package logging

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

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

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

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

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

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

<|endoftext|>


<commit_before>package controllers

import (
	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/types"
	"github.com/lfq7413/tomato/utils"
)

// GlobalConfigController 处理 /config 接口的请求
type GlobalConfigController struct {
	ClassesController
}

// HandleGet 获取配置信息
// @router / [get]
func (g *GlobalConfigController) HandleGet() {
	results, _ := orm.TomatoDBController.Find("_GlobalConfig", types.M{"objectId": "1"}, types.M{"limit": 1})
	if len(results) != 1 {
		g.Data["json"] = types.M{"params": types.M{}}
		g.ServeJSON()
		return
	}
	globalConfig := utils.M(results[0])
	if globalConfig == nil {
		g.Data["json"] = types.M{"params": types.M{}}
		g.ServeJSON()
		return
	}
	g.Data["json"] = types.M{"params": globalConfig["params"]}
	g.ServeJSON()
}

// HandlePut 修改配置信息
// @router / [put]
func (g *GlobalConfigController) HandlePut() {
	if g.EnforceMasterKeyAccess() == false {
		return
	}

	if g.JSONBody == nil || utils.M(g.JSONBody["params"]) == nil {
		g.Data["json"] = types.M{"result": true}
		g.ServeJSON()
		return
	}
	params := utils.M(g.JSONBody["params"])
	update := types.M{}
	for k, v := range params {
		update["params."+k] = v
	}
	_, err := orm.TomatoDBController.Update("_GlobalConfig", types.M{"objectId": "1"}, update, types.M{"upsert": true}, false)
	if err != nil {
		g.HandleError(err, 0)
		return
	}
	g.Data["json"] = types.M{"result": true}
	g.ServeJSON()
}

// Post ...
// @router / [post]
func (g *GlobalConfigController) Post() {
	g.ClassesController.Post()
}

// Delete ...
// @router / [delete]
func (g *GlobalConfigController) Delete() {
	g.ClassesController.Delete()
}
<commit_msg>获取配置信息不再验证权限<commit_after>package controllers

import (
	"strings"

	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/types"
	"github.com/lfq7413/tomato/utils"
)

// GlobalConfigController 处理 /config 接口的请求
type GlobalConfigController struct {
	ClassesController
}

// Prepare ...
func (g *GlobalConfigController) Prepare() {
	if g.Ctx.Input.Method() == "GET" && strings.HasPrefix(g.Ctx.Input.URL(), "/v1/config") {
		return
	}
	g.ClassesController.Prepare()
}

// HandleGet 获取配置信息
// @router / [get]
func (g *GlobalConfigController) HandleGet() {
	results, _ := orm.TomatoDBController.Find("_GlobalConfig", types.M{"objectId": "1"}, types.M{"limit": 1})
	if len(results) != 1 {
		g.Data["json"] = types.M{"params": types.M{}}
		g.ServeJSON()
		return
	}
	globalConfig := utils.M(results[0])
	if globalConfig == nil {
		g.Data["json"] = types.M{"params": types.M{}}
		g.ServeJSON()
		return
	}
	g.Data["json"] = types.M{"params": globalConfig["params"]}
	g.ServeJSON()
}

// HandlePut 修改配置信息
// @router / [put]
func (g *GlobalConfigController) HandlePut() {
	if g.EnforceMasterKeyAccess() == false {
		return
	}

	if g.JSONBody == nil || utils.M(g.JSONBody["params"]) == nil {
		g.Data["json"] = types.M{"result": true}
		g.ServeJSON()
		return
	}
	params := utils.M(g.JSONBody["params"])
	update := types.M{}
	for k, v := range params {
		update["params."+k] = v
	}
	_, err := orm.TomatoDBController.Update("_GlobalConfig", types.M{"objectId": "1"}, update, types.M{"upsert": true}, false)
	if err != nil {
		g.HandleError(err, 0)
		return
	}
	g.Data["json"] = types.M{"result": true}
	g.ServeJSON()
}

// Post ...
// @router / [post]
func (g *GlobalConfigController) Post() {
	g.ClassesController.Post()
}

// Delete ...
// @router / [delete]
func (g *GlobalConfigController) Delete() {
	g.ClassesController.Delete()
}
<|endoftext|>


<commit_before>package aws

import (
	"bytes"
	"fmt"
	"log"
	"sort"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

func resourceAwsSecurityGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSecurityGroupCreate,
		Read:   resourceAwsSecurityGroupRead,
		Update: resourceAwsSecurityGroupUpdate,
		Delete: resourceAwsSecurityGroupDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"ingress": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"from_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"to_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"protocol": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},

						"cidr_blocks": &schema.Schema{
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},

						"security_groups": &schema.Schema{
							Type:     schema.TypeSet,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
							Set: func(v interface{}) int {
								return hashcode.String(v.(string))
							},
						},

						"self": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							Default:  false,
						},
					},
				},
				Set: resourceAwsSecurityGroupRuleHash,
			},

			"egress": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"from_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"to_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"protocol": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},

						"cidr_blocks": &schema.Schema{
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},

						"security_groups": &schema.Schema{
							Type:     schema.TypeSet,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
							Set: func(v interface{}) int {
								return hashcode.String(v.(string))
							},
						},

						"self": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							Default:  false,
						},
					},
				},
				Set: resourceAwsSecurityGroupRuleHash,
			},

			"owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	securityGroupOpts := ec2.SecurityGroup{
		Name: d.Get("name").(string),
	}

	if v := d.Get("vpc_id"); v != nil {
		securityGroupOpts.VpcId = v.(string)
	}

	if v := d.Get("description"); v != nil {
		securityGroupOpts.Description = v.(string)
	}

	log.Printf(
		"[DEBUG] Security Group create configuration: %#v", securityGroupOpts)
	createResp, err := ec2conn.CreateSecurityGroup(securityGroupOpts)
	if err != nil {
		return fmt.Errorf("Error creating Security Group: %s", err)
	}

	d.SetId(createResp.Id)

	log.Printf("[INFO] Security Group ID: %s", d.Id())

	// Wait for the security group to truly exist
	log.Printf(
		"[DEBUG] Waiting for Security Group (%s) to exist",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{""},
		Target:  "exists",
		Refresh: SGStateRefreshFunc(ec2conn, d.Id()),
		Timeout: 1 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for Security Group (%s) to become available: %s",
			d.Id(), err)
	}

	return resourceAwsSecurityGroupUpdate(d, meta)
}

func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if sgRaw == nil {
		d.SetId("")
		return nil
	}

	sg := sgRaw.(*ec2.SecurityGroupInfo)

	ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPerms)
	egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermsEgress)

	d.Set("description", sg.Description)
	d.Set("name", sg.Name)
	d.Set("vpc_id", sg.VpcId)
	d.Set("owner_id", sg.OwnerId)
	d.Set("ingress", ingressRules)
	d.Set("egress", egressRules)
	d.Set("tags", tagsToMap(sg.Tags))

	return nil
}

func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if sgRaw == nil {
		d.SetId("")
		return nil
	}
	group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup

	err = resourceAwsSecurityGroupUpdateRules(d, "ingress", meta, group)
	if err != nil {
		return err
	}

	if d.Get("vpc_id") != nil {
		err = resourceAwsSecurityGroupUpdateRules(d, "egress", meta, group)
		if err != nil {
			return err
		}
	}

	if err := setTags(ec2conn, d); err != nil {
		return err
	}

	d.SetPartial("tags")

	return resourceAwsSecurityGroupRead(d, meta)
}

func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	log.Printf("[DEBUG] Security Group destroy: %v", d.Id())

	return resource.Retry(5*time.Minute, func() error {
		_, err := ec2conn.DeleteSecurityGroup(ec2.SecurityGroup{Id: d.Id()})
		if err != nil {
			ec2err, ok := err.(*ec2.Error)
			if !ok {
				return err
			}

			switch ec2err.Code {
			case "InvalidGroup.NotFound":
				return nil
			case "DependencyViolation":
				// If it is a dependency violation, we want to retry
				return err
			default:
				// Any other error, we want to quit the retry loop immediately
				return resource.RetryError{err}
			}
		}

		return nil
	})
}

func resourceAwsSecurityGroupRuleHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int)))
	buf.WriteString(fmt.Sprintf("%d-", m["to_port"].(int)))
	buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string)))

	// We need to make sure to sort the strings below so that we always
	// generate the same hash code no matter what is in the set.
	if v, ok := m["cidr_blocks"]; ok {
		vs := v.([]interface{})
		s := make([]string, len(vs))
		for i, raw := range vs {
			s[i] = raw.(string)
		}
		sort.Strings(s)

		for _, v := range s {
			buf.WriteString(fmt.Sprintf("%s-", v))
		}
	}
	if v, ok := m["security_groups"]; ok {
		vs := v.(*schema.Set).List()
		s := make([]string, len(vs))
		for i, raw := range vs {
			s[i] = raw.(string)
		}
		sort.Strings(s)

		for _, v := range s {
			buf.WriteString(fmt.Sprintf("%s-", v))
		}
	}

	return hashcode.String(buf.String())
}

func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPerm) []map[string]interface{} {
	ruleMap := make(map[string]map[string]interface{})
	for _, perm := range permissions {
		k := fmt.Sprintf("%s-%d-%d", perm.Protocol, perm.FromPort, perm.ToPort)
		m, ok := ruleMap[k]
		if !ok {
			m = make(map[string]interface{})
			ruleMap[k] = m
		}

		m["from_port"] = perm.FromPort
		m["to_port"] = perm.ToPort
		m["protocol"] = perm.Protocol

		if len(perm.SourceIPs) > 0 {
			raw, ok := m["cidr_blocks"]
			if !ok {
				raw = make([]string, 0, len(perm.SourceIPs))
			}
			list := raw.([]string)

			list = append(list, perm.SourceIPs...)
			m["cidr_blocks"] = list
		}

		var groups []string
		if len(perm.SourceGroups) > 0 {
			groups = flattenSecurityGroups(perm.SourceGroups)
		}
		for i, id := range groups {
			if id == d.Id() {
				groups[i], groups = groups[len(groups)-1], groups[:len(groups)-1]
				m["self"] = true
			}
		}

		if len(groups) > 0 {
			raw, ok := m["security_groups"]
			if !ok {
				raw = make([]string, 0, len(groups))
			}
			list := raw.([]string)

			list = append(list, groups...)
			m["security_groups"] = list
		}
	}
	rules := make([]map[string]interface{}, 0, len(ruleMap))
	for _, m := range ruleMap {
		rules = append(rules, m)
	}

	return rules
}

func resourceAwsSecurityGroupUpdateRules(
	d *schema.ResourceData, ruleset string,
	meta interface{}, group ec2.SecurityGroup) error {
	if d.HasChange(ruleset) {
		o, n := d.GetChange(ruleset)
		if o == nil {
			o = new(schema.Set)
		}
		if n == nil {
			n = new(schema.Set)
		}

		os := o.(*schema.Set)
		ns := n.(*schema.Set)

		remove := expandIPPerms(d.Id(), os.Difference(ns).List())
		add := expandIPPerms(d.Id(), ns.Difference(os).List())

		// TODO: We need to handle partial state better in the in-between
		// in this update.

		// TODO: It'd be nicer to authorize before removing, but then we have
		// to deal with complicated unrolling to get individual CIDR blocks
		// to avoid authorizing already authorized sources. Removing before
		// adding is easier here, and Terraform should be fast enough to
		// not have service issues.

		if len(remove) > 0 || len(add) > 0 {
			ec2conn := meta.(*AWSClient).ec2conn

			if len(remove) > 0 {
				// Revoke the old rules
				revoke := ec2conn.RevokeSecurityGroup
				if ruleset == "egress" {
					revoke = ec2conn.RevokeSecurityGroupEgress
				}
				if _, err := revoke(group, remove); err != nil {
					return fmt.Errorf(
						"Error revoking security group %s rules: %s",
						ruleset, err)
				}
			}

			if len(add) > 0 {
				// Authorize the new rules
				authorize := ec2conn.AuthorizeSecurityGroup
				if ruleset == "egress" {
					authorize = ec2conn.AuthorizeSecurityGroupEgress
				}
				if _, err := authorize(group, add); err != nil {
					return fmt.Errorf(
						"Error authorizing security group %s rules: %s",
						ruleset, err)
				}
			}
		}
	}

	return nil
}

// SGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a security group.
func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		sgs := []ec2.SecurityGroup{ec2.SecurityGroup{Id: id}}
		resp, err := conn.SecurityGroups(sgs, nil)
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok {
				if ec2err.Code == "InvalidSecurityGroupID.NotFound" ||
					ec2err.Code == "InvalidGroup.NotFound" {
					resp = nil
					err = nil
				}
			}

			if err != nil {
				log.Printf("Error on SGStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			return nil, "", nil
		}

		group := &resp.Groups[0]
		return group, "exists", nil
	}
}
<commit_msg>providers/aws: egress should be computed<commit_after>package aws

import (
	"bytes"
	"fmt"
	"log"
	"sort"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/mitchellh/goamz/ec2"
)

func resourceAwsSecurityGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsSecurityGroupCreate,
		Read:   resourceAwsSecurityGroupRead,
		Update: resourceAwsSecurityGroupUpdate,
		Delete: resourceAwsSecurityGroupDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"ingress": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"from_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"to_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"protocol": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},

						"cidr_blocks": &schema.Schema{
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},

						"security_groups": &schema.Schema{
							Type:     schema.TypeSet,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
							Set: func(v interface{}) int {
								return hashcode.String(v.(string))
							},
						},

						"self": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							Default:  false,
						},
					},
				},
				Set: resourceAwsSecurityGroupRuleHash,
			},

			"egress": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"from_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"to_port": &schema.Schema{
							Type:     schema.TypeInt,
							Required: true,
						},

						"protocol": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},

						"cidr_blocks": &schema.Schema{
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},

						"security_groups": &schema.Schema{
							Type:     schema.TypeSet,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
							Set: func(v interface{}) int {
								return hashcode.String(v.(string))
							},
						},

						"self": &schema.Schema{
							Type:     schema.TypeBool,
							Optional: true,
							Default:  false,
						},
					},
				},
				Set: resourceAwsSecurityGroupRuleHash,
			},

			"owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	securityGroupOpts := ec2.SecurityGroup{
		Name: d.Get("name").(string),
	}

	if v := d.Get("vpc_id"); v != nil {
		securityGroupOpts.VpcId = v.(string)
	}

	if v := d.Get("description"); v != nil {
		securityGroupOpts.Description = v.(string)
	}

	log.Printf(
		"[DEBUG] Security Group create configuration: %#v", securityGroupOpts)
	createResp, err := ec2conn.CreateSecurityGroup(securityGroupOpts)
	if err != nil {
		return fmt.Errorf("Error creating Security Group: %s", err)
	}

	d.SetId(createResp.Id)

	log.Printf("[INFO] Security Group ID: %s", d.Id())

	// Wait for the security group to truly exist
	log.Printf(
		"[DEBUG] Waiting for Security Group (%s) to exist",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{""},
		Target:  "exists",
		Refresh: SGStateRefreshFunc(ec2conn, d.Id()),
		Timeout: 1 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for Security Group (%s) to become available: %s",
			d.Id(), err)
	}

	return resourceAwsSecurityGroupUpdate(d, meta)
}

func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if sgRaw == nil {
		d.SetId("")
		return nil
	}

	sg := sgRaw.(*ec2.SecurityGroupInfo)

	ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPerms)
	egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermsEgress)

	d.Set("description", sg.Description)
	d.Set("name", sg.Name)
	d.Set("vpc_id", sg.VpcId)
	d.Set("owner_id", sg.OwnerId)
	d.Set("ingress", ingressRules)
	d.Set("egress", egressRules)
	d.Set("tags", tagsToMap(sg.Tags))

	return nil
}

func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
	if err != nil {
		return err
	}
	if sgRaw == nil {
		d.SetId("")
		return nil
	}
	group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup

	err = resourceAwsSecurityGroupUpdateRules(d, "ingress", meta, group)
	if err != nil {
		return err
	}

	if d.Get("vpc_id") != nil {
		err = resourceAwsSecurityGroupUpdateRules(d, "egress", meta, group)
		if err != nil {
			return err
		}
	}

	if err := setTags(ec2conn, d); err != nil {
		return err
	}

	d.SetPartial("tags")

	return resourceAwsSecurityGroupRead(d, meta)
}

func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2conn

	log.Printf("[DEBUG] Security Group destroy: %v", d.Id())

	return resource.Retry(5*time.Minute, func() error {
		_, err := ec2conn.DeleteSecurityGroup(ec2.SecurityGroup{Id: d.Id()})
		if err != nil {
			ec2err, ok := err.(*ec2.Error)
			if !ok {
				return err
			}

			switch ec2err.Code {
			case "InvalidGroup.NotFound":
				return nil
			case "DependencyViolation":
				// If it is a dependency violation, we want to retry
				return err
			default:
				// Any other error, we want to quit the retry loop immediately
				return resource.RetryError{err}
			}
		}

		return nil
	})
}

func resourceAwsSecurityGroupRuleHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int)))
	buf.WriteString(fmt.Sprintf("%d-", m["to_port"].(int)))
	buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string)))

	// We need to make sure to sort the strings below so that we always
	// generate the same hash code no matter what is in the set.
	if v, ok := m["cidr_blocks"]; ok {
		vs := v.([]interface{})
		s := make([]string, len(vs))
		for i, raw := range vs {
			s[i] = raw.(string)
		}
		sort.Strings(s)

		for _, v := range s {
			buf.WriteString(fmt.Sprintf("%s-", v))
		}
	}
	if v, ok := m["security_groups"]; ok {
		vs := v.(*schema.Set).List()
		s := make([]string, len(vs))
		for i, raw := range vs {
			s[i] = raw.(string)
		}
		sort.Strings(s)

		for _, v := range s {
			buf.WriteString(fmt.Sprintf("%s-", v))
		}
	}

	return hashcode.String(buf.String())
}

func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPerm) []map[string]interface{} {
	ruleMap := make(map[string]map[string]interface{})
	for _, perm := range permissions {
		k := fmt.Sprintf("%s-%d-%d", perm.Protocol, perm.FromPort, perm.ToPort)
		m, ok := ruleMap[k]
		if !ok {
			m = make(map[string]interface{})
			ruleMap[k] = m
		}

		m["from_port"] = perm.FromPort
		m["to_port"] = perm.ToPort
		m["protocol"] = perm.Protocol

		if len(perm.SourceIPs) > 0 {
			raw, ok := m["cidr_blocks"]
			if !ok {
				raw = make([]string, 0, len(perm.SourceIPs))
			}
			list := raw.([]string)

			list = append(list, perm.SourceIPs...)
			m["cidr_blocks"] = list
		}

		var groups []string
		if len(perm.SourceGroups) > 0 {
			groups = flattenSecurityGroups(perm.SourceGroups)
		}
		for i, id := range groups {
			if id == d.Id() {
				groups[i], groups = groups[len(groups)-1], groups[:len(groups)-1]
				m["self"] = true
			}
		}

		if len(groups) > 0 {
			raw, ok := m["security_groups"]
			if !ok {
				raw = make([]string, 0, len(groups))
			}
			list := raw.([]string)

			list = append(list, groups...)
			m["security_groups"] = list
		}
	}
	rules := make([]map[string]interface{}, 0, len(ruleMap))
	for _, m := range ruleMap {
		rules = append(rules, m)
	}

	return rules
}

func resourceAwsSecurityGroupUpdateRules(
	d *schema.ResourceData, ruleset string,
	meta interface{}, group ec2.SecurityGroup) error {
	if d.HasChange(ruleset) {
		o, n := d.GetChange(ruleset)
		if o == nil {
			o = new(schema.Set)
		}
		if n == nil {
			n = new(schema.Set)
		}

		os := o.(*schema.Set)
		ns := n.(*schema.Set)

		remove := expandIPPerms(d.Id(), os.Difference(ns).List())
		add := expandIPPerms(d.Id(), ns.Difference(os).List())

		// TODO: We need to handle partial state better in the in-between
		// in this update.

		// TODO: It'd be nicer to authorize before removing, but then we have
		// to deal with complicated unrolling to get individual CIDR blocks
		// to avoid authorizing already authorized sources. Removing before
		// adding is easier here, and Terraform should be fast enough to
		// not have service issues.

		if len(remove) > 0 || len(add) > 0 {
			ec2conn := meta.(*AWSClient).ec2conn

			if len(remove) > 0 {
				// Revoke the old rules
				revoke := ec2conn.RevokeSecurityGroup
				if ruleset == "egress" {
					revoke = ec2conn.RevokeSecurityGroupEgress
				}

				log.Printf("[DEBUG] Revoking security group %s %s rule: %#v",
					group, ruleset, remove)
				if _, err := revoke(group, remove); err != nil {
					return fmt.Errorf(
						"Error revoking security group %s rules: %s",
						ruleset, err)
				}
			}

			if len(add) > 0 {
				// Authorize the new rules
				authorize := ec2conn.AuthorizeSecurityGroup
				if ruleset == "egress" {
					authorize = ec2conn.AuthorizeSecurityGroupEgress
				}

				log.Printf("[DEBUG] Authorizing security group %s %s rule: %#v",
					group, ruleset, add)
				if _, err := authorize(group, add); err != nil {
					return fmt.Errorf(
						"Error authorizing security group %s rules: %s",
						ruleset, err)
				}
			}
		}
	}

	return nil
}

// SGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a security group.
func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		sgs := []ec2.SecurityGroup{ec2.SecurityGroup{Id: id}}
		resp, err := conn.SecurityGroups(sgs, nil)
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok {
				if ec2err.Code == "InvalidSecurityGroupID.NotFound" ||
					ec2err.Code == "InvalidGroup.NotFound" {
					resp = nil
					err = nil
				}
			}

			if err != nil {
				log.Printf("Error on SGStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			return nil, "", nil
		}

		group := &resp.Groups[0]
		return group, "exists", nil
	}
}
<|endoftext|>


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

package solrmanapi

// TODO: rename 'NodeStatuses'
type SolrCloudStatus map[string]*SolrNodeStatus // keys are hostnames

type SolrNodeStatus struct {
	Hostname string                     // the node's hostname, as determined by gethostbyaddr
	NodeName string                     // the node's identifier within SolrCloud (e.g. "1.1.1.1:8983_solr")
	Cores    map[string]*SolrCoreStatus // keys are core names
	Zone     string                     // cloud zone where host exists
}

type SolrCoreStatus struct {
	Name         string
	NodeName     string // the node's identifier within SolrCloud (e.g. "1.1.1.1:8983_solr")
	Collection   string // collection name (e.g. "1A00E" or "thefullstory.com")
	Shard        string // shard name (e.g. "shard1")
	ShardState   string // e.g. "active", "inactive"
	Range        string // // e.g. "80000000-b332ffff"
	Replica      string // replica name (e.g. "core_node_2")
	ReplicaState string // e.g. "active", "inactive", "recovering", "down"
	IsLeader     bool   // whether this replica is the leader of its shard
	HasStats     bool   // if false, core status could not be queried and following attributes are expected to be -1
	NumDocs      int64  // total number of indexed documents
	IndexSize    int64  // in bytes
	Type         string // e.g. "NRT", "PULL", "TLOG"
}
<commit_msg>Add fields to SolrCoreStatus to support replication issue detection. (#48)<commit_after>// Copyright 2016 FullStory, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package solrmanapi

import "time"

// TODO: rename 'NodeStatuses'
type SolrCloudStatus map[string]*SolrNodeStatus // keys are hostnames

type SolrNodeStatus struct {
	Hostname string                     // the node's hostname, as determined by gethostbyaddr
	NodeName string                     // the node's identifier within SolrCloud (e.g. "1.1.1.1:8983_solr")
	Cores    map[string]*SolrCoreStatus // keys are core names
	Zone     string                     // cloud zone where host exists
}

type SolrCoreStatus struct {
	Name         string
	NodeName     string    // the node's identifier within SolrCloud (e.g. "1.1.1.1:8983_solr")
	Collection   string    // collection name (e.g. "1A00E" or "thefullstory.com")
	Shard        string    // shard name (e.g. "shard1")
	ShardState   string    // e.g. "active", "inactive"
	Range        string    // // e.g. "80000000-b332ffff"
	Replica      string    // replica name (e.g. "core_node_2")
	ReplicaState string    // e.g. "active", "inactive", "recovering", "down"
	IsLeader     bool      // whether this replica is the leader of its shard
	HasStats     bool      // if false, core status could not be queried and following attributes are expected to be -1
	NumDocs      int64     // total number of indexed documents
	IndexSize    int64     // in bytes
	Type         string    // e.g. "NRT", "PULL", "TLOG"
	Version      int64     // Update version of the replica (may be empty)
	LastModified time.Time // Last time the replica was modified (may be empty)
}
<|endoftext|>


<commit_before>/*
Package lmdb provides bindings to the lmdb C API.  The package bindings are
fairly low level and are designed to provide a minimal interface that prevents
misuse to a reasonable extent.  When in doubt refer to the C documentation as a
reference.

	http://symas.com/mdb/doc/group__mdb.html

Environment

An LMDB environment holds named databases (key-value stores).  An environment
is represented as one file on the filesystem (though often a corresponding lock
file exists).

LMDB recommends setting an environment's size as large as possible at the time
of creation.  On filesystems that support sparse files this should not
adversely affect disk usage.  Resizing an environment is possible but must be
handled with care when concurrent access is involved.

Databases

A database in an LMDB environment is an ordered key-value store that holds
arbitrary binary data.  Typically the keys are unique but duplicate keys may be
allowed (DupSort), in which case the values for each duplicate key are ordered.

A single LMDB environment can have multiple named databases.  But there is also
a 'root' (unnamed) database that can be used to store data.  Use caution
storing data in the root database when named databases are in use.  The root
database serves as an index for named databases.

A database is referenced by an opaque handle known as its DBI which must be
opened inside a transaction with the OpenDBI or OpenRoot methods.  DBIs may be
closed but it is not required.  Typically, applications aquire handles for all
their databases immediately after opening an environment and retain them for
the lifetime of the process.

Transactions

View (readonly) transactions in LMDB operate on a snapshot of the database at
the time the transaction began.  The number of simultaneously active view
transactions is bounded and configured when the environment is initialized.

Update (read-write) transactions are serialized in LMDB.  Attempts to create
update transactions block until a lock may be obtained.  Update transactions
can create subtransactions which may be rolled back independently from their
parent.

The lmdb package supplies managed and unmanaged transactions. Managed
transactions do not require explicit calling of Abort/Commit and are provided
through the Env methods Update, View, and RunTxn.  The BeginTxn method on Env
creates an unmanaged transaction but its use is not advised in most
applications.
*/
package lmdb

/*
#cgo CFLAGS: -pthread -W -Wall -Wno-unused-parameter -Wno-format-extra-args -Wbad-function-cast -O2 -g
#cgo freebsd CFLAGS: -DMDB_DSYNC=O_SYNC
#cgo openbsd CFLAGS: -DMDB_DSYNC=O_SYNC
#cgo netbsd CFLAGS: -DMDB_DSYNC=O_SYNC

#include "lmdb.h"
*/
import "C"

// Version return the major, minor, and patch version numbers of the LMDB C
// library and a string representation of the version.
//
// See mdb_version.
func Version() (major, minor, patch int, s string) {
	var maj, min, pat C.int
	verstr := C.mdb_version(&maj, &min, &pat)
	return int(maj), int(min), int(pat), C.GoString(verstr)
}

// VersionString returns a string representation of the LMDB C library version.
//
// See mdb_version.
func VersionString() string {
	var maj, min, pat C.int
	verstr := C.mdb_version(&maj, &min, &pat)
	return C.GoString(verstr)
}

func cbool(b bool) C.int {
	if b {
		return 1
	}
	return 0
}
<commit_msg>lmdb: remove bsd specific build tags (fixed upstream with ITS#7209)<commit_after>/*
Package lmdb provides bindings to the lmdb C API.  The package bindings are
fairly low level and are designed to provide a minimal interface that prevents
misuse to a reasonable extent.  When in doubt refer to the C documentation as a
reference.

	http://symas.com/mdb/doc/group__mdb.html

Environment

An LMDB environment holds named databases (key-value stores).  An environment
is represented as one file on the filesystem (though often a corresponding lock
file exists).

LMDB recommends setting an environment's size as large as possible at the time
of creation.  On filesystems that support sparse files this should not
adversely affect disk usage.  Resizing an environment is possible but must be
handled with care when concurrent access is involved.

Databases

A database in an LMDB environment is an ordered key-value store that holds
arbitrary binary data.  Typically the keys are unique but duplicate keys may be
allowed (DupSort), in which case the values for each duplicate key are ordered.

A single LMDB environment can have multiple named databases.  But there is also
a 'root' (unnamed) database that can be used to store data.  Use caution
storing data in the root database when named databases are in use.  The root
database serves as an index for named databases.

A database is referenced by an opaque handle known as its DBI which must be
opened inside a transaction with the OpenDBI or OpenRoot methods.  DBIs may be
closed but it is not required.  Typically, applications aquire handles for all
their databases immediately after opening an environment and retain them for
the lifetime of the process.

Transactions

View (readonly) transactions in LMDB operate on a snapshot of the database at
the time the transaction began.  The number of simultaneously active view
transactions is bounded and configured when the environment is initialized.

Update (read-write) transactions are serialized in LMDB.  Attempts to create
update transactions block until a lock may be obtained.  Update transactions
can create subtransactions which may be rolled back independently from their
parent.

The lmdb package supplies managed and unmanaged transactions. Managed
transactions do not require explicit calling of Abort/Commit and are provided
through the Env methods Update, View, and RunTxn.  The BeginTxn method on Env
creates an unmanaged transaction but its use is not advised in most
applications.
*/
package lmdb

/*
#cgo CFLAGS: -pthread -W -Wall -Wno-unused-parameter -Wno-format-extra-args -Wbad-function-cast -O2 -g

#include "lmdb.h"
*/
import "C"

// Version return the major, minor, and patch version numbers of the LMDB C
// library and a string representation of the version.
//
// See mdb_version.
func Version() (major, minor, patch int, s string) {
	var maj, min, pat C.int
	verstr := C.mdb_version(&maj, &min, &pat)
	return int(maj), int(min), int(pat), C.GoString(verstr)
}

// VersionString returns a string representation of the LMDB C library version.
//
// See mdb_version.
func VersionString() string {
	var maj, min, pat C.int
	verstr := C.mdb_version(&maj, &min, &pat)
	return C.GoString(verstr)
}

func cbool(b bool) C.int {
	if b {
		return 1
	}
	return 0
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package addons

const (
	KubeProxyConfigMap = `
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-proxy
  namespace: kube-system
  labels:
    app: kube-proxy
data:
  kubeconfig.conf: |
    apiVersion: v1
    kind: Config
    clusters:
    - cluster:
        certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        server: {{ .MasterEndpoint }}
      name: default
    contexts:
    - context:
        cluster: default
        namespace: default
        user: default
      name: default
    current-context: default
    users:
    - name: default
      user:
        tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
`

	KubeProxyDaemonSet = `
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  labels:
    k8s-app: kube-proxy
  name: kube-proxy
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: kube-proxy
  template:
    metadata:
      labels:
        k8s-app: kube-proxy
      annotations:
        # TODO: Move this to the beta tolerations field below as soon as the Tolerations field exists in PodSpec
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"dedicated","value":"master","effect":"NoSchedule"}]'
    spec:
      containers:
      - name: kube-proxy
        image: {{ .Image }}
        imagePullPolicy: IfNotPresent
        command:
        - /usr/local/bin/kube-proxy
        - --kubeconfig=/var/lib/kube-proxy/kubeconfig.conf
        {{ .ClusterCIDR }}
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /var/lib/kube-proxy
          name: kube-proxy
      hostNetwork: true
      serviceAccountName: kube-proxy
      # Tolerate running on the master
      # tolerations:
      # - key: dedicated
      #   value: master
      #   effect: NoSchedule
      volumes:
      - name: kube-proxy
        configMap:
          name: kube-proxy
`

	KubeDNSVersion = "1.13.0"

	KubeDNSDeployment = `

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
spec:
  # replicas: not specified here:
  # 1. In order to make Addon Manager do not reconcile this replicas parameter.
  # 2. Default is 1.
  # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 0
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        # TODO: Move this to the beta tolerations field below as soon as the Tolerations field exists in PodSpec
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}, {"key":"dedicated","value":"master","effect":"NoSchedule"}]'
    spec:
      volumes:
      - name: kube-dns-config
        configMap:
          name: kube-dns
          optional: true
      containers:
      - name: kubedns
        image: {{ .ImageRepository }}/k8s-dns-kube-dns-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthcheck/kubedns
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        - --domain={{ .DNSDomain }}.
        - --dns-port=10053
        - --config-dir=/kube-dns-config
        - --v=2
        # Do we need to set __PILLAR__FEDERATIONS__DOMAIN__MAP__ here?
        env:
        - name: PROMETHEUS_PORT
          value: "10055"
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
        - containerPort: 10055
          name: metrics
          protocol: TCP
        volumeMounts:
        - name: kube-dns-config
          mountPath: /kube-dns-config
      - name: dnsmasq
        image: {{ .ImageRepository }}/k8s-dns-dnsmasq-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /healthcheck/dnsmasq
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=/{{ .DNSDomain }}/127.0.0.1#10053
        - --server=/in-addr.arpa/127.0.0.1#10053
        - --server=/ip6.arpa/127.0.0.1#10053
        - --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
        resources:
          requests:
            cpu: 150m
            memory: 10Mi
      - name: sidecar
        image: {{ .ImageRepository }}/k8s-dns-sidecar-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /metrics
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --v=2
        - --logtostderr
        - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.{{ .DNSDomain }},5,A
        - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.{{ .DNSDomain }},5,A
        ports:
        - containerPort: 10054
          name: metrics
          protocol: TCP
        resources:
          requests:
            memory: 20Mi
            cpu: 10m
      dnsPolicy: Default  # Don't use cluster DNS.
      serviceAccountName: kube-dns
      # tolerations:
      # - key: dedicated
      #   value: master
      #   effect: NoSchedule
      # TODO: Remove this affinity field as soon as we are using manifest lists
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: beta.kubernetes.io/arch
                operator: In
                values:
                - {{ .Arch }}
`

	KubeDNSService = `
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
  name: kube-dns
  namespace: kube-system
spec:
  clusterIP: {{ .DNSIP }}
  ports:
  - name: dns
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53
  selector:
    k8s-app: kube-dns
`
)
<commit_msg>-no-resolv will make upstream DNS unreachable<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package addons

const (
	KubeProxyConfigMap = `
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-proxy
  namespace: kube-system
  labels:
    app: kube-proxy
data:
  kubeconfig.conf: |
    apiVersion: v1
    kind: Config
    clusters:
    - cluster:
        certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        server: {{ .MasterEndpoint }}
      name: default
    contexts:
    - context:
        cluster: default
        namespace: default
        user: default
      name: default
    current-context: default
    users:
    - name: default
      user:
        tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
`

	KubeProxyDaemonSet = `
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  labels:
    k8s-app: kube-proxy
  name: kube-proxy
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: kube-proxy
  template:
    metadata:
      labels:
        k8s-app: kube-proxy
      annotations:
        # TODO: Move this to the beta tolerations field below as soon as the Tolerations field exists in PodSpec
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"dedicated","value":"master","effect":"NoSchedule"}]'
    spec:
      containers:
      - name: kube-proxy
        image: {{ .Image }}
        imagePullPolicy: IfNotPresent
        command:
        - /usr/local/bin/kube-proxy
        - --kubeconfig=/var/lib/kube-proxy/kubeconfig.conf
        {{ .ClusterCIDR }}
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /var/lib/kube-proxy
          name: kube-proxy
      hostNetwork: true
      serviceAccountName: kube-proxy
      # Tolerate running on the master
      # tolerations:
      # - key: dedicated
      #   value: master
      #   effect: NoSchedule
      volumes:
      - name: kube-proxy
        configMap:
          name: kube-proxy
`

	KubeDNSVersion = "1.13.0"

	KubeDNSDeployment = `

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
spec:
  # replicas: not specified here:
  # 1. In order to make Addon Manager do not reconcile this replicas parameter.
  # 2. Default is 1.
  # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 0
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        # TODO: Move this to the beta tolerations field below as soon as the Tolerations field exists in PodSpec
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}, {"key":"dedicated","value":"master","effect":"NoSchedule"}]'
    spec:
      volumes:
      - name: kube-dns-config
        configMap:
          name: kube-dns
          optional: true
      containers:
      - name: kubedns
        image: {{ .ImageRepository }}/k8s-dns-kube-dns-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthcheck/kubedns
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        - --domain={{ .DNSDomain }}.
        - --dns-port=10053
        - --config-dir=/kube-dns-config
        - --v=2
        # Do we need to set __PILLAR__FEDERATIONS__DOMAIN__MAP__ here?
        env:
        - name: PROMETHEUS_PORT
          value: "10055"
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
        - containerPort: 10055
          name: metrics
          protocol: TCP
        volumeMounts:
        - name: kube-dns-config
          mountPath: /kube-dns-config
      - name: dnsmasq
        image: {{ .ImageRepository }}/k8s-dns-dnsmasq-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /healthcheck/dnsmasq
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --server=/{{ .DNSDomain }}/127.0.0.1#10053
        - --server=/in-addr.arpa/127.0.0.1#10053
        - --server=/ip6.arpa/127.0.0.1#10053
        - --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
        resources:
          requests:
            cpu: 150m
            memory: 10Mi
      - name: sidecar
        image: {{ .ImageRepository }}/k8s-dns-sidecar-{{ .Arch }}:{{ .Version }}
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /metrics
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --v=2
        - --logtostderr
        - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.{{ .DNSDomain }},5,A
        - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.{{ .DNSDomain }},5,A
        ports:
        - containerPort: 10054
          name: metrics
          protocol: TCP
        resources:
          requests:
            memory: 20Mi
            cpu: 10m
      dnsPolicy: Default  # Don't use cluster DNS.
      serviceAccountName: kube-dns
      # tolerations:
      # - key: dedicated
      #   value: master
      #   effect: NoSchedule
      # TODO: Remove this affinity field as soon as we are using manifest lists
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: beta.kubernetes.io/arch
                operator: In
                values:
                - {{ .Arch }}
`

	KubeDNSService = `
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
  name: kube-dns
  namespace: kube-system
spec:
  clusterIP: {{ .DNSIP }}
  ports:
  - name: dns
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53
  selector:
    k8s-app: kube-dns
`
)
<|endoftext|>


<commit_before>// Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package peer

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/ava-labs/avalanchego/message"
	"github.com/ava-labs/avalanchego/utils/logging"
)

func TestBlockingMessageQueue(t *testing.T) {
	require := require.New(t)

	q := NewBlockingMessageQueue(
		SendFailedFunc(func(msg message.OutboundMessage) {
			t.Fail()
		}),
		logging.NoLog{},
		0,
	)

	mc := newMessageCreator(t)
	msg, err := mc.Ping()
	require.NoError(err)

	numToSend := 10
	go func() {
		for i := 0; i < numToSend; i++ {
			q.Push(context.Background(), msg)
		}
	}()

	for i := 0; i < numToSend; i++ {
		_, ok := q.Pop()
		require.True(ok)
	}

	_, ok := q.PopNow()
	require.False(ok)

	q.Close()

	_, ok = q.Pop()
	require.False(ok)
}
<commit_msg>Improve message queue tests (#2220)<commit_after>// Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package peer

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/ava-labs/avalanchego/message"
	"github.com/ava-labs/avalanchego/utils/logging"
)

func TestMessageQueue(t *testing.T) {
	require := require.New(t)

	expectFail := false
	q := NewBlockingMessageQueue(
		SendFailedFunc(func(msg message.OutboundMessage) {
			require.True(expectFail)
		}),
		logging.NoLog{},
		0,
	)

	mc := newMessageCreator(t)
	msgs := []message.OutboundMessage{}
	numToSend := 10

	// Assert that the messages are popped in the same order they were pushed
	for i := 0; i < numToSend; i++ {
		m, err := mc.Pong(uint8(i))
		require.NoError(err)
		msgs = append(msgs, m)
	}

	go func() {
		for i := 0; i < numToSend; i++ {
			q.Push(context.Background(), msgs[i])
		}
	}()

	for i := 0; i < numToSend; i++ {
		msg, ok := q.Pop()
		require.True(ok)
		require.Equal(msgs[i], msg)
	}

	// Assert that PopNow returns false when the queue is empty
	_, ok := q.PopNow()
	require.False(ok)

	// Assert that Push returns false when the context is canceled
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	expectFail = true
	done := make(chan struct{})
	go func() {
		ok := q.Push(ctx, msgs[0])
		require.False(ok)
		close(done)
	}()
	<-done

	// Assert that Push returns false when the queue is closed
	done = make(chan struct{})
	go func() {
		ok := q.Push(context.Background(), msgs[0])
		require.False(ok)
		close(done)
	}()
	q.Close()
	<-done

	// Assert Pop returns false when the queue is closed
	_, ok = q.Pop()
	require.False(ok)
}
<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

// Package mocks offers dedicated mocking interface / structures for testing
package mocks

import (
	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/dutycycle"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// NOTE: All the code below could be generated

// AppClient mocks the core.AppClient interface
type AppClient struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx  context.Context
		Req  *core.DataAppReq
		Opts []grpc.CallOption
	}
	OutHandleData struct {
		Res *core.DataAppRes
	}
}

// NewAppClient creates a new mock AppClient
func NewAppClient() *AppClient {
	return &AppClient{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.AppClient interface
func (m *AppClient) HandleData(ctx context.Context, in *core.DataAppReq, opts ...grpc.CallOption) (*core.DataAppRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	m.InHandleData.Opts = opts
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// HandlerClient mocks the core.HandlerClient interface
type HandlerClient struct {
	Failures       map[string]error
	InHandleDataUp struct {
		Ctx  context.Context
		Req  *core.DataUpHandlerReq
		Opts []grpc.CallOption
	}
	OutHandleDataUp struct {
		Res *core.DataUpHandlerRes
	}
	InHandleDataDown struct {
		Ctx  context.Context
		Req  *core.DataDownHandlerReq
		Opts []grpc.CallOption
	}
	OutHandleDataDown struct {
		Res *core.DataDownHandlerRes
	}
	InSubscribePersonalized struct {
		Ctx  context.Context
		Req  *core.ABPSubHandlerReq
		Opts []grpc.CallOption
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubHandlerRes
	}
}

// NewHandlerClient creates a new mock HandlerClient
func NewHandlerClient() *HandlerClient {
	return &HandlerClient{
		Failures: make(map[string]error),
	}
}

// HandleDataUp implements the core.HandlerClient interface
func (m *HandlerClient) HandleDataUp(ctx context.Context, in *core.DataUpHandlerReq, opts ...grpc.CallOption) (*core.DataUpHandlerRes, error) {
	m.InHandleDataUp.Ctx = ctx
	m.InHandleDataUp.Req = in
	m.InHandleDataUp.Opts = opts
	return m.OutHandleDataUp.Res, m.Failures["HandleDataUp"]
}

// HandleDataDown implements the core.HandlerClient interface
func (m *HandlerClient) HandleDataDown(ctx context.Context, in *core.DataDownHandlerReq, opts ...grpc.CallOption) (*core.DataDownHandlerRes, error) {
	m.InHandleDataDown.Ctx = ctx
	m.InHandleDataDown.Req = in
	m.InHandleDataDown.Opts = opts
	return m.OutHandleDataDown.Res, m.Failures["HandleDataDown"]
}

// SubscribePersonalized implements the core.HandlerClient interface
func (m *HandlerClient) SubscribePersonalized(ctx context.Context, in *core.ABPSubHandlerReq, opts ...grpc.CallOption) (*core.ABPSubHandlerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	m.InSubscribePersonalized.Opts = opts
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}

// BrokerClient mocks the core.BrokerClient interface
type BrokerClient struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx  context.Context
		Req  *core.DataBrokerReq
		Opts []grpc.CallOption
	}
	OutHandleData struct {
		Res *core.DataBrokerRes
	}
	InSubscribePersonalized struct {
		Ctx  context.Context
		Req  *core.ABPSubBrokerReq
		Opts []grpc.CallOption
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubBrokerRes
	}
}

// NewBrokerClient creates a new mock BrokerClient
func NewBrokerClient() *BrokerClient {
	return &BrokerClient{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.BrokerClient interface
func (m *BrokerClient) HandleData(ctx context.Context, in *core.DataBrokerReq, opts ...grpc.CallOption) (*core.DataBrokerRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	m.InHandleData.Opts = opts
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// SubscribePersonalized implements the core.BrokerClient interface
func (m *BrokerClient) SubscribePersonalized(ctx context.Context, in *core.ABPSubBrokerReq, opts ...grpc.CallOption) (*core.ABPSubBrokerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	m.InSubscribePersonalized.Opts = opts
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}

// RouterServer mocks the core.RouterServer interface
type RouterServer struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx context.Context
		Req *core.DataRouterReq
	}
	OutHandleData struct {
		Res *core.DataRouterRes
	}
	InHandleStats struct {
		Ctx context.Context
		Req *core.StatsReq
	}
	OutHandleStats struct {
		Res *core.StatsRes
	}
}

// NewRouterServer creates a new mock RouterServer
func NewRouterServer() *RouterServer {
	return &RouterServer{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.RouterServer interface
func (m *RouterServer) HandleData(ctx context.Context, in *core.DataRouterReq) (*core.DataRouterRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// HandleStats implements the core.RouterServer interface
func (m *RouterServer) HandleStats(ctx context.Context, in *core.StatsReq) (*core.StatsRes, error) {
	m.InHandleStats.Ctx = ctx
	m.InHandleStats.Req = in
	return m.OutHandleStats.Res, m.Failures["HandleStats"]
}

// DutyManager mocks the dutycycle.DutyManager interface
type DutyManager struct {
	Failures map[string]error
	InUpdate struct {
		ID   []byte
		Freq float32
		Size uint32
		Datr string
		Codr string
	}
	InLookup struct {
		ID []byte
	}
	OutLookup struct {
		Cycles dutycycle.Cycles
	}
	InClose struct {
		Called bool
	}
}

// NewDutyManager creates a new mock DutyManager
func NewDutyManager() *DutyManager {
	return &DutyManager{
		Failures: make(map[string]error),
	}
}

// Update implements the dutycycle.DutyManager interface
func (m *DutyManager) Update(id []byte, freq float32, size uint32, datr string, codr string) error {
	m.InUpdate.ID = id
	m.InUpdate.Freq = freq
	m.InUpdate.Size = size
	m.InUpdate.Datr = datr
	m.InUpdate.Codr = codr
	return m.Failures["Update"]
}

// Lookup implements the dutycycle.DutyManager interface
func (m *DutyManager) Lookup(id []byte) (dutycycle.Cycles, error) {
	m.InLookup.ID = id
	return m.OutLookup.Cycles, m.Failures["Lookup"]
}

// Close implements the dutycycle.DutyManager interface
func (m *DutyManager) Close() error {
	m.InClose.Called = true
	return m.Failures["Close"]
}

// HandlerServer mocks the core.HandlerServer interface
type HandlerServer struct {
	Failures       map[string]error
	InHandleDataUp struct {
		Ctx context.Context
		Req *core.DataUpHandlerReq
	}
	OutHandleDataUp struct {
		Res *core.DataUpHandlerRes
	}
	InHandleDataDown struct {
		Ctx context.Context
		Req *core.DataDownHandlerReq
	}
	OutHandleDataDown struct {
		Res *core.DataDownHandlerRes
	}
	InSubscribePersonalized struct {
		Ctx context.Context
		Req *core.ABPSubHandlerReq
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubHandlerRes
	}
}

// NewHandlerServer creates a new mock HandlerServer
func NewHandlerServer() *HandlerServer {
	return &HandlerServer{
		Failures: make(map[string]error),
	}
}

// HandleDataUp implements the core.HandlerServer interface
func (m *HandlerServer) HandleDataUp(ctx context.Context, in *core.DataUpHandlerReq) (*core.DataUpHandlerRes, error) {
	m.InHandleDataUp.Ctx = ctx
	m.InHandleDataUp.Req = in
	return m.OutHandleDataUp.Res, m.Failures["HandleDataUp"]
}

// HandleDataDown implements the core.HandlerServer interface
func (m *HandlerServer) HandleDataDown(ctx context.Context, in *core.DataDownHandlerReq) (*core.DataDownHandlerRes, error) {
	m.InHandleDataDown.Ctx = ctx
	m.InHandleDataDown.Req = in
	return m.OutHandleDataDown.Res, m.Failures["HandleDataDown"]
}

// SubscribePersonalized implements the core.HandlerServer interface
func (m *HandlerServer) SubscribePersonalized(ctx context.Context, in *core.ABPSubHandlerReq) (*core.ABPSubHandlerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}
<commit_msg>[feature/otaa] Add HandleJoin to mock routerserver<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

// Package mocks offers dedicated mocking interface / structures for testing
package mocks

import (
	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/dutycycle"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// NOTE: All the code below could be generated

// AppClient mocks the core.AppClient interface
type AppClient struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx  context.Context
		Req  *core.DataAppReq
		Opts []grpc.CallOption
	}
	OutHandleData struct {
		Res *core.DataAppRes
	}
}

// NewAppClient creates a new mock AppClient
func NewAppClient() *AppClient {
	return &AppClient{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.AppClient interface
func (m *AppClient) HandleData(ctx context.Context, in *core.DataAppReq, opts ...grpc.CallOption) (*core.DataAppRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	m.InHandleData.Opts = opts
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// HandlerClient mocks the core.HandlerClient interface
type HandlerClient struct {
	Failures       map[string]error
	InHandleDataUp struct {
		Ctx  context.Context
		Req  *core.DataUpHandlerReq
		Opts []grpc.CallOption
	}
	OutHandleDataUp struct {
		Res *core.DataUpHandlerRes
	}
	InHandleDataDown struct {
		Ctx  context.Context
		Req  *core.DataDownHandlerReq
		Opts []grpc.CallOption
	}
	OutHandleDataDown struct {
		Res *core.DataDownHandlerRes
	}
	InSubscribePersonalized struct {
		Ctx  context.Context
		Req  *core.ABPSubHandlerReq
		Opts []grpc.CallOption
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubHandlerRes
	}
}

// NewHandlerClient creates a new mock HandlerClient
func NewHandlerClient() *HandlerClient {
	return &HandlerClient{
		Failures: make(map[string]error),
	}
}

// HandleDataUp implements the core.HandlerClient interface
func (m *HandlerClient) HandleDataUp(ctx context.Context, in *core.DataUpHandlerReq, opts ...grpc.CallOption) (*core.DataUpHandlerRes, error) {
	m.InHandleDataUp.Ctx = ctx
	m.InHandleDataUp.Req = in
	m.InHandleDataUp.Opts = opts
	return m.OutHandleDataUp.Res, m.Failures["HandleDataUp"]
}

// HandleDataDown implements the core.HandlerClient interface
func (m *HandlerClient) HandleDataDown(ctx context.Context, in *core.DataDownHandlerReq, opts ...grpc.CallOption) (*core.DataDownHandlerRes, error) {
	m.InHandleDataDown.Ctx = ctx
	m.InHandleDataDown.Req = in
	m.InHandleDataDown.Opts = opts
	return m.OutHandleDataDown.Res, m.Failures["HandleDataDown"]
}

// SubscribePersonalized implements the core.HandlerClient interface
func (m *HandlerClient) SubscribePersonalized(ctx context.Context, in *core.ABPSubHandlerReq, opts ...grpc.CallOption) (*core.ABPSubHandlerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	m.InSubscribePersonalized.Opts = opts
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}

// BrokerClient mocks the core.BrokerClient interface
type BrokerClient struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx  context.Context
		Req  *core.DataBrokerReq
		Opts []grpc.CallOption
	}
	OutHandleData struct {
		Res *core.DataBrokerRes
	}
	InSubscribePersonalized struct {
		Ctx  context.Context
		Req  *core.ABPSubBrokerReq
		Opts []grpc.CallOption
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubBrokerRes
	}
}

// NewBrokerClient creates a new mock BrokerClient
func NewBrokerClient() *BrokerClient {
	return &BrokerClient{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.BrokerClient interface
func (m *BrokerClient) HandleData(ctx context.Context, in *core.DataBrokerReq, opts ...grpc.CallOption) (*core.DataBrokerRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	m.InHandleData.Opts = opts
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// SubscribePersonalized implements the core.BrokerClient interface
func (m *BrokerClient) SubscribePersonalized(ctx context.Context, in *core.ABPSubBrokerReq, opts ...grpc.CallOption) (*core.ABPSubBrokerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	m.InSubscribePersonalized.Opts = opts
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}

// RouterServer mocks the core.RouterServer interface
type RouterServer struct {
	Failures     map[string]error
	InHandleData struct {
		Ctx context.Context
		Req *core.DataRouterReq
	}
	OutHandleData struct {
		Res *core.DataRouterRes
	}
	InHandleStats struct {
		Ctx context.Context
		Req *core.StatsReq
	}
	OutHandleStats struct {
		Res *core.StatsRes
	}
	InHandleJoin struct {
		Ctx context.Context
		Req *core.JoinRouterReq
	}
	OutHandleJoin struct {
		Res *core.JoinRouterRes
	}
}

// NewRouterServer creates a new mock RouterServer
func NewRouterServer() *RouterServer {
	return &RouterServer{
		Failures: make(map[string]error),
	}
}

// HandleData implements the core.RouterServer interface
func (m *RouterServer) HandleData(ctx context.Context, in *core.DataRouterReq) (*core.DataRouterRes, error) {
	m.InHandleData.Ctx = ctx
	m.InHandleData.Req = in
	return m.OutHandleData.Res, m.Failures["HandleData"]
}

// HandleStats implements the core.RouterServer interface
func (m *RouterServer) HandleStats(ctx context.Context, in *core.StatsReq) (*core.StatsRes, error) {
	m.InHandleStats.Ctx = ctx
	m.InHandleStats.Req = in
	return m.OutHandleStats.Res, m.Failures["HandleStats"]
}

// HandleJoin implements the core.RouterServer interface
func (m *RouterServer) HandleJoin(ctx context.Context, in *core.JoinRouterReq) (*core.JoinRouterRes, error) {
	m.InHandleJoin.Ctx = ctx
	m.InHandleJoin.Req = in
	return m.OutHandleJoin.Res, m.Failures["HandleJoin"]
}

// DutyManager mocks the dutycycle.DutyManager interface
type DutyManager struct {
	Failures map[string]error
	InUpdate struct {
		ID   []byte
		Freq float32
		Size uint32
		Datr string
		Codr string
	}
	InLookup struct {
		ID []byte
	}
	OutLookup struct {
		Cycles dutycycle.Cycles
	}
	InClose struct {
		Called bool
	}
}

// NewDutyManager creates a new mock DutyManager
func NewDutyManager() *DutyManager {
	return &DutyManager{
		Failures: make(map[string]error),
	}
}

// Update implements the dutycycle.DutyManager interface
func (m *DutyManager) Update(id []byte, freq float32, size uint32, datr string, codr string) error {
	m.InUpdate.ID = id
	m.InUpdate.Freq = freq
	m.InUpdate.Size = size
	m.InUpdate.Datr = datr
	m.InUpdate.Codr = codr
	return m.Failures["Update"]
}

// Lookup implements the dutycycle.DutyManager interface
func (m *DutyManager) Lookup(id []byte) (dutycycle.Cycles, error) {
	m.InLookup.ID = id
	return m.OutLookup.Cycles, m.Failures["Lookup"]
}

// Close implements the dutycycle.DutyManager interface
func (m *DutyManager) Close() error {
	m.InClose.Called = true
	return m.Failures["Close"]
}

// HandlerServer mocks the core.HandlerServer interface
type HandlerServer struct {
	Failures       map[string]error
	InHandleDataUp struct {
		Ctx context.Context
		Req *core.DataUpHandlerReq
	}
	OutHandleDataUp struct {
		Res *core.DataUpHandlerRes
	}
	InHandleDataDown struct {
		Ctx context.Context
		Req *core.DataDownHandlerReq
	}
	OutHandleDataDown struct {
		Res *core.DataDownHandlerRes
	}
	InSubscribePersonalized struct {
		Ctx context.Context
		Req *core.ABPSubHandlerReq
	}
	OutSubscribePersonalized struct {
		Res *core.ABPSubHandlerRes
	}
}

// NewHandlerServer creates a new mock HandlerServer
func NewHandlerServer() *HandlerServer {
	return &HandlerServer{
		Failures: make(map[string]error),
	}
}

// HandleDataUp implements the core.HandlerServer interface
func (m *HandlerServer) HandleDataUp(ctx context.Context, in *core.DataUpHandlerReq) (*core.DataUpHandlerRes, error) {
	m.InHandleDataUp.Ctx = ctx
	m.InHandleDataUp.Req = in
	return m.OutHandleDataUp.Res, m.Failures["HandleDataUp"]
}

// HandleDataDown implements the core.HandlerServer interface
func (m *HandlerServer) HandleDataDown(ctx context.Context, in *core.DataDownHandlerReq) (*core.DataDownHandlerRes, error) {
	m.InHandleDataDown.Ctx = ctx
	m.InHandleDataDown.Req = in
	return m.OutHandleDataDown.Res, m.Failures["HandleDataDown"]
}

// SubscribePersonalized implements the core.HandlerServer interface
func (m *HandlerServer) SubscribePersonalized(ctx context.Context, in *core.ABPSubHandlerReq) (*core.ABPSubHandlerRes, error) {
	m.InSubscribePersonalized.Ctx = ctx
	m.InSubscribePersonalized.Req = in
	return m.OutSubscribePersonalized.Res, m.Failures["SubscribePersonalized"]
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package v1

import (
	"k8s.io/apimachinery/pkg/api/resource"
)

// Returns string version of ResourceName.
func (self ResourceName) String() string {
	return string(self)
}

// Returns the CPU limit if specified.
func (self *ResourceList) Cpu() *resource.Quantity {
	if val, ok := (*self)[ResourceCPU]; ok {
		return &val
	}
	return &resource.Quantity{Format: resource.DecimalSI}
}

// Returns the Memory limit if specified.
func (self *ResourceList) Memory() *resource.Quantity {
	if val, ok := (*self)[ResourceMemory]; ok {
		return &val
	}
	return &resource.Quantity{Format: resource.BinarySI}
}

func (self *ResourceList) Pods() *resource.Quantity {
	if val, ok := (*self)[ResourcePods]; ok {
		return &val
	}
	return &resource.Quantity{}
}

func (self *ResourceList) StorageEphemeral() *resource.Quantity {
	if val, ok := (*self)[ResourceEphemeralStorage]; ok {
		return &val
	}
	return &resource.Quantity{}
}
<commit_msg>Add getting Storage Quantity to ResourceList<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package v1

import (
	"k8s.io/apimachinery/pkg/api/resource"
)

// Returns string version of ResourceName.
func (self ResourceName) String() string {
	return string(self)
}

// Returns the CPU limit if specified.
func (self *ResourceList) Cpu() *resource.Quantity {
	if val, ok := (*self)[ResourceCPU]; ok {
		return &val
	}
	return &resource.Quantity{Format: resource.DecimalSI}
}

// Returns the Memory limit if specified.
func (self *ResourceList) Memory() *resource.Quantity {
	if val, ok := (*self)[ResourceMemory]; ok {
		return &val
	}
	return &resource.Quantity{Format: resource.BinarySI}
}

// Returns the Storage limit if specified.
func (self *ResourceList) Storage() *resource.Quantity {
	if val, ok := (*self)[ResourceStorage]; ok {
		return &val
	}
	return &resource.Quantity{Format: resource.BinarySI}
}

func (self *ResourceList) Pods() *resource.Quantity {
	if val, ok := (*self)[ResourcePods]; ok {
		return &val
	}
	return &resource.Quantity{}
}

func (self *ResourceList) StorageEphemeral() *resource.Quantity {
	if val, ok := (*self)[ResourceEphemeralStorage]; ok {
		return &val
	}
	return &resource.Quantity{}
}
<|endoftext|>