<commit_before>package commands

import cmds "github.com/jbenet/go-ipfs/commands"

type IpnsEntry struct {
	Name  string
	Value string
}

var nameCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "IPFS namespace (IPNS) tool",
		ShortDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.
`,
		LongDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.

Examples:

Publish a <ref> to your identity name:

  > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Publish a <ref> to another public key:

  > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve the value of your identity:

  > ipfs name resolve
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve the value of another name:

  > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

`,
	},

	Subcommands: map[string]*cmds.Command{
		"publish": publishCmd,
		"resolve": resolveCmd,
	},
}
<commit_msg>cmds2: name synopsis.<commit_after>package commands

import cmds "github.com/jbenet/go-ipfs/commands"

type IpnsEntry struct {
	Name  string
	Value string
}

var nameCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "IPFS namespace (IPNS) tool",
		Synopsis: `
ipfs name publish [<name>] <ipfs-path> - Publish an object to IPNS
ipfs name resolve [<name>]             - Gets the value currently published at an IPNS name
`,
		ShortDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.
`,
		LongDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.

Examples:

Publish a <ref> to your identity name:

  > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Publish a <ref> to another public key:

  > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve the value of your identity:

  > ipfs name resolve
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve the value of another name:

  > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

`,
	},

	Subcommands: map[string]*cmds.Command{
		"publish": publishCmd,
		"resolve": resolveCmd,
	},
}
<|endoftext|>


<commit_before>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

// +build linux

package procfs

import (
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/circonus-labs/circonus-agent/internal/builtins/collector"
	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/tags"
	cgm "github.com/circonus-labs/circonus-gometrics/v3"
	"github.com/pkg/errors"
	"github.com/rs/zerolog/log"
)

// Load metrics from the Linux ProcFS (actually from unix.Sysinfo call)
type Load struct {
	common
	processStatsFile string
}

// loadOptions defines what elements can be overridden in a config file
type loadOptions struct {
	// common
	ID                   string   `json:"id" toml:"id" yaml:"id"`
	ProcFSPath           string   `json:"procfs_path" toml:"procfs_path" yaml:"procfs_path"`
	MetricsEnabled       []string `json:"metrics_enabled" toml:"metrics_enabled" yaml:"metrics_enabled"`
	MetricsDisabled      []string `json:"metrics_disabled" toml:"metrics_disabled" yaml:"metrics_disabled"`
	MetricsDefaultStatus string   `json:"metrics_default_status" toml:"metrics_default_status" toml:"metrics_default_status"`
	RunTTL               string   `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"`
}

// NewLoadCollector creates new procfs load collector
func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, error) {
	procFile := NameLoad

	c := Load{}
	c.id = NameLoad
	c.pkgID = PKG_NAME + "." + c.id
	c.logger = log.With().Str("pkg", PKG_NAME).Str("id", c.id).Logger()
	c.procFSPath = procFSPath
	c.file = filepath.Join(c.procFSPath, procFile)
	c.processStatsFile = filepath.Join(c.procFSPath, "stat")
	c.baseTags = tags.FromList(tags.GetBaseTags())

	if cfgBaseName == "" {
		if _, err := os.Stat(c.file); os.IsNotExist(err) {
			return nil, errors.Wrap(err, c.pkgID)
		}
		return &c, nil
	}

	var opts loadOptions
	err := config.LoadConfigFile(cfgBaseName, &opts)
	if err != nil {
		if strings.Contains(err.Error(), "no config found matching") {
			return &c, nil
		}
		c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file")
		return nil, errors.Wrapf(err, "%s config", c.pkgID)
	}

	c.logger.Debug().Interface("config", opts).Msg("loaded config")

	if opts.ID != "" {
		c.id = opts.ID
	}

	if opts.ProcFSPath != "" {
		c.procFSPath = opts.ProcFSPath
		c.file = filepath.Join(c.procFSPath, procFile)
	}

	if opts.RunTTL != "" {
		dur, err := time.ParseDuration(opts.RunTTL)
		if err != nil {
			return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID)
		}
		c.runTTL = dur
	}

	if _, err := os.Stat(c.file); os.IsNotExist(err) {
		return nil, errors.Wrap(err, c.pkgID)
	}

	return &c, nil
}

// Collect metrics from the procfs resource
func (c *Load) Collect() error {
	metrics := cgm.Metrics{}

	c.Lock()

	if c.runTTL > time.Duration(0) {
		if time.Since(c.lastEnd) < c.runTTL {
			c.logger.Warn().Msg(collector.ErrTTLNotExpired.Error())
			c.Unlock()
			return collector.ErrTTLNotExpired
		}
	}
	if c.running {
		c.logger.Warn().Msg(collector.ErrAlreadyRunning.Error())
		c.Unlock()
		return collector.ErrAlreadyRunning
	}

	c.running = true
	c.lastStart = time.Now()
	c.Unlock()

	tagUnitsProcesses := tags.Tag{Category: "units", Value: "processes"}

	{
		// load metrics
		lines, err := c.readFile(c.file)
		if err != nil {
			c.setStatus(metrics, err)
			return errors.Wrap(err, c.pkgID)
		}

		metricType := "n"
		tagList := tags.Tags{tagUnitsProcesses}
		for _, l := range lines {
			line := string(l)
			fields := strings.Fields(line)

			if len(fields) < 3 {
				c.logger.Warn().Int("fields", len(fields)).Msg("invalid number of fields")
				continue
			}

			if v, err := strconv.ParseFloat(fields[0], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 1min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_1min", metricType, v, tagList)
			}

			if v, err := strconv.ParseFloat(fields[1], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 5min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_5min", metricType, v, tagList)
			}

			if v, err := strconv.ParseFloat(fields[2], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 15min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_15min", metricType, v, tagList)
			}
		}
	}

	{
		// process metrics
		lines, err := c.readFile(c.processStatsFile)
		if err != nil {
			c.setStatus(metrics, err)
			return errors.Wrap(err, c.pkgID)
		}

		var processes, running, blocked, ctxswitch uint64

		for _, l := range lines {
			var lineErr error
			line := string(l)
			fields := strings.Fields(line)

			switch fields[0] {
			case "processes":
				processes, lineErr = strconv.ParseUint(fields[1], 10, 64)

			case "procs_running":
				running, lineErr = strconv.ParseUint(fields[1], 10, 64)

			case "procs_blocked":
				blocked, lineErr = strconv.ParseUint(fields[1], 10, 64)

			case "ctxt":
				ctxswitch, lineErr = strconv.ParseUint(fields[1], 10, 64)
			default:
				continue
			}

			if lineErr != nil {
				c.setStatus(metrics, err)
				return errors.Wrapf(err, "%s parsing %s", c.pkgID, fields[0])
			}
		}

		metricType := "L"

		{
			tagList := tags.Tags{tagUnitsProcesses}
			c.addMetric(&metrics, "", "total", metricType, processes, tagList)
			c.addMetric(&metrics, "", "running", metricType, running, tagList)
			c.addMetric(&metrics, "", "blocked", metricType, blocked, tagList)
		}

		{
			tagList := tags.Tags{tags.Tag{Category: "units", Value: "switches"}}
			c.addMetric(&metrics, "", "ctxt", metricType, ctxswitch, tagList)
		}

	}

	c.setStatus(metrics, nil)
	return nil
}
<commit_msg>upd: reconcile naming<commit_after>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

// +build linux

package procfs

import (
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/circonus-labs/circonus-agent/internal/builtins/collector"
	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/tags"
	cgm "github.com/circonus-labs/circonus-gometrics/v3"
	"github.com/pkg/errors"
	"github.com/rs/zerolog/log"
)

// Load metrics from the Linux ProcFS (actually from unix.Sysinfo call)
type Load struct {
	common
	processStatsFile string
}

// loadOptions defines what elements can be overridden in a config file
type loadOptions struct {
	// common
	ID                   string   `json:"id" toml:"id" yaml:"id"`
	ProcFSPath           string   `json:"procfs_path" toml:"procfs_path" yaml:"procfs_path"`
	MetricsEnabled       []string `json:"metrics_enabled" toml:"metrics_enabled" yaml:"metrics_enabled"`
	MetricsDisabled      []string `json:"metrics_disabled" toml:"metrics_disabled" yaml:"metrics_disabled"`
	MetricsDefaultStatus string   `json:"metrics_default_status" toml:"metrics_default_status" toml:"metrics_default_status"`
	RunTTL               string   `json:"run_ttl" toml:"run_ttl" yaml:"run_ttl"`
}

// NewLoadCollector creates new procfs load collector
func NewLoadCollector(cfgBaseName, procFSPath string) (collector.Collector, error) {
	procFile := NameLoad

	c := Load{}
	c.id = NameLoad
	c.pkgID = PackageName + "." + c.id
	c.logger = log.With().Str("pkg", PackageName).Str("id", c.id).Logger()
	c.procFSPath = procFSPath
	c.file = filepath.Join(c.procFSPath, procFile)
	c.processStatsFile = filepath.Join(c.procFSPath, "stat")
	c.baseTags = tags.FromList(tags.GetBaseTags())

	if cfgBaseName == "" {
		if _, err := os.Stat(c.file); os.IsNotExist(err) {
			return nil, errors.Wrap(err, c.pkgID)
		}
		return &c, nil
	}

	var opts loadOptions
	err := config.LoadConfigFile(cfgBaseName, &opts)
	if err != nil {
		if strings.Contains(err.Error(), "no config found matching") {
			return &c, nil
		}
		c.logger.Warn().Err(err).Str("file", cfgBaseName).Msg("loading config file")
		return nil, errors.Wrapf(err, "%s config", c.pkgID)
	}

	c.logger.Debug().Interface("config", opts).Msg("loaded config")

	if opts.ID != "" {
		c.id = opts.ID
	}

	if opts.ProcFSPath != "" {
		c.procFSPath = opts.ProcFSPath
		c.file = filepath.Join(c.procFSPath, procFile)
	}

	if opts.RunTTL != "" {
		dur, err := time.ParseDuration(opts.RunTTL)
		if err != nil {
			return nil, errors.Wrapf(err, "%s parsing run_ttl", c.pkgID)
		}
		c.runTTL = dur
	}

	if _, err := os.Stat(c.file); os.IsNotExist(err) {
		return nil, errors.Wrap(err, c.pkgID)
	}

	return &c, nil
}

