<commit_before>package dataProcess

import (
	"../autils"
	"../config"
	"bytes"
	"database/sql"
	"github.com/gin-gonic/gin"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type detailInfo struct {
	Domian       string `json:"domain"`
	TotalPv      string `json:"totalPv"`
	Pv           string `json:"pv"`
	PvRate       string `json:"pvRate"`
	EstPv        string `json:"estPv"`
	EstPvRate    string `json:"estPvRate"`
	PatternEstPv string `json:"patternEstPv"`
	Urls         string `json:"urls"`
	RecordUrl    string `json:"recordUrl"`
	RecordRate   string `json:"recordRate"`
	PassUrl      string `json:"passUrl"`
	PassRate     string `json:"passRate"`
	RelativeUrl  string `json:"relativeUrl"`
	EffectUrl    string `json:"effectUrl"`
	EffectPv     string `json:"effectPv"`
	IneffectUrl  string `json:"ineffectUrl"`
	IneffectPv   string `json:"ineffectPv"`
	ShieldUrl    string `json:"shieldUrl"`
}

type detailData struct {
	Columns []tStruct    `json:"columns"`
	Rows    []detailInfo `json:"rows"`
	Total   int          `json:"total"`
}

var dateTotal = map[string]int{}

// 获取流量信息
func GetSDetail(c *gin.Context, db *sql.DB) {

	ts := tStruct{}
	td := detailData{}

	var FieldIdMap = map[string]string{}

	for i, v := range config.Titles {
		ts.Name = v
		ts.TextAlign = "center"
		ts.Id = config.Ids[i]
		td.Columns = append(td.Columns, ts)

		FieldIdMap[config.Ids[i]] = config.Field[i]
	}

	start := c.Query("start")
	limit := c.Query("limit")
	sortKey := c.Query("sortKey")
	sortType := c.Query("sortType")
	field := FieldIdMap[sortKey]

	var startDate string
	theDay := time.Now().AddDate(0, 0, -3)
	startDate = autils.GetCurrentData(theDay)

	q, _ := c.Get("conditions")
	_, eDate := autils.AnaDate(q)
	if eDate != "" {
		startDate = eDate
	}

	dn := autils.AnaSelect(q)

	ch := make(chan int)
	if dateTotal[startDate] == 0 {
		go getTotal(db, startDate, ch)
	}

	var domain, totalPv, pv, pvRate, /*estPv, estPvRate, patternEstPv,*/
		urls, recordUrl, recordRate, passUrl, passRate, relativeUrl, effectUrl, effectPv, ineffectUrl, ineffectPv, shieldUrl string

	var sqlStr bytes.Buffer
	sqlStr.WriteString("select " + strings.Join(config.Field, ",") + " from site_detail where date = '")
	sqlStr.WriteString(startDate)
	sqlStr.WriteString("'")
	if strings.Contains(dn, ".") {
		sqlStr.WriteString("and domain = '" + dn + "' ")
	}

	field = autils.CheckSql(field)
	if field == "" {
		field = "total_pv"
	}

	// 排序类型转换
	/*
	match, _ := regexp.MatchString("_rate", field)
	if match {
		field = "cast(" + field + " as real)"
	}
	*/

	sqlStr.WriteString(" order by " + field + " ")

	sortType = autils.CheckSql(sortType)
	if sortType == "" {
		sortType = "desc"
	}
	sqlStr.WriteString(" " + sortType + "")

	_, err := strconv.Atoi(limit)
	if err == nil {
		sqlStr.WriteString(" limit " + limit + "")
	}

	_, err = strconv.Atoi(start)
	if err == nil {
		sqlStr.WriteString(" offset " + start + "")
	}

	sqls := sqlStr.String()
	rows, err := db.Query(sqls)

	autils.ErrHadle(err)
	di := detailInfo{}
	for rows.Next() {
		err := rows.Scan(&domain, &totalPv, &pv, &pvRate, /*&estPv, &estPvRate, &patternEstPv,*/
			&urls, &recordUrl, &recordRate, &passUrl, &passRate, &relativeUrl, &effectUrl, &effectPv, &ineffectUrl, &ineffectPv, &shieldUrl)
		autils.ErrHadle(err)
		di.Domian = domain
		di.TotalPv = totalPv
		di.Pv = pv
		di.PvRate = clearZero(pvRate) + "%"
		/*di.EstPvRate = estPv
		di.EstPvRate = estPvRate
		di.PatternEstPv = patternEstPv*/
		di.Urls = urls
		di.RecordUrl = recordUrl
		di.RecordRate = clearZero(recordRate) + "%"
		di.PassUrl = passUrl
		di.PassRate = clearZero(passRate) + "%"
		di.RelativeUrl = relativeUrl
		di.EffectUrl = effectUrl
		di.EffectPv = effectPv
		di.IneffectUrl = ineffectUrl
		di.IneffectPv = ineffectPv
		di.ShieldUrl = shieldUrl
		td.Rows = append(td.Rows, di)

	}

	count := 0
	if dateTotal[startDate] == 0 {
		count = <-ch
		dateTotal[startDate] = count
	} else {
		count = dateTotal[startDate]
	}

	td.Total = count
	if strings.Contains(dn, ".") {
		td.Total = 1
	}

	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()

	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "ok",
		"data":   td,
	})
}

func clearZero(s string) string {
	if strings.Contains(s, "0.0") {
		return "0"
	}
	return s
}

func getTotal(db *sql.DB, date string, ch chan int) {
	rows, err := db.Query("select count(id) from site_detail where date = '" + date + "'")

	autils.ErrHadle(err)
	count := 0
	for rows.Next() {
		err := rows.Scan(&count)
		autils.ErrHadle(err)
	}

	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()

	ch <- count
}
<commit_msg>delete useless package.<commit_after>package dataProcess

import (
	"../autils"
	"../config"
	"bytes"
	"database/sql"
	"github.com/gin-gonic/gin"
	"net/http"
	//"regexp"
	"strconv"
	"strings"
	"time"
)

type detailInfo struct {
	Domian       string `json:"domain"`
	TotalPv      string `json:"totalPv"`
	Pv           string `json:"pv"`
	PvRate       string `json:"pvRate"`
	EstPv        string `json:"estPv"`
	EstPvRate    string `json:"estPvRate"`
	PatternEstPv string `json:"patternEstPv"`
	Urls         string `json:"urls"`
	RecordUrl    string `json:"recordUrl"`
	RecordRate   string `json:"recordRate"`
	PassUrl      string `json:"passUrl"`
	PassRate     string `json:"passRate"`
	RelativeUrl  string `json:"relativeUrl"`
	EffectUrl    string `json:"effectUrl"`
	EffectPv     string `json:"effectPv"`
	IneffectUrl  string `json:"ineffectUrl"`
	IneffectPv   string `json:"ineffectPv"`
	ShieldUrl    string `json:"shieldUrl"`
}

type detailData struct {
	Columns []tStruct    `json:"columns"`
	Rows    []detailInfo `json:"rows"`
	Total   int          `json:"total"`
}

var dateTotal = map[string]int{}

// 获取流量信息
func GetSDetail(c *gin.Context, db *sql.DB) {

	ts := tStruct{}
	td := detailData{}

	var FieldIdMap = map[string]string{}

	for i, v := range config.Titles {
		ts.Name = v
		ts.TextAlign = "center"
		ts.Id = config.Ids[i]
		td.Columns = append(td.Columns, ts)

		FieldIdMap[config.Ids[i]] = config.Field[i]
	}

	start := c.Query("start")
	limit := c.Query("limit")
	sortKey := c.Query("sortKey")
	sortType := c.Query("sortType")
	field := FieldIdMap[sortKey]

	var startDate string
	theDay := time.Now().AddDate(0, 0, -3)
	startDate = autils.GetCurrentData(theDay)

	q, _ := c.Get("conditions")
	_, eDate := autils.AnaDate(q)
	if eDate != "" {
		startDate = eDate
	}

	dn := autils.AnaSelect(q)

	ch := make(chan int)
	if dateTotal[startDate] == 0 {
		go getTotal(db, startDate, ch)
	}

	var domain, totalPv, pv, pvRate, /*estPv, estPvRate, patternEstPv,*/
		urls, recordUrl, recordRate, passUrl, passRate, relativeUrl, effectUrl, effectPv, ineffectUrl, ineffectPv, shieldUrl string

	var sqlStr bytes.Buffer
	sqlStr.WriteString("select " + strings.Join(config.Field, ",") + " from site_detail where date = '")
	sqlStr.WriteString(startDate)
	sqlStr.WriteString("'")
	if strings.Contains(dn, ".") {
		sqlStr.WriteString("and domain = '" + dn + "' ")
	}

	field = autils.CheckSql(field)
	if field == "" {
		field = "total_pv"
	}

	// 排序类型转换
	/*
		match, _ := regexp.MatchString("_rate", field)
		if match {
			field = "cast(" + field + " as real)"
		}
	*/

	sqlStr.WriteString(" order by " + field + " ")

	sortType = autils.CheckSql(sortType)
	if sortType == "" {
		sortType = "desc"
	}
	sqlStr.WriteString(" " + sortType + "")

	_, err := strconv.Atoi(limit)
	if err == nil {
		sqlStr.WriteString(" limit " + limit + "")
	}

	_, err = strconv.Atoi(start)
	if err == nil {
		sqlStr.WriteString(" offset " + start + "")
	}

	sqls := sqlStr.String()
	rows, err := db.Query(sqls)

	autils.ErrHadle(err)
	di := detailInfo{}
	for rows.Next() {
		err := rows.Scan(&domain, &totalPv, &pv, &pvRate, /*&estPv, &estPvRate, &patternEstPv,*/
			&urls, &recordUrl, &recordRate, &passUrl, &passRate, &relativeUrl, &effectUrl, &effectPv, &ineffectUrl, &ineffectPv, &shieldUrl)
		autils.ErrHadle(err)
		di.Domian = domain
		di.TotalPv = totalPv
		di.Pv = pv
		di.PvRate = clearZero(pvRate) + "%"
		/*di.EstPvRate = estPv
		di.EstPvRate = estPvRate
		di.PatternEstPv = patternEstPv*/
		di.Urls = urls
		di.RecordUrl = recordUrl
		di.RecordRate = clearZero(recordRate) + "%"
		di.PassUrl = passUrl
		di.PassRate = clearZero(passRate) + "%"
		di.RelativeUrl = relativeUrl
		di.EffectUrl = effectUrl
		di.EffectPv = effectPv
		di.IneffectUrl = ineffectUrl
		di.IneffectPv = ineffectPv
		di.ShieldUrl = shieldUrl
		td.Rows = append(td.Rows, di)

	}

	count := 0
	if dateTotal[startDate] == 0 {
		count = <-ch
		dateTotal[startDate] = count
	} else {
		count = dateTotal[startDate]
	}

	td.Total = count
	if strings.Contains(dn, ".") {
		td.Total = 1
	}

	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()

	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "ok",
		"data":   td,
	})
}

func clearZero(s string) string {
	if strings.Contains(s, "0.0") {
		return "0"
	}
	return s
}

func getTotal(db *sql.DB, date string, ch chan int) {
	rows, err := db.Query("select count(id) from site_detail where date = '" + date + "'")

	autils.ErrHadle(err)
	count := 0
	for rows.Next() {
		err := rows.Scan(&count)
		autils.ErrHadle(err)
	}

	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()

	ch <- count
}
<|endoftext|>


<commit_before>// Copyright 2016 IBM Corporation
//
//   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 envoy

// AbortFilter definition.
type AbortFilter struct {
	Percent    int `json:"abort_percent,omitempty"`
	HTTPStatus int `json:"http_status,omitempty"`
}

// DelayFilter definition.
type DelayFilter struct {
	Type     string `json:"type,omitempty"`
	Percent  int    `json:"fixed_delay_percent,omitempty"`
	Duration int    `json:"fixed_duration_ms,omitempty"`
}

// GrpcHttp1BridgeFilter definition
type GrpcHttp1BridgeFilter struct{}

