<commit_before>// Copyright 2015-2018 the u-root 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 main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"runtime"
	"sort"
	"strings"
	"time"

	gbbgolang "github.com/u-root/gobusybox/src/pkg/golang"
	"github.com/u-root/u-root/pkg/golang"
	"github.com/u-root/u-root/pkg/shlex"
	"github.com/u-root/u-root/pkg/uroot"
	"github.com/u-root/u-root/pkg/uroot/builder"
	"github.com/u-root/u-root/pkg/uroot/initramfs"
)

// multiFlag is used for flags that support multiple invocations, e.g. -files
type multiFlag []string

func (m *multiFlag) String() string {
	return fmt.Sprint(*m)
}

func (m *multiFlag) Set(value string) error {
	*m = append(*m, value)
	return nil
}

// Flags for u-root builder.
var (
	build, format, tmpDir, base, outputPath *string
	uinitCmd, initCmd                       *string
	defaultShell                            *string
	useExistingInit                         *bool
	noCommands                              *bool
	extraFiles                              multiFlag
	statsOutputPath                         *string
	statsLabel                              *string
	shellbang                               *bool
	tags                                    *string
	// For the new gobusybox support
	usegobusybox *bool
	genDir       *string
)

func init() {
	var sh string
	switch golang.Default().GOOS {
	case "plan9":
		sh = ""
	default:
		sh = "elvish"
	}

	build = flag.String("build", "gbb", "u-root build format (e.g. bb or binary).")
	format = flag.String("format", "cpio", "Archival format.")

	tmpDir = flag.String("tmpdir", "", "Temporary directory to put binaries in.")

	base = flag.String("base", "", "Base archive to add files to. By default, this is a couple of directories like /bin, /etc, etc. u-root has a default internally supplied set of files; use base=/dev/null if you don't want any base files.")
	useExistingInit = flag.Bool("useinit", false, "Use existing init from base archive (only if --base was specified).")
	outputPath = flag.String("o", "", "Path to output initramfs file.")

	initCmd = flag.String("initcmd", "init", "Symlink target for /init. Can be an absolute path or a u-root command name. Use initcmd=\"\" if you don't want the symlink.")
	uinitCmd = flag.String("uinitcmd", "", "Symlink target and arguments for /bin/uinit. Can be an absolute path or a u-root command name. Use uinitcmd=\"\" if you don't want the symlink. E.g. -uinitcmd=\"echo foobar\"")
	defaultShell = flag.String("defaultsh", sh, "Default shell. Can be an absolute path or a u-root command name. Use defaultsh=\"\" if you don't want the symlink.")

	noCommands = flag.Bool("nocmd", false, "Build no Go commands; initramfs only")

	flag.Var(&extraFiles, "files", "Additional files, directories, and binaries (with their ldd dependencies) to add to archive. Can be speficified multiple times.")

	shellbang = flag.Bool("shellbang", false, "Use #! instead of symlinks for busybox")

	statsOutputPath = flag.String("stats-output-path", "", "Write build stats to this file (JSON)")
	statsLabel = flag.String("stats-label", "", "Use this statsLabel when writing stats")

	tags = flag.String("tags", "", "Comma separated list of build tags")

	// Flags for the gobusybox, which we hope to move to, since it works with modules.
	genDir = flag.String("gen-dir", "", "Directory to generate source in")

}

type buildStats struct {
	Label      string  `json:"label,omitempty"`
	Time       int64   `json:"time"`
	Duration   float64 `json:"duration"`
	OutputSize int64   `json:"output_size"`
}

func writeBuildStats(stats buildStats, path string) error {
	var allStats []buildStats
	if data, err := os.ReadFile(*statsOutputPath); err == nil {
		json.Unmarshal(data, &allStats)
	}
	found := false
	for i, s := range allStats {
		if s.Label == stats.Label {
			allStats[i] = stats
			found = true
			break
		}
	}
	if !found {
		allStats = append(allStats, stats)
		sort.Slice(allStats, func(i, j int) bool {
			return strings.Compare(allStats[i].Label, allStats[j].Label) == -1
		})
	}
	data, err := json.MarshalIndent(allStats, "", "  ")
	if err != nil {
		return err
	}
	if err := os.WriteFile(*statsOutputPath, data, 0o644); err != nil {
		return err
	}
	return nil
}

func generateLabel() string {
	var baseCmds []string
	env := golang.Default()
	if len(flag.Args()) > 0 {
		// Use the last component of the name to keep the label short
		for _, e := range flag.Args() {
			baseCmds = append(baseCmds, path.Base(e))
		}
	} else {
		baseCmds = []string{"core"}
	}
	return fmt.Sprintf("%s-%s-%s-%s", *build, env.GOOS, env.GOARCH, strings.Join(baseCmds, "_"))
}

func main() {
	gbbOpts := &gbbgolang.BuildOpts{}
	gbbOpts.RegisterFlags(flag.CommandLine)

	// Register an alias for -go-no-strip for backwards compatibility.
	flag.CommandLine.BoolVar(&gbbOpts.NoStrip, "no-strip", false, "Build unstripped binaries")
	flag.Parse()

	start := time.Now()

	// Main is in a separate functions so defers run on return.
	if err := Main(gbbOpts); err != nil {
		log.Fatalf("Build error: %v", err)
	}

	elapsed := time.Now().Sub(start)

	stats := buildStats{
		Label:    *statsLabel,
		Time:     start.Unix(),
		Duration: float64(elapsed.Milliseconds()) / 1000,
	}
	if stats.Label == "" {
		stats.Label = generateLabel()
	}
	if stat, err := os.Stat(*outputPath); err == nil && stat.ModTime().After(start) {
		log.Printf("Successfully built %q (size %d).", *outputPath, stat.Size())
		stats.OutputSize = stat.Size()
		if *statsOutputPath != "" {
			if err := writeBuildStats(stats, *statsOutputPath); err == nil {
				log.Printf("Wrote stats to %q (label %q)", *statsOutputPath, stats.Label)
			} else {
				log.Printf("Failed to write stats to %s: %v", *statsOutputPath, err)
			}
		}
	}
}

var recommendedVersions = []string{
	"go1.17",
}

func isRecommendedVersion(v string) bool {
	for _, r := range recommendedVersions {
		if strings.HasPrefix(v, r) {
			return true
		}
	}
	return false
}

// Main is a separate function so defers are run on return, which they wouldn't
// on exit.
func Main(buildOpts *gbbgolang.BuildOpts) error {
	env := golang.Default()
	env.BuildTags = strings.Split(*tags, ",")
	if env.CgoEnabled {
		log.Printf("Disabling CGO for u-root...")
		env.CgoEnabled = false
	}
	log.Printf("Build environment: %s", env)
	if env.GOOS != "linux" {
		log.Printf("GOOS is not linux. Did you mean to set GOOS=linux?")
	}

	v, err := env.Version()
	if err != nil {
		log.Printf("Could not get environment's Go version, using runtime's version: %v", err)
		v = runtime.Version()
	}
	if !isRecommendedVersion(v) {
		log.Printf(`WARNING: You are not using one of the recommended Go versions (have = %s, recommended = %v).
			Some packages may not compile.
			Go to https://golang.org/doc/install to find out how to install a newer version of Go,
			or use https://godoc.org/golang.org/dl/%s to install an additional version of Go.`,
			v, recommendedVersions, recommendedVersions[0])
	}

	archiver, err := initramfs.GetArchiver(*format)
	if err != nil {
		return err
	}

	logger := log.New(os.Stderr, "", log.LstdFlags)
	// Open the target initramfs file.
	if *outputPath == "" {
		if len(env.GOOS) == 0 && len(env.GOARCH) == 0 {
			return fmt.Errorf("passed no path, GOOS, and GOARCH to CPIOArchiver.OpenWriter")
		}
		*outputPath = fmt.Sprintf("/tmp/initramfs.%s_%s.cpio", env.GOOS, env.GOARCH)
	}
	w, err := archiver.OpenWriter(logger, *outputPath)
	if err != nil {
		return err
	}

	var baseFile initramfs.Reader
	if *base != "" {
		bf, err := os.Open(*base)
		if err != nil {
			return err
		}
		defer bf.Close()
		baseFile = archiver.Reader(bf)
	} else {
		baseFile = uroot.DefaultRamfs().Reader()
	}

	tempDir := *tmpDir
	if tempDir == "" {
		var err error
		tempDir, err = os.MkdirTemp("", "u-root")
		if err != nil {
			return err
		}
		defer os.RemoveAll(tempDir)
	} else if _, err := os.Stat(tempDir); os.IsNotExist(err) {
		if err := os.MkdirAll(tempDir, 0o755); err != nil {
			return fmt.Errorf("temporary directory %q did not exist; tried to mkdir but failed: %v", tempDir, err)
		}
	}

	var (
		c           []uroot.Commands
		initCommand = *initCmd
	)
	if !*noCommands {
		var b builder.Builder
		switch *build {
		case "bb":
			b = builder.BBBuilder{ShellBang: *shellbang}
		case "gbb":
			log.Printf("NOTE: building with the new gobusybox; to get old behavior, use -build=bb")
			b = builder.GBBBuilder{ShellBang: *shellbang}
		case "binary":
			b = builder.BinaryBuilder{}
		case "source":
			return fmt.Errorf("source mode has been deprecated")
		default:
			return fmt.Errorf("could not find builder %q", *build)
		}

		// Resolve globs into package imports.
		//
		// Currently allowed formats:
		//   Go package imports; e.g. github.com/u-root/u-root/cmds/ls (must be in $GOPATH)
		//   Paths to Go package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/*
		var pkgs []string
		for _, a := range flag.Args() {
			p, ok := templates[a]
			if !ok {
				pkgs = append(pkgs, a)
				continue
			}
			pkgs = append(pkgs, p...)
		}
		if len(pkgs) == 0 {
			pkgs = []string{"github.com/u-root/u-root/cmds/core/*"}
		}

		// The command-line tool only allows specifying one build mode
		// right now.
		c = append(c, uroot.Commands{
			Builder:  b,
			Packages: pkgs,
		})
	}

	opts := uroot.Opts{
		Env:             env,
		Commands:        c,
		TempDir:         tempDir,
		ExtraFiles:      extraFiles,
		OutputFile:      w,
		BaseArchive:     baseFile,
		UseExistingInit: *useExistingInit,
		InitCmd:         initCommand,
		DefaultShell:    *defaultShell,
		BuildOpts:       buildOpts,
	}
	uinitArgs := shlex.Argv(*uinitCmd)
	if len(uinitArgs) > 0 {
		opts.UinitCmd = uinitArgs[0]
	}
	if len(uinitArgs) > 1 {
		opts.UinitArgs = uinitArgs[1:]
	}
	return uroot.CreateInitramfs(logger, opts)
}
<commit_msg>u-root: shorter log lines by only printing time<commit_after>// Copyright 2015-2018 the u-root 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 main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"runtime"
	"sort"
	"strings"
	"time"

	gbbgolang "github.com/u-root/gobusybox/src/pkg/golang"
	"github.com/u-root/u-root/pkg/golang"
	"github.com/u-root/u-root/pkg/shlex"
	"github.com/u-root/u-root/pkg/ulog"
	"github.com/u-root/u-root/pkg/uroot"
	"github.com/u-root/u-root/pkg/uroot/builder"
	"github.com/u-root/u-root/pkg/uroot/initramfs"
)

// multiFlag is used for flags that support multiple invocations, e.g. -files
type multiFlag []string

func (m *multiFlag) String() string {
	return fmt.Sprint(*m)
}

func (m *multiFlag) Set(value string) error {
	*m = append(*m, value)
	return nil
}

// Flags for u-root builder.
var (
	build, format, tmpDir, base, outputPath *string
	uinitCmd, initCmd                       *string
	defaultShell                            *string
	useExistingInit                         *bool
	noCommands                              *bool
	extraFiles                              multiFlag
	statsOutputPath                         *string
	statsLabel                              *string
	shellbang                               *bool
	tags                                    *string
	// For the new gobusybox support
	usegobusybox *bool
	genDir       *string
)