// Collect metrics from the procfs resource
func (c *Load) Collect() error {
	metrics := cgm.Metrics{}

	c.Lock()

	if c.runTTL > time.Duration(0) {
		if time.Since(c.lastEnd) < c.runTTL {
			c.logger.Warn().Msg(collector.ErrTTLNotExpired.Error())
			c.Unlock()
			return collector.ErrTTLNotExpired
		}
	}
	if c.running {
		c.logger.Warn().Msg(collector.ErrAlreadyRunning.Error())
		c.Unlock()
		return collector.ErrAlreadyRunning
	}

	c.running = true
	c.lastStart = time.Now()
	c.Unlock()

	tagUnitsProcesses := tags.Tag{Category: "units", Value: "processes"}

	{
		// load metrics
		lines, err := c.readFile(c.file)
		if err != nil {
			c.setStatus(metrics, err)
			return errors.Wrap(err, c.pkgID)
		}

		metricType := "n"
		tagList := tags.Tags{tagUnitsProcesses}
		for _, l := range lines {
			line := string(l)
			fields := strings.Fields(line)

			if len(fields) < 3 {
				c.logger.Warn().Int("fields", len(fields)).Msg("invalid number of fields")
				continue
			}

			if v, err := strconv.ParseFloat(fields[0], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 1min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_1min", metricType, v, tagList)
			}

			if v, err := strconv.ParseFloat(fields[1], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 5min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_5min", metricType, v, tagList)
			}

			if v, err := strconv.ParseFloat(fields[2], 64); err != nil {
				c.logger.Warn().Err(err).Msg("parsing 15min field")
				continue
			} else {
				c.addMetric(&metrics, "", "load_15min", metricType, v, tagList)
			}
		}
	}

	{
		// process metrics
		lines, err := c.readFile(c.processStatsFile)
		if err != nil {
			c.setStatus(metrics, err)
			return errors.Wrap(err, c.pkgID)
		}

		var processes, running, blocked, ctxswitch int64

		for _, l := range lines {
			var lineErr error
			line := string(l)
			fields := strings.Fields(line)

			switch fields[0] {
			case "processes":
				processes, lineErr = strconv.ParseInt(fields[1], 10, 64)

			case "procs_running":
				running, lineErr = strconv.ParseInt(fields[1], 10, 64)

			case "procs_blocked":
				blocked, lineErr = strconv.ParseInt(fields[1], 10, 64)

			case "ctxt":
				ctxswitch, lineErr = strconv.ParseInt(fields[1], 10, 64)
			default:
				continue
			}

			if lineErr != nil {
				c.setStatus(metrics, err)
				return errors.Wrapf(err, "%s parsing %s", c.pkgID, fields[0])
			}
		}

		metricType := "l"

		{
			tagList := tags.Tags{tagUnitsProcesses}
			c.addMetric(&metrics, "", "total", metricType, processes, tagList)
			c.addMetric(&metrics, "", "running", metricType, running, tagList)
			c.addMetric(&metrics, "", "blocked", metricType, blocked, tagList)
		}

		{
			tagList := tags.Tags{tags.Tag{Category: "units", Value: "switches"}}
			c.addMetric(&metrics, "", "ctxt", metricType, ctxswitch, tagList)
		}

	}

	c.setStatus(metrics, nil)
	return nil
}
<|endoftext|>


<commit_before>// Licensed to Elasticsearch B.V. under one or more agreements.
// Elasticsearch B.V. licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

package gentests

import (
  "fmt"
  "strings"

  "gopkg.in/yaml.v2"
)

var skipTests map[string][]string

func init() {
  err := yaml.NewDecoder(strings.NewReader(skipTestsYAML)).Decode(&skipTests)
  if err != nil {
    panic(fmt.Sprintf("ERROR: %v", err))
  }
}

var skipFiles = []string{
  "update/85_fields_meta.yml",            // Uses non-existing API property
  "update/86_fields_meta_with_types.yml", // --||--

  "ml/jobs_get_result_buckets.yml",    // Passes string value to int variable
  "ml/jobs_get_result_categories.yml", // --||--
  "ml/set_upgrade_mode.yml",           // --||--

  "ml/evaluate_data_frame.yml", // Floats as map keys

  "search/320_disallow_queries.yml", // Tries to match key in an empty map (`transient:{}`)

  "watcher/stats/10_basic.yml", // Sets "emit_stacktraces" as string ("true"), not bool
}

// TODO: Comments into descriptions for `Skip()`
//
var skipTestsYAML = `
---
# Cannot distinguish between missing value for refresh and an empty string
bulk/50_refresh.yml:
  - refresh=empty string immediately makes changes are visible in search
bulk/51_refresh_with_types.yml:
  - refresh=empty string immediately makes changes are visible in search
create/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
create/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/50_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/51_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"

# catch: bad_request, Expected [status] to not be nil
indices.data_stream/10_basic.yml:
  - Create data stream with invalid name

# Stash in value
cluster.reroute/11_explain.yml:
nodes.info/30_settings.yml:
nodes.stats/20_response_filtering.yml:
nodes.stats/30_discovery.yml:
  - Discovery stats
nodes.discovery/30_discovery.yml:
  - Discovery stats

# Arbitrary key
indices.shrink/10_basic.yml:
indices.shrink/20_source_mapping.yml:
indices.shrink/30_copy_settings.yml:
indices.split/30_copy_settings.yml:
nodes.info/10_basic.yml:
nodes.info/40_aggs.yml:
nodes.reload_secure_settings/10_basic.yml:
nodes.stats/50_indexing_pressure.yml:
nodes.stats/40_store_stats.yml:
nodes.stats/60_transport_stats.yml:

# Parsed response is YAML: value is map[interface {}]interface {}, not map[string]interface {}
cat.aliases/20_headers.yml:
  - Simple alias with yaml body through Accept header

# Incorrect int instead of float in match (aggregations.date_range.buckets.0.from: 1000000); TODO: PR
search.aggregation/40_range.yml:
  - Date range

# Mismatch in number parsing, 8623000 != 8.623e+06
search.aggregation/340_geo_distance.yml:
  - avg_bucket

# No support for headers per request yet
tasks.list/10_basic.yml:
  - tasks_list headers

# Node Selector feature not implemented
cat.aliases/10_basic.yml:
  - "Help (pre 7.4.0)"
  - "Simple alias (pre 7.4.0)"
  - "Complex alias (pre 7.4.0)"
  - "Column headers (pre 7.4.0)"
  - "Alias against closed index (pre 7.4.0)"

indices.put_mapping/10_basic.yml:
  - "Put mappings with explicit _doc type bwc"

# Test fails with: [400 Bad Request] illegal_argument_exception, "template [test] has index patterns [test-*] matching patterns from existing index templates [test2,test] with patterns (test2 => [test-*],test => [test-*, test2-*]), use index templates (/_index_template) instead"
test/indices.put_template/10_basic.yml:

# Incompatible regex
cat.templates/10_basic.yml:
  - "Sort templates"
  - "Multiple template"

# Missing test setup
cluster.voting_config_exclusions/10_basic.yml:
  - "Add voting config exclusion by unknown node name"
indices.resolve_index/10_basic_resolve_index.yml:
  - "Resolve index with hidden and closed indices"

# Not relevant
search/issue4895.yml:
search/issue9606.yml:

# FIXME
bulk/80_cas.yml:
bulk/81_cas_with_types.yml:

# ----- X-Pack ----------------------------------------------------------------

# Float "3.0" decoded as "3" by gopkg.in/yaml.v2
analytics/top_metrics.yml:
runtime_fields/30_double.yml:
  - docvalue_fields

# Stash in body
api_key/10_basic.yml:
  - Test invalidate api key
api_key/11_invalidation.yml:
  - Test invalidate api key by username
rollup/put_job.yml:
  - Test put job with templates

# Changing password locks out tests
change_password/10_basic.yml:
  - Test user changing their own password

# Missing refreshes in the test
data_frame/transforms_start_stop.yml:
ml/index_layout.yml:
transform/transforms_start_stop.yml:
  - Verify start transform reuses destination index
transform/transforms_start_stop.yml:
  - Test get multiple transform stats
transform/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get multiple transform stats where one does not have a task

# More QA tests than API tests
data_frame/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get transform stats on missing transform
  - Test get multiple transform stats where one does not have a task
ml/jobs_crud.yml:
  - Test reopen job resets the finished time

# Invalid license makes subsequent tests fail
license/20_put_license.yml:

# Test tries to match on map from body, but Go keys are not sorted
ml/jobs_crud.yml:
  - Test job with rules
  - Test put job with model_memory_limit as number
  - Test put job with model_memory_limit as string and lazy open

# Test gets stuck every time
ml/jobs_get_stats.yml:

# status_exception, Cannot process data because job [post-data-job] does not have a corresponding autodetect process
# resource_already_exists_exception, task with id {job-post-data-job} already exist
# status_exception, Cannot open job [start-stop-datafeed-job-foo-1] because it has already been opened
ml/post_data.yml:
  - Test flush with skip_time
  - Test POST data job api, flush, close and verify DataCounts doc
  - Test flush and close job WITHOUT sending any data
ml/start_stop_datafeed.yml:
  - Test stop given expression
transform/transforms_start_stop.yml:
  - Test start transform
  - Verify start transform reuses destination index

# Possible bad test setup, Cannot open job [start-stop-datafeed-job] because it has already been opened
# resource_already_exists_exception, task with id {job-start-stop-datafeed-job-foo-2} already exist
ml/start_stop_datafeed.yml:
  - Test start datafeed when persistent task allocation disabled

# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/10_basic.yml:
  - Bulk indexing of monitoring data on closed indices should throw an export exception
# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/20_privileges.yml:
  - Monitoring Bulk API

# Test tries to match on whole body, but map keys are unstable in Go
rollup/security_tests.yml:

# Test tries to match on map key, but map keys are unstable in Go
ml/data_frame_analytics_crud.yml:
  - Test put with description
  - Test put valid config with custom outlier detection

# Unsupported feature: allowed_warnings
ml/data_frame_analytics_crud.yml:
  - Test put classification given deprecated maximum_number_trees

# This test suite keeps failing too often: disable it altogether
ml/data_frame_analytics_crud.yml:

# 404s, panics, ... possible bad setup/teardown
ml/delete_model_snapshot.yml:
ml/get_datafeed_stats.yml:
ml/get_model_snapshots.yml:

# TEMPORARY: Missing 'body: { indices: "test_index" }' payload, TODO: PR
snapshot/10_basic.yml:
  - Create a source only snapshot and then restore it

# illegal_argument_exception: Provided password hash uses [NOOP] but the configured hashing algorithm is [BCRYPT]
users/10_basic.yml:
  - Test put user with password hash

# Slash in index name is not escaped (BUG)
security/authz/13_index_datemath.yml:
  - Test indexing documents with datemath, when permitted

# Possibly a cluster health color mismatch...
security/authz/14_cat_indices.yml:

# Test looks for "testnode.crt", but "ca.crt" is returned first
ssl/10_basic.yml:
  - Test get SSL certificates

# class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues cannot be cast to class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$SparseVectorScriptDocValues ...
vectors/30_sparse_vector_basic.yml:
  - Dot Product
# java.lang.IllegalArgumentException: No field found for [my_dense_vector] in mapping
vectors/40_sparse_vector_special_cases.yml:
  - Vectors of different dimensions and data types
  - Dimensions can be sorted differently
  - Distance functions for documents missing vector field should return 0

# Cannot connect to Docker IP
watcher/execute_watch/60_http_input.yml:

# Test tries to match on "tagline", which requires "human=false", which doesn't work in the Go API.
# Also test does too much within a single test, so has to be disabled as whole, unfortunately.
xpack/15_basic.yml:

# Test uses "y" as a property name, which is parsed as 'true' in the Go YAML library;
# see https://yaml.org/type/bool.html
ml/explain_data_frame_analytics.yml:
  - Test empty data frame given body
  - Test non-empty data frame given body
runtime_fields/10_keyword.yml:
  - docvalue_fields

# Test uses "n" as a property name, which is parsed as 'false' in the Go YAML library;
search.aggregation/10_histogram.yml:
`
<commit_msg>Generator: Tests: Update the list of skipped tests<commit_after>// Licensed to Elasticsearch B.V. under one or more agreements.
// Elasticsearch B.V. licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

package gentests

import (
  "fmt"
  "strings"

  "gopkg.in/yaml.v2"
)

var skipTests map[string][]string

func init() {
  err := yaml.NewDecoder(strings.NewReader(skipTestsYAML)).Decode(&skipTests)
  if err != nil {
    panic(fmt.Sprintf("ERROR: %v", err))
  }
}

var skipFiles = []string{
  "update/85_fields_meta.yml",            // Uses non-existing API property
  "update/86_fields_meta_with_types.yml", // --||--

  "ml/jobs_get_result_buckets.yml",    // Passes string value to int variable
  "ml/jobs_get_result_categories.yml", // --||--
  "ml/set_upgrade_mode.yml",           // --||--

  "ml/evaluate_data_frame.yml", // Floats as map keys

  "search/320_disallow_queries.yml", // Tries to match key in an empty map (`transient:{}`)

  "watcher/stats/10_basic.yml", // Sets "emit_stacktraces" as string ("true"), not bool
}