// Header definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_filters/fault_filter.html#config-http-filters-fault-injection-headers
type Header struct {
	Name  string `json:"name"`
	Value string `json:"value"`
	Regex bool   `json:"regex"`
}

// FilterFaultConfig definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_filters/fault_filter.html
type FilterFaultConfig struct {
	Abort   *AbortFilter `json:"abort,omitempty"`
	Delay   *DelayFilter `json:"delay,omitempty"`
	Headers []Header     `json:"headers,omitempty"`
}

// FilterRouterConfig definition.
type FilterRouterConfig struct {
	DynamicStats bool `json:"dynamic_stats"`
}

// Filter definition.
type Filter struct {
	Type   string      `json:"type"`
	Name   string      `json:"name"`
	Config interface{} `json:"config"`
}

// Runtime definition.
type Runtime struct {
	Key     string `json:"key"`
	Default int    `json:"default"`
}

// RetryPolicy definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#retry-policy
type RetryPolicy struct {
	Policy     string `json:"retry_on"` //5xx,connect-failure,refused-stream
	NumRetries int    `json:"num_retries,omitempty"`
}

// WeightedCluster definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#weighted-clusters
type WeightedCluster struct {
	Name   string `json:"name"`
	Weight int    `json:"weight"`
}

// WeightedClusters definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#weighted-clusters
type WeightedClusters struct {
	Clusters         []WeightedCluster `json:"clusters"`
	RunTimeKeyPrefix string            `json:"runtime_key_prefix,omitempty"`
}

// Route definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#config-http-conn-man-route-table-route
type Route struct {
	Runtime          *Runtime         `json:"runtime,omitempty"`
	Path             string           `json:"path,omitempty"`
	Prefix           string           `json:"prefix,omitempty"`
	PrefixRewrite    string           `json:"prefix_rewrite,omitempty"`
	WeightedClusters WeightedClusters `json:"weighted_clusters,omitempty"`
	Cluster          string           `json:"cluster,omitempty"`
	Headers          []Header         `json:"headers,omitempty"`
	TimeoutMS        int              `json:"timeout_ms,omitempty"`
	RetryPolicy      RetryPolicy      `json:"retry_policy"`
}

// VirtualHost definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/vhost.html#config-http-conn-man-route-table-vhost
type VirtualHost struct {
	Name    string   `json:"name"`
	Domains []string `json:"domains"`
	Routes  []Route  `json:"routes"`
}

// RouteConfig definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route_config.html#config-http-conn-man-route-table
type RouteConfig struct {
	VirtualHosts []VirtualHost `json:"virtual_hosts"`
}

// AccessLog definition.
type AccessLog struct {
	Path   string `json:"path"`
	Format string `json:"format,omitempty"`
	Filter string `json:"filter,omitempty"`
}

// RDS definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/rds.html#config-http-conn-man-rds
type RDS struct {
	Cluster         string `json:"cluster"`
	RefreshDelayMS  int    `json:"refresh_delay_ms"`
	RouteConfigName string `json:"route_config_name"`
}

// NetworkFilterConfig definition.
type NetworkFilterConfig struct {
	CodecType         string       `json:"codec_type"`
	StatPrefix        string       `json:"stat_prefix"`
	GenerateRequestID bool         `json:"generate_request_id"`
	UserAgent         bool         `json:"add_user_agent"`
	RouteConfig       *RouteConfig `json:"route_config,omitempty"`
	RDS               *RDS         `json:"rds,omitempty"`
	Filters           []Filter     `json:"filters"`
	AccessLog         []AccessLog  `json:"access_log"`
}

// NetworkFilter definition.
// See: https://lyft.github.io/envoy/docs/configuration/listeners/filters.html#config-listener-filters
type NetworkFilter struct {
	Type   string              `json:"type"`
	Name   string              `json:"name"`
	Config NetworkFilterConfig `json:"config"`
}

// SSLContext defintion
// See: https://lyft.github.io/envoy/docs/configuration/listeners/ssl.html#config-listener-ssl-context
type SSLContext struct {
	CertChainFile   string  `json:"cert_chain_file"`
	PrivateKeyFile  string  `json:"private_key_file"`
	CACertFile      *string `json:"ca_cert_file,omitempty"`
}

// Listener definition.
// See: https://lyft.github.io/envoy/docs/configuration/listeners/listeners.html#config-listeners
type Listener struct {
	Port       int             `json:"port"`
	Filters    []NetworkFilter `json:"filters"`
	SSLContext *SSLContext     `json:"ssl_context,omitempty"`
}

// Admin definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/admin.html#config-admin
type Admin struct {
	AccessLogPath string `json:"access_log_path"`
	Port          int    `json:"port"`
}

// Host definition.
type Host struct {
	URL string `json:"url"`
}

// Cluster definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster.html#config-cluster-manager-cluster
type Cluster struct {
	Name                     string            `json:"name"`
	ServiceName              string            `json:"service_name,omitempty"`
	ConnectTimeoutMs         int               `json:"connect_timeout_ms"`
	Type                     string            `json:"type"`
	LbType                   string            `json:"lb_type"`
	MaxRequestsPerConnection int               `json:"max_requests_per_connection,omitempty"`
	Hosts                    []Host            `json:"hosts,omitempty"`
	CircuitBreakers          *CircuitBreakers  `json:"circuit_breakers,omitempty"`
	OutlierDetection         *OutlierDetection `json:"outlier_detection,omitempty"`
	SSLContext               *SSLContext       `json:"ssl_context,omitempty"`
}

// OutlierDetection definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_runtime.html#outlier-detection
type OutlierDetection struct {
	ConsecutiveError   int `json:"consecutive_5xx,omitempty"`
	IntervalMS         int `json:"interval_ms,omitempty"`
	BaseEjectionTimeMS int `json:"base_ejection_time_ms,omitempty"`
	MaxEjectionPercent int `json:"max_ejection_percent,omitempty"`
}

// CircuitBreakers definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_circuit_breakers.html#circuit-breakers
type CircuitBreakers struct {
	MaxConnections    int `json:"max_connections,omitempty"`
	MaxPendingRequest int `json:"max_pending_requests,omitempty"`
	MaxRequests       int `json:"max_requests,omitempty"`
	MaxRetries        int `json:"max_retries,omitempty"`
}

// ClustersByName implements name based sort for clusters.
type ClustersByName []Cluster

// Len length.
func (s ClustersByName) Len() int {
	return len(s)
}

// Swap elements.
func (s ClustersByName) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// Less compare elements.
func (s ClustersByName) Less(i, j int) bool {
	return s[i].Name < s[j].Name
}

// SDS definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/sds.html#config-cluster-manager-sds
type SDS struct {
	Cluster        Cluster `json:"cluster"`
	RefreshDelayMs int     `json:"refresh_delay_ms"`
}

// CDS definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cds.html#config-cluster-manager-cds
type CDS struct {
	Cluster        Cluster `json:"cluster"`
	RefreshDelayMs int     `json:"refresh_delay_ms"`
}

// ClusterManager definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_manager.html#config-cluster-manager
type ClusterManager struct {
	Clusters []Cluster `json:"clusters"`
	SDS      SDS       `json:"sds"`
	CDS      CDS       `json:"cds"`
}

// RootRuntime definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/overview.html
type RootRuntime struct {
	SymlinkRoot          string `json:"symlink_root"`
	Subdirectory         string `json:"subdirectory"`
	OverrideSubdirectory string `json:"override_subdirectory,omitempty"`
}

// Config definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/overview.html
type Config struct {
	RootRuntime    RootRuntime    `json:"runtime"`
	Listeners      []Listener     `json:"listeners"`
	Admin          Admin          `json:"admin"`
	ClusterManager ClusterManager `json:"cluster_manager"`
}
<commit_msg>save changes on resources<commit_after>// Copyright 2016 IBM Corporation
//
//   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 envoy

// AbortFilter definition.
type AbortFilter struct {
	Percent    int `json:"abort_percent,omitempty"`
	HTTPStatus int `json:"http_status,omitempty"`
}

// DelayFilter definition.
type DelayFilter struct {
	Type     string `json:"type,omitempty"`
	Percent  int    `json:"fixed_delay_percent,omitempty"`
	Duration int    `json:"fixed_duration_ms,omitempty"`
}

// GrpcHttp1BridgeFilter definition
type GrpcHttp1BridgeFilter struct{}

// Header definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_filters/fault_filter.html#config-http-filters-fault-injection-headers
type Header struct {
	Name  string `json:"name"`
	Value string `json:"value"`
	Regex bool   `json:"regex"`
}

// FilterFaultConfig definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_filters/fault_filter.html
type FilterFaultConfig struct {
	Abort   *AbortFilter `json:"abort,omitempty"`
	Delay   *DelayFilter `json:"delay,omitempty"`
	Headers []Header     `json:"headers,omitempty"`
}

// FilterRouterConfig definition.
type FilterRouterConfig struct {
	DynamicStats bool `json:"dynamic_stats"`
}

// Filter definition.
type Filter struct {
	Type   string      `json:"type"`
	Name   string      `json:"name"`
	Config interface{} `json:"config"`
}

// Runtime definition.
type Runtime struct {
	Key     string `json:"key"`
	Default int    `json:"default"`
}

// RetryPolicy definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#retry-policy
type RetryPolicy struct {
	Policy     string `json:"retry_on"` //5xx,connect-failure,refused-stream
	NumRetries int    `json:"num_retries,omitempty"`
}

// WeightedCluster definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#weighted-clusters
type WeightedCluster struct {
	Name   string `json:"name"`
	Weight int    `json:"weight"`
}

// WeightedClusters definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#weighted-clusters
type WeightedClusters struct {
	Clusters         []WeightedCluster `json:"clusters"`
	RunTimeKeyPrefix string            `json:"runtime_key_prefix,omitempty"`
}

// Route definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route.html#config-http-conn-man-route-table-route
type Route struct {
	Runtime          *Runtime         `json:"runtime,omitempty"`
	Path             string           `json:"path,omitempty"`
	Prefix           string           `json:"prefix,omitempty"`
	PrefixRewrite    string           `json:"prefix_rewrite,omitempty"`
	WeightedClusters WeightedClusters `json:"weighted_clusters,omitempty"`
	Cluster          string           `json:"cluster,omitempty"`
	Headers          []Header         `json:"headers,omitempty"`
	TimeoutMS        int              `json:"timeout_ms,omitempty"`
	RetryPolicy      RetryPolicy      `json:"retry_policy"`
}

// VirtualHost definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/vhost.html#config-http-conn-man-route-table-vhost
type VirtualHost struct {
	Name    string   `json:"name"`
	Domains []string `json:"domains"`
	Routes  []Route  `json:"routes"`
}

// RouteConfig definition.
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/route_config.html#config-http-conn-man-route-table
type RouteConfig struct {
	VirtualHosts []VirtualHost `json:"virtual_hosts"`
}

// AccessLog definition.
type AccessLog struct {
	Path   string `json:"path"`
	Format string `json:"format,omitempty"`
	Filter string `json:"filter,omitempty"`
}

// RDS definition
// See: https://lyft.github.io/envoy/docs/configuration/http_conn_man/rds.html#config-http-conn-man-rds
type RDS struct {
	Cluster         string `json:"cluster"`
	RefreshDelayMS  int    `json:"refresh_delay_ms"`
	RouteConfigName string `json:"route_config_name"`
}

// NetworkFilterConfig definition.
type NetworkFilterConfig struct {
	CodecType         string       `json:"codec_type"`
	StatPrefix        string       `json:"stat_prefix"`
	GenerateRequestID bool         `json:"generate_request_id"`
	UserAgent         bool         `json:"add_user_agent"`
	RouteConfig       *RouteConfig `json:"route_config,omitempty"`
	RDS               *RDS         `json:"rds,omitempty"`
	Filters           []Filter     `json:"filters"`
	AccessLog         []AccessLog  `json:"access_log"`
}

// NetworkFilter definition.
// See: https://lyft.github.io/envoy/docs/configuration/listeners/filters.html#config-listener-filters
type NetworkFilter struct {
	Type   string              `json:"type"`
	Name   string              `json:"name"`
	Config NetworkFilterConfig `json:"config"`
}