func init() {
	var sh string
	switch golang.Default().GOOS {
	case "plan9":
		sh = ""
	default:
		sh = "elvish"
	}

	build = flag.String("build", "gbb", "u-root build format (e.g. bb or binary).")
	format = flag.String("format", "cpio", "Archival format.")

	tmpDir = flag.String("tmpdir", "", "Temporary directory to put binaries in.")

	base = flag.String("base", "", "Base archive to add files to. By default, this is a couple of directories like /bin, /etc, etc. u-root has a default internally supplied set of files; use base=/dev/null if you don't want any base files.")
	useExistingInit = flag.Bool("useinit", false, "Use existing init from base archive (only if --base was specified).")
	outputPath = flag.String("o", "", "Path to output initramfs file.")

	initCmd = flag.String("initcmd", "init", "Symlink target for /init. Can be an absolute path or a u-root command name. Use initcmd=\"\" if you don't want the symlink.")
	uinitCmd = flag.String("uinitcmd", "", "Symlink target and arguments for /bin/uinit. Can be an absolute path or a u-root command name. Use uinitcmd=\"\" if you don't want the symlink. E.g. -uinitcmd=\"echo foobar\"")
	defaultShell = flag.String("defaultsh", sh, "Default shell. Can be an absolute path or a u-root command name. Use defaultsh=\"\" if you don't want the symlink.")

	noCommands = flag.Bool("nocmd", false, "Build no Go commands; initramfs only")

	flag.Var(&extraFiles, "files", "Additional files, directories, and binaries (with their ldd dependencies) to add to archive. Can be speficified multiple times.")

	shellbang = flag.Bool("shellbang", false, "Use #! instead of symlinks for busybox")

	statsOutputPath = flag.String("stats-output-path", "", "Write build stats to this file (JSON)")
	statsLabel = flag.String("stats-label", "", "Use this statsLabel when writing stats")

	tags = flag.String("tags", "", "Comma separated list of build tags")

	// Flags for the gobusybox, which we hope to move to, since it works with modules.
	genDir = flag.String("gen-dir", "", "Directory to generate source in")

}

type buildStats struct {
	Label      string  `json:"label,omitempty"`
	Time       int64   `json:"time"`
	Duration   float64 `json:"duration"`
	OutputSize int64   `json:"output_size"`
}

func writeBuildStats(stats buildStats, path string) error {
	var allStats []buildStats
	if data, err := os.ReadFile(*statsOutputPath); err == nil {
		json.Unmarshal(data, &allStats)
	}
	found := false
	for i, s := range allStats {
		if s.Label == stats.Label {
			allStats[i] = stats
			found = true
			break
		}
	}
	if !found {
		allStats = append(allStats, stats)
		sort.Slice(allStats, func(i, j int) bool {
			return strings.Compare(allStats[i].Label, allStats[j].Label) == -1
		})
	}
	data, err := json.MarshalIndent(allStats, "", "  ")
	if err != nil {
		return err
	}
	if err := os.WriteFile(*statsOutputPath, data, 0o644); err != nil {
		return err
	}
	return nil
}

func generateLabel() string {
	var baseCmds []string
	env := golang.Default()
	if len(flag.Args()) > 0 {
		// Use the last component of the name to keep the label short
		for _, e := range flag.Args() {
			baseCmds = append(baseCmds, path.Base(e))
		}
	} else {
		baseCmds = []string{"core"}
	}
	return fmt.Sprintf("%s-%s-%s-%s", *build, env.GOOS, env.GOARCH, strings.Join(baseCmds, "_"))
}

func main() {
	gbbOpts := &gbbgolang.BuildOpts{}
	gbbOpts.RegisterFlags(flag.CommandLine)

	l := log.New(os.Stderr, "", log.Ltime)

	// Register an alias for -go-no-strip for backwards compatibility.
	flag.CommandLine.BoolVar(&gbbOpts.NoStrip, "no-strip", false, "Build unstripped binaries")
	flag.Parse()

	start := time.Now()

	// Main is in a separate functions so defers run on return.
	if err := Main(l, gbbOpts); err != nil {
		l.Fatalf("Build error: %v", err)
	}

	elapsed := time.Now().Sub(start)

	stats := buildStats{
		Label:    *statsLabel,
		Time:     start.Unix(),
		Duration: float64(elapsed.Milliseconds()) / 1000,
	}
	if stats.Label == "" {
		stats.Label = generateLabel()
	}
	if stat, err := os.Stat(*outputPath); err == nil && stat.ModTime().After(start) {
		l.Printf("Successfully built %q (size %d).", *outputPath, stat.Size())
		stats.OutputSize = stat.Size()
		if *statsOutputPath != "" {
			if err := writeBuildStats(stats, *statsOutputPath); err == nil {
				l.Printf("Wrote stats to %q (label %q)", *statsOutputPath, stats.Label)
			} else {
				l.Printf("Failed to write stats to %s: %v", *statsOutputPath, err)
			}
		}
	}
}

var recommendedVersions = []string{
	"go1.17",
}

func isRecommendedVersion(v string) bool {
	for _, r := range recommendedVersions {
		if strings.HasPrefix(v, r) {
			return true
		}
	}
	return false
}

// Main is a separate function so defers are run on return, which they wouldn't
// on exit.
func Main(l ulog.Logger, buildOpts *gbbgolang.BuildOpts) error {
	env := golang.Default()
	env.BuildTags = strings.Split(*tags, ",")
	if env.CgoEnabled {
		l.Printf("Disabling CGO for u-root...")
		env.CgoEnabled = false
	}
	l.Printf("Build environment: %s", env)
	if env.GOOS != "linux" {
		l.Printf("GOOS is not linux. Did you mean to set GOOS=linux?")
	}

	v, err := env.Version()
	if err != nil {
		l.Printf("Could not get environment's Go version, using runtime's version: %v", err)
		v = runtime.Version()
	}
	if !isRecommendedVersion(v) {
		l.Printf(`WARNING: You are not using one of the recommended Go versions (have = %s, recommended = %v).
			Some packages may not compile.
			Go to https://golang.org/doc/install to find out how to install a newer version of Go,
			or use https://godoc.org/golang.org/dl/%s to install an additional version of Go.`,
			v, recommendedVersions, recommendedVersions[0])
	}

	archiver, err := initramfs.GetArchiver(*format)
	if err != nil {
		return err
	}

	// Open the target initramfs file.
	if *outputPath == "" {
		if len(env.GOOS) == 0 && len(env.GOARCH) == 0 {
			return fmt.Errorf("passed no path, GOOS, and GOARCH to CPIOArchiver.OpenWriter")
		}
		*outputPath = fmt.Sprintf("/tmp/initramfs.%s_%s.cpio", env.GOOS, env.GOARCH)
	}
	w, err := archiver.OpenWriter(l, *outputPath)
	if err != nil {
		return err
	}

	var baseFile initramfs.Reader
	if *base != "" {
		bf, err := os.Open(*base)
		if err != nil {
			return err
		}
		defer bf.Close()
		baseFile = archiver.Reader(bf)
	} else {
		baseFile = uroot.DefaultRamfs().Reader()
	}

	tempDir := *tmpDir
	if tempDir == "" {
		var err error
		tempDir, err = os.MkdirTemp("", "u-root")
		if err != nil {
			return err
		}
		defer os.RemoveAll(tempDir)
	} else if _, err := os.Stat(tempDir); os.IsNotExist(err) {
		if err := os.MkdirAll(tempDir, 0o755); err != nil {
			return fmt.Errorf("temporary directory %q did not exist; tried to mkdir but failed: %v", tempDir, err)
		}
	}

	var (
		c           []uroot.Commands
		initCommand = *initCmd
	)
	if !*noCommands {
		var b builder.Builder
		switch *build {
		case "bb":
			b = builder.BBBuilder{ShellBang: *shellbang}
		case "gbb":
			l.Printf("NOTE: building with the new gobusybox; to get old behavior, use -build=bb")
			b = builder.GBBBuilder{ShellBang: *shellbang}
		case "binary":
			b = builder.BinaryBuilder{}
		case "source":
			return fmt.Errorf("source mode has been deprecated")
		default:
			return fmt.Errorf("could not find builder %q", *build)
		}

		// Resolve globs into package imports.
		//
		// Currently allowed formats:
		//   Go package imports; e.g. github.com/u-root/u-root/cmds/ls (must be in $GOPATH)
		//   Paths to Go package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/*
		var pkgs []string
		for _, a := range flag.Args() {
			p, ok := templates[a]
			if !ok {
				pkgs = append(pkgs, a)
				continue
			}
			pkgs = append(pkgs, p...)
		}
		if len(pkgs) == 0 {
			pkgs = []string{"github.com/u-root/u-root/cmds/core/*"}
		}

		// The command-line tool only allows specifying one build mode
		// right now.
		c = append(c, uroot.Commands{
			Builder:  b,
			Packages: pkgs,
		})
	}

	opts := uroot.Opts{
		Env:             env,
		Commands:        c,
		TempDir:         tempDir,
		ExtraFiles:      extraFiles,
		OutputFile:      w,
		BaseArchive:     baseFile,
		UseExistingInit: *useExistingInit,
		InitCmd:         initCommand,
		DefaultShell:    *defaultShell,
		BuildOpts:       buildOpts,
	}
	uinitArgs := shlex.Argv(*uinitCmd)
	if len(uinitArgs) > 0 {
		opts.UinitCmd = uinitArgs[0]
	}
	if len(uinitArgs) > 1 {
		opts.UinitArgs = uinitArgs[1:]
	}
	return uroot.CreateInitramfs(l, opts)
}
<|endoftext|>


<commit_before>package examples

import (
	"fmt"
	"github.com/jonnonz/zed"
)

func organizationExamples() {

	client := zd.NewClient("zendesk_domain", "email/token", "token", nil)

	// get Organization
	existingOrg, _, err := client.Organizations.GetOrganizationById("org_id")

	if err != nil {
		fmt.Println("Oh no!")
	}

	// add tags
	existingOrg.Tags = []string{"test_tags"}

	// Change Name
	existingOrg.Name = "Oh hello!"

	// Update organization fields
	existingOrg.OrganizationFields = map[string]string{
		"key": "value",
	}

	// update the organization, handle any errors etc..
	updatedOrganization , _ := client.Organizations.UpdateOrganization(existingOrg)

	fmt.Println(updatedOrganization.UpdatedAt)

	// create a new org
	newOrg := zd.Organization{
		Name: "brand new org",
	}

	response, _ := client.Organizations.CreateOrganization(&newOrg)

	// print the id of new org.
	fmt.Println(response.ID)
}
<commit_msg>removed uneeded changes<commit_after>package examples

import (
	"fmt"
	"github.com/pzurek/zed"
)

func organizationExamples() {

	client := zd.NewClient("zendesk_domain", "email/token", "token", nil)

	// get Organization
	existingOrg, _, err := client.Organizations.GetOrganizationById("org_id")

	if err != nil {
		fmt.Println("Oh no!")
	}

	// add tags
	existingOrg.Tags = []string{"test_tags"}

	// Change Name
	existingOrg.Name = "Oh hello!"

	// Update organization fields
	existingOrg.OrganizationFields = map[string]string{
		"key": "value",
	}

	// update the organization, handle any errors etc..
	updatedOrganization , _ := client.Organizations.UpdateOrganization(existingOrg)

	fmt.Println(updatedOrganization.UpdatedAt)

	// create a new org
	newOrg := zd.Organization{
		Name: "brand new org",
	}

	response, _ := client.Organizations.CreateOrganization(&newOrg)

	// print the id of new org.
	fmt.Println(response.ID)
}
<|endoftext|>


<commit_before>package tests

import (
	"context"
	"fmt"
	"net"
	"os"
	"sync"
	"testing"

	"github.com/golang/protobuf/ptypes/empty"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"

	"github.com/networkservicemesh/networkservicemesh/controlplane/api/crossconnect"
	"github.com/networkservicemesh/networkservicemesh/pkg/tools"
	monitor_crossconnect "github.com/networkservicemesh/networkservicemesh/sdk/monitor/crossconnect"
)