// TODO: Comments into descriptions for `Skip()`
//
var skipTestsYAML = `
---
# Cannot distinguish between missing value for refresh and an empty string
bulk/50_refresh.yml:
  - refresh=empty string immediately makes changes are visible in search
bulk/51_refresh_with_types.yml:
  - refresh=empty string immediately makes changes are visible in search
create/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
create/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/50_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/51_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"

# catch: bad_request, Expected [status] to not be nil
indices.data_stream/10_basic.yml:
  - Create data stream with invalid name

# Stash in value
cluster.reroute/11_explain.yml:
nodes.info/30_settings.yml:
nodes.stats/20_response_filtering.yml:
nodes.stats/30_discovery.yml:
  - Discovery stats
nodes.discovery/30_discovery.yml:
  - Discovery stats

# Arbitrary key
indices.shrink/10_basic.yml:
indices.shrink/20_source_mapping.yml:
indices.shrink/30_copy_settings.yml:
indices.split/30_copy_settings.yml:
nodes.info/10_basic.yml:
nodes.info/40_aggs.yml:
nodes.reload_secure_settings/10_basic.yml:
nodes.stats/50_indexing_pressure.yml:
nodes.stats/40_store_stats.yml:
nodes.stats/60_transport_stats.yml:

# Parsed response is YAML: value is map[interface {}]interface {}, not map[string]interface {}
cat.aliases/20_headers.yml:
  - Simple alias with yaml body through Accept header

# Incorrect int instead of float in match (aggregations.date_range.buckets.0.from: 1000000); TODO: PR
search.aggregation/40_range.yml:
  - Date range

# Mismatch in number parsing, 8623000 != 8.623e+06
search.aggregation/340_geo_distance.yml:
  - avg_bucket

# No support for headers per request yet
tasks.list/10_basic.yml:
  - tasks_list headers

# Node Selector feature not implemented
cat.aliases/10_basic.yml:
  - "Help (pre 7.4.0)"
  - "Simple alias (pre 7.4.0)"
  - "Complex alias (pre 7.4.0)"
  - "Column headers (pre 7.4.0)"
  - "Alias against closed index (pre 7.4.0)"

indices.put_mapping/10_basic.yml:
  - "Put mappings with explicit _doc type bwc"

# Test fails with: [400 Bad Request] illegal_argument_exception, "template [test] has index patterns [test-*] matching patterns from existing index templates [test2,test] with patterns (test2 => [test-*],test => [test-*, test2-*]), use index templates (/_index_template) instead"
test/indices.put_template/10_basic.yml:

# Incompatible regex
cat.templates/10_basic.yml:
  - "Sort templates"
  - "Multiple template"

# Missing test setup
cluster.voting_config_exclusions/10_basic.yml:
  - "Add voting config exclusion by unknown node name"
indices.resolve_index/10_basic_resolve_index.yml:
  - "Resolve index with hidden and closed indices"

# Not relevant
search/issue4895.yml:
search/issue9606.yml:

# FIXME
bulk/80_cas.yml:
bulk/81_cas_with_types.yml:

# ----- X-Pack ----------------------------------------------------------------

# Float "3.0" decoded as "3" by gopkg.in/yaml.v2
analytics/top_metrics.yml:
runtime_fields/30_double.yml:
  - docvalue_fields

# Stash in body
api_key/10_basic.yml:
  - Test invalidate api key
api_key/11_invalidation.yml:
  - Test invalidate api key by username
rollup/put_job.yml:
  - Test put job with templates

# Changing password locks out tests
change_password/10_basic.yml:
  - Test user changing their own password

# Missing refreshes in the test
data_frame/transforms_start_stop.yml:
ml/index_layout.yml:
transform/transforms_start_stop.yml:
  - Verify start transform reuses destination index
transform/transforms_start_stop.yml:
  - Test get multiple transform stats
transform/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get multiple transform stats where one does not have a task

# More QA tests than API tests
data_frame/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get transform stats on missing transform
  - Test get multiple transform stats where one does not have a task
ml/jobs_crud.yml:
  - Test reopen job resets the finished time

# Invalid license makes subsequent tests fail
license/20_put_license.yml:

# Test tries to match on map from body, but Go keys are not sorted
ml/jobs_crud.yml:
  - Test job with rules
  - Test put job with model_memory_limit as number
  - Test put job with model_memory_limit as string and lazy open

# Test gets stuck every time
ml/jobs_get_stats.yml:

# status_exception, Cannot process data because job [post-data-job] does not have a corresponding autodetect process
# resource_already_exists_exception, task with id {job-post-data-job} already exist
# status_exception, Cannot open job [start-stop-datafeed-job-foo-1] because it has already been opened
ml/post_data.yml:
  - Test flush with skip_time
  - Test POST data job api, flush, close and verify DataCounts doc
  - Test flush and close job WITHOUT sending any data
ml/start_stop_datafeed.yml:
  - Test stop given expression
transform/transforms_start_stop.yml:
  - Test start transform
  - Verify start transform reuses destination index

# Possible bad test setup, Cannot open job [start-stop-datafeed-job] because it has already been opened
# resource_already_exists_exception, task with id {job-start-stop-datafeed-job-foo-2} already exist
ml/start_stop_datafeed.yml:
  - Test start datafeed when persistent task allocation disabled

# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/10_basic.yml:
  - Bulk indexing of monitoring data on closed indices should throw an export exception
# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/20_privileges.yml:
  - Monitoring Bulk API

# Test tries to match on whole body, but map keys are unstable in Go
rollup/security_tests.yml:

# Test tries to match on map key, but map keys are unstable in Go
ml/data_frame_analytics_crud.yml:
  - Test put with description
  - Test put valid config with custom outlier detection

# Unsupported feature: allowed_warnings
ml/data_frame_analytics_crud.yml:
  - Test put classification given deprecated maximum_number_trees

# This test suite keeps failing too often: disable it altogether
ml/data_frame_analytics_crud.yml:

# 404s, panics, ... possible bad setup/teardown
ml/delete_model_snapshot.yml:
ml/get_datafeed_stats.yml:
ml/get_model_snapshots.yml:

# TEMPORARY: Missing 'body: { indices: "test_index" }' payload, TODO: PR
snapshot/10_basic.yml:
  - Create a source only snapshot and then restore it

# illegal_argument_exception: Provided password hash uses [NOOP] but the configured hashing algorithm is [BCRYPT]
users/10_basic.yml:
  - Test put user with password hash

# Slash in index name is not escaped (BUG)
security/authz/13_index_datemath.yml:
  - Test indexing documents with datemath, when permitted

# Possibly a cluster health color mismatch...
security/authz/14_cat_indices.yml:

# Test looks for "testnode.crt", but "ca.crt" is returned first
ssl/10_basic.yml:
  - Test get SSL certificates

# class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues cannot be cast to class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$SparseVectorScriptDocValues ...
vectors/30_sparse_vector_basic.yml:
  - Dot Product
# java.lang.IllegalArgumentException: No field found for [my_dense_vector] in mapping
vectors/40_sparse_vector_special_cases.yml:
  - Vectors of different dimensions and data types
  - Dimensions can be sorted differently
  - Distance functions for documents missing vector field should return 0

# Cannot connect to Docker IP
watcher/execute_watch/60_http_input.yml:

# Test tries to match on "tagline", which requires "human=false", which doesn't work in the Go API.
# Also test does too much within a single test, so has to be disabled as whole, unfortunately.
xpack/15_basic.yml:

# Test uses "y" as a property name, which is parsed as 'true' in the Go YAML library;
# see https://yaml.org/type/bool.html
ml/explain_data_frame_analytics.yml:
  - Test empty data frame given body
  - Test non-empty data frame given body
runtime_fields/10_keyword.yml:
  - docvalue_fields

# Test uses "n" as a property name, which is parsed as 'false' in the Go YAML library;
search.aggregation/10_histogram.yml:

# Getting "no matching index template found for data stream [invalid-data-stream]"
data_stream/10_basic.yml:
  - Create data stream with invalid name

# The matcher like 'indices.0.aliases.0' points to internal index
data_stream/80_resolve_index_data_streams.yml:
  - Resolve index with indices, aliases, and data streams
  - Resolve index with hidden and closed indices

# Zero matchers like '...shards.0.stores.0.allocation:primary' expect array, not map
data_stream/40_supported_apis.yml:
  - Verify shard stores api
`
<|endoftext|>


<commit_before>package main

import (
	"github.com/hydroflame/gopencl/v1.2/cl"
	"log"
	"unsafe"
)

const (
	DATA_SIZE = 1024
)

func main() {
	StatInfo()
}