// SSLContext defintion
// See: https://lyft.github.io/envoy/docs/configuration/listeners/ssl.html#config-listener-ssl-context
type SSLContext struct {
	CertChainFile  string  `json:"cert_chain_file"`
	PrivateKeyFile string  `json:"private_key_file"`
	CACertFile     *string `json:"ca_cert_file,omitempty"`
}

// Listener definition.
// See: https://lyft.github.io/envoy/docs/configuration/listeners/listeners.html#config-listeners
type Listener struct {
	Port       int             `json:"port"`
	Filters    []NetworkFilter `json:"filters"`
	SSLContext *SSLContext     `json:"ssl_context,omitempty"`
}

// Admin definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/admin.html#config-admin
type Admin struct {
	AccessLogPath string `json:"access_log_path"`
	Port          int    `json:"port"`
}

// Host definition.
type Host struct {
	URL string `json:"url"`
}

// Cluster definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster.html#config-cluster-manager-cluster
type Cluster struct {
	Name                     string            `json:"name"`
	ServiceName              string            `json:"service_name,omitempty"`
	ConnectTimeoutMs         int               `json:"connect_timeout_ms"`
	Type                     string            `json:"type"`
	LbType                   string            `json:"lb_type"`
	MaxRequestsPerConnection int               `json:"max_requests_per_connection,omitempty"`
	Hosts                    []Host            `json:"hosts,omitempty"`
	CircuitBreakers          *CircuitBreakers  `json:"circuit_breakers,omitempty"`
	OutlierDetection         *OutlierDetection `json:"outlier_detection,omitempty"`
	SSLContext               *SSLContext       `json:"ssl_context,omitempty"`
}

// OutlierDetection definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_runtime.html#outlier-detection
type OutlierDetection struct {
	ConsecutiveError   int `json:"consecutive_5xx,omitempty"`
	IntervalMS         int `json:"interval_ms,omitempty"`
	BaseEjectionTimeMS int `json:"base_ejection_time_ms,omitempty"`
	MaxEjectionPercent int `json:"max_ejection_percent,omitempty"`
}

// CircuitBreakers definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_circuit_breakers.html#circuit-breakers
type CircuitBreakers struct {
	MaxConnections    int `json:"max_connections,omitempty"`
	MaxPendingRequest int `json:"max_pending_requests,omitempty"`
	MaxRequests       int `json:"max_requests,omitempty"`
	MaxRetries        int `json:"max_retries,omitempty"`
}

// ClustersByName implements name based sort for clusters.
type ClustersByName []Cluster

// Len length.
func (s ClustersByName) Len() int {
	return len(s)
}

// Swap elements.
func (s ClustersByName) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// Less compare elements.
func (s ClustersByName) Less(i, j int) bool {
	return s[i].Name < s[j].Name
}

// SDS definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/sds.html#config-cluster-manager-sds
type SDS struct {
	Cluster        Cluster `json:"cluster"`
	RefreshDelayMs int     `json:"refresh_delay_ms"`
}

// CDS definition
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cds.html#config-cluster-manager-cds
type CDS struct {
	Cluster        Cluster `json:"cluster"`
	RefreshDelayMs int     `json:"refresh_delay_ms"`
}

// ClusterManager definition.
// See: https://lyft.github.io/envoy/docs/configuration/cluster_manager/cluster_manager.html#config-cluster-manager
type ClusterManager struct {
	Clusters []Cluster `json:"clusters"`
	SDS      SDS       `json:"sds"`
	CDS      CDS       `json:"cds"`
}

// RootRuntime definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/overview.html
type RootRuntime struct {
	SymlinkRoot          string `json:"symlink_root"`
	Subdirectory         string `json:"subdirectory"`
	OverrideSubdirectory string `json:"override_subdirectory,omitempty"`
}

// Config definition.
// See: https://lyft.github.io/envoy/docs/configuration/overview/overview.html
type Config struct {
	RootRuntime    RootRuntime    `json:"runtime"`
	Listeners      []Listener     `json:"listeners"`
	Admin          Admin          `json:"admin"`
	ClusterManager ClusterManager `json:"cluster_manager"`
}
<|endoftext|>


<commit_before>// This is a program to update DNS record on Route53
//
// Requires config.yaml to be in same path as the executable
// assumption is that this program is scheduled to run under
// a unix cron like program to update Route53 record every time
// external IP changes.
//
// nataraj.basappa
//@version 1.0, 02/12/2015
//

package main

import (
	"os"
	"fmt"
	"time"
	"bytes"
	"strings"
	"net/http"
	"io/ioutil"
	"text/template"
	"github.com/zpatrick/go-config"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/route53"
)

const (
	CommentTemplate = "Updating Route53 record for {{.DNSRecordName}} at {{.Timestamp}}"
	ActionType = "UPSERT"
	RecordType = "A"
	TTL = 300
)

type UpdateComment struct {
	DNSRecordName string
	Timestamp     string
}

func main() {

	// Initialise and read configuration properties from config.yaml file
	yamlFile := config.NewYAMLFile("config.yaml")
	conf := config.NewConfig([]config.Provider{yamlFile})

	externalIp := getExternalIP(conf)

	// Read configuration properties from config.yaml file
	AWSAccessKeyId, _ := conf.String("aws_setting.aws_access_key_id")
	AWSSecretAccessKey, _ := conf.String("aws_setting.aws_secret_access_key")
	AWSHostedZoneId, _ := conf.String("aws_setting.aws_hosted_zone_id")
	AWSFQDN, _ := conf.String("aws_setting.aws_fqdn")

	// Connect to AWS Route53 service with configurations provided in config.yaml and obtain a session
	svc := route53.New(session.New(&aws.Config{Credentials:credentials.NewStaticCredentials(AWSAccessKeyId, AWSSecretAccessKey, "")}))

	awsIP := getCurrentAWSIP(svc, AWSHostedZoneId, AWSFQDN)

	if strings.Compare(awsIP, externalIp) != 0 {
		updateRoute53Record(svc, AWSHostedZoneId, AWSFQDN, externalIp)
	}

	os.Exit(0)
}

func getExternalIP(conf *config.Config) (externalIP string) {

	var currentIP []byte
	// Read ip_resolvers configuration properties from config.yaml file
	IPResolver, _ := conf.String("ip_resolvers.ip_resolver")
	IPResolverFallback, _ := conf.String("ip_resolvers.ip_resolver_fallback")

	// Check if you have to update Route53 with new IP
	resp1, err1 := http.Get(IPResolver)
	if err1 != nil {
		resp2, err2 := http.Get(IPResolverFallback)
		if err2 != nil {
			fmt.Println(err2.Error())
		}
		currentIP, _ = ioutil.ReadAll(resp2.Body)
	} else {
		currentIP, _ = ioutil.ReadAll(resp1.Body)
	}

	externalIP = strings.TrimSpace(string(currentIP))
	return externalIP
}

func getCurrentAWSIP(svc *route53.Route53, AWSHostedZoneId string, FQDN string) (awsIP string) {

	// Preparing input to retreive records from Route53
	CheckRecord := &route53.ListResourceRecordSetsInput{
		HostedZoneId:aws.String(AWSHostedZoneId),
		StartRecordType:aws.String(RecordType),
		StartRecordName:aws.String(FQDN),
	}

	// Get the record set from Route53 to check currently set IP
	resp, err := svc.ListResourceRecordSets(CheckRecord)
	if err != nil {
		fmt.Println(err.Error())
	}

	// Iterate over the record set to find the right record and value
	var setIP *string
	for _, record := range resp.ResourceRecordSets {
		if *record.Type == RecordType {
			setIP = record.ResourceRecords[0].Value
		}
	}

	if setIP != nil {
		awsIP = *setIP
	}
	return awsIP
}

func updateRoute53Record(svc *route53.Route53, AWSHostedZoneId string, FQDN string, externalIP string) {

	// Bit of templating to read and apply comments to be passed to Route53
	parsed_template, _ := template.New("comments").Parse(CommentTemplate)
	var comments bytes.Buffer
	parsed_template.Execute(&comments, UpdateComment{DNSRecordName:FQDN, Timestamp:time.Now().Format(time.RFC822)})
	AWSUpdateComment := comments.String()

	// Prepare the change set to be applied to Route53
	ChangeRecord := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Comment: aws.String(AWSUpdateComment),
			Changes: []*route53.Change{
				{
					Action: aws.String(ActionType),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(FQDN),
						Type: aws.String(RecordType),
						TTL: aws.Int64(TTL),
						ResourceRecords: []*route53.ResourceRecord{
							{
								Value: aws.String(externalIP),
							},
						},
					},
				},
			},
		},
		HostedZoneId: aws.String(AWSHostedZoneId),
	}

	// Apply the change set prepared above to Route53, using the passed session
	// ignore response coming back as its not useful to what we are doing
	_, err := svc.ChangeResourceRecordSets(ChangeRecord)

	if err != nil {
		fmt.Println(err.Error())
	}

	return
}<commit_msg>Corrected file copywrite info<commit_after>// This is a program to update DNS record on Route53
//
// Requires config.yaml to be in same path as the executable
// assumption is that this program is scheduled to run under
// a unix cron like program to update Route53 record every time
// external IP changes.
//
// nataraj.basappa <nataraj.basappa@yahoo.com>
//

package main

import (
	"os"
	"fmt"
	"time"
	"bytes"
	"strings"
	"net/http"
	"io/ioutil"
	"text/template"
	"github.com/zpatrick/go-config"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/route53"
)

const (
	CommentTemplate = "Updating Route53 record for {{.DNSRecordName}} at {{.Timestamp}}"
	ActionType = "UPSERT"
	RecordType = "A"
	TTL = 300
)

type UpdateComment struct {
	DNSRecordName string
	Timestamp     string
}

func main() {

	// Initialise and read configuration properties from config.yaml file
	yamlFile := config.NewYAMLFile("config.yaml")
	conf := config.NewConfig([]config.Provider{yamlFile})

	externalIp := getExternalIP(conf)

	// Read configuration properties from config.yaml file
	AWSAccessKeyId, _ := conf.String("aws_setting.aws_access_key_id")
	AWSSecretAccessKey, _ := conf.String("aws_setting.aws_secret_access_key")
	AWSHostedZoneId, _ := conf.String("aws_setting.aws_hosted_zone_id")
	AWSFQDN, _ := conf.String("aws_setting.aws_fqdn")

	// Connect to AWS Route53 service with configurations provided in config.yaml and obtain a session
	svc := route53.New(session.New(&aws.Config{Credentials:credentials.NewStaticCredentials(AWSAccessKeyId, AWSSecretAccessKey, "")}))

	awsIP := getCurrentAWSIP(svc, AWSHostedZoneId, AWSFQDN)

	if strings.Compare(awsIP, externalIp) != 0 {
		updateRoute53Record(svc, AWSHostedZoneId, AWSFQDN, externalIp)
	}

	os.Exit(0)
}

func getExternalIP(conf *config.Config) (externalIP string) {

	var currentIP []byte
	// Read ip_resolvers configuration properties from config.yaml file
	IPResolver, _ := conf.String("ip_resolvers.ip_resolver")
	IPResolverFallback, _ := conf.String("ip_resolvers.ip_resolver_fallback")

	// Check if you have to update Route53 with new IP
	resp1, err1 := http.Get(IPResolver)
	if err1 != nil {
		resp2, err2 := http.Get(IPResolverFallback)
		if err2 != nil {
			fmt.Println(err2.Error())
		}
		currentIP, _ = ioutil.ReadAll(resp2.Body)
	} else {
		currentIP, _ = ioutil.ReadAll(resp1.Body)
	}

	externalIP = strings.TrimSpace(string(currentIP))
	return externalIP
}