func startClient(g *WithT, target string) {
	_ = os.Setenv(tools.InsecureEnv, "true")
	conn, err := tools.DialTCP(target)
	defer conn.Close()

	g.Expect(err).To(BeNil())
	monitorClient := crossconnect.NewMonitorCrossConnectClient(conn)
	stream, err := monitorClient.MonitorCrossConnects(context.Background(), &empty.Empty{})
	g.Expect(err).To(BeNil())

	event, err := stream.Recv()
	g.Expect(err).To(BeNil())
	logrus.Infof("Receive event: %v", event)
	g.Expect(event).NotTo(BeNil())
	g.Expect(event.Type).To(Equal(crossconnect.CrossConnectEventType_INITIAL_STATE_TRANSFER))
	g.Expect(event.CrossConnects).NotTo(BeNil())
	g.Expect(event.CrossConnects["1"]).NotTo(BeNil())
}

func TestSimple(t *testing.T) {
	g := NewWithT(t)

	listener, err := net.Listen("tcp", "localhost:0")
	defer listener.Close()
	g.Expect(err).To(BeNil())

	grpcServer := grpc.NewServer()
	monitor := monitor_crossconnect.NewMonitorServer()
	crossconnect.RegisterMonitorCrossConnectServer(grpcServer, monitor)

	go func() {
		grpcServer.Serve(listener)
	}()

	monitor.Update(context.Background(), &crossconnect.CrossConnect{Id: "1"})

	startClient(g, listenerAddress(listener))
}

func listenerAddress(listener net.Listener) string {
	port := listener.Addr().(*net.TCPAddr).Port
	logrus.Infof("Connect to port: %d", port)
	return fmt.Sprintf("localhost:%d", port)
}

func TestSeveralRecipient(t *testing.T) {
	g := NewWithT(t)

	listener, err := net.Listen("tcp", "localhost:0")
	defer listener.Close()
	g.Expect(err).To(BeNil())

	grpcServer := grpc.NewServer()
	monitor := monitor_crossconnect.NewMonitorServer()
	crossconnect.RegisterMonitorCrossConnectServer(grpcServer, monitor)

	var waitServe sync.WaitGroup
	waitServe.Add(1)
	go func() {
		go waitServe.Done()
		_ = grpcServer.Serve(listener)
	}()
	waitServe.Wait()
	monitor.Update(context.Background(), &crossconnect.CrossConnect{Id: "1"})

	var wg sync.WaitGroup
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go func() {
			startClient(g, listenerAddress(listener))
			wg.Done()
		}()
	}
	wg.Wait()
	logrus.Infof("######END")
}
<commit_msg>fix test (#1815)<commit_after>package tests

import (
	"context"
	"fmt"
	"net"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/golang/protobuf/ptypes/empty"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"

	"github.com/networkservicemesh/networkservicemesh/controlplane/api/crossconnect"
	"github.com/networkservicemesh/networkservicemesh/pkg/tools"
	monitor_crossconnect "github.com/networkservicemesh/networkservicemesh/sdk/monitor/crossconnect"
)

func startClient(g *WithT, target string, ids ...string) {
	visit := map[string]bool{}
	for _, id := range ids {
		visit[id] = false
	}
	timeout := time.After(time.Second)
	logrus.Infof("Expected cross connects with ids = %v", ids)
	_ = os.Setenv(tools.InsecureEnv, "true")
	conn, err := tools.DialTCP(target)
	defer conn.Close()

	g.Expect(err).To(BeNil())
	monitorClient := crossconnect.NewMonitorCrossConnectClient(conn)
	stream, err := monitorClient.MonitorCrossConnects(context.Background(), &empty.Empty{})
	g.Expect(err).To(BeNil())
	for {
		select {
		case <-timeout:
			logrus.Error("timeout for wait events")
			g.Expect(true).Should(BeFalse())
		default:
			event, err := stream.Recv()
			g.Expect(err).To(BeNil())
			logrus.Infof("Receive event: %v", event)
			g.Expect(event).NotTo(BeNil())
			for _, crossconnect := range event.CrossConnects {
				visit[crossconnect.Id] = true
			}
			exit := true
			for _, v := range visit {
				if !v {
					exit = false
				}
			}
			if exit {
				return
			}
		}
	}
}

func TestEachClientShouldGetAllEvents(t *testing.T) {
	g := NewWithT(t)

	listener, err := net.Listen("tcp", "localhost:0")
	defer listener.Close()
	g.Expect(err).To(BeNil())

	grpcServer := grpc.NewServer()
	monitor := monitor_crossconnect.NewMonitorServer()
	crossconnect.RegisterMonitorCrossConnectServer(grpcServer, monitor)

	go func() {
		grpcServer.Serve(listener)
	}()
	ids := []string{}
	for id := 0; id < 10; id++ {
		monitor.Update(context.Background(), &crossconnect.CrossConnect{Id: fmt.Sprint(id)})
		ids = append(ids, fmt.Sprint(id))
		startClient(g, listenerAddress(listener), ids...)
	}
}

func listenerAddress(listener net.Listener) string {
	port := listener.Addr().(*net.TCPAddr).Port
	logrus.Infof("Connect to port: %d", port)
	return fmt.Sprintf("localhost:%d", port)
}

func TestSeveralRecipient(t *testing.T) {
	g := NewWithT(t)

	listener, err := net.Listen("tcp", "localhost:0")
	defer listener.Close()
	g.Expect(err).To(BeNil())

	grpcServer := grpc.NewServer()
	monitor := monitor_crossconnect.NewMonitorServer()
	crossconnect.RegisterMonitorCrossConnectServer(grpcServer, monitor)

	var waitServe sync.WaitGroup
	waitServe.Add(1)
	go func() {
		go waitServe.Done()
		_ = grpcServer.Serve(listener)
	}()
	waitServe.Wait()
	monitor.Update(context.Background(), &crossconnect.CrossConnect{Id: "1"})

	var wg sync.WaitGroup
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go func() {
			startClient(g, listenerAddress(listener), "1")
			wg.Done()
		}()
	}
	wg.Wait()
	logrus.Infof("######END")
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
)

// NodeDestroyResource represents a resource that is to be destroyed.
type NodeDestroyResource struct {
	*NodeAbstractResource
}

func (n *NodeDestroyResource) Name() string {
	return n.NodeAbstractResource.Name() + " (destroy)"
}

// GraphNodeDestroyer
func (n *NodeDestroyResource) DestroyAddr() *ResourceAddress {
	return n.Addr
}

// GraphNodeDestroyerCBD
func (n *NodeDestroyResource) CreateBeforeDestroy() bool {
	// If we have no config, we just assume no
	if n.Config == nil {
		return false
	}

	return n.Config.Lifecycle.CreateBeforeDestroy
}

// GraphNodeEvalable
func (n *NodeDestroyResource) EvalTree() EvalNode {
	// stateId is the ID to put into the state
	stateId := n.Addr.stateId()
	if n.Addr.Index > -1 {
		stateId = fmt.Sprintf("%s.%d", stateId, n.Addr.Index)
	}

	// Build the instance info. More of this will be populated during eval
	info := &InstanceInfo{
		Id:   stateId,
		Type: n.Addr.Type,
	}

	// Get our state
	rs := n.ResourceState
	if rs == nil {
		rs = &ResourceState{}
	}
	rs.Provider = n.ProvidedBy()[0]

	var diffApply *InstanceDiff
	var provider ResourceProvider
	var state *InstanceState
	var err error
	return &EvalOpFilter{
		Ops: []walkOperation{walkApply, walkDestroy},
		Node: &EvalSequence{
			Nodes: []EvalNode{
				// Get the saved diff for apply
				&EvalReadDiff{
					Name: stateId,
					Diff: &diffApply,
				},

				// Filter the diff so we only get the destroy
				&EvalFilterDiff{
					Diff:    &diffApply,
					Output:  &diffApply,
					Destroy: true,
				},

				// If we're not destroying, then compare diffs
				&EvalIf{
					If: func(ctx EvalContext) (bool, error) {
						if diffApply != nil && diffApply.GetDestroy() {
							return true, nil
						}

						return true, EvalEarlyExitError{}
					},
					Then: EvalNoop{},
				},

				// Load the instance info so we have the module path set
				&EvalInstanceInfo{Info: info},

				&EvalGetProvider{
					Name:   n.ProvidedBy()[0],
					Output: &provider,
				},
				&EvalReadState{
					Name:   stateId,
					Output: &state,
				},
				&EvalRequireState{
					State: &state,
				},
				// Make sure we handle data sources properly.
				&EvalIf{
					If: func(ctx EvalContext) (bool, error) {
						/* TODO: data source
						if n.Resource.Mode == config.DataResourceMode {
							return true, nil
						}
						*/

						return false, nil
					},

					Then: &EvalReadDataApply{
						Info:     info,
						Diff:     &diffApply,
						Provider: &provider,
						Output:   &state,
					},
					Else: &EvalApply{
						Info:     info,
						State:    &state,
						Diff:     &diffApply,
						Provider: &provider,
						Output:   &state,
						Error:    &err,
					},
				},
				&EvalWriteState{
					Name:         stateId,
					ResourceType: n.Addr.Type,
					Provider:     rs.Provider,
					Dependencies: rs.Dependencies,
					State:        &state,
				},
				&EvalApplyPost{
					Info:  info,
					State: &state,
					Error: &err,
				},
				&EvalUpdateStateHook{},
			},
		},
	}
}
<commit_msg>terraform: destroy resource should have no references<commit_after>package terraform

import (
	"fmt"
)

// NodeDestroyResource represents a resource that is to be destroyed.
type NodeDestroyResource struct {
	*NodeAbstractResource
}

func (n *NodeDestroyResource) Name() string {
	return n.NodeAbstractResource.Name() + " (destroy)"
}

// GraphNodeDestroyer
func (n *NodeDestroyResource) DestroyAddr() *ResourceAddress {
	return n.Addr
}

// GraphNodeDestroyerCBD
func (n *NodeDestroyResource) CreateBeforeDestroy() bool {
	// If we have no config, we just assume no
	if n.Config == nil {
		return false
	}

	return n.Config.Lifecycle.CreateBeforeDestroy
}

// GraphNodeReferenceable, overriding NodeAbstractResource
func (n *NodeDestroyResource) ReferenceableName() []string {
	return nil
}

// GraphNodeReferencer, overriding NodeAbstractResource
func (n *NodeDestroyResource) References() []string {
	return nil
}

// GraphNodeEvalable
func (n *NodeDestroyResource) EvalTree() EvalNode {
	// stateId is the ID to put into the state
	stateId := n.Addr.stateId()
	if n.Addr.Index > -1 {
		stateId = fmt.Sprintf("%s.%d", stateId, n.Addr.Index)
	}

	// Build the instance info. More of this will be populated during eval
	info := &InstanceInfo{
		Id:   stateId,
		Type: n.Addr.Type,
	}

	// Get our state
	rs := n.ResourceState
	if rs == nil {
		rs = &ResourceState{}
	}
	rs.Provider = n.ProvidedBy()[0]

	var diffApply *InstanceDiff
	var provider ResourceProvider
	var state *InstanceState
	var err error
	return &EvalOpFilter{
		Ops: []walkOperation{walkApply, walkDestroy},
		Node: &EvalSequence{
			Nodes: []EvalNode{
				// Get the saved diff for apply
				&EvalReadDiff{
					Name: stateId,
					Diff: &diffApply,
				},

				// Filter the diff so we only get the destroy
				&EvalFilterDiff{
					Diff:    &diffApply,
					Output:  &diffApply,
					Destroy: true,
				},

				// If we're not destroying, then compare diffs
				&EvalIf{
					If: func(ctx EvalContext) (bool, error) {
						if diffApply != nil && diffApply.GetDestroy() {
							return true, nil
						}

						return true, EvalEarlyExitError{}
					},
					Then: EvalNoop{},
				},

				// Load the instance info so we have the module path set
				&EvalInstanceInfo{Info: info},

				&EvalGetProvider{
					Name:   n.ProvidedBy()[0],
					Output: &provider,
				},
				&EvalReadState{
					Name:   stateId,
					Output: &state,
				},
				&EvalRequireState{
					State: &state,
				},
				// Make sure we handle data sources properly.
				&EvalIf{
					If: func(ctx EvalContext) (bool, error) {
						/* TODO: data source
						if n.Resource.Mode == config.DataResourceMode {
							return true, nil
						}
						*/

						return false, nil
					},

					Then: &EvalReadDataApply{
						Info:     info,
						Diff:     &diffApply,
						Provider: &provider,
						Output:   &state,
					},
					Else: &EvalApply{
						Info:     info,
						State:    &state,
						Diff:     &diffApply,
						Provider: &provider,
						Output:   &state,
						Error:    &err,
					},
				},
				&EvalWriteState{
					Name:         stateId,
					ResourceType: n.Addr.Type,
					Provider:     rs.Provider,
					Dependencies: rs.Dependencies,
					State:        &state,
				},
				&EvalApplyPost{
					Info:  info,
					State: &state,
					Error: &err,
				},
				&EvalUpdateStateHook{},
			},
		},
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	kodingmodels "koding/db/models"
	"koding/db/mongodb/modelhelper"
	"socialapi/models"
	"socialapi/workers/common/sem"
	"sync"
	"time"

	"github.com/nlopes/slack"
	"gopkg.in/mgo.v2/bson"
)

type SlackUser struct {
	slack.User
	LastActivity *time.Time `json:"lastActivity,omitempty"`
}

type SlackChannelsResponse struct {
	Groups   []slack.Group   `json:"groups,omitempty"`
	Channels []slack.Channel `json:"channels,omitempty"`
}

// getChannels send a request to the slack with user's token & gets the channels
func getChannels(token string) (*SlackChannelsResponse, error) {
	api := slack.New(token)
	var groups []slack.Group
	var channels []slack.Channel
	var gerr, cerr error
	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		groups, gerr = api.GetGroups(true)
		wg.Done()
	}()

	go func() {
		channels, cerr = api.GetChannels(true)
		wg.Done()
	}()

	wg.Wait()

	if gerr != nil {
		return nil, gerr
	}

	if cerr != nil {
		return nil, cerr
	}

	return &SlackChannelsResponse{
		Groups:   groups,
		Channels: channels,
	}, nil
}