func StatInfo() {
	ids := make([]cl.PlatformID, 100)
	actual := uint32(0)
	cl.GetPlatformIDs(uint32(len(ids)), &ids[0], &actual)
	for x := 0; x < int(actual); x++ {
		data := make([]byte, DATA_SIZE)
		size := uint64(0)
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_PROFILE, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		profilestring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_VERSION, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		versionstring := string(data[0:size])

		cl.GetPlatformInfo(ids[x], cl.PLATFORM_NAME, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		namestring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_VENDOR, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		vendorstring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_EXTENSIONS, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		extensionsstring := string(data[0:size])
		log.Print("PLATFORM_PROFILE:\t\t", profilestring)
		log.Print("PLATFORM_VERSION:\t\t", versionstring)
		log.Print("PLATFORM_NAME:\t\t", namestring)
		log.Print("PLATFORM_VENDOR:\t\t", vendorstring)
		log.Print("PLATFORM_EXTENSIONS:\t", extensionsstring)

		devices := make([]cl.DeviceId, 100)
		actualDid := uint32(0)
		cl.GetDeviceIDs(ids[x], cl.DEVICE_TYPE_ALL, uint32(len(devices)), &devices[0], &actualDid)
		log.Println("Devices: ")
		for y := 0; y < int(actualDid); y++ {
			cl.GetDeviceInfo(devices[y], cl.DEVICE_NAME, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
			deviceName := string(data[0:size])
			log.Print("\tname: "+deviceName+" @ ", &devices[y])
		}
	}
}
<commit_msg>Update statinfo.go<commit_after>package main

import (
	"github.com/go-gl/cl/v1.2/cl"
	"log"
	"unsafe"
)

const (
	DATA_SIZE = 1024
)

func main() {
	StatInfo()
}

func StatInfo() {
	ids := make([]cl.PlatformID, 100)
	actual := uint32(0)
	cl.GetPlatformIDs(uint32(len(ids)), &ids[0], &actual)
	for x := 0; x < int(actual); x++ {
		data := make([]byte, DATA_SIZE)
		size := uint64(0)
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_PROFILE, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		profilestring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_VERSION, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		versionstring := string(data[0:size])

		cl.GetPlatformInfo(ids[x], cl.PLATFORM_NAME, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		namestring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_VENDOR, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		vendorstring := string(data[0:size])
		cl.GetPlatformInfo(ids[x], cl.PLATFORM_EXTENSIONS, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
		extensionsstring := string(data[0:size])
		log.Print("PLATFORM_PROFILE:\t\t", profilestring)
		log.Print("PLATFORM_VERSION:\t\t", versionstring)
		log.Print("PLATFORM_NAME:\t\t", namestring)
		log.Print("PLATFORM_VENDOR:\t\t", vendorstring)
		log.Print("PLATFORM_EXTENSIONS:\t", extensionsstring)

		devices := make([]cl.DeviceId, 100)
		actualDid := uint32(0)
		cl.GetDeviceIDs(ids[x], cl.DEVICE_TYPE_ALL, uint32(len(devices)), &devices[0], &actualDid)
		log.Println("Devices: ")
		for y := 0; y < int(actualDid); y++ {
			cl.GetDeviceInfo(devices[y], cl.DEVICE_NAME, DATA_SIZE, unsafe.Pointer(&data[0]), &size)
			deviceName := string(data[0:size])
			log.Print("\tname: "+deviceName+" @ ", &devices[y])
		}
	}
}
<|endoftext|>


<commit_before>package out

import (
	"crypto/md5"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/robdimsdale/concourse-pipeline-resource/concourse"
	"github.com/robdimsdale/concourse-pipeline-resource/concourse/api"
	"github.com/robdimsdale/concourse-pipeline-resource/fly"
	"github.com/robdimsdale/concourse-pipeline-resource/logger"
	"github.com/robdimsdale/concourse-pipeline-resource/pipelinerunner"
)

const (
	apiPrefix = "/api/v1"
)

type OutCommand struct {
	logger        logger.Logger
	binaryVersion string
	flyConn       fly.FlyConn
	sourcesDir    string
}

func NewOutCommand(
	binaryVersion string,
	logger logger.Logger,
	flyConn fly.FlyConn,
	sourcesDir string,
) *OutCommand {
	return &OutCommand{
		logger:        logger,
		binaryVersion: binaryVersion,
		flyConn:       flyConn,
		sourcesDir:    sourcesDir,
	}
}

func (c *OutCommand) Run(input concourse.OutRequest) (concourse.OutResponse, error) {
	if input.Source.Target == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "target")
	}

	if input.Source.Username == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "username")
	}

	if input.Source.Password == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "password")
	}

	if input.Params.Pipelines == nil || len(input.Params.Pipelines) == 0 {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "pipelines")
	}

	for i, p := range input.Params.Pipelines {
		if p.Name == "" {
			return concourse.OutResponse{}, fmt.Errorf("%s must be provided for pipeline[%d]", "name", i)
		}

		if p.ConfigFile == "" {
			return concourse.OutResponse{}, fmt.Errorf("%s must be provided for pipeline[%d]", "config_file", i)
		}
	}

	c.logger.Debugf("Received input: %+v\n", input)

	loginOutput, err := c.flyConn.Login(
		input.Source.Target,
		input.Source.Username,
		input.Source.Password,
	)
	if err != nil {
		c.logger.Debugf("%s\n", string(loginOutput))
		return concourse.OutResponse{}, err
	}

	for _, p := range input.Params.Pipelines {
		configFilepath := filepath.Join(c.sourcesDir, p.ConfigFile)

		out, err := c.flyConn.Run("set-pipeline", "-n", "-p", p.Name, "-c", configFilepath)
		c.logger.Debugf("fly output for pipeline '%s': %s\n", p.Name, out)
		if err != nil {
			return concourse.OutResponse{}, err
		}
	}

	apiClient := api.NewClient(input.Source.Target)
	pipelines, err := apiClient.Pipelines()
	if err != nil {
		return concourse.OutResponse{}, err
	}

	c.logger.Debugf("Found pipelines: %+v\n", pipelines)

	gpFunc := func(index int, pipeline api.Pipeline) (string, error) {
		b, err := c.flyConn.Run("get-pipeline", "-p", pipeline.Name)
		return string(b), err
	}

	pipelinesContents, err := pipelinerunner.RunForAllPipelines(gpFunc, pipelines, c.logger)
	if err != nil {
		return concourse.OutResponse{}, err
	}

	allContent := strings.Join(pipelinesContents, "")

	pipelinesChecksumString := fmt.Sprintf(
		"%x",
		md5.Sum([]byte(allContent)),
	)
	c.logger.Debugf("pipeline content checksum: %s\n", pipelinesChecksumString)

	if pipelinesChecksumString == "" {
		panic("no versions found")
		// c.logger.Debugf("No versions found\n")
		// return concourse.CheckResponse{}, fmt.Errorf("no versions found")
	}

	metadata := []concourse.Metadata{}

	response := concourse.OutResponse{
		Version: concourse.Version{
			PipelinesChecksum: pipelinesChecksumString,
		},
		Metadata: metadata,
	}

	return response, nil
}
<commit_msg>Do not print output of fly set-pipeline.<commit_after>package out

import (
	"crypto/md5"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/robdimsdale/concourse-pipeline-resource/concourse"
	"github.com/robdimsdale/concourse-pipeline-resource/concourse/api"
	"github.com/robdimsdale/concourse-pipeline-resource/fly"
	"github.com/robdimsdale/concourse-pipeline-resource/logger"
	"github.com/robdimsdale/concourse-pipeline-resource/pipelinerunner"
)

const (
	apiPrefix = "/api/v1"
)

type OutCommand struct {
	logger        logger.Logger
	binaryVersion string
	flyConn       fly.FlyConn
	sourcesDir    string
}

func NewOutCommand(
	binaryVersion string,
	logger logger.Logger,
	flyConn fly.FlyConn,
	sourcesDir string,
) *OutCommand {
	return &OutCommand{
		logger:        logger,
		binaryVersion: binaryVersion,
		flyConn:       flyConn,
		sourcesDir:    sourcesDir,
	}
}

func (c *OutCommand) Run(input concourse.OutRequest) (concourse.OutResponse, error) {
	if input.Source.Target == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "target")
	}

	if input.Source.Username == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "username")
	}

	if input.Source.Password == "" {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "password")
	}

	if input.Params.Pipelines == nil || len(input.Params.Pipelines) == 0 {
		return concourse.OutResponse{}, fmt.Errorf("%s must be provided", "pipelines")
	}

	for i, p := range input.Params.Pipelines {
		if p.Name == "" {
			return concourse.OutResponse{}, fmt.Errorf("%s must be provided for pipeline[%d]", "name", i)
		}

		if p.ConfigFile == "" {
			return concourse.OutResponse{}, fmt.Errorf("%s must be provided for pipeline[%d]", "config_file", i)
		}
	}

	c.logger.Debugf("Received input: %+v\n", input)

	loginOutput, err := c.flyConn.Login(
		input.Source.Target,
		input.Source.Username,
		input.Source.Password,
	)
	if err != nil {
		c.logger.Debugf("%s\n", string(loginOutput))
		return concourse.OutResponse{}, err
	}

	for _, p := range input.Params.Pipelines {
		configFilepath := filepath.Join(c.sourcesDir, p.ConfigFile)

		out, err := c.flyConn.Run("set-pipeline", "-n", "-p", p.Name, "-c", configFilepath)
		if err != nil {
			return concourse.OutResponse{}, err
		}
	}

	apiClient := api.NewClient(input.Source.Target)
	pipelines, err := apiClient.Pipelines()
	if err != nil {
		return concourse.OutResponse{}, err
	}

	c.logger.Debugf("Found pipelines: %+v\n", pipelines)

	gpFunc := func(index int, pipeline api.Pipeline) (string, error) {
		b, err := c.flyConn.Run("get-pipeline", "-p", pipeline.Name)
		return string(b), err
	}

	pipelinesContents, err := pipelinerunner.RunForAllPipelines(gpFunc, pipelines, c.logger)
	if err != nil {
		return concourse.OutResponse{}, err
	}

	allContent := strings.Join(pipelinesContents, "")

	pipelinesChecksumString := fmt.Sprintf(
		"%x",
		md5.Sum([]byte(allContent)),
	)
	c.logger.Debugf("pipeline content checksum: %s\n", pipelinesChecksumString)

	if pipelinesChecksumString == "" {
		panic("no versions found")
		// c.logger.Debugf("No versions found\n")
		// return concourse.CheckResponse{}, fmt.Errorf("no versions found")
	}

	metadata := []concourse.Metadata{}

	response := concourse.OutResponse{
		Version: concourse.Version{
			PipelinesChecksum: pipelinesChecksumString,
		},
		Metadata: metadata,
	}

	return response, nil
}
<|endoftext|>


<commit_before>package gentests

import (
	"fmt"
	"strings"

	"gopkg.in/yaml.v2"
)

var skipTests map[string][]string

func init() {
	err := yaml.NewDecoder(strings.NewReader(skipTestsYAML)).Decode(&skipTests)
	if err != nil {
		panic(fmt.Sprintf("ERROR: %v", err))
	}
}

var skipFiles = []string{
	"update/85_fields_meta.yml",            // Uses non-existing API property
	"update/86_fields_meta_with_types.yml", // --||--

	"ml/jobs_get_result_buckets.yml",    // Passes string value to int variable
	"ml/jobs_get_result_categories.yml", // --||--
	"ml/set_upgrade_mode.yml",           // --||--

	"ml/evaluate_data_frame.yml", // Floats as map keys

	"watcher/stats/10_basic.yml", // Sets "emit_stacktraces" as string ("true"), not bool
}

// TODO: Comments into descriptions for `Skip()`
//
var skipTestsYAML = `
---
# Cannot distinguish between missing value for refresh and an empty string
bulk/50_refresh.yml:
  - refresh=empty string immediately makes changes are visible in search
bulk/51_refresh_with_types.yml:
  - refresh=empty string immediately makes changes are visible in search
create/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
create/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/50_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/51_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"

# Stash in value
cluster.reroute/11_explain.yml:
nodes.info/30_settings.yml:
nodes.stats/20_response_filtering.yml:
nodes.stats/30_discovery.yml:
  - Discovery stats
nodes.discovery/30_discovery.yml:
  - Discovery stats

# Arbitrary key
indices.shrink/10_basic.yml:
indices.shrink/20_source_mapping.yml:
indices.shrink/30_copy_settings.yml:
indices.split/30_copy_settings.yml:

# Parsed response is YAML: value is map[interface {}]interface {}, not map[string]interface {}
cat.aliases/20_headers.yml:
  - Simple alias with yaml body through Accept header

# Incorrect int instead of float in match (aggregations.date_range.buckets.0.from: 1000000); TODO: PR
search.aggregation/40_range.yml:
  - Date range

# No support for headers per request yet
tasks.list/10_basic.yml:
  - tasks_list headers

# Node Selector feature not implemented
cat.aliases/10_basic.yml:
  - "Help (pre 7.4.0)"
  - "Simple alias (pre 7.4.0)"
  - "Complex alias (pre 7.4.0)"
  - "Column headers (pre 7.4.0)"
  - "Alias against closed index (pre 7.4.0)"

indices.put_mapping/10_basic.yml:
  - "Put mappings with explicit _doc type bwc"

# Not relevant
search/issue4895.yml:
search/issue9606.yml:

# FIXME
bulk/80_cas.yml:
bulk/81_cas_with_types.yml:

# ----- X-Pack ----------------------------------------------------------------

# Stash in body
api_key/10_basic.yml:
  - Test invalidate api key
rollup/put_job.yml:
  - Test put job with templates

# Changing password locks out tests
change_password/10_basic.yml:
  - Test user changing their own password

# Missing refreshes in the test
data_frame/transforms_start_stop.yml:
ml/index_layout.yml:

# More QA tests than API tests
data_frame/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get transform stats on missing transform
  - Test get multiple transform stats where one does not have a task

# Invalid license makes subsequent tests fail
license/20_put_license.yml:

# Test tries to match on map from body, but Go keys are not sorted
ml/jobs_crud.yml:
  - Test job with rules

# Test gets stuck every time
ml/jobs_get_stats.yml:

# # status_exception, Cannot process data because job [post-data-job] does not have a corresponding autodetect process
# # resource_already_exists_exception, task with id {job-post-data-job} already exist
# ml/post_data.yml:

# Possible bad test setup, Cannot open job [start-stop-datafeed-job] because it has already been opened
# resource_already_exists_exception, task with id {job-start-stop-datafeed-job-foo-2} already exist
ml/start_stop_datafeed.yml:
  - Test start datafeed when persistent task allocation disabled

# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/10_basic.yml:
  - Bulk indexing of monitoring data on closed indices should throw an export exception
# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/20_privileges.yml:
  - Monitoring Bulk API

# Test tries to match on whole body, but map keys are unstable in Go
rollup/security_tests.yml:

# TEMPORARY: Missing 'body: { indices: "test_index" }' payload, TODO: PR
snapshot/10_basic.yml:
  - Create a source only snapshot and then restore it

# illegal_argument_exception: Provided password hash uses [NOOP] but the configured hashing algorithm is [BCRYPT]
users/10_basic.yml:
  - Test put user with password hash

# Slash in index name is not escaped (BUG)
security/authz/13_index_datemath.yml:
  - Test indexing documents with datemath, when permitted

# Possibly a cluster health color mismatch...
security/authz/14_cat_indices.yml:

# Test looks for "testnode.crt", but "ca.crt" is returned first
ssl/10_basic.yml:
  - Test get SSL certificates

# class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues cannot be cast to class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$SparseVectorScriptDocValues ...
vectors/30_sparse_vector_basic.yml:
  - Dot Product
# java.lang.IllegalArgumentException: No field found for [my_dense_vector] in mapping
vectors/40_sparse_vector_special_cases.yml:
  - Vectors of different dimensions and data types
  - Dimensions can be sorted differently
  - Distance functions for documents missing vector field should return 0

# Cannot connect to Docker IP
watcher/execute_watch/60_http_input.yml:

# Test tries to match on "tagline", which requires "human=false", which doesn't work in the Go API.
# Also test does too much within a single test, so has to be disabled as whole, unfortunately.
xpack/15_basic.yml:
`
<commit_msg>Generator: Tests: Update the list of skipped tests<commit_after>package gentests