func getCurrentAWSIP(svc *route53.Route53, AWSHostedZoneId string, FQDN string) (awsIP string) {

	// Preparing input to retreive records from Route53
	CheckRecord := &route53.ListResourceRecordSetsInput{
		HostedZoneId:aws.String(AWSHostedZoneId),
		StartRecordType:aws.String(RecordType),
		StartRecordName:aws.String(FQDN),
	}

	// Get the record set from Route53 to check currently set IP
	resp, err := svc.ListResourceRecordSets(CheckRecord)
	if err != nil {
		fmt.Println(err.Error())
	}

	// Iterate over the record set to find the right record and value
	var setIP *string
	for _, record := range resp.ResourceRecordSets {
		if *record.Type == RecordType {
			setIP = record.ResourceRecords[0].Value
		}
	}

	if setIP != nil {
		awsIP = *setIP
	}
	return awsIP
}

func updateRoute53Record(svc *route53.Route53, AWSHostedZoneId string, FQDN string, externalIP string) {

	// Bit of templating to read and apply comments to be passed to Route53
	parsed_template, _ := template.New("comments").Parse(CommentTemplate)
	var comments bytes.Buffer
	parsed_template.Execute(&comments, UpdateComment{DNSRecordName:FQDN, Timestamp:time.Now().Format(time.RFC822)})
	AWSUpdateComment := comments.String()

	// Prepare the change set to be applied to Route53
	ChangeRecord := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Comment: aws.String(AWSUpdateComment),
			Changes: []*route53.Change{
				{
					Action: aws.String(ActionType),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(FQDN),
						Type: aws.String(RecordType),
						TTL: aws.Int64(TTL),
						ResourceRecords: []*route53.ResourceRecord{
							{
								Value: aws.String(externalIP),
							},
						},
					},
				},
			},
		},
		HostedZoneId: aws.String(AWSHostedZoneId),
	}

	// Apply the change set prepared above to Route53, using the passed session
	// ignore response coming back as its not useful to what we are doing
	_, err := svc.ChangeResourceRecordSets(ChangeRecord)

	if err != nil {
		fmt.Println(err.Error())
	}

	return
}<|endoftext|>


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

package poll_test

import (
	"internal/poll"
	"runtime"
	"syscall"
	"testing"
	"time"
)

// checkPipes returns true if all pipes are closed properly, false otherwise.
func checkPipes(fds []int) bool {
	for _, fd := range fds {
		// Check if each pipe fd has been closed.
		err := syscall.FcntlFlock(uintptr(fd), syscall.F_GETFD, nil)
		if err == nil {
			return false
		}
	}
	return true
}

func TestSplicePipePool(t *testing.T) {
	const N = 64
	var (
		p   *poll.SplicePipe
		ps  []*poll.SplicePipe
		fds []int
		err error
	)
	for i := 0; i < N; i++ {
		p, _, err = poll.GetPipe()
		if err != nil {
			t.Skip("failed to create pipe, skip this test")
		}
		prfd, pwfd := poll.GetPipeFds(p)
		fds = append(fds, prfd, pwfd)
		ps = append(ps, p)
	}
	for _, p = range ps {
		poll.PutPipe(p)
	}
	ps = nil

	var ok bool
	// Trigger garbage collection to free the pipes in sync.Pool and check whether or not
	// those pipe buffers have been closed as we expected.
	for i := 0; i < 5; i++ {
		runtime.GC()
		time.Sleep(time.Duration(i*100+10) * time.Millisecond)
		if ok = checkPipes(fds); ok {
			break
		}
	}

	if !ok {
		t.Fatal("at least one pipe is still open")
	}
}

func BenchmarkSplicePipe(b *testing.B) {
	b.Run("SplicePipeWithPool", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p, _, _ := poll.GetPipe()
			poll.PutPipe(p)
		}
	})
	b.Run("SplicePipeWithoutPool", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p := poll.NewPipe()
			poll.DestroyPipe(p)
		}
	})
}

func BenchmarkSplicePipePoolParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			p, _, _ := poll.GetPipe()
			poll.PutPipe(p)
		}
	})
}

func BenchmarkSplicePipeNativeParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			p := poll.NewPipe()
			poll.DestroyPipe(p)
		}
	})
}
<commit_msg>internal/poll: fix the intermittent build failures with pipe pool<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package poll_test

import (
	"internal/poll"
	"internal/syscall/unix"
	"runtime"
	"syscall"
	"testing"
	"time"
)

// checkPipes returns true if all pipes are closed properly, false otherwise.
func checkPipes(fds []int) bool {
	for _, fd := range fds {
		// Check if each pipe fd has been closed.
		_, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0)
		if errno == 0 {
			return false
		}
	}
	return true
}

func TestSplicePipePool(t *testing.T) {
	const N = 64
	var (
		p   *poll.SplicePipe
		ps  []*poll.SplicePipe
		fds []int
		err error
	)
	for i := 0; i < N; i++ {
		p, _, err = poll.GetPipe()
		if err != nil {
			t.Skip("failed to create pipe, skip this test")
		}
		_, pwfd := poll.GetPipeFds(p)
		fds = append(fds, pwfd)
		ps = append(ps, p)
	}
	for _, p = range ps {
		poll.PutPipe(p)
	}
	ps = nil

	// Exploit the timeout of "go test" as a timer for the subsequent verification.
	timeout := 5 * time.Minute
	if deadline, ok := t.Deadline(); ok {
		timeout = deadline.Sub(time.Now())
		timeout -= timeout / 10 // Leave 10% headroom for cleanup.
	}
	expiredTime := time.NewTimer(timeout)
	defer expiredTime.Stop()

	// Trigger garbage collection repeatedly, waiting for all pipes in sync.Pool
	// to either be deallocated and closed, or to time out.
	for {
		runtime.GC()
		time.Sleep(10 * time.Millisecond)
		if checkPipes(fds) {
			break
		}
		select {
		case <-expiredTime.C:
			t.Fatal("at least one pipe is still open")
		default:
		}
	}
}

func BenchmarkSplicePipe(b *testing.B) {
	b.Run("SplicePipeWithPool", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p, _, _ := poll.GetPipe()
			poll.PutPipe(p)
		}
	})
	b.Run("SplicePipeWithoutPool", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p := poll.NewPipe()
			poll.DestroyPipe(p)
		}
	})
}

func BenchmarkSplicePipePoolParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			p, _, _ := poll.GetPipe()
			poll.PutPipe(p)
		}
	})
}

func BenchmarkSplicePipeNativeParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			p := poll.NewPipe()
			poll.DestroyPipe(p)
		}
	})
}
<|endoftext|>


<commit_before>package validate

import (
	"fmt"
	"log"
	"net/url"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/crypto/ssh"

	"github.com/codegangsta/cli"
	"github.com/marcosnils/cmt/cmd"
)

var Command = cli.Command{
	Name:  "validate",
	Usage: "Validate host migration capabilities",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "src",
			Usage: "Source host URL [user@host:port]",
		},
		cli.StringFlag{
			Name:  "dst",
			Usage: "Destination host URL [user@host:port]",
		},
	},
	Action: func(c *cli.Context) {
		src := c.String("src")
		if src != "" && !strings.HasPrefix(src, "ssh://") {
			src = fmt.Sprintf("ssh://%s", src)
		}

		dst := c.String("dst")
		if dst != "" && !strings.HasPrefix(dst, "ssh://") {
			dst = fmt.Sprintf("ssh://%s", dst)
		}

		srcURL := parseURL(src)
		dstURL := parseURL(dst)

		Validate(srcURL, dstURL)
		println("Validation succeded")

	},
}

func parseURL(stringURL string) *url.URL {
	if stringURL == "" {
		return nil
	}

	parsedURL, err := url.Parse(stringURL)
	if err != nil || parsedURL.Host == "" {
		log.Fatal("Error parsing host: ", stringURL)
	}

	return parsedURL

}

func Validate(src, dst *url.URL) {
	if src == nil && dst == nil {
		log.Fatal("Either one of dst or src must be specified")
	}

	srcCmd := getCommand(src)
	dstCmd := getCommand(dst)

	if e := checkVersion(srcCmd, dstCmd, "criu"); e != nil {
		log.Fatal(e)
	}
	if e := checkVersion(srcCmd, dstCmd, "runc"); e != nil {
		log.Fatal(e)
	}

}

func getCommand(hostURL *url.URL) cmd.Cmd {
	if hostURL != nil {
		hostPort := strings.Split(hostURL.Host, ":")
		var port int
		if len(hostPort) > 1 {
			p, err := strconv.Atoi(hostPort[1])
			if err != nil {
				log.Fatal("Unable to parse port: ", hostPort[1])
			}
			port = p
		} else {
			// SSH default port
			port = 22
		}
		rc := cmd.NewSSH(hostURL.User.Username(), hostPort[0], port)
		if err := rc.UseAgent(); err != nil {
			log.Fatal("Unable to use SSH agent for host: ", hostURL.String())
		}
		return rc

	}

	return cmd.NewLocal()

}

func checkVersion(sCmd, dCmd cmd.Cmd, name string) error {
	var wg sync.WaitGroup
	wg.Add(2)
	var sourceVersion, destVersion string
	var sourceError, destError error
	go func() {
		sourceVersion, sourceError = getVersion(sCmd, name)
		wg.Done()
	}()
	go func() {
		destVersion, destError = getVersion(dCmd, name)
		wg.Done()
	}()

	wg.Wait()

	if sourceError != nil {
		return fmt.Errorf("%s in src", sourceError)
	}
	if destError != nil {
		return fmt.Errorf("%s in dst", destError)
	}

	if sourceVersion != destVersion {
		return fmt.Errorf("ERROR: Source and destination versions of %s do not match", name)
	}

	return nil
}

func getVersion(command cmd.Cmd, name string) (string, error) {
	version, _, err := command.Run("sudo", name, "--version")
	if _, ok := err.(*ssh.ExitError); ok {
		return "", fmt.Errorf("Error %s does not exist", name)
	} else if _, ok := err.(*exec.ExitError); ok {
		return "", fmt.Errorf("Error %s does not exist", name)
	} else if err != nil {
		return "", fmt.Errorf("Connection error: %s ", err)
	}
	return version, nil
}
<commit_msg>Check kernel capabilities for criu on both src and dst<commit_after>package validate

import (
	"fmt"
	"log"
	"net/url"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/crypto/ssh"

	"github.com/codegangsta/cli"
	"github.com/marcosnils/cmt/cmd"
)

var Command = cli.Command{
	Name:  "validate",
	Usage: "Validate host migration capabilities",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "src",
			Usage: "Source host URL [user@host:port]",
		},
		cli.StringFlag{
			Name:  "dst",
			Usage: "Destination host URL [user@host:port]",
		},
	},
	Action: func(c *cli.Context) {
		src := c.String("src")
		if src != "" && !strings.HasPrefix(src, "ssh://") {
			src = fmt.Sprintf("ssh://%s", src)
		}

		dst := c.String("dst")
		if dst != "" && !strings.HasPrefix(dst, "ssh://") {
			dst = fmt.Sprintf("ssh://%s", dst)
		}

		srcURL := parseURL(src)
		dstURL := parseURL(dst)

		Validate(srcURL, dstURL)
		println("Validation succeded")

	},
}

func parseURL(stringURL string) *url.URL {
	if stringURL == "" {
		return nil
	}

	parsedURL, err := url.Parse(stringURL)
	if err != nil || parsedURL.Host == "" {
		log.Fatal("Error parsing host: ", stringURL)
	}

	return parsedURL

}

func Validate(src, dst *url.URL) {
	if src == nil && dst == nil {
		log.Fatal("Either one of dst or src must be specified")
	}

	srcCmd := getCommand(src)
	dstCmd := getCommand(dst)

	if e := checkVersion(srcCmd, dstCmd, "criu"); e != nil {
		log.Fatal(e)
	}
	if e := checkVersion(srcCmd, dstCmd, "runc"); e != nil {
		log.Fatal(e)
	}
	if e := checkKernelCap(srcCmd); e != nil {
		log.Fatal(e)
	}
	if e := checkKernelCap(dstCmd); e != nil {
		log.Fatal(e)
	}
}