func getUsers(token string) ([]SlackUser, error) {
	api := slack.New(token)
	allusers, err := api.GetUsers()
	if err != nil {
		return nil, err
	}

	activeUsersChan := make(chan SlackUser) // idk the total valid number

	sem := sem.New(20) // run 20 goroutines concurrently
	var wg sync.WaitGroup
	wg.Add(len(allusers))

	var activeUsers []SlackUser
	go func() {
		for t := range activeUsersChan {
			activeUsers = append(activeUsers, t)
		}
	}()

	for _, u := range allusers {
		sem.Lock()
		go func(u slack.User) {
			defer sem.Unlock()
			defer wg.Done()

			// no need to add deleted users
			if u.Deleted {
				return
			}

			// filter bots
			if u.IsBot {
				return
			}

			// even if we get error from slack api set it to nil
			var lastActive *time.Time

			// presence information is optional, so we can skip the errored ones
			p, err := api.GetUserPresence(u.ID)
			if err != nil || p == nil {
				activeUsersChan <- SlackUser{u, lastActive}
				return
			}

			// set presence info
			u.Presence = p.Presence

			// LastActivity works inconsistently
			// if u.Presence != slackAway {
			//  LastActiveTime := p.LastActivity.Time()
			//  lastActive = &LastActiveTime
			// }

			activeUsersChan <- SlackUser{u, lastActive}
		}(u)
	}

	wg.Wait()
	close(activeUsersChan)

	return activeUsers, nil
}

func postMessage(token string, req *SlackMessageRequest) (string, error) {
	api := slack.New(token)
	_, id, err := api.PostMessage(req.Channel, req.Text, req.Params)
	return id, err
}

func getTeamInfo(token string) (*slack.TeamInfo, error) {
	api := slack.New(token)
	info, err := api.GetTeamInfo()
	if err != nil {
		return nil, err
	}

	return info, nil
}

func updateUserSlackToken(user *kodingmodels.User, groupName string, m string) error {
	selector := bson.M{"username": user.Name}
	key := fmt.Sprintf("foreignAuth.slack.%s.token", groupName)
	update := bson.M{key: m}

	return modelhelper.UpdateUser(selector, update)
}

// getSlackToken fetches the user's slack token with user's accountID
func getSlackToken(context *models.Context) (string, error) {
	var token string

	user, err := modelhelper.GetUser(context.Client.Account.Nick)
	if err != nil {
		return token, err
	}

	groupName := context.GroupName

	if user.ForeignAuth.Slack != nil {
		if gName, ok := user.ForeignAuth.Slack[groupName]; ok {
			if gName.Token != "" {
				return gName.Token, nil
			}
		}
	}

	return token, models.ErrTokenIsNotFound

}
<commit_msg>social: instead of sem, use producer, consumer pattern<commit_after>package api

import (
	"fmt"
	kodingmodels "koding/db/models"
	"koding/db/mongodb/modelhelper"
	"socialapi/models"
	"sync"
	"time"

	"github.com/nlopes/slack"
	"gopkg.in/mgo.v2/bson"
)

type SlackUser struct {
	slack.User
	LastActivity *time.Time `json:"lastActivity,omitempty"`
}

type SlackChannelsResponse struct {
	Groups   []slack.Group   `json:"groups,omitempty"`
	Channels []slack.Channel `json:"channels,omitempty"`
}

// getChannels send a request to the slack with user's token & gets the channels
func getChannels(token string) (*SlackChannelsResponse, error) {
	api := slack.New(token)
	var groups []slack.Group
	var channels []slack.Channel
	var gerr, cerr error
	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		groups, gerr = api.GetGroups(true)
		wg.Done()
	}()

	go func() {
		channels, cerr = api.GetChannels(true)
		wg.Done()
	}()

	wg.Wait()

	if gerr != nil {
		return nil, gerr
	}

	if cerr != nil {
		return nil, cerr
	}

	return &SlackChannelsResponse{
		Groups:   groups,
		Channels: channels,
	}, nil
}

func getUsers(token string) ([]SlackUser, error) {
	api := slack.New(token)
	allusers, err := api.GetUsers()
	if err != nil {
		return nil, err
	}

	resultChan := make(chan SlackUser)
	workChan := make(chan slack.User)

	// produce the work
	go func() {
		for _, u := range allusers {
			workChan <- u
		}

		close(workChan)
	}()

	// start consuming
	var wg sync.WaitGroup
	const concurrency = 20
	for i := 0; i < concurrency; i++ {
		wg.Add(1)
		go func() {
			processPresence(api, workChan, resultChan)
			wg.Done()
		}()
	}

	// mark we are done
	go func() {
		wg.Wait()
		close(resultChan)
	}()

	// collect result set
	var activeUsers []SlackUser
	for t := range resultChan {
		activeUsers = append(activeUsers, t)
	}

	return activeUsers, nil
}

func processPresence(api *slack.Client, workChan chan slack.User, resultChan chan SlackUser) {
	for u := range workChan {
		if u.ID == "" {
			continue
		}

		// no need to add deleted users
		if u.Deleted {
			continue
		}

		// filter bots
		if u.IsBot {
			continue
		}

		// even if we get error from slack api set it to nil
		var lastActive *time.Time

		// presence information is optional, so we can skip the errored ones
		p, err := api.GetUserPresence(u.ID)
		if err != nil || p == nil {
			resultChan <- SlackUser{u, lastActive}
			continue
		}

		// set presence info
		u.Presence = p.Presence

		// LastActivity works inconsistently, disabling it for now
		// if u.Presence != slackAway {
		//  LastActiveTime := p.LastActivity.Time()
		//  lastActive = &LastActiveTime
		// }

		resultChan <- SlackUser{u, lastActive}
	}
}

func postMessage(token string, req *SlackMessageRequest) (string, error) {
	api := slack.New(token)
	_, id, err := api.PostMessage(req.Channel, req.Text, req.Params)
	return id, err
}

func getTeamInfo(token string) (*slack.TeamInfo, error) {
	api := slack.New(token)
	info, err := api.GetTeamInfo()
	if err != nil {
		return nil, err
	}

	return info, nil
}

func updateUserSlackToken(user *kodingmodels.User, groupName string, m string) error {
	selector := bson.M{"username": user.Name}
	key := fmt.Sprintf("foreignAuth.slack.%s.token", groupName)
	update := bson.M{key: m}

	return modelhelper.UpdateUser(selector, update)
}

// getSlackToken fetches the user's slack token with user's accountID
func getSlackToken(context *models.Context) (string, error) {
	var token string

	user, err := modelhelper.GetUser(context.Client.Account.Nick)
	if err != nil {
		return token, err
	}

	groupName := context.GroupName

	if user.ForeignAuth.Slack != nil {
		if gName, ok := user.ForeignAuth.Slack[groupName]; ok {
			if gName.Token != "" {
				return gName.Token, nil
			}
		}
	}

	return token, models.ErrTokenIsNotFound

}
<|endoftext|>


<commit_before>package tarexport

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"github.com/docker/distribution"
	"github.com/docker/distribution/digest"
	"github.com/docker/docker/image"
	"github.com/docker/docker/image/v1"
	"github.com/docker/docker/layer"
	"github.com/docker/docker/pkg/archive"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/reference"
)

type imageDescriptor struct {
	refs   []reference.NamedTagged
	layers []string
}

type saveSession struct {
	*tarexporter
	outDir      string
	images      map[image.ID]*imageDescriptor
	savedLayers map[string]struct{}
}

func (l *tarexporter) Save(names []string, outStream io.Writer) error {
	images, err := l.parseNames(names)
	if err != nil {
		return err
	}

	return (&saveSession{tarexporter: l, images: images}).save(outStream)
}

func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor, error) {
	imgDescr := make(map[image.ID]*imageDescriptor)

	addAssoc := func(id image.ID, ref reference.Named) {
		if _, ok := imgDescr[id]; !ok {
			imgDescr[id] = &imageDescriptor{}
		}

		if ref != nil {
			var tagged reference.NamedTagged
			if _, ok := ref.(reference.Canonical); ok {
				return
			}
			var ok bool
			if tagged, ok = ref.(reference.NamedTagged); !ok {
				var err error
				if tagged, err = reference.WithTag(ref, reference.DefaultTag); err != nil {
					return
				}
			}

			for _, t := range imgDescr[id].refs {
				if tagged.String() == t.String() {
					return
				}
			}
			imgDescr[id].refs = append(imgDescr[id].refs, tagged)
		}
	}

	for _, name := range names {
		id, ref, err := reference.ParseIDOrReference(name)
		if err != nil {
			return nil, err
		}
		if id != "" {
			_, err := l.is.Get(image.ID(id))
			if err != nil {
				return nil, err
			}
			addAssoc(image.ID(id), nil)
			continue
		}
		if ref.Name() == string(digest.Canonical) {
			imgID, err := l.is.Search(name)
			if err != nil {
				return nil, err
			}
			addAssoc(imgID, nil)
			continue
		}
		if reference.IsNameOnly(ref) {
			assocs := l.rs.ReferencesByName(ref)
			for _, assoc := range assocs {
				addAssoc(assoc.ImageID, assoc.Ref)
			}
			if len(assocs) == 0 {
				imgID, err := l.is.Search(name)
				if err != nil {
					return nil, err
				}
				addAssoc(imgID, nil)
			}
			continue
		}
		var imgID image.ID
		if imgID, err = l.rs.Get(ref); err != nil {
			return nil, err
		}
		addAssoc(imgID, ref)

	}
	return imgDescr, nil
}