import (
	"fmt"
	"strings"

	"gopkg.in/yaml.v2"
)

var skipTests map[string][]string

func init() {
	err := yaml.NewDecoder(strings.NewReader(skipTestsYAML)).Decode(&skipTests)
	if err != nil {
		panic(fmt.Sprintf("ERROR: %v", err))
	}
}

var skipFiles = []string{
	"update/85_fields_meta.yml",            // Uses non-existing API property
	"update/86_fields_meta_with_types.yml", // --||--

	"ml/jobs_get_result_buckets.yml",    // Passes string value to int variable
	"ml/jobs_get_result_categories.yml", // --||--
	"ml/set_upgrade_mode.yml",           // --||--

	"ml/evaluate_data_frame.yml", // Floats as map keys

	"watcher/stats/10_basic.yml", // Sets "emit_stacktraces" as string ("true"), not bool
}

// TODO: Comments into descriptions for `Skip()`
//
var skipTestsYAML = `
---
# Cannot distinguish between missing value for refresh and an empty string
bulk/50_refresh.yml:
  - refresh=empty string immediately makes changes are visible in search
bulk/51_refresh_with_types.yml:
  - refresh=empty string immediately makes changes are visible in search
create/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
create/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/50_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
delete/51_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
index/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/60_refresh.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"
update/61_refresh_with_types.yml:
  - When refresh url parameter is an empty string that means "refresh immediately"

# Stash in value
cluster.reroute/11_explain.yml:
nodes.info/30_settings.yml:
nodes.stats/20_response_filtering.yml:
nodes.stats/30_discovery.yml:
  - Discovery stats
nodes.discovery/30_discovery.yml:
  - Discovery stats

# Arbitrary key
indices.shrink/10_basic.yml:
indices.shrink/20_source_mapping.yml:
indices.shrink/30_copy_settings.yml:
indices.split/30_copy_settings.yml:

# Parsed response is YAML: value is map[interface {}]interface {}, not map[string]interface {}
cat.aliases/20_headers.yml:
  - Simple alias with yaml body through Accept header

# Incorrect int instead of float in match (aggregations.date_range.buckets.0.from: 1000000); TODO: PR
search.aggregation/40_range.yml:
  - Date range

# No support for headers per request yet
tasks.list/10_basic.yml:
  - tasks_list headers

# Node Selector feature not implemented
cat.aliases/10_basic.yml:
  - "Help (pre 7.4.0)"
  - "Simple alias (pre 7.4.0)"
  - "Complex alias (pre 7.4.0)"
  - "Column headers (pre 7.4.0)"
  - "Alias against closed index (pre 7.4.0)"

indices.put_mapping/10_basic.yml:
  - "Put mappings with explicit _doc type bwc"

# Not relevant
search/issue4895.yml:
search/issue9606.yml:

# FIXME
bulk/80_cas.yml:
bulk/81_cas_with_types.yml:

# ----- X-Pack ----------------------------------------------------------------

# Stash in body
api_key/10_basic.yml:
  - Test invalidate api key
rollup/put_job.yml:
  - Test put job with templates

# Changing password locks out tests
change_password/10_basic.yml:
  - Test user changing their own password

# Missing refreshes in the test
data_frame/transforms_start_stop.yml:
ml/index_layout.yml:

# More QA tests than API tests
data_frame/transforms_stats.yml:
  - Test get multiple transform stats
  - Test get transform stats on missing transform
  - Test get multiple transform stats where one does not have a task

# Invalid license makes subsequent tests fail
license/20_put_license.yml:

# Test tries to match on map from body, but Go keys are not sorted
ml/jobs_crud.yml:
  - Test job with rules

# Test gets stuck every time
ml/jobs_get_stats.yml:

# # status_exception, Cannot process data because job [post-data-job] does not have a corresponding autodetect process
# # resource_already_exists_exception, task with id {job-post-data-job} already exist
# ml/post_data.yml:

# Possible bad test setup, Cannot open job [start-stop-datafeed-job] because it has already been opened
# resource_already_exists_exception, task with id {job-start-stop-datafeed-job-foo-2} already exist
ml/start_stop_datafeed.yml:
  - Test start datafeed when persistent task allocation disabled

# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/10_basic.yml:
  - Bulk indexing of monitoring data on closed indices should throw an export exception
# Indexing step doesn't appear to work (getting total.hits=0)
monitoring/bulk/20_privileges.yml:
  - Monitoring Bulk API

# Test tries to match on whole body, but map keys are unstable in Go
rollup/security_tests.yml:

# Test tries to match on map key, but map keys are unstable in Go
ml/data_frame_analytics_crud.yml:
  - "Test put with description"

# TEMPORARY: Missing 'body: { indices: "test_index" }' payload, TODO: PR
snapshot/10_basic.yml:
  - Create a source only snapshot and then restore it

# illegal_argument_exception: Provided password hash uses [NOOP] but the configured hashing algorithm is [BCRYPT]
users/10_basic.yml:
  - Test put user with password hash

# Slash in index name is not escaped (BUG)
security/authz/13_index_datemath.yml:
  - Test indexing documents with datemath, when permitted

# Possibly a cluster health color mismatch...
security/authz/14_cat_indices.yml:

# Test looks for "testnode.crt", but "ca.crt" is returned first
ssl/10_basic.yml:
  - Test get SSL certificates

# class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues cannot be cast to class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$SparseVectorScriptDocValues ...
vectors/30_sparse_vector_basic.yml:
  - Dot Product
# java.lang.IllegalArgumentException: No field found for [my_dense_vector] in mapping
vectors/40_sparse_vector_special_cases.yml:
  - Vectors of different dimensions and data types
  - Dimensions can be sorted differently
  - Distance functions for documents missing vector field should return 0

# Cannot connect to Docker IP
watcher/execute_watch/60_http_input.yml:

# Test tries to match on "tagline", which requires "human=false", which doesn't work in the Go API.
# Also test does too much within a single test, so has to be disabled as whole, unfortunately.
xpack/15_basic.yml:
`
<|endoftext|>


<commit_before>// Copyright Istio 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 configdump

import (
	"encoding/json"
	"fmt"
	"reflect"
	"sort"
	"strings"
	"text/tabwriter"

	listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
	route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
	httpConn "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
	tcp "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3"
	"github.com/envoyproxy/go-control-plane/pkg/wellknown"
	"github.com/golang/protobuf/ptypes"

	protio "istio.io/istio/istioctl/pkg/util/proto"
	"istio.io/istio/pilot/pkg/networking/util"
	v3 "istio.io/istio/pilot/pkg/xds/v3"
)

const (
	// HTTPListener identifies a listener as being of HTTP type by the presence of an HTTP connection manager filter
	HTTPListener = wellknown.HTTPConnectionManager

	// TCPListener identifies a listener as being of TCP type by the presence of TCP proxy filter
	TCPListener = wellknown.TCPProxy
)

// ListenerFilter is used to pass filter information into listener based config writer print functions
type ListenerFilter struct {
	Address string
	Port    uint32
	Type    string
	Verbose bool
}

// Verify returns true if the passed listener matches the filter fields
func (l *ListenerFilter) Verify(listener *listener.Listener) bool {
	if l.Address == "" && l.Port == 0 && l.Type == "" {
		return true
	}
	if l.Address != "" && !strings.EqualFold(retrieveListenerAddress(listener), l.Address) {
		return false
	}
	if l.Port != 0 && retrieveListenerPort(listener) != l.Port {
		return false
	}
	if l.Type != "" && !strings.EqualFold(retrieveListenerType(listener), l.Type) {
		return false
	}
	return true
}

// retrieveListenerType classifies a Listener as HTTP|TCP|HTTP+TCP|UNKNOWN
func retrieveListenerType(l *listener.Listener) string {
	nHTTP := 0
	nTCP := 0
	for _, filterChain := range l.GetFilterChains() {
		for _, filter := range filterChain.GetFilters() {
			if filter.Name == HTTPListener {
				nHTTP++
			} else if filter.Name == TCPListener {
				if !strings.Contains(string(filter.GetTypedConfig().GetValue()), util.BlackHoleCluster) {
					nTCP++
				}
			}
		}
	}

	if nHTTP > 0 {
		if nTCP == 0 {
			return "HTTP"
		}
		return "HTTP+TCP"
	} else if nTCP > 0 {
		return "TCP"
	}

	return "UNKNOWN"
}

func retrieveListenerAddress(l *listener.Listener) string {
	return l.Address.GetSocketAddress().Address
}

func retrieveListenerPort(l *listener.Listener) uint32 {
	return l.Address.GetSocketAddress().GetPortValue()
}

// PrintListenerSummary prints a summary of the relevant listeners in the config dump to the ConfigWriter stdout
func (c *ConfigWriter) PrintListenerSummary(filter ListenerFilter) error {
	w, listeners, err := c.setupListenerConfigWriter()
	if err != nil {
		return err
	}

	verifiedListeners := []*listener.Listener{}
	for _, l := range listeners {
		if filter.Verify(l) {
			verifiedListeners = append(verifiedListeners, l)
		}
	}

	// Sort by port, addr, type
	sort.Slice(verifiedListeners, func(i, j int) bool {
		iPort := retrieveListenerPort(verifiedListeners[i])
		jPort := retrieveListenerPort(verifiedListeners[j])
		if iPort != jPort {
			return iPort < jPort
		}
		iAddr := retrieveListenerAddress(verifiedListeners[i])
		jAddr := retrieveListenerAddress(verifiedListeners[j])
		if iAddr != jAddr {
			return iAddr < jAddr
		}
		iType := retrieveListenerType(verifiedListeners[i])
		jType := retrieveListenerType(verifiedListeners[j])
		return iType < jType
	})

	if filter.Verbose {
		fmt.Fprintln(w, "ADDRESS\tPORT\tMATCH\tDESTINATION")
	} else {
		fmt.Fprintln(w, "ADDRESS\tPORT\tTYPE")
	}
	for _, l := range verifiedListeners {
		address := retrieveListenerAddress(l)
		port := retrieveListenerPort(l)
		if filter.Verbose {

			matches := retrieveListenerMatches(l)
			sort.Slice(matches, func(i, j int) bool {
				return matches[i].destination > matches[j].destination
			})
			for _, match := range matches {
				fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", address, port, match.match, match.destination)
			}
		} else {
			listenerType := retrieveListenerType(l)
			fmt.Fprintf(w, "%v\t%v\t%v\n", address, port, listenerType)
		}
	}
	return w.Flush()
}