func checkKernelCap(c cmd.Cmd) error {
	_, _, err := c.Run("sudo", "criu", "check", "--ms")
	if _, ok := err.(*ssh.ExitError); ok {
		return fmt.Errorf("Error criu checks do not pass")
	} else if _, ok := err.(*exec.ExitError); ok {
		return fmt.Errorf("Error criu checks do not pass")
	} else if err != nil {
		return fmt.Errorf("Connection error: %s ", err)
	}
	return err
}

func getCommand(hostURL *url.URL) cmd.Cmd {
	if hostURL != nil {
		hostPort := strings.Split(hostURL.Host, ":")
		var port int
		if len(hostPort) > 1 {
			p, err := strconv.Atoi(hostPort[1])
			if err != nil {
				log.Fatal("Unable to parse port: ", hostPort[1])
			}
			port = p
		} else {
			// SSH default port
			port = 22
		}
		rc := cmd.NewSSH(hostURL.User.Username(), hostPort[0], port)
		if err := rc.UseAgent(); err != nil {
			log.Fatal("Unable to use SSH agent for host: ", hostURL.String())
		}
		return rc

	}

	return cmd.NewLocal()

}

func checkVersion(sCmd, dCmd cmd.Cmd, name string) error {
	var wg sync.WaitGroup
	wg.Add(2)
	var sourceVersion, destVersion string
	var sourceError, destError error
	go func() {
		sourceVersion, sourceError = getVersion(sCmd, name)
		wg.Done()
	}()
	go func() {
		destVersion, destError = getVersion(dCmd, name)
		wg.Done()
	}()

	wg.Wait()

	if sourceError != nil {
		return fmt.Errorf("%s in src", sourceError)
	}
	if destError != nil {
		return fmt.Errorf("%s in dst", destError)
	}

	if sourceVersion != destVersion {
		return fmt.Errorf("ERROR: Source and destination versions of %s do not match", name)
	}

	return nil
}

func getVersion(command cmd.Cmd, name string) (string, error) {
	version, _, err := command.Run("sudo", name, "--version")
	if _, ok := err.(*ssh.ExitError); ok {
		return "", fmt.Errorf("Error %s does not exist", name)
	} else if _, ok := err.(*exec.ExitError); ok {
		return "", fmt.Errorf("Error %s does not exist", name)
	} else if err != nil {
		return "", fmt.Errorf("Connection error: %s ", err)
	}
	return version, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sort"
	"strings"
	"unicode"
)

var VERSION = "unknown-snapshot"

var logger = log.New(os.Stderr, "", 0)

func main() {
	app(os.Args, os.Stdout)
}

func app(args []string, output io.Writer) {
	app := cli.NewApp()
	app.Name = "chtignore"
	app.Usage = "print .gitignore templates in standard output"
	app.ArgsUsage = "template"
	app.Action = printTemplates
	app.Version = VERSION
	app.Commands = []cli.Command{
		{
			Name:   "list",
			Usage:  "list available templates",
			Action: list,
		},
	}
	app.Writer = output
	app.Run(args)
}

func printTemplates(c *cli.Context) {
	args := c.Args()
	output := c.App.Writer

	length := len(args)
	if length == 0 {
		cli.ShowAppHelp(c)
	}

	contents := make(chan string, length)
	for _, candidate := range args {
		go func(candidate string) {
			candidate = upperFirstChar(candidate)
			content := tryGetTemplate(candidate)

			if content != "" {
				contents <- fmt.Sprintf("# %s\n%s", candidate, content)
			} else {
				contents <- ""
			}
		}(candidate)
	}

	for i := 0; i < length; i++ {
		if content := <-contents; content != "" {
			fmt.Fprintln(output, content)
		}
	}
}

func list(c *cli.Context) {
	fmt.Fprintln(c.App.Writer, listTemplates())
}

func tryGetTemplate(template string) string {
	var resp *http.Response

	if template == "JetBrains-build" {
		resp = get("https://raw.githubusercontent.com/github/gitignore/38d6cac990a82a1f7814571634e08295086763b5/Global/JetBrains.gitignore")
	} else {
		resp = get(fmt.Sprintf("https://raw.githubusercontent.com/github/gitignore/master/%s.gitignore", template))
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusNotFound {
		resp = get(fmt.Sprintf("https://raw.githubusercontent.com/github/gitignore/master/Global/%s.gitignore", template))
	}

	if resp.StatusCode != http.StatusOK {
		logger.Fatal("Cannot find a template for: ", template)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Fatal(err)
	}

	return string(body)
}

func get(url string) (resp *http.Response) {
	resp, err := http.Get(url)
	if err != nil {
		logger.Fatal(err)
	}

	return resp
}

func upperFirstChar(str string) string {
	a := []rune(str)
	firstChar := a[0]

	if unicode.IsUpper(firstChar) {
		return str
	}
	a[0] = unicode.ToUpper(firstChar)
	return string(a)
}

func listTemplates() string {
	templates := make([]string, 0)
	templates = getAndAppend(templates, "https://api.github.com/repos/github/gitignore/contents/")
	templates = getAndAppend(templates, "https://api.github.com/repos/github/gitignore/contents/Global")
	templates = append(templates, "JetBrains-build")
	sort.Strings(templates)
	return strings.Join(templates, ", ")
}

func getAndAppend(templates []string, url string) []string {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		logger.Fatal(err)
	}
	req.Header.Add("Accept", "application/vnd.github.v3+json")

	resp, err := client.Do(req)
	if err != nil {
		logger.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		logger.Fatal("Cannot list templates: ", resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Fatal(err)
	}

	result := make([]GitIgnoreTemplate, 0)
	if err := json.Unmarshal(body, &result); err != nil {
		logger.Fatal(err)
	}

	for _, template := range result {
		if template.Name != "" && strings.Contains(template.Name, ".gitignore") {
			templates = append(templates, strings.Replace(template.Name, ".gitignore", "", 1))
		}
	}

	return templates
}

type GitIgnoreTemplate struct {
	Name string `json:"name"`
}
<commit_msg>Cleaner channel usage with a sync.WaitGroup<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sort"
	"strings"
	"sync"
	"unicode"
)

var VERSION = "unknown-snapshot"

var logger = log.New(os.Stderr, "", 0)

func main() {
	app(os.Args, os.Stdout)
}

func app(args []string, output io.Writer) {
	app := cli.NewApp()
	app.Name = "chtignore"
	app.Usage = "print .gitignore templates in standard output"
	app.ArgsUsage = "template"
	app.Action = printTemplates
	app.Version = VERSION
	app.Commands = []cli.Command{
		{
			Name:   "list",
			Usage:  "list available templates",
			Action: list,
		},
	}
	app.Writer = output
	app.Run(args)
}

func printTemplates(c *cli.Context) {
	args := c.Args()
	output := c.App.Writer

	if len(args) == 0 {
		cli.ShowAppHelp(c)
	}

	var wg sync.WaitGroup
	contents := make(chan string)
	for _, candidate := range args {
		wg.Add(1)
		go func(candidate string) {
			defer wg.Done()
			candidate = upperFirstChar(candidate)
			content := tryGetTemplate(candidate)

			if content != "" {
				contents <- fmt.Sprintf("# %s\n%s", candidate, content)
			}
		}(candidate)
	}
	go func() {
		wg.Wait()
		close(contents)
	}()

	for content := range contents {
		fmt.Fprintln(output, content)
	}
}

func list(c *cli.Context) {
	fmt.Fprintln(c.App.Writer, listTemplates())
}