func (s *saveSession) save(outStream io.Writer) error {
	s.savedLayers = make(map[string]struct{})

	// get image json
	tempDir, err := ioutil.TempDir("", "docker-export-")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDir)

	s.outDir = tempDir
	reposLegacy := make(map[string]map[string]string)

	var manifest []manifestItem
	var parentLinks []parentLink

	for id, imageDescr := range s.images {
		foreignSrcs, err := s.saveImage(id)
		if err != nil {
			return err
		}

		var repoTags []string
		var layers []string

		for _, ref := range imageDescr.refs {
			if _, ok := reposLegacy[ref.Name()]; !ok {
				reposLegacy[ref.Name()] = make(map[string]string)
			}
			reposLegacy[ref.Name()][ref.Tag()] = imageDescr.layers[len(imageDescr.layers)-1]
			repoTags = append(repoTags, ref.String())
		}

		for _, l := range imageDescr.layers {
			layers = append(layers, filepath.Join(l, legacyLayerFileName))
		}

		manifest = append(manifest, manifestItem{
			Config:       digest.Digest(id).Hex() + ".json",
			RepoTags:     repoTags,
			Layers:       layers,
			LayerSources: foreignSrcs,
		})

		parentID, _ := s.is.GetParent(id)
		parentLinks = append(parentLinks, parentLink{id, parentID})
		s.tarexporter.loggerImgEvent.LogImageEvent(id.String(), id.String(), "save")
	}

	for i, p := range validatedParentLinks(parentLinks) {
		if p.parentID != "" {
			manifest[i].Parent = p.parentID
		}
	}

	if len(reposLegacy) > 0 {
		reposFile := filepath.Join(tempDir, legacyRepositoriesFileName)
		f, err := os.OpenFile(reposFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
		if err != nil {
			f.Close()
			return err
		}
		if err := json.NewEncoder(f).Encode(reposLegacy); err != nil {
			return err
		}
		if err := f.Close(); err != nil {
			return err
		}
		if err := system.Chtimes(reposFile, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
			return err
		}
	}

	manifestFileName := filepath.Join(tempDir, manifestFileName)
	f, err := os.OpenFile(manifestFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		f.Close()
		return err
	}
	if err := json.NewEncoder(f).Encode(manifest); err != nil {
		return err
	}
	if err := f.Close(); err != nil {
		return err
	}
	if err := system.Chtimes(manifestFileName, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
		return err
	}

	fs, err := archive.Tar(tempDir, archive.Uncompressed)
	if err != nil {
		return err
	}
	defer fs.Close()

	if _, err := io.Copy(outStream, fs); err != nil {
		return err
	}
	return nil
}

func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Descriptor, error) {
	img, err := s.is.Get(id)
	if err != nil {
		return nil, err
	}

	if len(img.RootFS.DiffIDs) == 0 {
		return nil, fmt.Errorf("empty export - not implemented")
	}

	var parent digest.Digest
	var layers []string
	var foreignSrcs map[layer.DiffID]distribution.Descriptor
	for i := range img.RootFS.DiffIDs {
		v1Img := image.V1Image{}
		if i == len(img.RootFS.DiffIDs)-1 {
			v1Img = img.V1Image
		}
		rootFS := *img.RootFS
		rootFS.DiffIDs = rootFS.DiffIDs[:i+1]
		v1ID, err := v1.CreateID(v1Img, rootFS.ChainID(), parent)
		if err != nil {
			return nil, err
		}

		v1Img.ID = v1ID.Hex()
		if parent != "" {
			v1Img.Parent = parent.Hex()
		}

		src, err := s.saveLayer(rootFS.ChainID(), v1Img, img.Created)
		if err != nil {
			return nil, err
		}
		layers = append(layers, v1Img.ID)
		parent = v1ID
		if src.Digest != "" {
			if foreignSrcs == nil {
				foreignSrcs = make(map[layer.DiffID]distribution.Descriptor)
			}
			foreignSrcs[img.RootFS.DiffIDs[i]] = src
		}
	}

	configFile := filepath.Join(s.outDir, digest.Digest(id).Hex()+".json")
	if err := ioutil.WriteFile(configFile, img.RawJSON(), 0644); err != nil {
		return nil, err
	}
	if err := system.Chtimes(configFile, img.Created, img.Created); err != nil {
		return nil, err
	}

	s.images[id].layers = layers
	return foreignSrcs, nil
}

func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, createdTime time.Time) (distribution.Descriptor, error) {
	if _, exists := s.savedLayers[legacyImg.ID]; exists {
		return distribution.Descriptor{}, nil
	}

	outDir := filepath.Join(s.outDir, legacyImg.ID)
	if err := os.Mkdir(outDir, 0755); err != nil {
		return distribution.Descriptor{}, err
	}

	// todo: why is this version file here?
	if err := ioutil.WriteFile(filepath.Join(outDir, legacyVersionFileName), []byte("1.0"), 0644); err != nil {
		return distribution.Descriptor{}, err
	}

	imageConfig, err := json.Marshal(legacyImg)
	if err != nil {
		return distribution.Descriptor{}, err
	}

	if err := ioutil.WriteFile(filepath.Join(outDir, legacyConfigFileName), imageConfig, 0644); err != nil {
		return distribution.Descriptor{}, err
	}

	// serialize filesystem
	tarFile, err := os.Create(filepath.Join(outDir, legacyLayerFileName))
	if err != nil {
		return distribution.Descriptor{}, err
	}
	defer tarFile.Close()

	l, err := s.ls.Get(id)
	if err != nil {
		return distribution.Descriptor{}, err
	}
	defer layer.ReleaseAndLog(s.ls, l)

	arch, err := l.TarStream()
	if err != nil {
		return distribution.Descriptor{}, err
	}
	defer arch.Close()

	if _, err := io.Copy(tarFile, arch); err != nil {
		return distribution.Descriptor{}, err
	}

	for _, fname := range []string{"", legacyVersionFileName, legacyConfigFileName, legacyLayerFileName} {
		// todo: maybe save layer created timestamp?
		if err := system.Chtimes(filepath.Join(outDir, fname), createdTime, createdTime); err != nil {
			return distribution.Descriptor{}, err
		}
	}

	s.savedLayers[legacyImg.ID] = struct{}{}

	var src distribution.Descriptor
	if fs, ok := l.(distribution.Describable); ok {
		src = fs.Descriptor()
	}
	return src, nil
}
<commit_msg>Fix duplicate layers in exported tar<commit_after>package tarexport

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"github.com/docker/distribution"
	"github.com/docker/distribution/digest"
	"github.com/docker/docker/image"
	"github.com/docker/docker/image/v1"
	"github.com/docker/docker/layer"
	"github.com/docker/docker/pkg/archive"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/reference"
)

type imageDescriptor struct {
	refs   []reference.NamedTagged
	layers []string
}

type saveSession struct {
	*tarexporter
	outDir      string
	images      map[image.ID]*imageDescriptor
	savedLayers map[string]struct{}
	diffIDPaths map[layer.DiffID]string // cache every diffID blob to avoid duplicates
}

func (l *tarexporter) Save(names []string, outStream io.Writer) error {
	images, err := l.parseNames(names)
	if err != nil {
		return err
	}

	return (&saveSession{tarexporter: l, images: images}).save(outStream)
}

func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor, error) {
	imgDescr := make(map[image.ID]*imageDescriptor)

	addAssoc := func(id image.ID, ref reference.Named) {
		if _, ok := imgDescr[id]; !ok {
			imgDescr[id] = &imageDescriptor{}
		}

		if ref != nil {
			var tagged reference.NamedTagged
			if _, ok := ref.(reference.Canonical); ok {
				return
			}
			var ok bool
			if tagged, ok = ref.(reference.NamedTagged); !ok {
				var err error
				if tagged, err = reference.WithTag(ref, reference.DefaultTag); err != nil {
					return
				}
			}

			for _, t := range imgDescr[id].refs {
				if tagged.String() == t.String() {
					return
				}
			}
			imgDescr[id].refs = append(imgDescr[id].refs, tagged)
		}
	}

	for _, name := range names {
		id, ref, err := reference.ParseIDOrReference(name)
		if err != nil {
			return nil, err
		}
		if id != "" {
			_, err := l.is.Get(image.ID(id))
			if err != nil {
				return nil, err
			}
			addAssoc(image.ID(id), nil)
			continue
		}
		if ref.Name() == string(digest.Canonical) {
			imgID, err := l.is.Search(name)
			if err != nil {
				return nil, err
			}
			addAssoc(imgID, nil)
			continue
		}
		if reference.IsNameOnly(ref) {
			assocs := l.rs.ReferencesByName(ref)
			for _, assoc := range assocs {
				addAssoc(assoc.ImageID, assoc.Ref)
			}
			if len(assocs) == 0 {
				imgID, err := l.is.Search(name)
				if err != nil {
					return nil, err
				}
				addAssoc(imgID, nil)
			}
			continue
		}
		var imgID image.ID
		if imgID, err = l.rs.Get(ref); err != nil {
			return nil, err
		}
		addAssoc(imgID, ref)

	}
	return imgDescr, nil
}

func (s *saveSession) save(outStream io.Writer) error {
	s.savedLayers = make(map[string]struct{})
	s.diffIDPaths = make(map[layer.DiffID]string)

	// get image json
	tempDir, err := ioutil.TempDir("", "docker-export-")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDir)

	s.outDir = tempDir
	reposLegacy := make(map[string]map[string]string)

	var manifest []manifestItem
	var parentLinks []parentLink

	for id, imageDescr := range s.images {
		foreignSrcs, err := s.saveImage(id)
		if err != nil {
			return err
		}

		var repoTags []string
		var layers []string

		for _, ref := range imageDescr.refs {
			if _, ok := reposLegacy[ref.Name()]; !ok {
				reposLegacy[ref.Name()] = make(map[string]string)
			}
			reposLegacy[ref.Name()][ref.Tag()] = imageDescr.layers[len(imageDescr.layers)-1]
			repoTags = append(repoTags, ref.String())
		}

		for _, l := range imageDescr.layers {
			layers = append(layers, filepath.Join(l, legacyLayerFileName))
		}

		manifest = append(manifest, manifestItem{
			Config:       digest.Digest(id).Hex() + ".json",
			RepoTags:     repoTags,
			Layers:       layers,
			LayerSources: foreignSrcs,
		})

		parentID, _ := s.is.GetParent(id)
		parentLinks = append(parentLinks, parentLink{id, parentID})
		s.tarexporter.loggerImgEvent.LogImageEvent(id.String(), id.String(), "save")
	}

	for i, p := range validatedParentLinks(parentLinks) {
		if p.parentID != "" {
			manifest[i].Parent = p.parentID
		}
	}

	if len(reposLegacy) > 0 {
		reposFile := filepath.Join(tempDir, legacyRepositoriesFileName)
		f, err := os.OpenFile(reposFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
		if err != nil {
			f.Close()
			return err
		}
		if err := json.NewEncoder(f).Encode(reposLegacy); err != nil {
			return err
		}
		if err := f.Close(); err != nil {
			return err
		}
		if err := system.Chtimes(reposFile, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
			return err
		}
	}

	manifestFileName := filepath.Join(tempDir, manifestFileName)
	f, err := os.OpenFile(manifestFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		f.Close()
		return err
	}
	if err := json.NewEncoder(f).Encode(manifest); err != nil {
		return err
	}
	if err := f.Close(); err != nil {
		return err
	}
	if err := system.Chtimes(manifestFileName, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
		return err
	}

	fs, err := archive.Tar(tempDir, archive.Uncompressed)
	if err != nil {
		return err
	}
	defer fs.Close()

	if _, err := io.Copy(outStream, fs); err != nil {
		return err
	}
	return nil
}

func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Descriptor, error) {
	img, err := s.is.Get(id)
	if err != nil {
		return nil, err
	}

	if len(img.RootFS.DiffIDs) == 0 {
		return nil, fmt.Errorf("empty export - not implemented")
	}

	var parent digest.Digest
	var layers []string
	var foreignSrcs map[layer.DiffID]distribution.Descriptor
	for i := range img.RootFS.DiffIDs {
		v1Img := image.V1Image{}
		if i == len(img.RootFS.DiffIDs)-1 {
			v1Img = img.V1Image
		}
		rootFS := *img.RootFS
		rootFS.DiffIDs = rootFS.DiffIDs[:i+1]
		v1ID, err := v1.CreateID(v1Img, rootFS.ChainID(), parent)
		if err != nil {
			return nil, err
		}

		v1Img.ID = v1ID.Hex()
		if parent != "" {
			v1Img.Parent = parent.Hex()
		}

		src, err := s.saveLayer(rootFS.ChainID(), v1Img, img.Created)
		if err != nil {
			return nil, err
		}
		layers = append(layers, v1Img.ID)
		parent = v1ID
		if src.Digest != "" {
			if foreignSrcs == nil {
				foreignSrcs = make(map[layer.DiffID]distribution.Descriptor)
			}
			foreignSrcs[img.RootFS.DiffIDs[i]] = src
		}
	}

	configFile := filepath.Join(s.outDir, digest.Digest(id).Hex()+".json")
	if err := ioutil.WriteFile(configFile, img.RawJSON(), 0644); err != nil {
		return nil, err
	}
	if err := system.Chtimes(configFile, img.Created, img.Created); err != nil {
		return nil, err
	}

	s.images[id].layers = layers
	return foreignSrcs, nil
}