type filterchain struct {
	match       string
	destination string
}

var (
	plaintextHTTPALPNs = []string{"http/1.0", "http/1.1", "h2c"}
	istioHTTPPlaintext = []string{"istio", "istio-http/1.0", "istio-http/1.1", "istio-h2"}
	httpTLS            = []string{"http/1.0", "http/1.1", "h2c", "istio-http/1.0", "istio-http/1.1", "istio-h2"}
	tcpTLS             = []string{"istio-peer-exchange", "istio"}

	protDescrs = map[string][]string{
		"App: HTTP TLS":         httpTLS,
		"App: Istio HTTP Plain": istioHTTPPlaintext,
		"App: TCP TLS":          tcpTLS,
		"App: HTTP":             plaintextHTTPALPNs,
	}
)

func retrieveListenerMatches(l *listener.Listener) []filterchain {
	resp := []filterchain{}
	for _, filterChain := range l.GetFilterChains() {
		match := filterChain.FilterChainMatch
		if match == nil {
			match = &listener.FilterChainMatch{}
		}
		// filterChaince also has SuffixLen, SourceType, SourcePrefixRanges which are not rendered.

		descrs := []string{}
		if len(match.ServerNames) > 0 {
			descrs = append(descrs, fmt.Sprintf("SNI: %s", strings.Join(match.ServerNames, ",")))
		}
		if len(match.TransportProtocol) > 0 {
			descrs = append(descrs, fmt.Sprintf("Trans: %s", match.TransportProtocol))
		}

		if len(match.ApplicationProtocols) > 0 {
			found := false
			for protDescr, protocols := range protDescrs {
				if reflect.DeepEqual(match.ApplicationProtocols, protocols) {
					found = true
					descrs = append(descrs, protDescr)
					break
				}
			}
			if !found {
				descrs = append(descrs, fmt.Sprintf("App: %s", strings.Join(match.ApplicationProtocols, ",")))
			}
		}

		port := ""
		if match.DestinationPort != nil {
			port = fmt.Sprintf(":%d", match.DestinationPort.GetValue())
		}
		if match.AddressSuffix != "" {
			descrs = append(descrs, fmt.Sprintf("Addr: %s%s", match.AddressSuffix, port))
		}
		if len(match.PrefixRanges) > 0 {
			pf := []string{}
			for _, p := range match.PrefixRanges {
				pf = append(pf, fmt.Sprintf("%s/%d", p.AddressPrefix, p.GetPrefixLen().GetValue()))
			}
			descrs = append(descrs, fmt.Sprintf("Addr: %s%s", strings.Join(pf, ","), port))
		}
		if len(descrs) == 0 {
			descrs = []string{"ALL"}
		}
		fc := filterchain{
			destination: getFilterType(filterChain.GetFilters()),
			match:       strings.Join(descrs, "; "),
		}
		resp = append(resp, fc)
	}
	return resp
}

func getFilterType(filters []*listener.Filter) string {
	for _, filter := range filters {
		if filter.Name == HTTPListener {

			httpProxy := &httpConn.HttpConnectionManager{}
			// Allow Unmarshal to work even if Envoy and istioctl are different
			filter.GetTypedConfig().TypeUrl = "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
			err := ptypes.UnmarshalAny(filter.GetTypedConfig(), httpProxy)
			if err != nil {
				return err.Error()
			}
			if httpProxy.GetRouteConfig() != nil {
				return describeRouteConfig(httpProxy.GetRouteConfig())
			}
			if httpProxy.GetRds().GetRouteConfigName() != "" {
				return fmt.Sprintf("Route: %s", httpProxy.GetRds().GetRouteConfigName())
			}
			return "HTTP"
		} else if filter.Name == TCPListener {
			if !strings.Contains(string(filter.GetTypedConfig().GetValue()), util.BlackHoleCluster) {
				tcpProxy := &tcp.TcpProxy{}
				// Allow Unmarshal to work even if Envoy and istioctl are different
				filter.GetTypedConfig().TypeUrl = "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy"
				err := ptypes.UnmarshalAny(filter.GetTypedConfig(), tcpProxy)
				if err != nil {
					return err.Error()
				}
				if strings.Contains(tcpProxy.GetCluster(), "Cluster") {
					return tcpProxy.GetCluster()
				}
				return fmt.Sprintf("Cluster: %s", tcpProxy.GetCluster())
			}
		}
	}
	return "Non-HTTP/Non-TCP"
}

func describeRouteConfig(route *route.RouteConfiguration) string {
	vhosts := []string{}
	for _, vh := range route.GetVirtualHosts() {
		if describeDomains(vh) == "" {
			vhosts = append(vhosts, describeRoutes(vh))
		} else {
			vhosts = append(vhosts, fmt.Sprintf("%s %s", describeDomains(vh), describeRoutes(vh)))
		}
	}
	return fmt.Sprintf("Inline Route: %s", strings.Join(vhosts, "; "))
}

func describeDomains(vh *route.VirtualHost) string {
	if len(vh.GetDomains()) == 1 && vh.GetDomains()[0] == "*" {
		return ""
	}
	return strings.Join(vh.GetDomains(), "/")
}

func describeRoutes(vh *route.VirtualHost) string {
	routes := []string{}
	for _, route := range vh.GetRoutes() {
		routes = append(routes, describeMatch(route.GetMatch()))
	}
	return strings.Join(routes, ", ")
}

func describeMatch(match *route.RouteMatch) string {
	conds := []string{}
	if match.GetPrefix() != "" {
		conds = append(conds, fmt.Sprintf("%s*", match.GetPrefix()))
	}
	if match.GetPath() != "" {
		conds = append(conds, match.GetPath())
	}
	if match.GetSafeRegex() != nil {
		conds = append(conds, fmt.Sprintf("regex %s", match.GetSafeRegex().String()))
	}
	// Ignore headers
	return strings.Join(conds, " ")
}

// PrintListenerDump prints the relevant listeners in the config dump to the ConfigWriter stdout
func (c *ConfigWriter) PrintListenerDump(filter ListenerFilter) error {
	_, listeners, err := c.setupListenerConfigWriter()
	if err != nil {
		return err
	}
	filteredListeners := protio.MessageSlice{}
	for _, listener := range listeners {
		if filter.Verify(listener) {
			filteredListeners = append(filteredListeners, listener)
		}
	}
	out, err := json.MarshalIndent(filteredListeners, "", "    ")
	if err != nil {
		return fmt.Errorf("failed to marshal listeners: %v", err)
	}
	fmt.Fprintln(c.Stdout, string(out))
	return nil
}

func (c *ConfigWriter) setupListenerConfigWriter() (*tabwriter.Writer, []*listener.Listener, error) {
	listeners, err := c.retrieveSortedListenerSlice()
	if err != nil {
		return nil, nil, err
	}
	w := new(tabwriter.Writer).Init(c.Stdout, 0, 8, 1, ' ', 0)
	return w, listeners, nil
}