func tryGetTemplate(template string) string {
	var resp *http.Response

	if template == "JetBrains-build" {
		resp = get("https://raw.githubusercontent.com/github/gitignore/38d6cac990a82a1f7814571634e08295086763b5/Global/JetBrains.gitignore")
	} else {
		resp = get(fmt.Sprintf("https://raw.githubusercontent.com/github/gitignore/master/%s.gitignore", template))
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusNotFound {
		resp = get(fmt.Sprintf("https://raw.githubusercontent.com/github/gitignore/master/Global/%s.gitignore", template))
	}

	if resp.StatusCode != http.StatusOK {
		logger.Fatal("Cannot find a template for: ", template)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Fatal(err)
	}

	return string(body)
}

func get(url string) (resp *http.Response) {
	resp, err := http.Get(url)
	if err != nil {
		logger.Fatal(err)
	}

	return resp
}

func upperFirstChar(str string) string {
	a := []rune(str)
	firstChar := a[0]

	if unicode.IsUpper(firstChar) {
		return str
	}
	a[0] = unicode.ToUpper(firstChar)
	return string(a)
}

func listTemplates() string {
	templates := make([]string, 0)
	templates = getAndAppend(templates, "https://api.github.com/repos/github/gitignore/contents/")
	templates = getAndAppend(templates, "https://api.github.com/repos/github/gitignore/contents/Global")
	templates = append(templates, "JetBrains-build")
	sort.Strings(templates)
	return strings.Join(templates, ", ")
}

func getAndAppend(templates []string, url string) []string {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		logger.Fatal(err)
	}
	req.Header.Add("Accept", "application/vnd.github.v3+json")

	resp, err := client.Do(req)
	if err != nil {
		logger.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		logger.Fatal("Cannot list templates: ", resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Fatal(err)
	}

	result := make([]GitIgnoreTemplate, 0)
	if err := json.Unmarshal(body, &result); err != nil {
		logger.Fatal(err)
	}

	for _, template := range result {
		if template.Name != "" && strings.Contains(template.Name, ".gitignore") {
			templates = append(templates, strings.Replace(template.Name, ".gitignore", "", 1))
		}
	}

	return templates
}

type GitIgnoreTemplate struct {
	Name string `json:"name"`
}
<|endoftext|>


<commit_before>package gown

import (
    //"fmt"
    "testing"
)

func TestLoadSenseIndex(t *testing.T) {
    dictDir, _ := GetWordNetDictDir()
    senseIndexFile := dictDir + "/index.sense"
    senseIndex, err := loadSenseIndex(senseIndexFile)
    if senseIndex == nil {
        t.Fatalf("Failed to load sense index: %v", err)
    }

    // ------------------------------------------------------------------------
    // validate "computer"
    /*
    computer: {1  6 0 0 3086983 1 6} { NOUN, file: noun.artifact, lex_id: 0 head: , head_id: 0, synset_offset: 3086983, sense_number: 1, tag_cnt: 6 }
    computer: {1 18 0 0 9906486 2 0} { NOUN, file: noun.person,   lex_id: 0 head: , head_id: 0, synset_offset: 9906486, sense_number: 2, tag_cnt: 0 }
    */
    computerLemmas, _ := (*senseIndex)["computer"]
    if computerLemmas == nil || len(computerLemmas) == 0 {
        t.Fatalf("\"computer\" not found in sense index. Not loaded correctly?")
    }
    if len(computerLemmas) != 2 {
        t.Fatalf("expected 2 lemmas for \"computer\", but got %d\n", len(computerLemmas))
    }
    expected_computer_pos := map[int]int { POS_NOUN: 2 }
    actual_computer_pos := map[int]int {}
    expected_computer_files := map[string]int {
        "noun.artifact": 1,
        "noun.person": 1,
    }
    actual_computer_files := map[string]int {}
    for _, lemma_index := range computerLemmas {
        //fmt.Printf("%s: %v %s\n", "computer", lemma_index, lemma_index.ToString())
        actual_computer_pos[lemma_index.PartOfSpeech]++
        actual_computer_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "computer", expected_computer_pos, actual_computer_pos)
    validate_counts(t, "computer", expected_computer_files, actual_computer_files)
    //fmt.Printf("\n")

    // ------------------------------------------------------------------------
    // validate "live"
    /*
    live%2:31:00:: 00598039 6 1
    live%2:42:00:: 02620216 5 14
    live%2:42:01:: 02622766 4 16
    live%2:42:04:: 02624202 3 29
    live%2:42:06:: 02620422 2 51
    live%2:42:07:: 02621023 7 0
    live%2:42:08:: 02655932 1 129
    live%3:00:00:: 00095301 3 0
    live%3:00:01:: 00100143 2 0
    live%3:00:02:: 01425429 1 6
    live%4:02:00:: 00260451 1 0
    live%5:00:00:charged:00 00359472 10 0
    live%5:00:00:current:00 00670576 9 0
    live%5:00:00:elastic:00 00847134 6 0
    live%5:00:00:lively:00 00809813 7 0
    live%5:00:00:loaded:00 01427469 5 0
    live%5:00:00:reverberant:00 02017537 4 0
    live%5:00:02:current:00 00670686 8 0
    live%5:00:07:active:05 00041710 11 0
    */
    liveLemmas, _ := (*senseIndex)["live"]
    if liveLemmas == nil || len(liveLemmas) == 0 {
        t.Fatalf("\"live\" not found in sense index. Not loaded correctly?")
    }
    if len(liveLemmas) != 19 {
        t.Fatalf("expected 19 lemmas for \"live\", but got %d\n", len(liveLemmas))
    }
    expected_live_pos := map[int]int {
        POS_VERB: 7,
        POS_ADJECTIVE: 3,
        POS_ADVERB: 1,
        POS_ADJECTIVE_SATELLITE: 8,
    }
    actual_live_pos := map[int]int {}
    expected_live_files := map[string]int {
        "verb.cognition": 1,
        "verb.stative": 6,
        "adj.all": 11,
        "adv.all": 1,
    }
    actual_live_files := map[string]int {}
    for _, lemma_index := range liveLemmas {
        //fmt.Printf("%s: %v %s\n", "live", lemma_index, lemma_index.ToString())
        actual_live_pos[lemma_index.PartOfSpeech]++
        actual_live_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "live", expected_live_pos, actual_live_pos)
    validate_counts(t, "live", expected_live_files, actual_live_files)

    // ------------------------------------------------------------------------
    // validate "Angus"
    /*
    02408581 05 n 03 Aberdeen_Angus 0 Angus 0 black_Angus 0 001 @ 02406838 n 0000 | black hornless breed from Scotland
    */
    angusLemmas, _ := (*senseIndex)["angus"]
    //fmt.Printf("angusLemmas = %v\n", angusLemmas)
    if angusLemmas == nil || len(angusLemmas) == 0 {
        t.Fatalf("\"angus\" not found in sense index. Not loaded correctly?")
    }
    if len(angusLemmas) != 2 {
        t.Fatalf("expected 2 lemmas for \"angus\", but got %d\n", len(angusLemmas))
    }
    expected_angus_pos := map[int]int { POS_NOUN: 2 }
    actual_angus_pos := map[int]int {}
    expected_angus_files := map[string]int {
        "noun.animal": 1,
        "noun.person": 1,
    }
    actual_angus_files := map[string]int {}
    for _, lemma_index := range angusLemmas {
        //fmt.Printf("%s: %v %s\n", "angus", lemma_index, lemma_index.ToString())
        actual_angus_pos[lemma_index.PartOfSpeech]++
        actual_angus_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "angus", expected_angus_pos, actual_angus_pos)
    validate_counts(t, "angus", expected_angus_files, actual_angus_files)
    //fmt.Printf("\n")
}

func validate_pos(t *testing.T, word string, expected map[int]int, actual map[int]int) {
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
}

func validate_counts(t *testing.T, word string, expected map[string]int, actual map[string]int) {
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
}
<commit_msg>convert printfs in test to logfs<commit_after>package gown

import (
    "testing"
)

func TestLoadSenseIndex(t *testing.T) {
    dictDir, _ := GetWordNetDictDir()
    senseIndexFile := dictDir + "/index.sense"
    senseIndex, err := loadSenseIndex(senseIndexFile)
    if senseIndex == nil {
        t.Fatalf("Failed to load sense index: %v", err)
    }

    // ------------------------------------------------------------------------
    // validate "computer"
    /*
    computer: {1  6 0 0 3086983 1 6} { NOUN, file: noun.artifact, lex_id: 0 head: , head_id: 0, synset_offset: 3086983, sense_number: 1, tag_cnt: 6 }
    computer: {1 18 0 0 9906486 2 0} { NOUN, file: noun.person,   lex_id: 0 head: , head_id: 0, synset_offset: 9906486, sense_number: 2, tag_cnt: 0 }
    */
    computerLemmas, _ := (*senseIndex)["computer"]
    if computerLemmas == nil || len(computerLemmas) == 0 {
        t.Fatalf("\"computer\" not found in sense index. Not loaded correctly?")
    }
    if len(computerLemmas) != 2 {
        t.Fatalf("expected 2 lemmas for \"computer\", but got %d\n", len(computerLemmas))
    }
    expected_computer_pos := map[int]int { POS_NOUN: 2 }
    actual_computer_pos := map[int]int {}
    expected_computer_files := map[string]int {
        "noun.artifact": 1,
        "noun.person": 1,
    }
    actual_computer_files := map[string]int {}
    for _, lemma_index := range computerLemmas {
        t.Logf("%s: %v %s\n", "computer", lemma_index, lemma_index.ToString())
        actual_computer_pos[lemma_index.PartOfSpeech]++
        actual_computer_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "computer", expected_computer_pos, actual_computer_pos)
    validate_counts(t, "computer", expected_computer_files, actual_computer_files)
    t.Logf("\n")

    // ------------------------------------------------------------------------
    // validate "live"
    /*
    live%2:31:00:: 00598039 6 1
    live%2:42:00:: 02620216 5 14
    live%2:42:01:: 02622766 4 16
    live%2:42:04:: 02624202 3 29
    live%2:42:06:: 02620422 2 51
    live%2:42:07:: 02621023 7 0
    live%2:42:08:: 02655932 1 129
    live%3:00:00:: 00095301 3 0
    live%3:00:01:: 00100143 2 0
    live%3:00:02:: 01425429 1 6
    live%4:02:00:: 00260451 1 0
    live%5:00:00:charged:00 00359472 10 0
    live%5:00:00:current:00 00670576 9 0
    live%5:00:00:elastic:00 00847134 6 0
    live%5:00:00:lively:00 00809813 7 0
    live%5:00:00:loaded:00 01427469 5 0
    live%5:00:00:reverberant:00 02017537 4 0
    live%5:00:02:current:00 00670686 8 0
    live%5:00:07:active:05 00041710 11 0
    */
    liveLemmas, _ := (*senseIndex)["live"]
    if liveLemmas == nil || len(liveLemmas) == 0 {
        t.Fatalf("\"live\" not found in sense index. Not loaded correctly?")
    }
    if len(liveLemmas) != 19 {
        t.Fatalf("expected 19 lemmas for \"live\", but got %d\n", len(liveLemmas))
    }
    expected_live_pos := map[int]int {
        POS_VERB: 7,
        POS_ADJECTIVE: 3,
        POS_ADVERB: 1,
        POS_ADJECTIVE_SATELLITE: 8,
    }
    actual_live_pos := map[int]int {}
    expected_live_files := map[string]int {
        "verb.cognition": 1,
        "verb.stative": 6,
        "adj.all": 11,
        "adv.all": 1,
    }
    actual_live_files := map[string]int {}
    for _, lemma_index := range liveLemmas {
        t.Logf("%s: %v %s\n", "live", lemma_index, lemma_index.ToString())
        actual_live_pos[lemma_index.PartOfSpeech]++
        actual_live_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "live", expected_live_pos, actual_live_pos)
    validate_counts(t, "live", expected_live_files, actual_live_files)
    t.Logf("\n")

    // ------------------------------------------------------------------------
    // validate "Angus"
    /*
    02408581 05 n 03 Aberdeen_Angus 0 Angus 0 black_Angus 0 001 @ 02406838 n 0000 | black hornless breed from Scotland
    */
    angusLemmas, _ := (*senseIndex)["angus"]
    t.Logf("angusLemmas = %v\n", angusLemmas)
    if angusLemmas == nil || len(angusLemmas) == 0 {
        t.Fatalf("\"angus\" not found in sense index. Not loaded correctly?")
    }
    if len(angusLemmas) != 2 {
        t.Fatalf("expected 2 lemmas for \"angus\", but got %d\n", len(angusLemmas))
    }
    expected_angus_pos := map[int]int { POS_NOUN: 2 }
    actual_angus_pos := map[int]int {}
    expected_angus_files := map[string]int {
        "noun.animal": 1,
        "noun.person": 1,
    }
    actual_angus_files := map[string]int {}
    for _, lemma_index := range angusLemmas {
        t.Logf("%s: %v %s\n", "angus", lemma_index, lemma_index.ToString())
        actual_angus_pos[lemma_index.PartOfSpeech]++
        actual_angus_files[LEXOGRAPHER_FILE_NUM_TO_NAME[lemma_index.LexographerFilenum]]++
    }
    validate_pos(t, "angus", expected_angus_pos, actual_angus_pos)
    validate_counts(t, "angus", expected_angus_files, actual_angus_files)
    t.Logf("\n")
}

func validate_pos(t *testing.T, word string, expected map[int]int, actual map[int]int) {
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected pos %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
}

func validate_counts(t *testing.T, word string, expected map[string]int, actual map[string]int) {
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
    for k, v := range actual {
        if expected[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, expected[k], v)
        }
    }
    for k, v := range expected {
        if actual[k] != v {
            t.Fatalf("%v expected file %v with count %v, but had %v", word, k, actual[k], v)
        }
    }
}
<|endoftext|>


<commit_before>package versions

import "strconv"

// Version is the ID of a Dwarf Fortress save version.
type Version uint32

// Versions is a map of all known save versions to the corresponding release's
// version number.
var Versions = map[Version]string{
	1107: "0.21.93.19a",
	1108: "0.21.93.19c",
	// => "0.21.95.19a",
	// => "0.21.95.19b",
	1110: "0.21.95.19c",
	// => "0.21.100.19a",
	1113: "0.21.101.19a",
	1114: "0.21.101.19d",
	1117: "0.21.102.19a",
	1119: "0.21.104.19b",
	1121: "0.21.104.19d",
	1123: "0.21.104.21a",
	1125: "0.21.104.21b",
	1128: "0.21.105.21a",
	// => "0.22.107.21a",
	1134: "0.22.110.22e",
	1137: "0.22.110.22f",
	1148: "0.22.110.23a",
	1151: "0.22.120.23a",
	1161: "0.22.121.23b",
	1165: "0.22.123.23a",
	1169: "0.23.130.23a",

	1205: "0.27.169.32a",
	1206: "0.27.169.33a",
	1209: "0.27.169.33b",
	1211: "0.27.169.33c",
	1212: "0.27.169.33d",
	1213: "0.27.169.33e",
	1215: "0.27.169.33f",
	1216: "0.27.169.33g",
	1223: "0.27.173.38a",
	1231: "0.27.176.38a",
	1234: "0.27.176.38b",
	1235: "0.27.176.38c",
	1254: "0.28.181.39a",
	1255: "0.28.181.39b",
	1256: "0.28.181.39c",
	1259: "0.28.181.39d",
	1260: "0.28.181.39e",
	1261: "0.28.181.39f",
	1265: "0.28.181.40a",
	1266: "0.28.181.40b",
	1267: "0.28.181.40c",
	1268: "0.28.181.40d",

	1287: "0.31.01",
	1288: "0.31.02",
	1289: "0.31.03",
	1292: "0.31.04",
	1295: "0.31.05",
	1297: "0.31.06",
	1300: "0.31.08",
	1304: "0.31.09",
	1305: "0.31.10",
	1310: "0.31.11",
	1311: "0.31.12",
	1323: "0.31.13",
	1325: "0.31.14",
	1326: "0.31.15",
	1327: "0.31.16",
	1340: "0.31.17",
	1341: "0.31.18",
	1351: "0.31.19",
	1353: "0.31.20",
	1354: "0.31.21",
	1359: "0.31.22",
	1360: "0.31.23",
	1361: "0.31.24",
	1362: "0.31.25",

	1372: "0.34.01",
	1374: "0.34.02",
	1376: "0.34.03",
	1377: "0.34.04",
	1378: "0.34.05",
	1382: "0.34.06",
	1383: "0.34.07",
	1400: "0.34.08",
	1402: "0.34.09",
	1403: "0.34.10",
	1404: "0.34.11",

	1441: "0.40.01",
	1442: "0.40.02",
	1443: "0.40.03",
	1444: "0.40.04",
	1445: "0.40.05",
	1446: "0.40.06",
	1448: "0.40.07",
	1449: "0.40.08",
	1451: "0.40.09",
	1452: "0.40.10",
	1456: "0.40.11",
	1459: "0.40.12",
	1462: "0.40.13",
	1469: "0.40.14",
	1470: "0.40.15",
	1471: "0.40.16",
	1472: "0.40.17",
	1473: "0.40.18",
	1474: "0.40.19",
	1477: "0.40.20",
	1478: "0.40.21",
	1479: "0.40.22",
	1480: "0.40.23",
	1481: "0.40.24",

	1531: "0.42.01",
	1532: "0.42.02",
	1533: "0.42.03",
	1534: "0.42.04",
	1537: "0.42.05",
	1542: "0.42.06",

	1551: "0.43.01",
}