func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, createdTime time.Time) (distribution.Descriptor, error) {
	if _, exists := s.savedLayers[legacyImg.ID]; exists {
		return distribution.Descriptor{}, nil
	}

	outDir := filepath.Join(s.outDir, legacyImg.ID)
	if err := os.Mkdir(outDir, 0755); err != nil {
		return distribution.Descriptor{}, err
	}

	// todo: why is this version file here?
	if err := ioutil.WriteFile(filepath.Join(outDir, legacyVersionFileName), []byte("1.0"), 0644); err != nil {
		return distribution.Descriptor{}, err
	}

	imageConfig, err := json.Marshal(legacyImg)
	if err != nil {
		return distribution.Descriptor{}, err
	}

	if err := ioutil.WriteFile(filepath.Join(outDir, legacyConfigFileName), imageConfig, 0644); err != nil {
		return distribution.Descriptor{}, err
	}

	// serialize filesystem
	layerPath := filepath.Join(outDir, legacyLayerFileName)
	l, err := s.ls.Get(id)
	if err != nil {
		return distribution.Descriptor{}, err
	}
	defer layer.ReleaseAndLog(s.ls, l)

	if oldPath, exists := s.diffIDPaths[l.DiffID()]; exists {
		relPath, err := filepath.Rel(layerPath, oldPath)
		if err != nil {
			return distribution.Descriptor{}, err
		}
		os.Symlink(relPath, layerPath)
	} else {

		tarFile, err := os.Create(layerPath)
		if err != nil {
			return distribution.Descriptor{}, err
		}
		defer tarFile.Close()

		arch, err := l.TarStream()
		if err != nil {
			return distribution.Descriptor{}, err
		}
		defer arch.Close()

		if _, err := io.Copy(tarFile, arch); err != nil {
			return distribution.Descriptor{}, err
		}

		for _, fname := range []string{"", legacyVersionFileName, legacyConfigFileName, legacyLayerFileName} {
			// todo: maybe save layer created timestamp?
			if err := system.Chtimes(filepath.Join(outDir, fname), createdTime, createdTime); err != nil {
				return distribution.Descriptor{}, err
			}
		}

		s.diffIDPaths[l.DiffID()] = layerPath
	}
	s.savedLayers[legacyImg.ID] = struct{}{}

	var src distribution.Descriptor
	if fs, ok := l.(distribution.Describable); ok {
		src = fs.Descriptor()
	}
	return src, nil
}
<|endoftext|>


<commit_before>package generatorControllers

import (
	. "eaciit/wfdemo-git/library/models"
	. "eaciit/wfdemo-git/processapp/summaryGenerator/controllers"

	"eaciit/wfdemo-git/web/helper"

	"os"
	"time"

	"github.com/eaciit/crowd"
	"github.com/eaciit/dbox"
	_ "github.com/eaciit/dbox/dbc/mongo"
	tk "github.com/eaciit/toolkit"
)

type GenDataWindDistribution struct {
	*BaseController
}

var windCats = [...]float64{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15}

func (d *GenDataWindDistribution) GenerateCurrentMonth(base *BaseController) {
	d.BaseController = base

	type ScadaAnalyticsWDDataX struct {
		Project  string
		Category float64
		Minutes  float64
	}

	type ScadaAnalyticsWDDataGroup struct {
		Project  string
		Category float64
	}

	type MiniScada struct {
		AvgWindSpeed float64
		Project      string
		Count        int
	}

	conn, e := PrepareConnection()
	if e != nil {
		d.Log.AddLog(tk.Sprintf("Wind Distribution : %s"+e.Error()), sWarning)
		os.Exit(0)
	}
	defer conn.Close()

	projects, _ := helper.GetProjectList()

	mdl := new(LatestDataPeriod)
	csr, e := conn.NewQuery().
		Select().
		From(mdl.TableName()).
		Where(dbox.Eq("type", "ScadaData")).
		Cursor(nil)

	if e != nil {
		d.Log.AddLog(tk.Sprintf("Wind Distribution : %s"+e.Error()), sWarning)
	}
	defer csr.Close()

	latesttime := time.Time{}
	for {
		mdl = new(LatestDataPeriod)
		e = csr.Fetch(mdl, 1, false)
		if e != nil {
			break
		}

		if latesttime.IsZero() || latesttime.UTC().Before(mdl.Data[1].UTC()) {
			latesttime = mdl.Data[1].UTC()
		}
	}

	stime := time.Date(latesttime.Year(), latesttime.Month(), 1, 0, 0, 0, 0, latesttime.Location())

	query, pipes := []tk.M{}, []tk.M{}
	query = append(query, tk.M{"_id": tk.M{"$ne": ""}})
	query = append(query, tk.M{"dateinfo.dateid": tk.M{"$gte": stime}})
	query = append(query, tk.M{"dateinfo.dateid": tk.M{"$lte": latesttime}})
	query = append(query, tk.M{"avgwindspeed": tk.M{"$gte": 0.5}})
	query = append(query, tk.M{"available": tk.M{"$eq": 1}})

	iquery := []tk.M{}
	qSave := conn.NewQuery().
		From("rpt_winddistributioncurrentmonth").
		SetConfig("multiexec", true).
		Save()

	defer qSave.Close()

	for _, oproject := range projects {
		proj := oproject.Value

		// ==========================================
		_ = conn.NewQuery().
			Delete().
			From("rpt_winddistributioncurrentmonth").
			Where(dbox.Eq("Project", proj)).
			SetConfig("multiexec", true).
			Exec(nil)
		// ==========================================

		_data := []tk.M{}
		pipes = []tk.M{}

		tmpResult := []MiniScada{}

		iquery = query
		iquery = append(iquery, tk.M{"projectname": proj})
		pipes = append(pipes, tk.M{"$match": tk.M{"$and": iquery}})
		pipes = append(pipes, tk.M{"$group": tk.M{"_id": tk.M{"projectname": "$projectname", "avgwindspeed": "$avgwindspeed"}, "count": tk.M{"$sum": 1}}})
		pipes = append(pipes, tk.M{"$project": tk.M{"_id.projectname": 1, "_id.avgwindspeed": 1, "count": 1}})

		csrx, _ := conn.NewQuery().
			From(new(ScadaData).TableName()).
			Command("pipe", pipes).Cursor(nil)

		e = csrx.Fetch(&_data, 0, false)
		if e != nil {
			break
		}
		csrx.Close()

		for _, v := range _data {
			id := v.Get("_id").(tk.M)
			tmpResult = append(tmpResult, MiniScada{
				AvgWindSpeed: id.GetFloat64("avgwindspeed"),
				Project:      id.GetString("projectname"),
				Count:        v.GetInt("count"),
			})
		}

		if len(tmpResult) > 0 {
			totalCount := 0
			datas := crowd.From(&tmpResult).Apply(func(x interface{}) interface{} {
				dt := x.(MiniScada)

				var di ScadaAnalyticsWDDataX
				di.Project = dt.Project
				di.Category = getWindDistrCategory(dt.AvgWindSpeed)
				di.Minutes = float64(10 * dt.Count)
				totalCount += dt.Count

				return di
			}).Exec().Group(func(x interface{}) interface{} {
				dt := x.(ScadaAnalyticsWDDataX)

				var dig ScadaAnalyticsWDDataGroup
				dig.Project = dt.Project
				dig.Category = dt.Category

				return dig
			}, nil).Exec()

			dts := datas.Apply(func(x interface{}) interface{} {
				kv := x.(crowd.KV)
				keys := kv.Key.(ScadaAnalyticsWDDataGroup)
				vs := kv.Value.([]ScadaAnalyticsWDDataX)
				total := 0.0

				for _, v := range vs {
					total += v.Minutes
				}

				var di ScadaAnalyticsWDDataX
				di.Project = keys.Project
				di.Category = keys.Category
				di.Minutes = total

				return di
			}).Exec().Result.Data().([]ScadaAnalyticsWDDataX)

			totalMinutes := float64(totalCount * 10)

			for _, wc := range windCats {
				exist := crowd.From(&dts).Where(func(x interface{}) interface{} {
					y := x.(ScadaAnalyticsWDDataX)
					Project := y.Project == proj
					Category := y.Category == wc
					return Project && Category
				}).Exec().Result.Data().([]ScadaAnalyticsWDDataX)

				distHelper := tk.M{}

				if len(exist) > 0 {
					distHelper.Set("Project", proj)
					distHelper.Set("Category", wc)

					Minute := crowd.From(&exist).Sum(func(x interface{}) interface{} {
						dt := x.(ScadaAnalyticsWDDataX)
						return dt.Minutes
					}).Exec().Result.Sum

					distHelper.Set("Contribute", Minute/totalMinutes)
				} else {
					distHelper.Set("Project", proj)
					distHelper.Set("Category", wc)
					distHelper.Set("Contribute", -0.0)
				}

				distHelper.Set("_id", tk.Sprintf("%s_%v", proj, wc))
				_ = qSave.Exec(tk.M{}.Set("data", distHelper))
			}
		}
	}

}

func getWindDistrCategory(windValue float64) float64 {
	var datas float64

	for _, val := range windCats {
		if val >= windValue {
			datas = val
			return datas
		}
	}

	return datas
}
<commit_msg>implement last year for wind distribution<commit_after>package generatorControllers

import (
	. "eaciit/wfdemo-git/library/models"
	. "eaciit/wfdemo-git/processapp/summaryGenerator/controllers"

	"eaciit/wfdemo-git/web/helper"

	"os"
	"time"

	"github.com/eaciit/crowd"
	"github.com/eaciit/dbox"
	_ "github.com/eaciit/dbox/dbc/mongo"
	tk "github.com/eaciit/toolkit"
)

type GenDataWindDistribution struct {
	*BaseController
}

var windCats = [...]float64{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15}