func (c *ConfigWriter) retrieveSortedListenerSlice() ([]*listener.Listener, error) {
	if c.configDump == nil {
		return nil, fmt.Errorf("config writer has not been primed")
	}
	listenerDump, err := c.configDump.GetListenerConfigDump()
	if err != nil {
		return nil, fmt.Errorf("listener dump: %v", err)
	}
	listeners := make([]*listener.Listener, 0)
	for _, l := range listenerDump.DynamicListeners {
		if l.ActiveState != nil && l.ActiveState.Listener != nil {
			listenerTyped := &listener.Listener{}
			// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
			l.ActiveState.Listener.TypeUrl = v3.ListenerType
			err = ptypes.UnmarshalAny(l.ActiveState.Listener, listenerTyped)
			if err != nil {
				return nil, fmt.Errorf("unmarshal listener: %v", err)
			}
			listeners = append(listeners, listenerTyped)
		}
	}

	for _, l := range listenerDump.StaticListeners {
		if l.Listener != nil {
			listenerTyped := &listener.Listener{}
			// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
			l.Listener.TypeUrl = v3.ListenerType
			err = ptypes.UnmarshalAny(l.Listener, listenerTyped)
			if err != nil {
				return nil, fmt.Errorf("unmarshal listener: %v", err)
			}
			listeners = append(listeners, listenerTyped)
		}
	}
	if len(listeners) == 0 {
		return nil, fmt.Errorf("no listeners found")
	}
	return listeners, nil
}
<commit_msg>Show cluster for single cluster route destinations (#26564)<commit_after>// Copyright Istio 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 configdump

import (
	"encoding/json"
	"fmt"
	"reflect"
	"sort"
	"strings"
	"text/tabwriter"

	listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
	route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
	httpConn "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
	tcp "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3"
	"github.com/envoyproxy/go-control-plane/pkg/wellknown"
	"github.com/golang/protobuf/ptypes"

	protio "istio.io/istio/istioctl/pkg/util/proto"
	"istio.io/istio/pilot/pkg/networking/util"
	v3 "istio.io/istio/pilot/pkg/xds/v3"
)

const (
	// HTTPListener identifies a listener as being of HTTP type by the presence of an HTTP connection manager filter
	HTTPListener = wellknown.HTTPConnectionManager

	// TCPListener identifies a listener as being of TCP type by the presence of TCP proxy filter
	TCPListener = wellknown.TCPProxy
)

// ListenerFilter is used to pass filter information into listener based config writer print functions
type ListenerFilter struct {
	Address string
	Port    uint32
	Type    string
	Verbose bool
}

// Verify returns true if the passed listener matches the filter fields
func (l *ListenerFilter) Verify(listener *listener.Listener) bool {
	if l.Address == "" && l.Port == 0 && l.Type == "" {
		return true
	}
	if l.Address != "" && !strings.EqualFold(retrieveListenerAddress(listener), l.Address) {
		return false
	}
	if l.Port != 0 && retrieveListenerPort(listener) != l.Port {
		return false
	}
	if l.Type != "" && !strings.EqualFold(retrieveListenerType(listener), l.Type) {
		return false
	}
	return true
}

// retrieveListenerType classifies a Listener as HTTP|TCP|HTTP+TCP|UNKNOWN
func retrieveListenerType(l *listener.Listener) string {
	nHTTP := 0
	nTCP := 0
	for _, filterChain := range l.GetFilterChains() {
		for _, filter := range filterChain.GetFilters() {
			if filter.Name == HTTPListener {
				nHTTP++
			} else if filter.Name == TCPListener {
				if !strings.Contains(string(filter.GetTypedConfig().GetValue()), util.BlackHoleCluster) {
					nTCP++
				}
			}
		}
	}

	if nHTTP > 0 {
		if nTCP == 0 {
			return "HTTP"
		}
		return "HTTP+TCP"
	} else if nTCP > 0 {
		return "TCP"
	}

	return "UNKNOWN"
}

func retrieveListenerAddress(l *listener.Listener) string {
	return l.Address.GetSocketAddress().Address
}

func retrieveListenerPort(l *listener.Listener) uint32 {
	return l.Address.GetSocketAddress().GetPortValue()
}

// PrintListenerSummary prints a summary of the relevant listeners in the config dump to the ConfigWriter stdout
func (c *ConfigWriter) PrintListenerSummary(filter ListenerFilter) error {
	w, listeners, err := c.setupListenerConfigWriter()
	if err != nil {
		return err
	}

	verifiedListeners := []*listener.Listener{}
	for _, l := range listeners {
		if filter.Verify(l) {
			verifiedListeners = append(verifiedListeners, l)
		}
	}

	// Sort by port, addr, type
	sort.Slice(verifiedListeners, func(i, j int) bool {
		iPort := retrieveListenerPort(verifiedListeners[i])
		jPort := retrieveListenerPort(verifiedListeners[j])
		if iPort != jPort {
			return iPort < jPort
		}
		iAddr := retrieveListenerAddress(verifiedListeners[i])
		jAddr := retrieveListenerAddress(verifiedListeners[j])
		if iAddr != jAddr {
			return iAddr < jAddr
		}
		iType := retrieveListenerType(verifiedListeners[i])
		jType := retrieveListenerType(verifiedListeners[j])
		return iType < jType
	})

	if filter.Verbose {
		fmt.Fprintln(w, "ADDRESS\tPORT\tMATCH\tDESTINATION")
	} else {
		fmt.Fprintln(w, "ADDRESS\tPORT\tTYPE")
	}
	for _, l := range verifiedListeners {
		address := retrieveListenerAddress(l)
		port := retrieveListenerPort(l)
		if filter.Verbose {

			matches := retrieveListenerMatches(l)
			sort.Slice(matches, func(i, j int) bool {
				return matches[i].destination > matches[j].destination
			})
			for _, match := range matches {
				fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", address, port, match.match, match.destination)
			}
		} else {
			listenerType := retrieveListenerType(l)
			fmt.Fprintf(w, "%v\t%v\t%v\n", address, port, listenerType)
		}
	}
	return w.Flush()
}

type filterchain struct {
	match       string
	destination string
}

var (
	plaintextHTTPALPNs = []string{"http/1.0", "http/1.1", "h2c"}
	istioHTTPPlaintext = []string{"istio", "istio-http/1.0", "istio-http/1.1", "istio-h2"}
	httpTLS            = []string{"http/1.0", "http/1.1", "h2c", "istio-http/1.0", "istio-http/1.1", "istio-h2"}
	tcpTLS             = []string{"istio-peer-exchange", "istio"}

	protDescrs = map[string][]string{
		"App: HTTP TLS":         httpTLS,
		"App: Istio HTTP Plain": istioHTTPPlaintext,
		"App: TCP TLS":          tcpTLS,
		"App: HTTP":             plaintextHTTPALPNs,
	}
)

func retrieveListenerMatches(l *listener.Listener) []filterchain {
	resp := []filterchain{}
	for _, filterChain := range l.GetFilterChains() {
		match := filterChain.FilterChainMatch
		if match == nil {
			match = &listener.FilterChainMatch{}
		}
		// filterChaince also has SuffixLen, SourceType, SourcePrefixRanges which are not rendered.

		descrs := []string{}
		if len(match.ServerNames) > 0 {
			descrs = append(descrs, fmt.Sprintf("SNI: %s", strings.Join(match.ServerNames, ",")))
		}
		if len(match.TransportProtocol) > 0 {
			descrs = append(descrs, fmt.Sprintf("Trans: %s", match.TransportProtocol))
		}

		if len(match.ApplicationProtocols) > 0 {
			found := false
			for protDescr, protocols := range protDescrs {
				if reflect.DeepEqual(match.ApplicationProtocols, protocols) {
					found = true
					descrs = append(descrs, protDescr)
					break
				}
			}
			if !found {
				descrs = append(descrs, fmt.Sprintf("App: %s", strings.Join(match.ApplicationProtocols, ",")))
			}
		}

		port := ""
		if match.DestinationPort != nil {
			port = fmt.Sprintf(":%d", match.DestinationPort.GetValue())
		}
		if match.AddressSuffix != "" {
			descrs = append(descrs, fmt.Sprintf("Addr: %s%s", match.AddressSuffix, port))
		}
		if len(match.PrefixRanges) > 0 {
			pf := []string{}
			for _, p := range match.PrefixRanges {
				pf = append(pf, fmt.Sprintf("%s/%d", p.AddressPrefix, p.GetPrefixLen().GetValue()))
			}
			descrs = append(descrs, fmt.Sprintf("Addr: %s%s", strings.Join(pf, ","), port))
		}
		if len(descrs) == 0 {
			descrs = []string{"ALL"}
		}
		fc := filterchain{
			destination: getFilterType(filterChain.GetFilters()),
			match:       strings.Join(descrs, "; "),
		}
		resp = append(resp, fc)
	}
	return resp
}

func getFilterType(filters []*listener.Filter) string {
	for _, filter := range filters {
		if filter.Name == HTTPListener {
			httpProxy := &httpConn.HttpConnectionManager{}
			// Allow Unmarshal to work even if Envoy and istioctl are different
			filter.GetTypedConfig().TypeUrl = "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
			err := ptypes.UnmarshalAny(filter.GetTypedConfig(), httpProxy)
			if err != nil {
				return err.Error()
			}
			if httpProxy.GetRouteConfig() != nil {
				return describeRouteConfig(httpProxy.GetRouteConfig())
			}
			if httpProxy.GetRds().GetRouteConfigName() != "" {
				return fmt.Sprintf("Route: %s", httpProxy.GetRds().GetRouteConfigName())
			}
			return "HTTP"
		} else if filter.Name == TCPListener {
			if !strings.Contains(string(filter.GetTypedConfig().GetValue()), util.BlackHoleCluster) {
				tcpProxy := &tcp.TcpProxy{}
				// Allow Unmarshal to work even if Envoy and istioctl are different
				filter.GetTypedConfig().TypeUrl = "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy"
				err := ptypes.UnmarshalAny(filter.GetTypedConfig(), tcpProxy)
				if err != nil {
					return err.Error()
				}
				if strings.Contains(tcpProxy.GetCluster(), "Cluster") {
					return tcpProxy.GetCluster()
				}
				return fmt.Sprintf("Cluster: %s", tcpProxy.GetCluster())
			}
		}
	}
	return "Non-HTTP/Non-TCP"
}

func describeRouteConfig(route *route.RouteConfiguration) string {
	if cluster := getMatchAllCluster(route); cluster != "" {
		return cluster
	}
	vhosts := []string{}
	for _, vh := range route.GetVirtualHosts() {
		if describeDomains(vh) == "" {
			vhosts = append(vhosts, describeRoutes(vh))
		} else {
			vhosts = append(vhosts, fmt.Sprintf("%s %s", describeDomains(vh), describeRoutes(vh)))
		}
	}
	return fmt.Sprintf("Inline Route: %s", strings.Join(vhosts, "; "))
}

// If this is a route that matches everything and forwards to a cluster, just report the cluster.
func getMatchAllCluster(er *route.RouteConfiguration) string {
	if len(er.GetVirtualHosts()) != 1 {
		return ""
	}
	vh := er.GetVirtualHosts()[0]
	if !reflect.DeepEqual(vh.Domains, []string{"*"}) {
		return ""
	}
	if len(vh.GetRoutes()) != 1 {
		return ""
	}
	r := vh.GetRoutes()[0]
	if r.GetMatch().GetPrefix() != "/" {
		return ""
	}
	a, ok := r.GetAction().(*route.Route_Route)
	if !ok {
		return ""
	}
	cl, ok := a.Route.ClusterSpecifier.(*route.RouteAction_Cluster)
	if !ok {
		return ""
	}
	if strings.Contains(cl.Cluster, "Cluster") {
		return cl.Cluster
	}
	return fmt.Sprintf("Cluster: %s", cl.Cluster)
}

func describeDomains(vh *route.VirtualHost) string {
	if len(vh.GetDomains()) == 1 && vh.GetDomains()[0] == "*" {
		return ""
	}
	return strings.Join(vh.GetDomains(), "/")
}

func describeRoutes(vh *route.VirtualHost) string {
	routes := []string{}
	for _, route := range vh.GetRoutes() {
		routes = append(routes, describeMatch(route.GetMatch()))
	}
	return strings.Join(routes, ", ")
}

func describeMatch(match *route.RouteMatch) string {
	conds := []string{}
	if match.GetPrefix() != "" {
		conds = append(conds, fmt.Sprintf("%s*", match.GetPrefix()))
	}
	if match.GetPath() != "" {
		conds = append(conds, match.GetPath())
	}
	if match.GetSafeRegex() != nil {
		conds = append(conds, fmt.Sprintf("regex %s", match.GetSafeRegex().String()))
	}
	// Ignore headers
	return strings.Join(conds, " ")
}

// PrintListenerDump prints the relevant listeners in the config dump to the ConfigWriter stdout
func (c *ConfigWriter) PrintListenerDump(filter ListenerFilter) error {
	_, listeners, err := c.setupListenerConfigWriter()
	if err != nil {
		return err
	}
	filteredListeners := protio.MessageSlice{}
	for _, listener := range listeners {
		if filter.Verify(listener) {
			filteredListeners = append(filteredListeners, listener)
		}
	}
	out, err := json.MarshalIndent(filteredListeners, "", "    ")
	if err != nil {
		return fmt.Errorf("failed to marshal listeners: %v", err)
	}
	fmt.Fprintln(c.Stdout, string(out))
	return nil
}

func (c *ConfigWriter) setupListenerConfigWriter() (*tabwriter.Writer, []*listener.Listener, error) {
	listeners, err := c.retrieveSortedListenerSlice()
	if err != nil {
		return nil, nil, err
	}
	w := new(tabwriter.Writer).Init(c.Stdout, 0, 8, 1, ' ', 0)
	return w, listeners, nil
}

func (c *ConfigWriter) retrieveSortedListenerSlice() ([]*listener.Listener, error) {
	if c.configDump == nil {
		return nil, fmt.Errorf("config writer has not been primed")
	}
	listenerDump, err := c.configDump.GetListenerConfigDump()
	if err != nil {
		return nil, fmt.Errorf("listener dump: %v", err)
	}
	listeners := make([]*listener.Listener, 0)
	for _, l := range listenerDump.DynamicListeners {
		if l.ActiveState != nil && l.ActiveState.Listener != nil {
			listenerTyped := &listener.Listener{}
			// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
			l.ActiveState.Listener.TypeUrl = v3.ListenerType
			err = ptypes.UnmarshalAny(l.ActiveState.Listener, listenerTyped)
			if err != nil {
				return nil, fmt.Errorf("unmarshal listener: %v", err)
			}
			listeners = append(listeners, listenerTyped)
		}
	}

	for _, l := range listenerDump.StaticListeners {
		if l.Listener != nil {
			listenerTyped := &listener.Listener{}
			// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
			l.Listener.TypeUrl = v3.ListenerType
			err = ptypes.UnmarshalAny(l.Listener, listenerTyped)
			if err != nil {
				return nil, fmt.Errorf("unmarshal listener: %v", err)
			}
			listeners = append(listeners, listenerTyped)
		}
	}
	if len(listeners) == 0 {
		return nil, fmt.Errorf("no listeners found")
	}
	return listeners, nil
}
<|endoftext|>


<commit_before>// Copyright 2009 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 net

import (
	"fmt"
	"testing"
)

func TestDNSThreadLimit(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}

	const N = 10000
	c := make(chan int, N)
	for i := 0; i < N; i++ {
		go func(i int) {
			LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
			c <- 1
		}(i)
	}
	// Don't bother waiting for the stragglers; stop at 0.9 N.
	for i := 0; i < N*9/10; i++ {
		if i%100 == 0 {
			//println("TestDNSThreadLimit:", i)
		}
		<-c
	}

	// If we're still here, it worked.
}
<commit_msg>net: disable TestDNSThreadLimit even in non-short mode by default<commit_after>// Copyright 2009 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 net

import (
	"flag"
	"fmt"
	"testing"
)

var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")