// IsKnown returns true if v is a known version number.
func (v Version) IsKnown() bool {
	_, ok := Versions[v]
	return ok
}

// String implements fmt.Stringer.
func (v Version) String() string {
	if s, ok := Versions[v]; ok {
		return s
	}

	return strconv.Itoa(int(v))
}
<commit_msg>update versions<commit_after>package versions

import "strconv"

// Version is the ID of a Dwarf Fortress save version.
type Version uint32

// Versions is a map of all known save versions to the corresponding release's
// version number.
var Versions = map[Version]string{
	1107: "0.21.93.19a",
	1108: "0.21.93.19c",
	// => "0.21.95.19a",
	// => "0.21.95.19b",
	1110: "0.21.95.19c",
	// => "0.21.100.19a",
	1113: "0.21.101.19a",
	1114: "0.21.101.19d",
	1117: "0.21.102.19a",
	1119: "0.21.104.19b",
	1121: "0.21.104.19d",
	1123: "0.21.104.21a",
	1125: "0.21.104.21b",
	1128: "0.21.105.21a",
	// => "0.22.107.21a",
	1134: "0.22.110.22e",
	1137: "0.22.110.22f",
	1148: "0.22.110.23a",
	1151: "0.22.120.23a",
	1161: "0.22.121.23b",
	1165: "0.22.123.23a",
	1169: "0.23.130.23a",

	1205: "0.27.169.32a",
	1206: "0.27.169.33a",
	1209: "0.27.169.33b",
	1211: "0.27.169.33c",
	1212: "0.27.169.33d",
	1213: "0.27.169.33e",
	1215: "0.27.169.33f",
	1216: "0.27.169.33g",
	1223: "0.27.173.38a",
	1231: "0.27.176.38a",
	1234: "0.27.176.38b",
	1235: "0.27.176.38c",
	1254: "0.28.181.39a",
	1255: "0.28.181.39b",
	1256: "0.28.181.39c",
	1259: "0.28.181.39d",
	1260: "0.28.181.39e",
	1261: "0.28.181.39f",
	1265: "0.28.181.40a",
	1266: "0.28.181.40b",
	1267: "0.28.181.40c",
	1268: "0.28.181.40d",

	1287: "0.31.01",
	1288: "0.31.02",
	1289: "0.31.03",
	1292: "0.31.04",
	1295: "0.31.05",
	1297: "0.31.06",
	1300: "0.31.08",
	1304: "0.31.09",
	1305: "0.31.10",
	1310: "0.31.11",
	1311: "0.31.12",
	1323: "0.31.13",
	1325: "0.31.14",
	1326: "0.31.15",
	1327: "0.31.16",
	1340: "0.31.17",
	1341: "0.31.18",
	1351: "0.31.19",
	1353: "0.31.20",
	1354: "0.31.21",
	1359: "0.31.22",
	1360: "0.31.23",
	1361: "0.31.24",
	1362: "0.31.25",

	1372: "0.34.01",
	1374: "0.34.02",
	1376: "0.34.03",
	1377: "0.34.04",
	1378: "0.34.05",
	1382: "0.34.06",
	1383: "0.34.07",
	1400: "0.34.08",
	1402: "0.34.09",
	1403: "0.34.10",
	1404: "0.34.11",

	1441: "0.40.01",
	1442: "0.40.02",
	1443: "0.40.03",
	1444: "0.40.04",
	1445: "0.40.05",
	1446: "0.40.06",
	1448: "0.40.07",
	1449: "0.40.08",
	1451: "0.40.09",
	1452: "0.40.10",
	1456: "0.40.11",
	1459: "0.40.12",
	1462: "0.40.13",
	1469: "0.40.14",
	1470: "0.40.15",
	1471: "0.40.16",
	1472: "0.40.17",
	1473: "0.40.18",
	1474: "0.40.19",
	1477: "0.40.20",
	1478: "0.40.21",
	1479: "0.40.22",
	1480: "0.40.23",
	1481: "0.40.24",

	1531: "0.42.01",
	1532: "0.42.02",
	1533: "0.42.03",
	1534: "0.42.04",
	1537: "0.42.05",
	1542: "0.42.06",

	1551: "0.43.01",
	1552: "0.43.02",
}

// IsKnown returns true if v is a known version number.
func (v Version) IsKnown() bool {
	_, ok := Versions[v]
	return ok
}

// String implements fmt.Stringer.
func (v Version) String() string {
	if s, ok := Versions[v]; ok {
		return s
	}

	return strconv.Itoa(int(v))
}
<|endoftext|>


<commit_before>package handlers

import (
	"os"
	"os/exec"
	"testing"

	"github.com/anonx/sunplate/command"
)

func TestStart(t *testing.T) {
	Start(command.Data{
		"--input":   "./testdata/controllers",
		"--output":  "./testdata/assets/handlers",
		"--package": "handlers",
	})

	cmd := exec.Command("go", "build", "./testdata/assets/handlers")
	cmd.Stderr = os.Stderr // Show the output of the program we run.
	if err := cmd.Run(); err != nil {
		t.Errorf(`There are problems with generated handlers, error: "%s".`, err)
	}

	// Remove the directory we have created.
	os.RemoveAll("./testdata/assets")
}
<commit_msg>Download dependencies when testing generated handlers<commit_after>package handlers

import (
	"os"
	"os/exec"
	"testing"

	"github.com/anonx/sunplate/command"
)

func TestStart(t *testing.T) {
	Start(command.Data{
		"--input":   "./testdata/controllers",
		"--output":  "./testdata/assets/handlers",
		"--package": "handlers",
	})

	cmd := exec.Command("go", "get", "-t", "./testdata/assets/handlers/...")
	cmd.Stderr = os.Stderr // Show the output of the program we run.
	if err := cmd.Run(); err != nil {
		t.Errorf(`There are problems with generated handlers, error: "%s".`, err)
	}

	// Remove the directory we have created.
	os.RemoveAll("./testdata/assets")
}
<|endoftext|>


<commit_before>package system

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/Masterminds/semver/v3"
	"github.com/rancher/rancher/pkg/api/steve/catalog/types"
	catalog "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1"
	"github.com/rancher/rancher/pkg/catalogv2/content"
	"github.com/rancher/rancher/pkg/catalogv2/helmop"
	corev1 "github.com/rancher/rancher/pkg/generated/norman/core/v1"
	corecontrollers "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/sirupsen/logrus"
	"helm.sh/helm/v3/pkg/action"
	release2 "helm.sh/helm/v3/pkg/release"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/equality"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apiserver/pkg/authentication/user"
	"k8s.io/cli-runtime/pkg/genericclioptions"
)

var (
	installUser = &user.DefaultInfo{
		Name: "helm-installer",
		UID:  "helm-installer",
		Groups: []string{
			"system:masters",
		},
	}
)

type Manager struct {
	ctx              context.Context
	operation        *helmop.Operations
	content          *content.Manager
	restClientGetter genericclioptions.RESTClientGetter
	pods             corecontrollers.PodClient
}

func NewManager(ctx context.Context,
	restClientGetter genericclioptions.RESTClientGetter,
	contentManager *content.Manager,
	ops *helmop.Operations,
	pods corecontrollers.PodClient) (*Manager, error) {

	return &Manager{
		ctx:              ctx,
		operation:        ops,
		content:          contentManager,
		restClientGetter: restClientGetter,
		pods:             pods,
	}, nil
}

func (m *Manager) Ensure(namespace, name, version string, values map[string]interface{}) error {
	if ok, err := m.isInstalled(namespace, name, version, values); err != nil {
		return err
	} else if ok {
		return nil
	}

	upgrade, err := json.Marshal(types.ChartUpgradeAction{
		Timeout:    &metav1.Duration{Duration: 5 * time.Minute},
		Wait:       true,
		Install:    true,
		MaxHistory: 5,
		Charts: []types.ChartUpgrade{
			{
				ChartName:   name,
				Version:     version,
				Namespace:   namespace,
				ReleaseName: name,
				Values:      values,
			},
		},
	})
	if err != nil {
		return err
	}

	op, err := m.operation.Upgrade(m.ctx, installUser, "", "rancher-charts", bytes.NewBuffer(upgrade))
	if err != nil {
		return err
	}

	return m.waitPodDone(op)
}

func (m *Manager) waitPodDone(op *catalog.Operation) error {
	pod, err := m.pods.Get(op.Status.PodNamespace, op.Status.PodName, metav1.GetOptions{})
	if err != nil {
		return err
	}

	if ok, err := podDone(op.Status.Chart, pod); err != nil {
		return err
	} else if ok {
		return nil
	}

	sec := int64(60)
	resp, err := m.pods.Watch(op.Status.PodNamespace, metav1.ListOptions{
		FieldSelector:   "metadata.name=" + pod.Name,
		ResourceVersion: pod.ResourceVersion,
		TimeoutSeconds:  &sec,
	})
	if err != nil {
		return err
	}
	defer func() {
		go func() {
			for range resp.ResultChan() {
			}
		}()
		resp.Stop()
	}()

	for event := range resp.ResultChan() {
		newPod, ok := event.Object.(*v1.Pod)
		if !ok {
			continue
		}
		if ok, err := podDone(op.Status.Chart, newPod); err != nil {
			return err
		} else if ok {
			return nil
		}
	}

	return fmt.Errorf("pod %s/%s failed, watch closed", pod.Namespace, pod.Name)
}

func podDone(chart string, newPod *corev1.Pod) (bool, error) {
	for _, container := range newPod.Status.ContainerStatuses {
		if container.Name != "helm" {
			continue
		}
		if container.State.Terminated != nil {
			if container.State.Terminated.ExitCode == 0 {
				return true, nil
			}
			return false, fmt.Errorf("failed to install %s, pod %s/%s exited %d", chart,
				newPod.Namespace, newPod.Name, container.State.Terminated.ExitCode)
		}
	}
	return false, nil
}

func (m *Manager) isInstalled(namespace, name, version string, values map[string]interface{}) (bool, error) {
	helmcfg := &action.Configuration{}
	if err := helmcfg.Init(m.restClientGetter, namespace, "", logrus.Infof); err != nil {
		return false, err
	}

	l := action.NewList(helmcfg)
	l.Filter = name

	releases, err := l.Run()
	if err != nil {
		return false, err
	}

	con, err := semver.NewConstraint(version)
	if err != nil {
		return false, err
	}

	for _, release := range releases {
		if release.Name != name || release.Info.Status != release2.StatusDeployed {
			continue
		}

		ver, err := semver.NewVersion(release.Chart.Metadata.Version)
		if err != nil {
			return false, err
		}

		if con.Check(ver) && equality.Semantic.DeepEqual(values, release.Config) {
			return true, nil
		}
	}

	return false, nil
}
<commit_msg>Handle situation when trying to upgrade a pending-install chart<commit_after>package system

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/Masterminds/semver/v3"
	"github.com/rancher/rancher/pkg/api/steve/catalog/types"
	catalog "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1"
	"github.com/rancher/rancher/pkg/catalogv2/content"
	"github.com/rancher/rancher/pkg/catalogv2/helmop"
	corev1 "github.com/rancher/rancher/pkg/generated/norman/core/v1"
	corecontrollers "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/sirupsen/logrus"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/release"
	release2 "helm.sh/helm/v3/pkg/release"
	"helm.sh/helm/v3/pkg/storage"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/equality"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apiserver/pkg/authentication/user"
	"k8s.io/cli-runtime/pkg/genericclioptions"
)