func (d *GenDataWindDistribution) GenerateCurrentMonth(base *BaseController) {
	d.BaseController = base

	type ScadaAnalyticsWDDataX struct {
		Project  string
		Category float64
		Minutes  float64
	}

	type ScadaAnalyticsWDDataGroup struct {
		Project  string
		Category float64
	}

	type MiniScada struct {
		AvgWindSpeed float64
		Project      string
		Count        int
	}

	conn, e := PrepareConnection()
	if e != nil {
		d.Log.AddLog(tk.Sprintf("Wind Distribution : %s"+e.Error()), sWarning)
		os.Exit(0)
	}
	defer conn.Close()

	projects, _ := helper.GetProjectList()

	mdl := new(LatestDataPeriod)
	csr, e := conn.NewQuery().
		Select().
		From(mdl.TableName()).
		Where(dbox.Eq("type", "ScadaData")).
		Cursor(nil)

	if e != nil {
		d.Log.AddLog(tk.Sprintf("Wind Distribution : %s"+e.Error()), sWarning)
	}
	defer csr.Close()

	latesttime := make(map[string]time.Time, 0)

	for {
		mdl = new(LatestDataPeriod)
		e = csr.Fetch(mdl, 1, false)
		if e != nil {
			break
		}

		latesttime[mdl.ProjectName] = mdl.Data[1].UTC()
	}

	qSave := conn.NewQuery().
		From("rpt_winddistributioncurrentmonth").
		SetConfig("multiexec", true).
		Save()

	defer qSave.Close()

	for _, oproject := range projects {
		proj := oproject.Value

		// ==========================================
		_ = conn.NewQuery().
			Delete().
			From("rpt_winddistributioncurrentmonth").
			Where(dbox.Eq("Project", proj)).
			SetConfig("multiexec", true).
			Exec(nil)
		// ==========================================

		_ltime := time.Now().UTC()
		if _, ishas := latesttime[proj]; ishas {
			_ltime = latesttime[proj]
		}

		_data := []tk.M{}
		query, pipes := []tk.M{}, []tk.M{}
		query = append(query, tk.M{"_id": tk.M{"$ne": ""}})
		query = append(query, tk.M{"dateinfo.dateid": tk.M{"$gte": _ltime.AddDate(-1, 0, 0)}})
		query = append(query, tk.M{"dateinfo.dateid": tk.M{"$lte": _ltime}})
		query = append(query, tk.M{"avgwindspeed": tk.M{"$gte": 0.5}})
		query = append(query, tk.M{"available": tk.M{"$eq": 1}})
		query = append(query, tk.M{"projectname": proj})

		tmpResult := []MiniScada{}

		pipes = append(pipes, tk.M{"$match": tk.M{"$and": query}})
		pipes = append(pipes, tk.M{"$group": tk.M{"_id": tk.M{"projectname": "$projectname", "avgwindspeed": "$avgwindspeed"}, "count": tk.M{"$sum": 1}}})
		pipes = append(pipes, tk.M{"$project": tk.M{"_id.projectname": 1, "_id.avgwindspeed": 1, "count": 1}})

		csrx, _ := conn.NewQuery().
			From(new(ScadaData).TableName()).
			Command("pipe", pipes).Cursor(nil)

		e = csrx.Fetch(&_data, 0, false)
		if e != nil {
			break
		}
		csrx.Close()

		for _, v := range _data {
			id := v.Get("_id").(tk.M)
			tmpResult = append(tmpResult, MiniScada{
				AvgWindSpeed: id.GetFloat64("avgwindspeed"),
				Project:      id.GetString("projectname"),
				Count:        v.GetInt("count"),
			})
		}

		if len(tmpResult) > 0 {
			totalCount := 0
			datas := crowd.From(&tmpResult).Apply(func(x interface{}) interface{} {
				dt := x.(MiniScada)

				var di ScadaAnalyticsWDDataX
				di.Project = dt.Project
				di.Category = getWindDistrCategory(dt.AvgWindSpeed)
				di.Minutes = float64(10 * dt.Count)
				totalCount += dt.Count

				return di
			}).Exec().Group(func(x interface{}) interface{} {
				dt := x.(ScadaAnalyticsWDDataX)

				var dig ScadaAnalyticsWDDataGroup
				dig.Project = dt.Project
				dig.Category = dt.Category

				return dig
			}, nil).Exec()

			dts := datas.Apply(func(x interface{}) interface{} {
				kv := x.(crowd.KV)
				keys := kv.Key.(ScadaAnalyticsWDDataGroup)
				vs := kv.Value.([]ScadaAnalyticsWDDataX)
				total := 0.0

				for _, v := range vs {
					total += v.Minutes
				}

				var di ScadaAnalyticsWDDataX
				di.Project = keys.Project
				di.Category = keys.Category
				di.Minutes = total

				return di
			}).Exec().Result.Data().([]ScadaAnalyticsWDDataX)

			totalMinutes := float64(totalCount * 10)

			for _, wc := range windCats {
				exist := crowd.From(&dts).Where(func(x interface{}) interface{} {
					y := x.(ScadaAnalyticsWDDataX)
					Project := y.Project == proj
					Category := y.Category == wc
					return Project && Category
				}).Exec().Result.Data().([]ScadaAnalyticsWDDataX)

				distHelper := tk.M{}

				if len(exist) > 0 {
					distHelper.Set("Project", proj)
					distHelper.Set("Category", wc)

					Minute := crowd.From(&exist).Sum(func(x interface{}) interface{} {
						dt := x.(ScadaAnalyticsWDDataX)
						return dt.Minutes
					}).Exec().Result.Sum

					distHelper.Set("Contribute", Minute/totalMinutes)
				} else {
					distHelper.Set("Project", proj)
					distHelper.Set("Category", wc)
					distHelper.Set("Contribute", -0.0)
				}

				distHelper.Set("_id", tk.Sprintf("%s_%v", proj, wc))
				_ = qSave.Exec(tk.M{}.Set("data", distHelper))
			}
		}
	}

}