func TestDNSThreadLimit(t *testing.T) {
	if !*testDNSFlood {
		t.Skip("test disabled; use -dnsflood to enable")
	}

	const N = 10000
	c := make(chan int, N)
	for i := 0; i < N; i++ {
		go func(i int) {
			LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
			c <- 1
		}(i)
	}
	// Don't bother waiting for the stragglers; stop at 0.9 N.
	for i := 0; i < N*9/10; i++ {
		if i%100 == 0 {
			//println("TestDNSThreadLimit:", i)
		}
		<-c
	}

	// If we're still here, it worked.
}
<|endoftext|>


<commit_before>package integration_test

import (
	"time"

	"github.com/concourse/baggageclaim"
	"github.com/concourse/baggageclaim/volume"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("TTL's", func() {
	var (
		runner *BaggageClaimRunner
		client baggageclaim.Client
	)

	BeforeEach(func() {
		runner = NewRunner(baggageClaimPath)
		runner.Start()

		client = runner.Client()
	})

	AfterEach(func() {
		runner.Stop()
		runner.Cleanup()
	})

	It("can set a ttl", func() {
		spec := baggageclaim.VolumeSpec{
			TTL: 10 * time.Second,
		}

		emptyVolume, err := client.CreateVolume(logger, spec)
		Expect(err).NotTo(HaveOccurred())

		expiresAt := time.Now().Add(volume.TTL(10).Duration())

		someVolume, err := client.LookupVolume(logger, emptyVolume.Handle())
		Expect(err).NotTo(HaveOccurred())

		ttl, expiresAt, err := someVolume.Expiration()
		Expect(err).NotTo(HaveOccurred())
		Expect(ttl).To(Equal(10 * time.Second))
		Expect(expiresAt).To(BeTemporally("~", expiresAt, 1*time.Second))
	})

	It("removes the volume after the ttl duration", func() {
		spec := baggageclaim.VolumeSpec{
			TTL: 1 * time.Second,
		}

		emptyVolume, err := client.CreateVolume(logger, spec)
		Expect(err).NotTo(HaveOccurred())

		emptyVolume.Release(0)

		volumes, err := client.ListVolumes(logger, nil)
		Expect(err).NotTo(HaveOccurred())
		Expect(volumes).To(HaveLen(1))

		volumes[0].Release(0)

		time.Sleep(2 * time.Second)

		Expect(runner.CurrentHandles()).To(BeEmpty())
	})

	Describe("heartbeating", func() {
		It("keeps the container alive, and lets it expire once released", func() {
			spec := baggageclaim.VolumeSpec{TTL: 2 * time.Second}

			volume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 3*time.Second).Should(ContainElement(volume.Handle()))

			volume.Release(0)

			// note: don't use Eventually; CurrentHandles causes it to heartbeat

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(BeEmpty())
		})

		Describe("releasing with a final ttl", func() {
			It("lets it expire after the given TTL", func() {
				spec := baggageclaim.VolumeSpec{TTL: 2 * time.Second}

				volume, err := client.CreateVolume(logger, spec)
				Expect(err).NotTo(HaveOccurred())

				Consistently(runner.CurrentHandles, 3*time.Second).Should(ContainElement(volume.Handle()))

				volume.Release(3 * time.Second)

				ttl, _, err := volume.Expiration()
				Expect(err).NotTo(HaveOccurred())
				Expect(ttl).To(Equal(3 * time.Second))

				time.Sleep(4 * time.Second)
				Expect(runner.CurrentHandles()).To(BeEmpty())
			})
		})

		Context("when you look up a volume by handle", func() {
			It("heartbeats the volume once before returning it", func() {
				spec := baggageclaim.VolumeSpec{
					TTL: 5 * time.Second,
				}

				emptyVolume, err := client.CreateVolume(logger, spec)
				Ω(err).ShouldNot(HaveOccurred())

				time.Sleep(2 * time.Second)

				_, err = client.LookupVolume(logger, emptyVolume.Handle())

				_, expiresAt, err := emptyVolume.Expiration()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(expiresAt).Should(BeTemporally("~", time.Now().Add(5*time.Second), 1*time.Second))
			})
		})
	})

	Describe("resetting the ttl", func() {
		It("pauses the parent if you create a cow volume", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}

			parentVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 1*time.Second).Should(ContainElement(parentVolume.Handle()))

			childVolume, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      4 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			parentVolume.Release(0)

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			childVolume.Release(0)

			time.Sleep(5 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume.Handle()))

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(parentVolume.Handle()))
		})

		It("pauses the parent as long as *any* child volumes are present", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}
			parentVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 1*time.Second).Should(ContainElement(parentVolume.Handle()))

			childVolume1, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      2 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			childVolume2, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      2 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			parentVolume.Release(0)

			By("the parent should stay paused")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			By("the first child should be removed")
			childVolume1.Release(0)
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume1.Handle()))

			By("the parent should still be paused")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			By("the second child should be removed")
			childVolume2.Release(0)
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume2.Handle()))

			By("the parent should be removed")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(parentVolume.Handle()))
		})

		It("resets to a new value if you update the ttl", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}

			emptyVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			ttl, _, err := emptyVolume.Expiration()
			Expect(err).NotTo(HaveOccurred())
			Expect(ttl).To(Equal(2 * time.Second))

			emptyVolume.Release(0)

			err = emptyVolume.SetTTL(3 * time.Second)
			Expect(err).NotTo(HaveOccurred())

			ttl, _, err = emptyVolume.Expiration()
			Expect(err).NotTo(HaveOccurred())
			Expect(ttl).To(Equal(3 * time.Second))
		})

		It("returns ErrVolumeNotFound when setting the TTL after it's expired", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 1 * time.Second,
			}

			emptyVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			emptyVolume.Release(0)
			time.Sleep(2 * time.Second)

			err = emptyVolume.SetTTL(1 * time.Second)
			Expect(err).To(Equal(baggageclaim.ErrVolumeNotFound))
		})
	})
})
<commit_msg>update variable names to be different<commit_after>package integration_test

import (
	"time"

	"github.com/concourse/baggageclaim"
	"github.com/concourse/baggageclaim/volume"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("TTL's", func() {
	var (
		runner *BaggageClaimRunner
		client baggageclaim.Client
	)

	BeforeEach(func() {
		runner = NewRunner(baggageClaimPath)
		runner.Start()

		client = runner.Client()
	})

	AfterEach(func() {
		runner.Stop()
		runner.Cleanup()
	})

	It("can set a ttl", func() {
		spec := baggageclaim.VolumeSpec{
			TTL: 10 * time.Second,
		}

		emptyVolume, err := client.CreateVolume(logger, spec)
		Expect(err).NotTo(HaveOccurred())

		expectedExpiresAt := time.Now().Add(volume.TTL(10).Duration())

		someVolume, err := client.LookupVolume(logger, emptyVolume.Handle())
		Expect(err).NotTo(HaveOccurred())

		ttl, actualExpiresAt, err := someVolume.Expiration()
		Expect(err).NotTo(HaveOccurred())
		Expect(ttl).To(Equal(10 * time.Second))
		Expect(actualExpiresAt).To(BeTemporally("~", expectedExpiresAt, 1*time.Second))
	})

	It("removes the volume after the ttl duration", func() {
		spec := baggageclaim.VolumeSpec{
			TTL: 1 * time.Second,
		}

		emptyVolume, err := client.CreateVolume(logger, spec)
		Expect(err).NotTo(HaveOccurred())

		emptyVolume.Release(0)

		volumes, err := client.ListVolumes(logger, nil)
		Expect(err).NotTo(HaveOccurred())
		Expect(volumes).To(HaveLen(1))

		volumes[0].Release(0)

		time.Sleep(2 * time.Second)

		Expect(runner.CurrentHandles()).To(BeEmpty())
	})

	Describe("heartbeating", func() {
		It("keeps the container alive, and lets it expire once released", func() {
			spec := baggageclaim.VolumeSpec{TTL: 2 * time.Second}

			volume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 3*time.Second).Should(ContainElement(volume.Handle()))

			volume.Release(0)

			// note: don't use Eventually; CurrentHandles causes it to heartbeat

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(BeEmpty())
		})

		Describe("releasing with a final ttl", func() {
			It("lets it expire after the given TTL", func() {
				spec := baggageclaim.VolumeSpec{TTL: 2 * time.Second}

				volume, err := client.CreateVolume(logger, spec)
				Expect(err).NotTo(HaveOccurred())

				Consistently(runner.CurrentHandles, 3*time.Second).Should(ContainElement(volume.Handle()))

				volume.Release(3 * time.Second)

				ttl, _, err := volume.Expiration()
				Expect(err).NotTo(HaveOccurred())
				Expect(ttl).To(Equal(3 * time.Second))

				time.Sleep(4 * time.Second)
				Expect(runner.CurrentHandles()).To(BeEmpty())
			})
		})

		Context("when you look up a volume by handle", func() {
			It("heartbeats the volume once before returning it", func() {
				spec := baggageclaim.VolumeSpec{
					TTL: 5 * time.Second,
				}

				emptyVolume, err := client.CreateVolume(logger, spec)
				Ω(err).ShouldNot(HaveOccurred())

				time.Sleep(2 * time.Second)

				_, err = client.LookupVolume(logger, emptyVolume.Handle())

				_, expiresAt, err := emptyVolume.Expiration()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(expiresAt).Should(BeTemporally("~", time.Now().Add(5*time.Second), 1*time.Second))
			})
		})
	})

	Describe("resetting the ttl", func() {
		It("pauses the parent if you create a cow volume", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}

			parentVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 1*time.Second).Should(ContainElement(parentVolume.Handle()))

			childVolume, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      4 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			parentVolume.Release(0)

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			childVolume.Release(0)

			time.Sleep(5 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume.Handle()))

			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(parentVolume.Handle()))
		})

		It("pauses the parent as long as *any* child volumes are present", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}
			parentVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			Consistently(runner.CurrentHandles, 1*time.Second).Should(ContainElement(parentVolume.Handle()))

			childVolume1, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      2 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			childVolume2, err := client.CreateVolume(logger, baggageclaim.VolumeSpec{
				Strategy: baggageclaim.COWStrategy{Parent: parentVolume},
				TTL:      2 * time.Second,
			})
			Expect(err).NotTo(HaveOccurred())

			parentVolume.Release(0)

			By("the parent should stay paused")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			By("the first child should be removed")
			childVolume1.Release(0)
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume1.Handle()))

			By("the parent should still be paused")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).To(ContainElement(parentVolume.Handle()))

			By("the second child should be removed")
			childVolume2.Release(0)
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(childVolume2.Handle()))

			By("the parent should be removed")
			time.Sleep(3 * time.Second)
			Expect(runner.CurrentHandles()).ToNot(ContainElement(parentVolume.Handle()))
		})

		It("resets to a new value if you update the ttl", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 2 * time.Second,
			}

			emptyVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			ttl, _, err := emptyVolume.Expiration()
			Expect(err).NotTo(HaveOccurred())
			Expect(ttl).To(Equal(2 * time.Second))

			emptyVolume.Release(0)

			err = emptyVolume.SetTTL(3 * time.Second)
			Expect(err).NotTo(HaveOccurred())

			ttl, _, err = emptyVolume.Expiration()
			Expect(err).NotTo(HaveOccurred())
			Expect(ttl).To(Equal(3 * time.Second))
		})

		It("returns ErrVolumeNotFound when setting the TTL after it's expired", func() {
			spec := baggageclaim.VolumeSpec{
				TTL: 1 * time.Second,
			}

			emptyVolume, err := client.CreateVolume(logger, spec)
			Expect(err).NotTo(HaveOccurred())

			emptyVolume.Release(0)
			time.Sleep(2 * time.Second)

			err = emptyVolume.SetTTL(1 * time.Second)
			Expect(err).To(Equal(baggageclaim.ErrVolumeNotFound))
		})
	})
})
<|endoftext|>