var (
	installUser = &user.DefaultInfo{
		Name: "helm-installer",
		UID:  "helm-installer",
		Groups: []string{
			"system:masters",
		},
	}
)

type Manager struct {
	ctx              context.Context
	operation        *helmop.Operations
	content          *content.Manager
	restClientGetter genericclioptions.RESTClientGetter
	pods             corecontrollers.PodClient
}

func NewManager(ctx context.Context,
	restClientGetter genericclioptions.RESTClientGetter,
	contentManager *content.Manager,
	ops *helmop.Operations,
	pods corecontrollers.PodClient) (*Manager, error) {

	return &Manager{
		ctx:              ctx,
		operation:        ops,
		content:          contentManager,
		restClientGetter: restClientGetter,
		pods:             pods,
	}, nil
}

func (m *Manager) Ensure(namespace, name, version string, values map[string]interface{}) error {
	if ok, err := m.isInstalled(namespace, name, version, values); err != nil {
		return err
	} else if ok {
		return nil
	}

	if ok, relName, err := m.isPendingUninstall(namespace, name); err != nil {
		return err
	} else if ok {
		uninstall, err := json.Marshal(types.ChartUninstallAction{
			Timeout: &metav1.Duration{Duration: 5 * time.Minute},
		})
		if err != nil {
			return err
		}

		op, err := m.operation.Uninstall(m.ctx, installUser, namespace, relName, bytes.NewBuffer(uninstall))
		if err != nil {
			return err
		}

		if err := m.waitPodDone(op); err != nil {
			return err
		}
	}

	upgrade, err := json.Marshal(types.ChartUpgradeAction{
		Timeout:    &metav1.Duration{Duration: 5 * time.Minute},
		Wait:       true,
		Install:    true,
		MaxHistory: 5,
		Charts: []types.ChartUpgrade{
			{
				ChartName:   name,
				Version:     version,
				Namespace:   namespace,
				ReleaseName: name,
				Values:      values,
				ResetValues: true,
			},
		},
	})
	if err != nil {
		return err
	}

	op, err := m.operation.Upgrade(m.ctx, installUser, "", "rancher-charts", bytes.NewBuffer(upgrade))
	if err != nil {
		return err
	}

	return m.waitPodDone(op)
}

func (m *Manager) waitPodDone(op *catalog.Operation) error {
	pod, err := m.pods.Get(op.Status.PodNamespace, op.Status.PodName, metav1.GetOptions{})
	if err != nil {
		return err
	}

	if ok, err := podDone(op.Status.Chart, pod); err != nil {
		return err
	} else if ok {
		return nil
	}

	sec := int64(60)
	resp, err := m.pods.Watch(op.Status.PodNamespace, metav1.ListOptions{
		FieldSelector:   "metadata.name=" + pod.Name,
		ResourceVersion: pod.ResourceVersion,
		TimeoutSeconds:  &sec,
	})
	if err != nil {
		return err
	}
	defer func() {
		go func() {
			for range resp.ResultChan() {
			}
		}()
		resp.Stop()
	}()

	for event := range resp.ResultChan() {
		newPod, ok := event.Object.(*v1.Pod)
		if !ok {
			continue
		}
		if ok, err := podDone(op.Status.Chart, newPod); err != nil {
			return err
		} else if ok {
			return nil
		}
	}

	return fmt.Errorf("pod %s/%s failed, watch closed", pod.Namespace, pod.Name)
}

func podDone(chart string, newPod *corev1.Pod) (bool, error) {
	for _, container := range newPod.Status.ContainerStatuses {
		if container.Name != "helm" {
			continue
		}
		if container.State.Terminated != nil {
			if container.State.Terminated.ExitCode == 0 {
				return true, nil
			}
			return false, fmt.Errorf("failed to install %s, pod %s/%s exited %d", chart,
				newPod.Namespace, newPod.Name, container.State.Terminated.ExitCode)
		}
	}
	return false, nil
}

func (m *Manager) isInstalled(namespace, name, version string, values map[string]interface{}) (bool, error) {
	helmcfg := &action.Configuration{}
	if err := helmcfg.Init(m.restClientGetter, namespace, "", logrus.Infof); err != nil {
		return false, err
	}

	l := action.NewList(helmcfg)
	l.Filter = "^" + name + "$"

	releases, err := l.Run()
	if err != nil {
		return false, err
	}

	con, err := semver.NewConstraint(version)
	if err != nil {
		return false, err
	}

	for _, release := range releases {
		if release.Info.Status != release2.StatusDeployed {
			continue
		}

		ver, err := semver.NewVersion(release.Chart.Metadata.Version)
		if err != nil {
			return false, err
		}

		if con.Check(ver) && equality.Semantic.DeepEqual(values, release.Config) {
			return true, nil
		}
	}

	return false, nil
}

func (m *Manager) isPendingUninstall(namespace, name string) (bool, string, error) {
	helmcfg := &action.Configuration{}
	if err := helmcfg.Init(m.restClientGetter, namespace, "", logrus.Infof); err != nil {
		return false, "", err
	}

	l := action.NewList(helmcfg)
	l.Filter = "^" + name + "$"
	l.Pending = true
	l.SetStateMask()

	releases, err := l.Run()
	if err != nil {
		return false, "", err
	}

	for _, release := range releases {
		if release.Info.Status == release2.StatusPendingInstall {
			return true, releaseName(release), nil
		}
	}

	return false, "", nil
}

// releaseName will create the internal name of the release stored in secrets.  This is a bit hacky
// but we only use one storage backend so, oh well.
func releaseName(release *release.Release) string {
	return fmt.Sprintf("%s.%s.v%d", storage.HelmStorageType, release.Name, release.Version)
}
<|endoftext|>


<commit_before>// Copyright 2018 the Service Broker Project 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 generator

import (
	"bytes"
	"log"
	"text/template"

	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/config/migration"
	"github.com/GoogleCloudPlatform/gcp-service-broker/utils"
)

const (
	appName         = "gcp-service-broker"
	appDescription  = "A service broker for Google Cloud Platform services."
	stemcellOs      = "ubuntu-xenial"
	stemcellVersion = "170.82"

	buildpack     = "go_buildpack"
	goPackageName = "github.com/GoogleCloudPlatform/gcp-service-broker"
	goVersion     = "go1.12"

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

# This file is AUTOGENERATED by ./gcp-service-broker generate, DO NOT EDIT IT.

---`
	manifestYmlTemplate = copyrightHeader + `
applications:
- name: {{.appName}}
  memory: 1G
  buildpack: {{.buildpack}}
  env:
    GOPACKAGENAME: {{.goPackageName}}
    GOVERSION: {{.goVersion}}`
	tileYmlTemplate = copyrightHeader + `
name: {{.appName}}
icon_file: gcp_logo.png
label: Google Cloud Platform Service Broker
description: '{{.appDescription}}'
product_version: "{{.appVersion}}"
org: system

stemcell_criteria:
  os: '{{.stemcellOs}}'
  version: '{{.stemcellVersion}}'

apply_open_security_group: true

migration: |
{{.migrationScript}}

packages:
- name: {{.appName}}
  type: app-broker
  manifest:
    buildpacks:
    - {{.buildpack}}
    path: /tmp/gcp-service-broker.zip
    env:
      GOPACKAGENAME: {{.goPackageName}}
      GOVERSION: {{.goVersion}}
      # You can override plans here.
  needs_cf_credentials: true
  enable_global_access_to_plans: true

# Uncomment this section if you want to display forms with configurable
# properties in Ops Manager. These properties will be passed to your
# applications as environment variables. You can also refer to them
# elsewhere in this template by using:
#     (( .properties.<property-name> ))
`
)

// GenerateManifest creates a manifest.yml from a template.
func GenerateManifest() string {
	return runPcfTemplate(manifestYmlTemplate)
}

// GenerateTile creates a tile.yml from a template.
func GenerateTile() string {
	return runPcfTemplate(tileYmlTemplate) + GenerateFormsString()
}

func runPcfTemplate(templateString string) string {
	migrator := migration.FullMigration()

	vars := map[string]interface{}{
		"appName":         appName,
		"appVersion":      utils.Version,
		"appDescription":  appDescription,
		"buildpack":       buildpack,
		"goPackageName":   goPackageName,
		"goVersion":       goVersion,
		"stemcellOs":      stemcellOs,
		"stemcellVersion": stemcellVersion,
		"migrationScript": utils.Indent(migrator.TileScript, "  "),
	}

	tmpl, err := template.New("tmpl").Parse(templateString)
	if err != nil {
		log.Fatalf("parsing: %s", err)
	}

	// Run the template to verify the output.
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, vars)
	if err != nil {
		log.Fatalf("execution: %s", err)
	}

	return buf.String()
}
<commit_msg>cmd: rename buildpacks->buildpack<commit_after>// Copyright 2018 the Service Broker Project 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 generator

import (
	"bytes"
	"log"
	"text/template"

	"github.com/GoogleCloudPlatform/gcp-service-broker/pkg/config/migration"
	"github.com/GoogleCloudPlatform/gcp-service-broker/utils"
)

const (
	appName         = "gcp-service-broker"
	appDescription  = "A service broker for Google Cloud Platform services."
	stemcellOs      = "ubuntu-xenial"
	stemcellVersion = "170.82"

	buildpack     = "go_buildpack"
	goPackageName = "github.com/GoogleCloudPlatform/gcp-service-broker"
	goVersion     = "go1.12"

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

# This file is AUTOGENERATED by ./gcp-service-broker generate, DO NOT EDIT IT.

---`
	manifestYmlTemplate = copyrightHeader + `
applications:
- name: {{.appName}}
  memory: 1G
  buildpack: {{.buildpack}}
  env:
    GOPACKAGENAME: {{.goPackageName}}
    GOVERSION: {{.goVersion}}`
	tileYmlTemplate = copyrightHeader + `
name: {{.appName}}
icon_file: gcp_logo.png
label: Google Cloud Platform Service Broker
description: '{{.appDescription}}'
product_version: "{{.appVersion}}"
org: system

stemcell_criteria:
  os: '{{.stemcellOs}}'
  version: '{{.stemcellVersion}}'

apply_open_security_group: true

migration: |
{{.migrationScript}}

packages:
- name: {{.appName}}
  type: app-broker
  manifest:
    buildpack: {{.buildpack}}
    path: /tmp/gcp-service-broker.zip
    env:
      GOPACKAGENAME: {{.goPackageName}}
      GOVERSION: {{.goVersion}}
      # You can override plans here.
  needs_cf_credentials: true
  enable_global_access_to_plans: true

# Uncomment this section if you want to display forms with configurable
# properties in Ops Manager. These properties will be passed to your
# applications as environment variables. You can also refer to them
# elsewhere in this template by using:
#     (( .properties.<property-name> ))
`
)

// GenerateManifest creates a manifest.yml from a template.
func GenerateManifest() string {
	return runPcfTemplate(manifestYmlTemplate)
}

// GenerateTile creates a tile.yml from a template.
func GenerateTile() string {
	return runPcfTemplate(tileYmlTemplate) + GenerateFormsString()
}

func runPcfTemplate(templateString string) string {
	migrator := migration.FullMigration()

	vars := map[string]interface{}{
		"appName":         appName,
		"appVersion":      utils.Version,
		"appDescription":  appDescription,
		"buildpack":       buildpack,
		"goPackageName":   goPackageName,
		"goVersion":       goVersion,
		"stemcellOs":      stemcellOs,
		"stemcellVersion": stemcellVersion,
		"migrationScript": utils.Indent(migrator.TileScript, "  "),
	}

	tmpl, err := template.New("tmpl").Parse(templateString)
	if err != nil {
		log.Fatalf("parsing: %s", err)
	}

	// Run the template to verify the output.
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, vars)
	if err != nil {
		log.Fatalf("execution: %s", err)
	}

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