func getWindDistrCategory(windValue float64) float64 {
	var datas float64

	for _, val := range windCats {
		if val >= windValue {
			datas = val
			return datas
		}
	}

	return datas
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/nightlyone/lockfile"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:       "update",
	Description: "updates heroku-cli",
	Args:        []Arg{{Name: "channel", Optional: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args["channel"]
		if channel == "" {
			channel = "master"
		}
		Errf("updating plugins... ")
		if err := node.UpdatePackages(); err != nil {
			panic(err)
		}
		Errln("done")
		manifest := getUpdateManifest(channel)
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		Errf("updating to %s (%s)... ", manifest.Version, manifest.Channel)
		update(build.URL, build.Sha1)
		Errln("done")
	},
}

var binPath = filepath.Join(AppDir, "heroku-cli")
var updateLockPath = filepath.Join(AppDir, "updating.lock")

func init() {
	if runtime.GOOS == "windows" {
		binPath = binPath + ".exe"
	}
}

// UpdateIfNeeded checks for and performs an autoupdate if there is a new version out.
func UpdateIfNeeded() {
	if !updateNeeded() {
		return
	}
	node.UpdatePackages()
	manifest := getUpdateManifest(Channel)
	if manifest.Version == Version {
		// Set timestamp of bin so we don't update again
		os.Chtimes(binPath, time.Now(), time.Now())
		return
	}
	if !updatable() {
		Errf("Out of date: You are running %s but %s is out.\n", Version, manifest.Version)
		return
	}
	// Leave out updating text until heroku-cli is used in place of ruby cli
	// So it doesn't confuse users with 2 different version numbers
	//Errf("Updating to %s... ", manifest.Version)
	build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
	update(build.URL, build.Sha1)
	//Errln("done")
	execBin()
	os.Exit(0)
}

func updateNeeded() bool {
	if Version == "dev" {
		return false
	}
	f, err := os.Stat(binPath)
	if err != nil {
		Errln("WARNING: cannot autoupdate. Try running `heroku update` to manually trigger an update.")
		return false
	}
	return f.ModTime().Add(60 * time.Minute).Before(time.Now())
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) manifest {
	res, err := http.Get("http://d1gvo455cekpjp.cloudfront.net/" + channel + "/manifest.json")
	if err != nil {
		panic(err)
	}
	var m manifest
	json.NewDecoder(res.Body).Decode(&m)
	return m
}

func updatable() bool {
	path, err := filepath.Abs(os.Args[0])
	if err != nil {
		Errln(err)
	}
	return path == binPath
}

func update(url, sha1 string) {
	// on windows we can't remove an existing file or remove the running binary
	// so we download the file to binName.new
	// move the running binary to binName.old (deleting any existing file first)
	// rename the downloaded file to binName

	lock, err := lockfile.New(updateLockPath)
	if err != nil {
		Errln("Cannot initialize update lockfile.")
		panic(err)
	}
	err = lock.TryLock()
	if err != nil {
		panic(err)
	}
	defer lock.Unlock()
	if err := downloadBin(binPath+".new", url); err != nil {
		panic(err)
	}
	if fileSha1(binPath+".new") != sha1 {
		panic("SHA mismatch")
	}
	os.Remove(binPath + ".old")
	if err := os.Rename(binPath, binPath+".old"); err != nil {
		panic(err)
	}
	if err := os.Rename(binPath+".new", binPath); err != nil {
		panic(err)
	}
}

func downloadBin(path, url string) error {
	out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer out.Close()
	client := &http.Client{}
	req, err := http.NewRequest("GET", url+".gz", nil)
	if err != nil {
		return err
	}
	req.Header.Add("Accept-Encoding", "gzip")
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return err
	}
	_, err = io.Copy(out, uncompressed)
	return err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

func execBin() {
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()
}
<commit_msg>block while waiting for update lock<commit_after>package main

import (
	"compress/gzip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/nightlyone/lockfile"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:       "update",
	Description: "updates heroku-cli",
	Args:        []Arg{{Name: "channel", Optional: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args["channel"]
		if channel == "" {
			channel = "master"
		}
		Errf("updating plugins... ")
		if err := node.UpdatePackages(); err != nil {
			panic(err)
		}
		Errln("done")
		manifest := getUpdateManifest(channel)
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		Errf("updating to %s (%s)... ", manifest.Version, manifest.Channel)
		update(build.URL, build.Sha1)
		Errln("done")
	},
}

var binPath = filepath.Join(AppDir, "heroku-cli")
var updateLockPath = filepath.Join(AppDir, "updating.lock")
var autoupdateFile = filepath.Join(AppDir, "autoupdate")

func init() {
	if runtime.GOOS == "windows" {
		binPath = binPath + ".exe"
	}
}

// UpdateIfNeeded checks for and performs an autoupdate if there is a new version out.
func UpdateIfNeeded() {
	if !updateNeeded() {
		return
	}
	touchAutoupdateFile()
	lock := getUpdateLock()
	defer lock.Unlock()
	manifest := getUpdateManifest(Channel)
	node.UpdatePackages()
	if manifest.Version == Version {
		return
	}
	if !updatable() {
		Errf("Out of date: You are running %s but %s is out.\n", Version, manifest.Version)
		return
	}
	// Leave out updating text until heroku-cli is used in place of ruby cli
	// So it doesn't confuse users with 2 different version numbers
	//Errf("Updating to %s... ", manifest.Version)
	build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
	update(build.URL, build.Sha1)
	//Errln("done")
	execBin()
	os.Exit(0)
}

// Attempts to get the lockfile
// Blocks if unavailable
func getUpdateLock() lockfile.Lockfile {
	lock, err := lockfile.New(updateLockPath)
	if err != nil {
		Errln("Cannot initialize update lockfile.")
		panic(err)
	}
	start := time.Now()
	for {
		if lock.TryLock() == nil {
			return lock
		}
		time.Sleep(10 * time.Millisecond)
		if time.Since(start) > 30*time.Second {
			Errln("ERROR: Can't get update lock file")
			Errln("You may need to delete " + updateLockPath + " if this message stays.")
			os.Exit(1)
		}
	}
}

func updateNeeded() bool {
	if Version == "dev" {
		return false
	}
	f, err := os.Stat(autoupdateFile)
	if err != nil {
		return true
	}
	return time.Since(f.ModTime()) > 1*time.Hour
}

func touchAutoupdateFile() {
	out, err := os.OpenFile(autoupdateFile, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		panic(err)
	}
	out.WriteString("")
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) manifest {
	res, err := http.Get("http://d1gvo455cekpjp.cloudfront.net/" + channel + "/manifest.json")
	if err != nil {
		panic(err)
	}
	var m manifest
	json.NewDecoder(res.Body).Decode(&m)
	return m
}

func updatable() bool {
	path, err := filepath.Abs(os.Args[0])
	if err != nil {
		Errln(err)
	}
	return path == binPath
}

func update(url, sha1 string) {
	// on windows we can't remove an existing file or remove the running binary
	// so we download the file to binName.new
	// move the running binary to binName.old (deleting any existing file first)
	// rename the downloaded file to binName
	if err := downloadBin(binPath+".new", url); err != nil {
		panic(err)
	}
	if fileSha1(binPath+".new") != sha1 {
		panic("SHA mismatch")
	}
	os.Remove(binPath + ".old")
	if err := os.Rename(binPath, binPath+".old"); err != nil {
		panic(err)
	}
	if err := os.Rename(binPath+".new", binPath); err != nil {
		panic(err)
	}
}

func downloadBin(path, url string) error {
	out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer out.Close()
	client := &http.Client{}
	req, err := http.NewRequest("GET", url+".gz", nil)
	if err != nil {
		return err
	}
	req.Header.Add("Accept-Encoding", "gzip")
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return err
	}
	_, err = io.Copy(out, uncompressed)
	return err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

func execBin() {
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/nightlyone/lockfile"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:       "update",
	Description: "updates heroku-cli",
	Args:        []Arg{{Name: "channel", Optional: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args["channel"]
		if channel == "" {
			channel = "master"
		}
		Errf("updating plugins... ")
		if err := node.UpdatePackages(); err != nil {
			panic(err)
		}
		Errln("done")
		manifest := getUpdateManifest(channel)
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		Errf("updating to %s (%s)... ", manifest.Version, manifest.Channel)
		update(build.URL, build.Sha1)
		Errln("done")
	},
}

var binPath = filepath.Join(AppDir, "heroku-cli")
var updateLockPath = filepath.Join(AppDir, "updating.lock")

func init() {
	if runtime.GOOS == "windows" {
		binPath = binPath + ".exe"
	}
}

// UpdateIfNeeded checks for and performs an autoupdate if there is a new version out.
func UpdateIfNeeded() {
	if !updateNeeded() {
		return
	}
	node.UpdatePackages()
	manifest := getUpdateManifest(Channel)
	if manifest.Version == Version {
		// Set timestamp of bin so we don't update again
		os.Chtimes(binPath, time.Now(), time.Now())
		return
	}
	if !updatable() {
		Errf("Out of date: You are running %s but %s is out.\n", Version, manifest.Version)
		return
	}
	// Leave out updating text until heroku-cli is used in place of ruby cli
	// So it doesn't confuse users with 2 different version numbers
	//Errf("Updating to %s... ", manifest.Version)
	build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
	update(build.URL, build.Sha1)
	//Errln("done")
	execBin()
	os.Exit(0)
}

func updateNeeded() bool {
	if Version == "dev" {
		return false
	}
	f, err := os.Stat(binPath)
	if err != nil {
		Errln("WARNING: Error autoupdating. The CLI will not be able to update itself.")
		return false
	}
	return f.ModTime().Add(60 * time.Minute).Before(time.Now())
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) manifest {
	res, err := http.Get("http://d1gvo455cekpjp.cloudfront.net/" + channel + "/manifest.json")
	if err != nil {
		panic(err)
	}
	var m manifest
	json.NewDecoder(res.Body).Decode(&m)
	return m
}

func updatable() bool {
	path, err := filepath.Abs(os.Args[0])
	if err != nil {
		Errln(err)
	}
	return path == binPath
}

func update(url, sha1 string) {
	lock, err := lockfile.New(updateLockPath)
	if err != nil {
		Errln("Cannot initialize update lockfile.")
		panic(err)
	}
	err = lock.TryLock()
	if err != nil {
		panic(err)
	}
	defer lock.Unlock()
	tmp, err := downloadBin(url)
	if err != nil {
		panic(err)
	}
	if fileSha1(tmp) != sha1 {
		panic("SHA mismatch")
	}
	os.Remove(binPath) // on windows you can't rename on top of an existing file
	if err := os.Rename(tmp, binPath); err != nil {
		panic(err)
	}
}

func downloadBin(url string) (string, error) {
	out, err := os.OpenFile(binPath+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return "", err
	}
	defer out.Close()
	client := &http.Client{}
	req, err := http.NewRequest("GET", url+".gz", nil)
	if err != nil {
		return "", err
	}
	req.Header.Add("Accept-Encoding", "gzip")
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return "", err
	}
	_, err = io.Copy(out, uncompressed)
	return out.Name(), err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

func execBin() {
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()
}
<commit_msg>removed extraneous warning<commit_after>package main

import (
	"compress/gzip"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/nightlyone/lockfile"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:       "update",
	Description: "updates heroku-cli",
	Args:        []Arg{{Name: "channel", Optional: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args["channel"]
		if channel == "" {
			channel = "master"
		}
		Errf("updating plugins... ")
		if err := node.UpdatePackages(); err != nil {
			panic(err)
		}
		Errln("done")
		manifest := getUpdateManifest(channel)
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		Errf("updating to %s (%s)... ", manifest.Version, manifest.Channel)
		update(build.URL, build.Sha1)
		Errln("done")
	},
}

var binPath = filepath.Join(AppDir, "heroku-cli")
var updateLockPath = filepath.Join(AppDir, "updating.lock")

func init() {
	if runtime.GOOS == "windows" {
		binPath = binPath + ".exe"
	}
}

// UpdateIfNeeded checks for and performs an autoupdate if there is a new version out.
func UpdateIfNeeded() {
	if !updateNeeded() {
		return
	}
	node.UpdatePackages()
	manifest := getUpdateManifest(Channel)
	if manifest.Version == Version {
		// Set timestamp of bin so we don't update again
		os.Chtimes(binPath, time.Now(), time.Now())
		return
	}
	if !updatable() {
		Errf("Out of date: You are running %s but %s is out.\n", Version, manifest.Version)
		return
	}
	// Leave out updating text until heroku-cli is used in place of ruby cli
	// So it doesn't confuse users with 2 different version numbers
	//Errf("Updating to %s... ", manifest.Version)
	build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
	update(build.URL, build.Sha1)
	//Errln("done")
	execBin()
	os.Exit(0)
}

func updateNeeded() bool {
	if Version == "dev" {
		return false
	}
	f, err := os.Stat(binPath)
	if err != nil {
		return false
	}
	return f.ModTime().Add(60 * time.Minute).Before(time.Now())
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) manifest {
	res, err := http.Get("http://d1gvo455cekpjp.cloudfront.net/" + channel + "/manifest.json")
	if err != nil {
		panic(err)
	}
	var m manifest
	json.NewDecoder(res.Body).Decode(&m)
	return m
}

func updatable() bool {
	path, err := filepath.Abs(os.Args[0])
	if err != nil {
		Errln(err)
	}
	return path == binPath
}

func update(url, sha1 string) {
	lock, err := lockfile.New(updateLockPath)
	if err != nil {
		Errln("Cannot initialize update lockfile.")
		panic(err)
	}
	err = lock.TryLock()
	if err != nil {
		panic(err)
	}
	defer lock.Unlock()
	tmp, err := downloadBin(url)
	if err != nil {
		panic(err)
	}
	if fileSha1(tmp) != sha1 {
		panic("SHA mismatch")
	}
	os.Remove(binPath) // on windows you can't rename on top of an existing file
	if err := os.Rename(tmp, binPath); err != nil {
		panic(err)
	}
}

func downloadBin(url string) (string, error) {
	out, err := os.OpenFile(binPath+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return "", err
	}
	defer out.Close()
	client := &http.Client{}
	req, err := http.NewRequest("GET", url+".gz", nil)
	if err != nil {
		return "", err
	}
	req.Header.Add("Accept-Encoding", "gzip")
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	uncompressed, err := gzip.NewReader(resp.Body)
	if err != nil {
		return "", err
	}
	_, err = io.Copy(out, uncompressed)
	return out.Name(), err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

func execBin() {
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package watcher

import (
	"expvar"
	"fmt"
	"sync"

	"github.com/fsnotify/fsnotify"
	"github.com/golang/glog"
)

var (
	eventCount = expvar.NewMap("log_watcher_event_count")
	errorCount = expvar.NewInt("log_watcher_error_count")
)

// LogWatcher implements a Watcher for watching real filesystems.
type LogWatcher struct {
	*fsnotify.Watcher

	events   []chan Event
	eventsMu sync.RWMutex

	doneResp chan struct{} // Channel to respond to Close
}

// NewLogWatcher returns a new LogWatcher, or returns an error.
func NewLogWatcher() (*LogWatcher, error) {
	f, err := fsnotify.NewWatcher()
	if err == nil {
		w := &LogWatcher{
			Watcher:  f,
			events:   make([]chan Event, 0),
			doneResp: make(chan struct{}),
		}
		go w.run()
		return w, nil
	}
	return nil, err
}

// Events returns a new readable channel of events from this watcher.
func (w *LogWatcher) Events() <-chan Event {
	w.eventsMu.Lock()
	defer w.eventsMu.Unlock()
	r := make(chan Event, 1)
	w.events = append(w.events, r)
	return r
}

func (w *LogWatcher) sendEvent(e Event) {
	w.eventsMu.RLock()
	for _, c := range w.events {
		c <- e
	}
	w.eventsMu.RUnlock()
}

func (w *LogWatcher) run() {
	defer close(w.doneResp)
	// Suck out errors and dump them to the error log.
	go func() {
		for err := range w.Watcher.Errors {
			errorCount.Add(1)
			glog.Errorf("fsnotify error: %s\n", err)
		}
	}()
	for e := range w.Watcher.Events {
		glog.V(2).Infof("watcher event %v", e)
		eventCount.Add(e.Name, 1)
		switch {
		case e.Op&fsnotify.Create == fsnotify.Create:
			w.sendEvent(CreateEvent{e.Name})
		case e.Op&fsnotify.Write == fsnotify.Write,
			e.Op&fsnotify.Chmod == fsnotify.Chmod:
			w.sendEvent(UpdateEvent{e.Name})
		case e.Op&fsnotify.Remove == fsnotify.Remove:
			w.sendEvent(DeleteEvent{e.Name})
		case e.Op&fsnotify.Rename == fsnotify.Rename:
			// Rename is only issued on the original file path; the new name receives a Create event
			w.sendEvent(DeleteEvent{e.Name})
		default:
			panic(fmt.Sprintf("unknown op type %v", e.Op))
		}
	}
	glog.Infof("Shutting down log watcher.")

	w.eventsMu.Lock()
	for _, c := range w.events {
		close(c)
	}
	w.eventsMu.Unlock()
}

func (w *LogWatcher) Close() (err error) {
	err = w.Watcher.Close()
	<-w.doneResp
	return
}
<commit_msg>Improves docstring for LogWatcher.Close()<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package watcher

import (
	"expvar"
	"fmt"
	"sync"

	"github.com/fsnotify/fsnotify"
	"github.com/golang/glog"
)

var (
	eventCount = expvar.NewMap("log_watcher_event_count")
	errorCount = expvar.NewInt("log_watcher_error_count")
)

// LogWatcher implements a Watcher for watching real filesystems.
type LogWatcher struct {
	*fsnotify.Watcher

	events   []chan Event
	eventsMu sync.RWMutex

	doneResp chan struct{} // Channel to respond to Close
}

// NewLogWatcher returns a new LogWatcher, or returns an error.
func NewLogWatcher() (*LogWatcher, error) {
	f, err := fsnotify.NewWatcher()
	if err == nil {
		w := &LogWatcher{
			Watcher:  f,
			events:   make([]chan Event, 0),
			doneResp: make(chan struct{}),
		}
		go w.run()
		return w, nil
	}
	return nil, err
}

// Events returns a new readable channel of events from this watcher.
func (w *LogWatcher) Events() <-chan Event {
	w.eventsMu.Lock()
	defer w.eventsMu.Unlock()
	r := make(chan Event, 1)
	w.events = append(w.events, r)
	return r
}

func (w *LogWatcher) sendEvent(e Event) {
	w.eventsMu.RLock()
	for _, c := range w.events {
		c <- e
	}
	w.eventsMu.RUnlock()
}

func (w *LogWatcher) run() {
	defer close(w.doneResp)
	// Suck out errors and dump them to the error log.
	go func() {
		for err := range w.Watcher.Errors {
			errorCount.Add(1)
			glog.Errorf("fsnotify error: %s\n", err)
		}
	}()
	for e := range w.Watcher.Events {
		glog.V(2).Infof("watcher event %v", e)
		eventCount.Add(e.Name, 1)
		switch {
		case e.Op&fsnotify.Create == fsnotify.Create:
			w.sendEvent(CreateEvent{e.Name})
		case e.Op&fsnotify.Write == fsnotify.Write,
			e.Op&fsnotify.Chmod == fsnotify.Chmod:
			w.sendEvent(UpdateEvent{e.Name})
		case e.Op&fsnotify.Remove == fsnotify.Remove:
			w.sendEvent(DeleteEvent{e.Name})
		case e.Op&fsnotify.Rename == fsnotify.Rename:
			// Rename is only issued on the original file path; the new name receives a Create event
			w.sendEvent(DeleteEvent{e.Name})
		default:
			panic(fmt.Sprintf("unknown op type %v", e.Op))
		}
	}
	glog.Infof("Shutting down log watcher.")

	w.eventsMu.Lock()
	for _, c := range w.events {
		close(c)
	}
	w.eventsMu.Unlock()
}

// Close shuts down the LogWatcher.
func (w *LogWatcher) Close() (err error) {
	err = w.Watcher.Close()
	<-w.doneResp
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.6.0-alpha1"
<commit_msg>Bump CA version to 0.6.0-alpha2<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package main

// ClusterAutoscalerVersion contains version of CA.
const ClusterAutoscalerVersion = "0.6.0-alpha2"
<|endoftext|>