<commit_before>package downloader_test

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/pivotal-cf-experimental/pivnet-resource/downloader"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
)

var _ = Describe("Downloader", func() {
	var (
		server     *ghttp.Server
		apiAddress string
		dir        string
	)

	BeforeEach(func() {
		var err error
		server = ghttp.NewServer()
		apiAddress = server.URL()
		dir, err = ioutil.TempDir("", "pivnet-resource")
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.RemoveAll(dir)
		Expect(err).NotTo(HaveOccurred())
	})

	Describe("Download", func() {
		var token string

		Context("Success", func() {
			BeforeEach(func() {
				header := http.Header{}
				header.Add("Location", apiAddress+"/some-redirect-link")
				token = "1234"

				server.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("POST", "/the-first-post", ""),
						ghttp.VerifyHeaderKV("Authorization", fmt.Sprintf("Token %s", token)),
						ghttp.RespondWith(http.StatusFound, nil, header),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/some-redirect-link"),
						ghttp.RespondWith(http.StatusOK, make([]byte, 10, 14)),
					),
				)
			})

			It("Downloads the files into the directory provided", func() {
				fileNames := map[string]string{
					"the-first-post": apiAddress + "/the-first-post",
				}

				err := downloader.Download(dir, fileNames, token)
				Expect(err).NotTo(HaveOccurred())

				dataDir, err := os.Open(dir)
				Expect(err).ShouldNot(HaveOccurred())

				files, err := dataDir.Readdir(1)
				Expect(err).ShouldNot(HaveOccurred())
				Expect(files).To(HaveLen(1))

				for _, f := range files {
					Expect(f.Size()).ToNot(BeZero())
				}
			})
		})

		Context("when it fails to make a request", func() {
			It("raises an error", func() {
				Expect(downloader.Download(
					dir,
					map[string]string{"^731drop": "&h%%%%"},
					token,
				)).NotTo(Succeed())
			})
		})
	})
})
<commit_msg>Add downloader test to verify contents of multiple downloaded files.<commit_after>package downloader_test

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/pivotal-cf-experimental/pivnet-resource/downloader"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
)

var _ = Describe("Downloader", func() {
	var (
		server     *ghttp.Server
		apiAddress string
		dir        string
	)

	BeforeEach(func() {
		var err error
		server = ghttp.NewServer()
		apiAddress = server.URL()
		dir, err = ioutil.TempDir("", "pivnet-resource")
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.RemoveAll(dir)
		Expect(err).NotTo(HaveOccurred())
	})

	Describe("Download", func() {
		var (
			token string
		)

		BeforeEach(func() {
			token = "1234-abcd"
		})

		Context("Success", func() {
			It("follows redirects", func() {
				header := http.Header{}
				header.Add("Location", apiAddress+"/some-redirect-link")

				server.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("POST", "/the-first-post", ""),
						ghttp.VerifyHeaderKV("Authorization", fmt.Sprintf("Token %s", token)),
						ghttp.RespondWith(http.StatusFound, nil, header),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/some-redirect-link"),
						ghttp.RespondWith(http.StatusOK, make([]byte, 10, 14)),
					),
				)

				fileNames := map[string]string{
					"the-first-post": apiAddress + "/the-first-post",
				}

				err := downloader.Download(dir, fileNames, token)
				Expect(err).NotTo(HaveOccurred())
			})

			It("Downloads the files into the directory provided", func() {
				fileNames := map[string]string{
					"file-0": apiAddress + "/post-0",
					"file-1": apiAddress + "/post-1",
					"file-2": apiAddress + "/post-2",
				}

				for i := 0; i < len(fileNames); i++ {
					url := fmt.Sprintf("/post-%d", i)
					server.RouteToHandler("POST", url, ghttp.CombineHandlers(
						ghttp.VerifyRequest("POST", url, ""),
						ghttp.RespondWith(http.StatusOK, fmt.Sprintf("contents-%d", i)),
					))
				}

				err := downloader.Download(dir, fileNames, token)
				Expect(err).NotTo(HaveOccurred())
				Expect(len(server.ReceivedRequests())).To(Equal(3))

				dataDir, err := os.Open(dir)
				Expect(err).ShouldNot(HaveOccurred())

				files, err := dataDir.Readdir(3)
				Expect(err).ShouldNot(HaveOccurred())
				Expect(files).To(HaveLen(3))

				for _, f := range files {
					fullPath := filepath.Join(dir, f.Name())
					contents, err := ioutil.ReadFile(fullPath)
					Expect(err).ShouldNot(HaveOccurred())

					split := strings.Split(f.Name(), "-")
					index := split[1]

					expectedContents := []byte(fmt.Sprintf("contents-%s", index))
					Expect(contents).To(Equal(expectedContents))
				}
			})
		})

		Context("when it fails to make a request", func() {
			It("raises an error", func() {
				Expect(downloader.Download(
					dir,
					map[string]string{"^731drop": "&h%%%%"},
					token,
				)).NotTo(Succeed())
			})
		})
	})
})
<|endoftext|>


<commit_before>package ginkgomon

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"time"

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

type Runner struct {
	Name              string
	BinPath           string
	AnsiColorCode     string
	StartCheck        string
	StartCheckTimeout time.Duration
	Args              []string
	Cleanup           func()
}

func (r *Runner) Run(sigChan <-chan os.Signal, ready chan<- struct{}) error {
	allOutput := gbytes.NewBuffer()

	session, err := gexec.Start(
		exec.Command(
			r.BinPath,
			r.Args...,
		),
		gexec.NewPrefixedWriter(
			fmt.Sprintf("\x1b[32m[o]\x1b[%s[%s]\x1b[0m ", r.AnsiColorCode, r.Name),
			io.MultiWriter(allOutput, ginkgo.GinkgoWriter),
		),
		gexec.NewPrefixedWriter(
			fmt.Sprintf("\x1b[91m[e]\x1b[%s[%s]\x1b[0m ", r.AnsiColorCode, r.Name),
			io.MultiWriter(allOutput, ginkgo.GinkgoWriter),
		),
	)

	Ω(err).ShouldNot(HaveOccurred())

	if r.StartCheck != "" {
		timeout := r.StartCheckTimeout
		if timeout == 0 {
			timeout = time.Second
		}

		Eventually(allOutput, timeout).Should(gbytes.Say(r.StartCheck))
	}

	close(ready)

	var signal os.Signal

	for {
		select {
		case signal = <-sigChan:
			session.Signal(signal)

		case <-session.Exited:
			if r.Cleanup != nil {
				r.Cleanup()
			}

			if session.ExitCode() == 0 {
				return nil
			}

			return fmt.Errorf("exit status %d", session.ExitCode())
		}
	}
}
<commit_msg>provide command rather than path/args<commit_after>package ginkgomon

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"time"

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

type Runner struct {
	Command           *exec.Cmd
	Name              string
	AnsiColorCode     string
	StartCheck        string
	StartCheckTimeout time.Duration
	Cleanup           func()
}

func (r *Runner) Run(sigChan <-chan os.Signal, ready chan<- struct{}) error {
	allOutput := gbytes.NewBuffer()

	session, err := gexec.Start(
		r.Command,
		gexec.NewPrefixedWriter(
			fmt.Sprintf("\x1b[32m[o]\x1b[%s[%s]\x1b[0m ", r.AnsiColorCode, r.Name),
			io.MultiWriter(allOutput, ginkgo.GinkgoWriter),
		),
		gexec.NewPrefixedWriter(
			fmt.Sprintf("\x1b[91m[e]\x1b[%s[%s]\x1b[0m ", r.AnsiColorCode, r.Name),
			io.MultiWriter(allOutput, ginkgo.GinkgoWriter),
		),
	)

	Ω(err).ShouldNot(HaveOccurred())

	if r.StartCheck != "" {
		timeout := r.StartCheckTimeout
		if timeout == 0 {
			timeout = time.Second
		}

		Eventually(allOutput, timeout).Should(gbytes.Say(r.StartCheck))
	}

	close(ready)

	var signal os.Signal

	for {
		select {
		case signal = <-sigChan:
			session.Signal(signal)

		case <-session.Exited:
			if r.Cleanup != nil {
				r.Cleanup()
			}

			if session.ExitCode() == 0 {
				return nil
			}

			return fmt.Errorf("exit status %d", session.ExitCode())
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"net/http"
	"sync"
	"time"
	"io/ioutil"
)

type VMInformation struct {
	mux sync.Mutex
	// TODO: Replace this map with more useful information (creation date etc)
	vms map[int]string
}

func (v *VMInformation) addVM() (vmId int) {
	v.mux.Lock()

	// Find the next ID we can use
	vmId = 100 + len(v.vms)
	v.vms[vmId] = "Placeholder"

	v.mux.Unlock()
	return
}

func main() {
	os.Exit(run())
}

func run() (int) {
	// Create our datastructure
	v := VMInformation{vms: make(map[int]string)}
	v.addVM() // Create the VM we know exists as VM 100

	http.HandleFunc("/create", func(w http.ResponseWriter, r *http.Request) {
		createHandler(w, r, v)
	})

	http.HandleFunc("/view/", func(w http.ResponseWriter, r *http.Request) {
		viewHandler(w, r, v)
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		indexHandler(w, r, v)
	})

	http.ListenAndServe(":80", nil)

	return 0
}

func createHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println("[%v] %v", time.Now(), r.URL.Path)
	if len(v.vms) >= 5 {
		fmt.Fprintf(w, "
Too many VMs are already running. Come back later
")
	} else {
		vmId := v.addVM()
		// fire off the request
		resp, err := http.Get(fmt.Sprintf("http://10.0.5.20/create/%v", vmId))
		if err != nil {
			fmt.Fprintln(os.Stderr, "error talking to hypervisor-daemon (create): %v", err)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error reading response from hypervisor-daemon (create): %v", err)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}

		status := string(body)
		if status != "creating" {
			fmt.Fprintln(os.Stderr, "unexpected response from create hypervisor-daemon: %v", status)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}

		http.Redirect(w, r, fmt.Sprintf("/view/%v", vmId), http.StatusFound)
	}
}

func viewHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println("[%v] %v", time.Now(), r.URL.Path)
	vmId := r.URL.Path[len("/view/"):]
	fmt.Fprintf(w, "
VM created. ID: %v
", vmId)

	// find out what the status is and print it
	resp, err := http.Get(fmt.Sprintf("http://10.0.5.20/view/%v", vmId))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error talking to hypervisor-daemon: %v", err)
		fmt.Fprintf(w, "shits fucked m8, come back later")
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error reading response from hypervisor-daemon: %v", err)
		fmt.Fprintf(w, "shits fucked m8, come back later")
		return
	}

	status := string(body)

	fmt.Fprintf(w, "here's a janky status of the VM if it's not created, or the hostname if it is: %v", status)
	fmt.Fprintf(w, "login as root@whatever, password is: emuguestpassword -- you're welcome to change this (please do)")
	fmt.Fprintf(w, "anything likely to attract LEA, I delete your VM. pls no cp. remove my SSH key from root's authorized keys, I delete your VM (for now, I will remove this restriction later)")

}

func indexHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println("[%v] %v", time.Now(), r.URL.Path)
	fmt.Fprintf(w, "
Free Dumb Hosting
There are currently %v VMs running. Create a new VM. no illegal stuff pls, no cp etc.
 more features, like being able to host a website instead of just a shell, coming later", len(v.vms))
}

<commit_msg>Fix some formatting issues<commit_after>package main

import (
	"fmt"
	"os"
	"net/http"
	"sync"
	"time"
	"io/ioutil"
)

type VMInformation struct {
	mux sync.Mutex
	// TODO: Replace this map with more useful information (creation date etc)
	vms map[int]string
}

func (v *VMInformation) addVM() (vmId int) {
	v.mux.Lock()

	// Find the next ID we can use
	vmId = 100 + len(v.vms)
	v.vms[vmId] = "Placeholder"

	v.mux.Unlock()
	return
}

func main() {
	os.Exit(run())
}

func run() (int) {
	// Create our datastructure
	v := VMInformation{vms: make(map[int]string)}
	v.addVM() // Create the VM we know exists as VM 100

	http.HandleFunc("/create", func(w http.ResponseWriter, r *http.Request) {
		createHandler(w, r, v)
	})

	http.HandleFunc("/view/", func(w http.ResponseWriter, r *http.Request) {
		viewHandler(w, r, v)
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		indexHandler(w, r, v)
	})

	http.ListenAndServe(":80", nil)

	return 0
}

func createHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println(fmt.Sprintf("[%v] %v", time.Now(), r.URL.Path))
	if len(v.vms) >= 5 {
		fmt.Fprintf(w, "
Too many VMs are already running. Come back later
")
	} else {
		vmId := v.addVM()
		// fire off the request
		resp, err := http.Get(fmt.Sprintf("http://10.0.5.20/create/%v", vmId))
		if err != nil {
			fmt.Fprintln(os.Stderr, "error talking to hypervisor-daemon (create): %v", err)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error reading response from hypervisor-daemon (create): %v", err)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}

		status := string(body)
		if status != "creating" {
			fmt.Fprintln(os.Stderr, "unexpected response from create hypervisor-daemon: %v", status)
			fmt.Fprintf(w, "shits fucked m8, come back later")
			return
		}

		http.Redirect(w, r, fmt.Sprintf("/view/%v", vmId), http.StatusFound)
	}
}

func viewHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println(fmt.Sprintf("[%v] %v", time.Now(), r.URL.Path))
	vmId := r.URL.Path[len("/view/"):]
	fmt.Fprintf(w, "
VM created. ID: %v
", vmId)

	// find out what the status is and print it
	resp, err := http.Get(fmt.Sprintf("http://10.0.5.20/view/%v", vmId))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error talking to hypervisor-daemon: %v", err)
		fmt.Fprintf(w, "shits fucked m8, come back later")
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error reading response from hypervisor-daemon: %v", err)
		fmt.Fprintf(w, "shits fucked m8, come back later")
		return
	}

	status := string(body)

	fmt.Fprintf(w, "here's a janky status of the VM if it's not created, or the hostname if it is: %v", status)
	fmt.Fprintf(w, "login as root@whatever, password is: emuguestpassword -- you're welcome to change this (please do)")
	fmt.Fprintf(w, "anything likely to attract LEA, I delete your VM. pls no cp. remove my SSH key from root's authorized keys, I delete your VM (for now, I will remove this restriction later)")

}

func indexHandler(w http.ResponseWriter, r *http.Request, v VMInformation) {
	fmt.Println(fmt.Sprintf("[%v] %v", time.Now(), r.URL.Path))
	fmt.Fprintf(w, "
Free Dumb Hosting
There are currently %v VMs running. Create a new VM. no illegal stuff pls, no cp etc.
 more features, like being able to host a website instead of just a shell, coming later", len(v.vms))
}

<|endoftext|>


<commit_before>
package main

import (
        "fmt"
        //"io/ioutil"
        "os"
        "encoding/xml"
)

type ScanSettings struct {
    XMLName         xml.Name    `xml:"http://www.hp.com/schemas/imaging/con/cnx/scan/2008/08/19 ScanSettings"`
    XResolution     int         `xml:"XResolution"` // 200
    YResolution     int         `xml:"YResolution"` // 200
    XStart          int         `xml:"XStart"` // 0
    YStart          int         `xml:"YStart"` // 0
    Width           int         `xml:"Width"`  // 2550
    Height          int         `xml:"Height"` // 3507
    Format          string      `xml:"Format"` // "Raw", "Jpeg"
    CompressionQFactor int      `xml:"CompressionQFactor"` // 15
    ColorSpace      string      `xml:"ColorSpace"` // "Color"
    BitDepth        int         `xml:"BitDepth"` // 8
    InputSource     string      `xml:"InputSource"` // "Platen"
    GrayRendering   string      `xml:"GrayRendering"` // "NTSC"
    Gamma           int         `xml:"ToneMap>Gamma"` // 1000
    Brightness      int         `xml:"ToneMap>Brightness"` // 1000
    Contrast        int         `xml:"ToneMap>Contrast"` // 1000
    Highlite        int         `xml:"ToneMap>Highlite"` // 179
    Shadow          int         `xml:"ToneMap>Shadow"` // 25
    Threshold       int         `xml:"ToneMap>Threshold"` // 0
    SharpeningLevel int         `xml:"SharpeningLevel"` // 128
    NoiseRemoval    int         `xml:"NoiseRemoval"` // 0
    ContentType     string      `xml:"ContentType"` // "Photo",
}

type CancelScan struct {
    //job_request += "<Job xmlns=\"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30 Jobs.xsd\">"
    XMLName         xml.Name    `xml:"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30 Job"`
    JobUrl          string                  // The job url from POST-ing SystemSettings
    JobState        string                  // "Canceled"
}

func main() {
    s := &ScanSettings{ XResolution:200, YResolution:201 }
    xmlString, err := xml.MarshalIndent(s, "", "    ")

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

    fmt.Printf("%s \n", string(xmlString))

    cs := &CancelScan{ JobUrl: "2323", JobState: "Canceled" }
    xmlString2, _ := xml.MarshalIndent(cs, "", "    ")
    os.Stdout.Write(xmlString2)
}
<commit_msg>add raw and jpeg scansettings<commit_after>package main

import (
        "fmt"
        //"io/ioutil"
        "os"
        "encoding/xml"
)

type ScanSettings struct {
    XMLName         xml.Name    `xml:"http://www.hp.com/schemas/imaging/con/cnx/scan/2008/08/19 ScanSettings"`
    XResolution     int         `xml:"XResolution"` // 200
    YResolution     int         `xml:"YResolution"` // 200
    XStart          int         `xml:"XStart"` // 0
    YStart          int         `xml:"YStart"` // 0
    Width           int         `xml:"Width"`  // 2550
    Height          int         `xml:"Height"` // 3507
    Format          string      `xml:"Format"` // "Raw", "Jpeg"
    CompressionQFactor int      `xml:"CompressionQFactor"` // 0, 15
    ColorSpace      string      `xml:"ColorSpace"` // "Color"
    BitDepth        int         `xml:"BitDepth"` // 8
    InputSource     string      `xml:"InputSource"` // "Platen"
    GrayRendering   string      `xml:"GrayRendering"` // "NTSC"
    Gamma           int         `xml:"ToneMap>Gamma"` // 1000
    Brightness      int         `xml:"ToneMap>Brightness"` // 1000
    Contrast        int         `xml:"ToneMap>Contrast"` // 1000
    Highlite        int         `xml:"ToneMap>Highlite"` // 179
    Shadow          int         `xml:"ToneMap>Shadow"` // 25
    Threshold       int         `xml:"ToneMap>Threshold"` // 0
    SharpeningLevel int         `xml:"SharpeningLevel"` // 128
    NoiseRemoval    int         `xml:"NoiseRemoval"` // 0
    ContentType     string      `xml:"ContentType"` // "Photo",
}

func DefaultSettings() *ScanSettings {
    return &ScanSettings{XResolution: 200, YResolution:200, XStart:0, YStart:0, Width: 2550, Height: 3507, Format: "Jpeg", CompressionQFactor: 15, ColorSpace: "Color", BitDepth: 8, InputSource: "Platen", GrayRendering:"NTSC", Gamma: 1000, Brightness: 1000, Contrast: 1000, Highlite: 179,Shadow: 25, Threshold: 0, SharpeningLevel: 128, NoiseRemoval: 0, ContentType: "Photo"}
}

func JpegScanSettings(xres int, yres int) *ScanSettings {
    s := DefaultSettings()
    s.XResolution = xres
    s.YResolution = yres
    return s
}

func RawScanSettings(xres int, yres int) *ScanSettings {
    s := DefaultSettings()
    s.XResolution = xres
    s.YResolution = yres
    s.Format = "Raw"
    s.CompressionQFactor = 0
    return s
}

type CancelScan struct {
    XMLName         xml.Name    `xml:"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30 Job"`
    JobUrl          string                  // The job url from POST-ing SystemSettings
    JobState        string                  // "Canceled"
}

func main() {
    //s := &ScanSettings{ XResolution:200, YResolution:201 }
    s := RawScanSettings(200, 200)
    xmlString, err := xml.MarshalIndent(s, "", "    ")

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

    fmt.Printf("%s \n", string(xmlString))

    cs := &CancelScan{ JobUrl: "2323", JobState: "Canceled" }
    xmlString2, _ := xml.MarshalIndent(cs, "", "    ")
    os.Stdout.Write([]byte( xml.Header+string(xmlString2)))
}
<|endoftext|>


<commit_before>// Copyright 2020 The LUCI 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 lib

import (
	"context"
	"fmt"
	"os"

	"github.com/bazelbuild/remote-apis-sdks/go/pkg/chunker"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/command"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/filemetadata"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/tree"
	"github.com/golang/protobuf/jsonpb"
	"github.com/maruel/subcommands"

	"go.chromium.org/luci/client/cas"
	"go.chromium.org/luci/client/isolated"
	"go.chromium.org/luci/common/cli"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/system/signals"
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive() *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>...",
		ShortDesc: "archive dirs/files to CAS",
		LongDesc: `Given a list of files and directories, creates a CAS tree and digest file for
that and uploads the tree to the CAS server.

When specifying directories and files, you must also specify a current working
directory for each file and directory. The current working directory will not be
included in the archived path. For example, to archive './usr/foo/bar' and have
it appear as 'foo/bar' in the CAS tree, specify '-paths ./usr:foo/bar' or
'-paths usr:foo/bar'. And all workind directories should be the same. When the
CAS tree is then downloaded, it will then appear under 'foo/bar' in the desired
directory.

Note that '.' may be omitted in general, so to upload 'foo' from the current
working directory, '-paths :foo' is sufficient.`,
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.Init()
			c.Flags.Var(&c.paths, "paths", "File(s)/Directory(ies) to archive. Specify as <working directory>:<relative path to file/dir>")
			c.Flags.StringVar(&c.digestJSON, "digest-json", "", "Outputs a JSON file to store the CAS root digest")
			return &c
		},
	}
}

type archiveRun struct {
	commonFlags
	paths      isolated.ScatterGather
	digestJSON string
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

// getRoot returns root directory if there is only one working directory.
func getRoot(paths isolated.ScatterGather) (string, error) {
	var rel0, wd0 string
	pickedOne := false
	for rel, wd := range paths {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	if !pickedOne {
		return "", errors.Reason("-paths should be specified at least once").Err()
	}

	return wd0, nil
}

// Does the archive by uploading to isolate-server.
func (c *archiveRun) doArchive(ctx context.Context, args []string) ([]digest.Digest, error) {
	ctx, cancel := context.WithCancel(ctx)
	signals.HandleInterrupt(cancel)

	root, err := getRoot(c.paths)
	if err != nil {
		return nil, err
	}

	is := command.InputSpec{}
	for path := range c.paths {
		is.Inputs = append(is.Inputs, path)
	}

	rootDg, chunkers, _, err := tree.ComputeMerkleTree(root, &is, chunker.DefaultChunkSize, filemetadata.NewNoopCache())
	if err != nil {
		return nil, errors.Annotate(err, "failed to call ComputeMerkleTree").Err()
	}

	client, err := cas.NewClient(ctx, c.casFlags.Instance, c.casFlags.TokenServerHost, false)
	if err != nil {
		return nil, errors.Annotate(err, "failed to create cas client").Err()
	}
	defer client.Close()

	uploadedDigests, err := client.UploadIfMissing(ctx, chunkers...)
	if err != nil {
		return nil, errors.Annotate(err, "failed to call UploadIfMissing").Err()
	}

	dj := c.digestJSON
	if dj == "" {
		return uploadedDigests, nil
	}

	f, err := os.Create(dj)
	if err != nil {
		return nil, errors.Annotate(err, "failed to create file").Err()
	}
	defer f.Close()

	if err := (&jsonpb.Marshaler{}).Marshal(f, rootDg.ToProto()); err != nil {
		return nil, errors.Annotate(err, "failed to marshal digest proto").Err()
	}

	return uploadedDigests, nil
}

func (c *archiveRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
	ctx := cli.GetContext(a, c, env)

	if err := c.Parse(a, args); err != nil {
		errors.Log(ctx, err)
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	defer c.profiler.Stop()

	// TODO: handle the stats
	if _, err := c.doArchive(ctx, args); err != nil {
		errors.Log(ctx, err)
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	return 0
}
<commit_msg>[cas] change flag for dump digest<commit_after>// Copyright 2020 The LUCI 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 lib

import (
	"context"
	"fmt"
	"io/ioutil"

	"github.com/bazelbuild/remote-apis-sdks/go/pkg/chunker"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/command"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/filemetadata"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/tree"
	"github.com/maruel/subcommands"

	"go.chromium.org/luci/client/cas"
	"go.chromium.org/luci/client/isolated"
	"go.chromium.org/luci/common/cli"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/system/signals"
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive() *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>...",
		ShortDesc: "archive dirs/files to CAS",
		LongDesc: `Given a list of files and directories, creates a CAS tree and digest file for
that and uploads the tree to the CAS server.

When specifying directories and files, you must also specify a current working
directory for each file and directory. The current working directory will not be
included in the archived path. For example, to archive './usr/foo/bar' and have
it appear as 'foo/bar' in the CAS tree, specify '-paths ./usr:foo/bar' or
'-paths usr:foo/bar'. And all workind directories should be the same. When the
CAS tree is then downloaded, it will then appear under 'foo/bar' in the desired
directory.

Note that '.' may be omitted in general, so to upload 'foo' from the current
working directory, '-paths :foo' is sufficient.`,
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.Init()
			c.Flags.Var(&c.paths, "paths", "File(s)/Directory(ies) to archive. Specify as <working directory>:<relative path to file/dir>")
			c.Flags.StringVar(&c.dumpDigest, "dump-digest", "", "Dump uploaded CAS root digest in the format of `<Hash>/<Size>`")
			return &c
		},
	}
}

type archiveRun struct {
	commonFlags
	paths      isolated.ScatterGather
	dumpDigest string
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

// getRoot returns root directory if there is only one working directory.
func getRoot(paths isolated.ScatterGather) (string, error) {
	var rel0, wd0 string
	pickedOne := false
	for rel, wd := range paths {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	if !pickedOne {
		return "", errors.Reason("-paths should be specified at least once").Err()
	}

	return wd0, nil
}

// Does the archive by uploading to isolate-server.
func (c *archiveRun) doArchive(ctx context.Context, args []string) ([]digest.Digest, error) {
	ctx, cancel := context.WithCancel(ctx)
	signals.HandleInterrupt(cancel)

	root, err := getRoot(c.paths)
	if err != nil {
		return nil, err
	}

	is := command.InputSpec{}
	for path := range c.paths {
		is.Inputs = append(is.Inputs, path)
	}

	rootDg, chunkers, _, err := tree.ComputeMerkleTree(root, &is, chunker.DefaultChunkSize, filemetadata.NewNoopCache())
	if err != nil {
		return nil, errors.Annotate(err, "failed to call ComputeMerkleTree").Err()
	}

	client, err := cas.NewClient(ctx, c.casFlags.Instance, c.casFlags.TokenServerHost, false)
	if err != nil {
		return nil, errors.Annotate(err, "failed to create cas client").Err()
	}
	defer client.Close()

	uploadedDigests, err := client.UploadIfMissing(ctx, chunkers...)
	if err != nil {
		return nil, errors.Annotate(err, "failed to call UploadIfMissing").Err()
	}

	if dd := c.dumpDigest; dd != "" {
		if err := ioutil.WriteFile(dd, []byte(rootDg.String()), 0600); err != nil {
			return nil, errors.Annotate(err, "failed to dump digest").Err()
		}
	}

	return uploadedDigests, nil
}

func (c *archiveRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
	ctx := cli.GetContext(a, c, env)

	if err := c.Parse(a, args); err != nil {
		errors.Log(ctx, err)
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	defer c.profiler.Stop()

	// TODO: handle the stats
	if _, err := c.doArchive(ctx, args); err != nil {
		errors.Log(ctx, err)
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"reflect"
	"syscall"
	"unsafe"
)

func lowerProcessPrio() {
	// TODO: implement me
}

type Mapping struct {
	mapping syscall.Handle
	addr    uintptr
}

func createMapping(name string, size int) (*Mapping, []byte) {
	f, err := os.OpenFile(name, os.O_RDWR, 0)
	if err != nil {
		log.Fatalf("failed to open comm file: %v", err)
	}
	defer f.Close()
	mapping, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, uint32(size), nil)
	if err != nil {
		log.Fatalf("failed to create file mapping: %v", err)
	}
	const FILE_MAP_ALL_ACCESS = 0xF001F
	addr, err := syscall.MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, uintptr(size))
	if err != nil {
		log.Fatalf("failed to mmap comm file: %v", err)
	}
	hdr := reflect.SliceHeader{addr, size, size}
	mem := *(*[]byte)(unsafe.Pointer(&hdr))
	mem[0] = 1 // test access
	return &Mapping{mapping, addr}, mem
}

func (m *Mapping) destroy() {
	syscall.UnmapViewOfFile(m.addr)
	syscall.CloseHandle(m.mapping)
}

func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) {
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_COMM_FD=%v", comm.mapping))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_IN_FD=%v", rOut.Fd()))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_OUT_FD=%v", wIn.Fd()))
}
<commit_msg>make handles inheritable on windows<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"reflect"
	"syscall"
	"unsafe"
)

func lowerProcessPrio() {
	// TODO: implement me
}

type Mapping struct {
	mapping syscall.Handle
	addr    uintptr
}

func createMapping(name string, size int) (*Mapping, []byte) {
	f, err := os.OpenFile(name, os.O_RDWR, 0)
	if err != nil {
		log.Fatalf("failed to open comm file: %v", err)
	}
	defer f.Close()
	mapping, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, uint32(size), nil)
	if err != nil {
		log.Fatalf("failed to create file mapping: %v", err)
	}
	const FILE_MAP_ALL_ACCESS = 0xF001F
	addr, err := syscall.MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, uintptr(size))
	if err != nil {
		log.Fatalf("failed to mmap comm file: %v", err)
	}
	hdr := reflect.SliceHeader{addr, size, size}
	mem := *(*[]byte)(unsafe.Pointer(&hdr))
	mem[0] = 1 // test access
	return &Mapping{mapping, addr}, mem
}

func (m *Mapping) destroy() {
	syscall.UnmapViewOfFile(m.addr)
	syscall.CloseHandle(m.mapping)
}

func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) {
	syscall.SetHandleInformation(Handle(comm.mapping), syscall.HANDLE_FLAG_INHERIT, 0)
	syscall.SetHandleInformation(Handle(rOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 0)
	syscall.SetHandleInformation(Handle(wIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 0)
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_COMM_FD=%v", comm.mapping))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_IN_FD=%v", rOut.Fd()))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_OUT_FD=%v", wIn.Fd()))
}
<|endoftext|>


<commit_before>package utils

import (
	"context"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/gregor1"
	"github.com/keybase/client/go/protocol/keybase1"
)

// parseDurationExtended is like time.ParseDuration, but adds "d" unit. "1d" is
// one day, defined as 24*time.Hour. Only whole days are supported for "d"
// unit, but it can be followed by smaller units, e.g., "1d1h".
func ParseDurationExtended(s string) (d time.Duration, err error) {
	p := strings.Index(s, "d")
	if p == -1 {
		// no "d" suffix
		return time.ParseDuration(s)
	}

	var days int
	if days, err = strconv.Atoi(s[:p]); err != nil {
		return time.Duration(0), err
	}
	d = time.Duration(days) * 24 * time.Hour

	if p < len(s)-1 {
		var dur time.Duration
		if dur, err = time.ParseDuration(s[p+1:]); err != nil {
			return time.Duration(0), err
		}
		d += dur
	}

	return d, nil
}

func ParseTimeFromRFC3339OrDurationFromPast(kbCtx KeybaseContext, s string) (t time.Time, err error) {
	var errt, errd error
	var d time.Duration

	if s == "" {
		return
	}

	if t, errt = time.Parse(time.RFC3339, s); errt == nil {
		return t, nil
	}
	if d, errd = ParseDurationExtended(s); errd == nil {
		return kbCtx.Clock().Now().Add(-d), nil
	}

	return time.Time{}, fmt.Errorf("given string is neither a valid time (%s) nor a valid duration (%v)", errt, errd)
}

// upper bounds takes higher priority
func Collar(lower int, ideal int, upper int) int {
	if ideal > upper {
		return upper
	}
	if ideal < lower {
		return lower
	}
	return ideal
}

func FilterByType(msgs []chat1.MessageUnboxed, query *chat1.GetThreadQuery) (res []chat1.MessageUnboxed) {
	if query != nil && len(query.MessageTypes) > 0 {
		typmap := make(map[chat1.MessageType]bool)
		for _, mt := range query.MessageTypes {
			typmap[mt] = true
		}
		for _, msg := range msgs {
			if _, ok := typmap[msg.GetMessageType()]; ok {
				res = append(res, msg)
			}
		}
	} else {
		res = msgs
	}
	return res
}

// AggRateLimitsP takes a list of rate limit responses and dedups them to the last one received
// of each category
func AggRateLimitsP(rlimits []*chat1.RateLimit) (res []chat1.RateLimit) {
	m := make(map[string]chat1.RateLimit)
	for _, l := range rlimits {
		if l != nil {
			m[l.Name] = *l
		}
	}
	for _, v := range m {
		res = append(res, v)
	}
	return res
}

func AggRateLimits(rlimits []chat1.RateLimit) (res []chat1.RateLimit) {
	m := make(map[string]chat1.RateLimit)
	for _, l := range rlimits {
		m[l.Name] = l
	}
	for _, v := range m {
		res = append(res, v)
	}
	return res
}

// Reorder participants based on the order in activeList.
// Only allows usernames from tlfname in the output.
// This never fails, worse comes to worst it just returns the split of tlfname.
func ReorderParticipants(udc *UserDeviceCache, uimap *UserInfoMapper, tlfname string, activeList []gregor1.UID) (writerNames []string, readerNames []string, err error) {
	srcWriterNames, srcReaderNames, _, err := splitAndNormalizeTLFNameCanonicalize(tlfname, false)
	if err != nil {
		return writerNames, readerNames, err
	}

	allowedWriters := make(map[string]bool)

	// Allow all writers from tlfname.
	for _, user := range srcWriterNames {
		allowedWriters[user] = true
	}

	// Fill from the active list first.
	for _, uid := range activeList {
		kbUID := keybase1.UID(uid.String())
		user, err := udc.LookupUsername(uimap, kbUID)
		if err != nil {
			continue
		}
		user, err = normalizeAssertionOrName(user)
		if err != nil {
			continue
		}
		if allowed, _ := allowedWriters[user]; allowed {
			writerNames = append(writerNames, user)
			// Allow only one occurrence.
			allowedWriters[user] = false
		}
	}

	// Include participants even if they weren't in the active list, in stable order.
	for _, user := range srcWriterNames {
		if allowed, _ := allowedWriters[user]; allowed {
			writerNames = append(writerNames, user)
			allowedWriters[user] = false
		}
	}

	readerNames = srcReaderNames

	return writerNames, readerNames, nil
}

// Drive splitAndNormalizeTLFName with one attempt to follow TlfNameNotCanonical.
func splitAndNormalizeTLFNameCanonicalize(name string, public bool) (writerNames, readerNames []string, extensionSuffix string, err error) {
	writerNames, readerNames, extensionSuffix, err = splitAndNormalizeTLFName(name, public)
	if retryErr, retry := err.(TlfNameNotCanonical); retry {
		return splitAndNormalizeTLFName(retryErr.NameToTry, public)
	}
	return writerNames, readerNames, extensionSuffix, err
}

func CryptKeysWrapper(ctx context.Context, tlfInterface keybase1.TlfInterface, tlfName string) (tlfID chat1.TLFID, canonicalTlfName string, err error) {
	resp, err := tlfInterface.CryptKeys(ctx, keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_CLI,
	})
	if err != nil {
		return nil, "", err
	}
	tlfIDb := resp.NameIDBreaks.TlfID.ToBytes()
	if tlfIDb == nil {
		return nil, "", errors.New("invalid TLF ID acquired")
	}
	tlfID = chat1.TLFID(tlfIDb)
	return tlfID, string(resp.NameIDBreaks.CanonicalName), nil
}

func GetInboxQueryLocalToRemote(ctx context.Context, tlfInterface keybase1.TlfInterface,
	lquery *chat1.GetInboxLocalQuery) (rquery *chat1.GetInboxQuery, err error) {

	if lquery == nil {
		return nil, nil
	}
	rquery = &chat1.GetInboxQuery{}
	if lquery.TlfName != nil && len(*lquery.TlfName) > 0 {
		tlfID, _, err := CryptKeysWrapper(ctx, tlfInterface, *lquery.TlfName)
		if err != nil {
			return nil, err
		}
		rquery.TlfID = &tlfID
	}

	rquery.After = lquery.After
	rquery.Before = lquery.Before
	rquery.TlfVisibility = lquery.TlfVisibility
	rquery.TopicType = lquery.TopicType
	rquery.UnreadOnly = lquery.UnreadOnly
	rquery.ReadOnly = lquery.ReadOnly
	rquery.ComputeActiveList = lquery.ComputeActiveList
	rquery.ConvID = lquery.ConvID
	rquery.OneChatTypePerTLF = lquery.OneChatTypePerTLF
	rquery.Status = lquery.Status

	return rquery, nil
}

const (
	ChatTopicIDLen    = 16
	ChatTopicIDSuffix = 0x20
)

func NewChatTopicID() (id []byte, err error) {
	if id, err = libkb.RandBytes(ChatTopicIDLen); err != nil {
		return nil, err
	}
	id[len(id)-1] = ChatTopicIDSuffix
	return id, nil
}

func AllChatConversationStatuses() (res []chat1.ConversationStatus) {
	for _, s := range chat1.ConversationStatusMap {
		res = append(res, s)
	}
	return
}

func VisibleChatConversationStatuses() []chat1.ConversationStatus {
	return []chat1.ConversationStatus{
		chat1.ConversationStatus_UNFILED,
		chat1.ConversationStatus_FAVORITE,
	}
}

func IsVisibleChatConversationStatus(status chat1.ConversationStatus) bool {
	for _, s := range VisibleChatConversationStatuses() {
		if status == s {
			return true
		}
	}
	return false
}
<commit_msg>wrong context (#4957)<commit_after>package utils

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/gregor1"
	"github.com/keybase/client/go/protocol/keybase1"
	"golang.org/x/net/context"
)

// parseDurationExtended is like time.ParseDuration, but adds "d" unit. "1d" is
// one day, defined as 24*time.Hour. Only whole days are supported for "d"
// unit, but it can be followed by smaller units, e.g., "1d1h".
func ParseDurationExtended(s string) (d time.Duration, err error) {
	p := strings.Index(s, "d")
	if p == -1 {
		// no "d" suffix
		return time.ParseDuration(s)
	}

	var days int
	if days, err = strconv.Atoi(s[:p]); err != nil {
		return time.Duration(0), err
	}
	d = time.Duration(days) * 24 * time.Hour

	if p < len(s)-1 {
		var dur time.Duration
		if dur, err = time.ParseDuration(s[p+1:]); err != nil {
			return time.Duration(0), err
		}
		d += dur
	}

	return d, nil
}

func ParseTimeFromRFC3339OrDurationFromPast(kbCtx KeybaseContext, s string) (t time.Time, err error) {
	var errt, errd error
	var d time.Duration

	if s == "" {
		return
	}

	if t, errt = time.Parse(time.RFC3339, s); errt == nil {
		return t, nil
	}
	if d, errd = ParseDurationExtended(s); errd == nil {
		return kbCtx.Clock().Now().Add(-d), nil
	}

	return time.Time{}, fmt.Errorf("given string is neither a valid time (%s) nor a valid duration (%v)", errt, errd)
}

// upper bounds takes higher priority
func Collar(lower int, ideal int, upper int) int {
	if ideal > upper {
		return upper
	}
	if ideal < lower {
		return lower
	}
	return ideal
}

func FilterByType(msgs []chat1.MessageUnboxed, query *chat1.GetThreadQuery) (res []chat1.MessageUnboxed) {
	if query != nil && len(query.MessageTypes) > 0 {
		typmap := make(map[chat1.MessageType]bool)
		for _, mt := range query.MessageTypes {
			typmap[mt] = true
		}
		for _, msg := range msgs {
			if _, ok := typmap[msg.GetMessageType()]; ok {
				res = append(res, msg)
			}
		}
	} else {
		res = msgs
	}
	return res
}

// AggRateLimitsP takes a list of rate limit responses and dedups them to the last one received
// of each category
func AggRateLimitsP(rlimits []*chat1.RateLimit) (res []chat1.RateLimit) {
	m := make(map[string]chat1.RateLimit)
	for _, l := range rlimits {
		if l != nil {
			m[l.Name] = *l
		}
	}
	for _, v := range m {
		res = append(res, v)
	}
	return res
}

func AggRateLimits(rlimits []chat1.RateLimit) (res []chat1.RateLimit) {
	m := make(map[string]chat1.RateLimit)
	for _, l := range rlimits {
		m[l.Name] = l
	}
	for _, v := range m {
		res = append(res, v)
	}
	return res
}

// Reorder participants based on the order in activeList.
// Only allows usernames from tlfname in the output.
// This never fails, worse comes to worst it just returns the split of tlfname.
func ReorderParticipants(udc *UserDeviceCache, uimap *UserInfoMapper, tlfname string, activeList []gregor1.UID) (writerNames []string, readerNames []string, err error) {
	srcWriterNames, srcReaderNames, _, err := splitAndNormalizeTLFNameCanonicalize(tlfname, false)
	if err != nil {
		return writerNames, readerNames, err
	}

	allowedWriters := make(map[string]bool)

	// Allow all writers from tlfname.
	for _, user := range srcWriterNames {
		allowedWriters[user] = true
	}

	// Fill from the active list first.
	for _, uid := range activeList {
		kbUID := keybase1.UID(uid.String())
		user, err := udc.LookupUsername(uimap, kbUID)
		if err != nil {
			continue
		}
		user, err = normalizeAssertionOrName(user)
		if err != nil {
			continue
		}
		if allowed, _ := allowedWriters[user]; allowed {
			writerNames = append(writerNames, user)
			// Allow only one occurrence.
			allowedWriters[user] = false
		}
	}

	// Include participants even if they weren't in the active list, in stable order.
	for _, user := range srcWriterNames {
		if allowed, _ := allowedWriters[user]; allowed {
			writerNames = append(writerNames, user)
			allowedWriters[user] = false
		}
	}

	readerNames = srcReaderNames

	return writerNames, readerNames, nil
}

// Drive splitAndNormalizeTLFName with one attempt to follow TlfNameNotCanonical.
func splitAndNormalizeTLFNameCanonicalize(name string, public bool) (writerNames, readerNames []string, extensionSuffix string, err error) {
	writerNames, readerNames, extensionSuffix, err = splitAndNormalizeTLFName(name, public)
	if retryErr, retry := err.(TlfNameNotCanonical); retry {
		return splitAndNormalizeTLFName(retryErr.NameToTry, public)
	}
	return writerNames, readerNames, extensionSuffix, err
}

func CryptKeysWrapper(ctx context.Context, tlfInterface keybase1.TlfInterface, tlfName string) (tlfID chat1.TLFID, canonicalTlfName string, err error) {
	resp, err := tlfInterface.CryptKeys(ctx, keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_CLI,
	})
	if err != nil {
		return nil, "", err
	}
	tlfIDb := resp.NameIDBreaks.TlfID.ToBytes()
	if tlfIDb == nil {
		return nil, "", errors.New("invalid TLF ID acquired")
	}
	tlfID = chat1.TLFID(tlfIDb)
	return tlfID, string(resp.NameIDBreaks.CanonicalName), nil
}

func GetInboxQueryLocalToRemote(ctx context.Context, tlfInterface keybase1.TlfInterface,
	lquery *chat1.GetInboxLocalQuery) (rquery *chat1.GetInboxQuery, err error) {

	if lquery == nil {
		return nil, nil
	}
	rquery = &chat1.GetInboxQuery{}
	if lquery.TlfName != nil && len(*lquery.TlfName) > 0 {
		tlfID, _, err := CryptKeysWrapper(ctx, tlfInterface, *lquery.TlfName)
		if err != nil {
			return nil, err
		}
		rquery.TlfID = &tlfID
	}

	rquery.After = lquery.After
	rquery.Before = lquery.Before
	rquery.TlfVisibility = lquery.TlfVisibility
	rquery.TopicType = lquery.TopicType
	rquery.UnreadOnly = lquery.UnreadOnly
	rquery.ReadOnly = lquery.ReadOnly
	rquery.ComputeActiveList = lquery.ComputeActiveList
	rquery.ConvID = lquery.ConvID
	rquery.OneChatTypePerTLF = lquery.OneChatTypePerTLF
	rquery.Status = lquery.Status

	return rquery, nil
}

const (
	ChatTopicIDLen    = 16
	ChatTopicIDSuffix = 0x20
)

func NewChatTopicID() (id []byte, err error) {
	if id, err = libkb.RandBytes(ChatTopicIDLen); err != nil {
		return nil, err
	}
	id[len(id)-1] = ChatTopicIDSuffix
	return id, nil
}

func AllChatConversationStatuses() (res []chat1.ConversationStatus) {
	for _, s := range chat1.ConversationStatusMap {
		res = append(res, s)
	}
	return
}

func VisibleChatConversationStatuses() []chat1.ConversationStatus {
	return []chat1.ConversationStatus{
		chat1.ConversationStatus_UNFILED,
		chat1.ConversationStatus_FAVORITE,
	}
}

func IsVisibleChatConversationStatus(status chat1.ConversationStatus) bool {
	for _, s := range VisibleChatConversationStatuses() {
		if status == s {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

/*
 * Statements for CHECK actions
 */

const tkStmtCreateCheckConfigurationBase = `
INSERT INTO soma.check_configurations (
            configuration_id,
            configuration_name,
            interval,
            repository_id,
            bucket_id,
            capability_id,
            configuration_object,
            configuration_object_type,
            configuration_active,
            enabled,
            inheritance_enabled,
            children_only,
            external_id)
SELECT $1::uuid,
       $2::varchar,
       $3::integer,
       $4::uuid,
       $5::uuid,
       $6::uuid,
       $7::uuid,
       $8::varchar,
       $9::boolean,
       $10::boolean,
       $11::boolean,
       $12::boolean,
       $13::varchar;`

const tkStmtCreateCheckConfigurationThreshold = `
INSERT INTO soma.configuration_thresholds (
            configuration_id,
            predicate,
            threshold,
            notification_level)
SELECT $1::uuid,
       $2::varchar,
       $3::varchar,
       $4::varchar;`

const tkStmtCreateCheckConfigurationConstraintSystem = `
INSERT INTO soma.constraints_system_property (
            configuration_id,
            system_property,
            property_value)
SELECT $1::uuid,
       $2::varchar,
       $3::text;`

const tkStmtCreateCheckConfigurationConstraintNative = `
INSERT INTO soma.constraints_native_property (
            configuration_id,
            native_property,
            property_value)
SELECT $1::uuid,
       $2::varchar,
       $3::text;`

const tkStmtCreateCheckConfigurationConstraintOncall = `
INSERT INTO soma.constraints_oncall_property (
            configuration_id,
            oncall_duty_id)
SELECT $1::uuid,
       $2::uuid;`

const tkStmtCreateCheckConfigurationConstraintCustom = `
INSERT INTO soma.constraints_custom_property (
            configuration_id,
            custom_property_id,
            repository_id,
            property_value)
SELECT $1::uuid,
       $2::uuid,
       $3::uuid,
       $4::text;`

const tkStmtCreateCheckConfigurationConstraintService = `
INSERT INTO soma.constraints_service_property (
            configuration_id,
            organizational_team_id,
            service_property)
SELECT $1::uuid,
       $2::uuid,
       $3::varchar;`

const tkStmtCreateCheckConfigurationConstraintAttribute = `
INSERT INTO soma.constraints_service_attribute (
            configuration_id,
            service_property_attribute,
            attribute_value)
SELECT $1::uuid,
       $2::varchar,
       $3::varchar;`

const tkStmtCreateCheck = `
INSERT INTO soma.checks (
            check_id,
            repository_id,
            bucket_id,
            source_check_id,
            source_object_type,
            source_object_id,
            configuration_id,
            capability_id,
            object_id,
            object_type)
SELECT $1::uuid,
       $2::uuid,
       $3::uuid,
       $4::uuid,
       $5::varchar,
       $6::uuid,
       $7::uuid,
       $8::uuid,
       $9::uuid,
       $10::varchar;`

const tkStmtCreateCheckInstance = `
INSERT INTO soma.check_instances (
	check_instance_id,
	check_id,
	check_configuration_id,
	last_configuration_created)
VALUES $1::uuid,
       $2::uuid,
	   $3::uuid,
	   $4::timestamptz;`

const tkStmtCreateCheckInstanceConfiguration = `
INSERT INTO soma.check_instance_configurations (
	check_instance_config_id,
	version,
	check_instance_id,
	constraint_hash,
	constraint_val_hash,
	instance_service,
	instance_service_cfg_hash,
	instance_service_cfg,
	created,
	status,
	next_status,
	awaiting_deletion,
	deployment_details)
VALUES $1::uuid,
       $2::integer,
	   $3::uuid,
	   $4::varchar,
	   $5::varchar,
	   $6::varchar,
	   $7::varchar,
	   $8::jsonb,
	   $9::timestamptz,
	   $10::varchar,
	   $11::varchar,
	   $12::boolean,
	   $13::jsonb;`

////////////////////////////////////////////////
const tkStmtDeployDetailsComputeList = `
SELECT check_instance_config_id
FROM   soma.check_instance_configurations
WHERE  status = 'awaiting_computation';`

const tkStmtDeployDetailsUpdate = `
UPDATE soma.check_instance_configurations
SET    status = 'computed',
       deployment_details = $1::jsonb,
	   monitoring_id = $2::uuid
WHERE  check_instance_config_id = $3::uuid;`

const tkStmtDeployDetailsCheckInstance = `
SELECT scic.version,
	   scic.check_instance_id,
	   scic.constraint_hash,
	   scic.constraint_val_hash,
	   scic.instance_service,
	   scic.instance_service_cfg_hash,
	   scic.instance_service_cfg,
	   sci.check_id,
	   sci.check_configuration_id
FROM   soma.check_instance_configurations scic
JOIN   soma.check_instances sci
ON     scic.check_instance_id = sci.check_instance_id
WHERE  scic.check_instance_config_id = $1::uuid;`

const tkStmtDeployDetailsCheck = `
SELECT sc.repository_id,
	   sc.source_check_id,
	   sc.source_object_type,
	   sc.source_object_id,
	   sc.capability_id,
	   sc.object_id,
	   sc.object_type,
	   scc.inheritance_enabled,
	   scc.children_only,
FROM   soma.checks sc
JOIN   soma.check_configurations scc
ON     sc.configuration_id = scc.configuration_id
WHERE  sc.check_id = $1::uuid;`

const tkStmtDeployDetailsCheckConfig = `
SELECT configuration_name,
       interval,
	   configuration_active,
	   enabled,
	   external_id
FROM   soma.check_configurations
WHERE  configuration_id = $1::uuid;`

const tkStmtDeployDetailsCheckConfigThreshold = `
SELECT sct.predicate,
	   sct.threshold,
	   sct.notification_level,
	   snl.level_shortname,
	   snl.level_numeric
FROM   soma.configuration_thresholds sct
JOIN   soma.notification_levels snl
WHERE  sct.configuration_id = $1::uuid;`

const tkStmtDeployDetailsCapabilityMonitoringMetric = `
SELECT smc.capability_metric,
       smc.capability_monitoring,
	   smc.capability_view,
	   smc.threshold_amount,
	   sms.monitoring_name,
	   sms.monitoring_system_mode,
	   sms.monitoring_contact,
	   sms.monitoring_owner_team,
	   sms.monitoring_callback_uri,
	   sm.metric_unit,
	   sm.description,
	   smu.metric_unit_long_name
FROM   soma.monitoring_capabilities smc
JOIN   soma.monitoring_systems sms
ON     smc.capability_monitoring = sms.monitoring_id
JOIN   soma.metrics sm
ON     smc.capability_metric = sm.metric
JOIN   soma.metric_units smu
ON     sm.metric_unit = smu.metric_unit
WHERE  smc.capability_id = $1::uuid;`

const tkStmtDeployDetailsProviders = `
SELECT metric_provider,
       package
FROM   soma.metric_packages
WHERE  metric = $1::varchar;`

const tkStmtDeployDetailsGroup = `
SELECT sg.bucket_id,
	   sg.group_name,
	   sg.object_state,
	   sg.organizational_team_id,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name,
FROM  soma.groups sg
JOIN  soma.buckets sb
ON    sg.bucket_id = sb.bucket_id
JOIN  soma.repositories sr
ON    sb.repository_id = sr.repository_id
WHERE sg.group_id = $1::uuid;`

const tkStmtDeployDetailsCluster = `
SELECT sc.cluster_name,
       sc.bucket_id,
	   sc.object_state,
	   sc.organizational_team_id,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name,
FROM   soma.clusters sc
JOIN   soma.buckets sb
ON     sc.bucket_id = sb.bucket_id
JOIN  soma.repositories sr
ON    sb.repository_id = sr.repository_id
WHERE sr.cluster_id = $1::uuid;`

const tkStmtDeployDetailsNode = `
SELECT sn.node_asset_id,
       sn.node_name,
	   sn.organizational_team_id,
	   sn.server_id,
	   sn.object_state,
	   sn.node_online,
	   sn.node_deleted,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name,
	   ins.server_asset_id,
	   ins.server_datacenter_name,
	   ins.server_datacenter_location,
	   ins.server_name,
	   ins.server_online,
	   ins.server_deleted
FROM  soma.nodes sn
JOIN  soma.node_bucket_assignment snba
ON    sn.node_id = snba.node_id
JOIN  soma.buckets sb
ON    snba.bucket_id = sb.bucket_id
JOIN  soma.repositories sr
ON    sb.repository_id = sr.repository_id
JOIN  inventory.servers ins
ON    sn.server_id = ins.server_id
WHERE sn.node_id = $1::uuid;`

const tkStmtDeployDetailsTeam = `
SELECT organizational_team_name,
       organizational_team_ldap_id
FROM   inventory.organizational_teams
WHERE  organizational_team_id = $1::uuid;`

const tkStmtDeployDetailsNodeOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
       iodt.oncall_duty_phone_number,
FROM   soma.node_oncall_property snop
JOIN   inventory.oncall_duty_teams iodt
ON     snop.oncall_duty_id = iodt.oncall_duty_id
WHERE  snop.node_id = $1::uuid
AND    snop.view = $2::varchar;`

const tkStmtDeployDetailsClusterOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
	   iodt.oncall_duty_phone_number,
FROM   soma.cluster_oncall_properties scop
JOIN   inventory.oncall_duty_teams iodt
ON     scop.oncall_duty_id = iodt.oncall_duty_id
WHERE  scop.cluster_id = $1::uuid
AND    (scop.view = $2::varchar OR scop.view = 'any');`

const tkStmtDeployDetailsGroupOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
	   iodt.oncall_duty_phone_number,
FROM   soma.group_oncall_properties sgop
JOIN   inventory.oncall_duty_teams iodt
ON     sgop.oncall_duty_id = iodt.oncall_duty_id
WHERE  sgop.group_id = $1::uuid
AND    (sgop.view = $2::varchar OR sgop.view = 'any');`

const tkStmtDeployDetailsGroupService = `
SELECT service_property,
       organizational_team_id
FROM   soma.group_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsClusterService = `
SELECT service_property,
       organizational_team_id
FROM   soma.cluster_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsNodeService = `
SELECT service_property,
       organizational_team_id
FROM   soma.node_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

//
//// PROPERTIES: SYSTEM + CUSTOM
const tkStmtDeployDetailsGroupSysProp = `
SELECT system_property,
       value
FROM   soma.group_system_properties
WHERE  group_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsGroupCustProp = `
SELECT sgcp.custom_property_id,
       scp.custom_property,
       sgcp.value
FROM   soma.group_custom_properties sgcp
JOIN   soma.custom_properties scp
ON     sgcp.custom_property_id = scp.custom_property_id
AND    sgcp.repository_id = scp.repository_id
WHERE  sgcp.group_id = $1::uuid
AND    (sgcp.view = $2::varchar OR sgcp.view = 'any');`

const tkStmtDeployDetailClusterSysProp = `
SELECT system_property,
       value
FROM   soma.cluster_system_properties
WHERE  cluster_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailClusterCustProp = `
SELECT sccp.custom_property_id,
       scp.custom_property,
	   sccp.value
FROM   soma.cluster_custom_properties sccp
JOIN   soma.custom_properties scp
ON     sccp.custom_property_id = scp.custom_property_id
AND    sccp.repository_id = scp.repository_id
WHERE  sccp.cluster_id = $1::uuid
AND    (sccp.view = $2::varchar OR sccp.view = 'any');`

const tkStmtDeployDetailNodeSysProp = `
SELECT system_property,
       value
FROM   soma.node_system_properties
WHERE  node_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailNodeCustProp = `
SELECT sncp.custom_property_id,
       scp.custom_property,
	   sncp.value
FROM   soma.node_custom_properties sncp
JOIN   soma.custom_properties scp
ON     sncp.custom_property_id = scp.custom_property_id
AND    sncp.repository_id = scp.repository_id
WHERE  sncp.node_id = $1::uuid
AND    (sncp.view = $2::varchar OR sncp.view = 'any');`

//
// DEFAULT DATACENTER
const tkStmtDeployDetailDefaultDatacenter = `
SELECT server_datacenter_name
FROM   inventory.servers
WHERE  server_asset_id = 0
AND    server_datacenter_location = 'none'
AND    server_name = 'soma-null-server';`

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Syntax fix all the sql statements<commit_after>package main

/*
 * Statements for CHECK actions
 */

const tkStmtCreateCheckConfigurationBase = `
INSERT INTO soma.check_configurations (
            configuration_id,
            configuration_name,
            interval,
            repository_id,
            bucket_id,
            capability_id,
            configuration_object,
            configuration_object_type,
            configuration_active,
            enabled,
            inheritance_enabled,
            children_only,
            external_id)
SELECT $1::uuid,
       $2::varchar,
       $3::integer,
       $4::uuid,
       $5::uuid,
       $6::uuid,
       $7::uuid,
       $8::varchar,
       $9::boolean,
       $10::boolean,
       $11::boolean,
       $12::boolean,
       $13::varchar;`

const tkStmtCreateCheckConfigurationThreshold = `
INSERT INTO soma.configuration_thresholds (
            configuration_id,
            predicate,
            threshold,
            notification_level)
SELECT $1::uuid,
       $2::varchar,
       $3::varchar,
       $4::varchar;`

const tkStmtCreateCheckConfigurationConstraintSystem = `
INSERT INTO soma.constraints_system_property (
            configuration_id,
            system_property,
            property_value)
SELECT $1::uuid,
       $2::varchar,
       $3::text;`

const tkStmtCreateCheckConfigurationConstraintNative = `
INSERT INTO soma.constraints_native_property (
            configuration_id,
            native_property,
            property_value)
SELECT $1::uuid,
       $2::varchar,
       $3::text;`

const tkStmtCreateCheckConfigurationConstraintOncall = `
INSERT INTO soma.constraints_oncall_property (
            configuration_id,
            oncall_duty_id)
SELECT $1::uuid,
       $2::uuid;`

const tkStmtCreateCheckConfigurationConstraintCustom = `
INSERT INTO soma.constraints_custom_property (
            configuration_id,
            custom_property_id,
            repository_id,
            property_value)
SELECT $1::uuid,
       $2::uuid,
       $3::uuid,
       $4::text;`

const tkStmtCreateCheckConfigurationConstraintService = `
INSERT INTO soma.constraints_service_property (
            configuration_id,
            organizational_team_id,
            service_property)
SELECT $1::uuid,
       $2::uuid,
       $3::varchar;`

const tkStmtCreateCheckConfigurationConstraintAttribute = `
INSERT INTO soma.constraints_service_attribute (
            configuration_id,
            service_property_attribute,
            attribute_value)
SELECT $1::uuid,
       $2::varchar,
       $3::varchar;`

const tkStmtCreateCheck = `
INSERT INTO soma.checks (
            check_id,
            repository_id,
            bucket_id,
            source_check_id,
            source_object_type,
            source_object_id,
            configuration_id,
            capability_id,
            object_id,
            object_type)
SELECT $1::uuid,
       $2::uuid,
       $3::uuid,
       $4::uuid,
       $5::varchar,
       $6::uuid,
       $7::uuid,
       $8::uuid,
       $9::uuid,
       $10::varchar;`

const tkStmtCreateCheckInstance = `
INSERT INTO soma.check_instances (
	check_instance_id,
	check_id,
	check_configuration_id,
	last_configuration_created)
SELECT $1::uuid,
       $2::uuid,
	   $3::uuid,
	   $4::timestamptz;`

const tkStmtCreateCheckInstanceConfiguration = `
INSERT INTO soma.check_instance_configurations (
	check_instance_config_id,
	version,
	check_instance_id,
	constraint_hash,
	constraint_val_hash,
	instance_service,
	instance_service_cfg_hash,
	instance_service_cfg,
	created,
	status,
	next_status,
	awaiting_deletion,
	deployment_details)
SELECT $1::uuid,
       $2::integer,
	   $3::uuid,
	   $4::varchar,
	   $5::varchar,
	   $6::varchar,
	   $7::varchar,
	   $8::jsonb,
	   $9::timestamptz,
	   $10::varchar,
	   $11::varchar,
	   $12::boolean,
	   $13::jsonb;`

////////////////////////////////////////////////
const tkStmtDeployDetailsComputeList = `
SELECT check_instance_config_id
FROM   soma.check_instance_configurations
WHERE  status = 'awaiting_computation';`

const tkStmtDeployDetailsUpdate = `
UPDATE soma.check_instance_configurations
SET    status = 'computed',
       deployment_details = $1::jsonb,
	   monitoring_id = $2::uuid
WHERE  check_instance_config_id = $3::uuid;`

const tkStmtDeployDetailsCheckInstance = `
SELECT scic.version,
	   scic.check_instance_id,
	   scic.constraint_hash,
	   scic.constraint_val_hash,
	   scic.instance_service,
	   scic.instance_service_cfg_hash,
	   scic.instance_service_cfg,
	   sci.check_id,
	   sci.check_configuration_id
FROM   soma.check_instance_configurations scic
JOIN   soma.check_instances sci
ON     scic.check_instance_id = sci.check_instance_id
WHERE  scic.check_instance_config_id = $1::uuid;`

const tkStmtDeployDetailsCheck = `
SELECT sc.repository_id,
	   sc.source_check_id,
	   sc.source_object_type,
	   sc.source_object_id,
	   sc.capability_id,
	   sc.object_id,
	   sc.object_type,
	   scc.inheritance_enabled,
	   scc.children_only
FROM   soma.checks sc
JOIN   soma.check_configurations scc
ON     sc.configuration_id = scc.configuration_id
WHERE  sc.check_id = $1::uuid;`

const tkStmtDeployDetailsCheckConfig = `
SELECT configuration_name,
       interval,
	   configuration_active,
	   enabled,
	   external_id
FROM   soma.check_configurations
WHERE  configuration_id = $1::uuid;`

const tkStmtDeployDetailsCheckConfigThreshold = `
SELECT sct.predicate,
	   sct.threshold,
	   sct.notification_level,
	   snl.level_shortname,
	   snl.level_numeric
FROM   soma.configuration_thresholds sct
JOIN   soma.notification_levels snl
ON     sct.notification_level = snl.level_name
WHERE  sct.configuration_id = $1::uuid;`

const tkStmtDeployDetailsCapabilityMonitoringMetric = `
SELECT smc.capability_metric,
       smc.capability_monitoring,
	   smc.capability_view,
	   smc.threshold_amount,
	   sms.monitoring_name,
	   sms.monitoring_system_mode,
	   sms.monitoring_contact,
	   sms.monitoring_owner_team,
	   sms.monitoring_callback_uri,
	   sm.metric_unit,
	   sm.description,
	   smu.metric_unit_long_name
FROM   soma.monitoring_capabilities smc
JOIN   soma.monitoring_systems sms
ON     smc.capability_monitoring = sms.monitoring_id
JOIN   soma.metrics sm
ON     smc.capability_metric = sm.metric
JOIN   soma.metric_units smu
ON     sm.metric_unit = smu.metric_unit
WHERE  smc.capability_id = $1::uuid;`

const tkStmtDeployDetailsProviders = `
SELECT metric_provider,
       package
FROM   soma.metric_packages
WHERE  metric = $1::varchar;`

const tkStmtDeployDetailsGroup = `
SELECT sg.bucket_id,
	   sg.group_name,
	   sg.object_state,
	   sg.organizational_team_id,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name
FROM   soma.groups sg
JOIN   soma.buckets sb
ON     sg.bucket_id = sb.bucket_id
JOIN   soma.repositories sr
ON     sb.repository_id = sr.repository_id
WHERE  sg.group_id = $1::uuid;`

const tkStmtDeployDetailsCluster = `
SELECT sc.cluster_name,
       sc.bucket_id,
	   sc.object_state,
	   sc.organizational_team_id,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name
FROM   soma.clusters sc
JOIN   soma.buckets sb
ON     sc.bucket_id = sb.bucket_id
JOIN   soma.repositories sr
ON     sb.repository_id = sr.repository_id
WHERE  sc.cluster_id = $1::uuid;`

const tkStmtDeployDetailsNode = `
SELECT sn.node_asset_id,
       sn.node_name,
	   sn.organizational_team_id,
	   sn.server_id,
	   sn.object_state,
	   sn.node_online,
	   sn.node_deleted,
	   sb.bucket_name,
	   sb.environment,
	   sr.repository_name,
	   ins.server_asset_id,
	   ins.server_datacenter_name,
	   ins.server_datacenter_location,
	   ins.server_name,
	   ins.server_online,
	   ins.server_deleted
FROM  soma.nodes sn
JOIN  soma.node_bucket_assignment snba
ON    sn.node_id = snba.node_id
JOIN  soma.buckets sb
ON    snba.bucket_id = sb.bucket_id
JOIN  soma.repositories sr
ON    sb.repository_id = sr.repository_id
JOIN  inventory.servers ins
ON    sn.server_id = ins.server_id
WHERE sn.node_id = $1::uuid;`

const tkStmtDeployDetailsTeam = `
SELECT organizational_team_name,
       organizational_team_ldap_id
FROM   inventory.organizational_teams
WHERE  organizational_team_id = $1::uuid;`

const tkStmtDeployDetailsNodeOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
       iodt.oncall_duty_phone_number
FROM   soma.node_oncall_property snop
JOIN   inventory.oncall_duty_teams iodt
ON     snop.oncall_duty_id = iodt.oncall_duty_id
WHERE  snop.node_id = $1::uuid
AND    snop.view = $2::varchar;`

const tkStmtDeployDetailsClusterOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
	   iodt.oncall_duty_phone_number
FROM   soma.cluster_oncall_properties scop
JOIN   inventory.oncall_duty_teams iodt
ON     scop.oncall_duty_id = iodt.oncall_duty_id
WHERE  scop.cluster_id = $1::uuid
AND    (scop.view = $2::varchar OR scop.view = 'any');`

const tkStmtDeployDetailsGroupOncall = `
SELECT iodt.oncall_duty_id,
       iodt.oncall_duty_name,
	   iodt.oncall_duty_phone_number
FROM   soma.group_oncall_properties sgop
JOIN   inventory.oncall_duty_teams iodt
ON     sgop.oncall_duty_id = iodt.oncall_duty_id
WHERE  sgop.group_id = $1::uuid
AND    (sgop.view = $2::varchar OR sgop.view = 'any');`

const tkStmtDeployDetailsGroupService = `
SELECT service_property,
       organizational_team_id
FROM   soma.group_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsClusterService = `
SELECT service_property,
       organizational_team_id
FROM   soma.cluster_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsNodeService = `
SELECT service_property,
       organizational_team_id
FROM   soma.node_service_properties
WHERE  instance_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

//
//// PROPERTIES: SYSTEM + CUSTOM
const tkStmtDeployDetailsGroupSysProp = `
SELECT system_property,
       value
FROM   soma.group_system_properties
WHERE  group_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailsGroupCustProp = `
SELECT sgcp.custom_property_id,
       scp.custom_property,
       sgcp.value
FROM   soma.group_custom_properties sgcp
JOIN   soma.custom_properties scp
ON     sgcp.custom_property_id = scp.custom_property_id
AND    sgcp.repository_id = scp.repository_id
WHERE  sgcp.group_id = $1::uuid
AND    (sgcp.view = $2::varchar OR sgcp.view = 'any');`

const tkStmtDeployDetailClusterSysProp = `
SELECT system_property,
       value
FROM   soma.cluster_system_properties
WHERE  cluster_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailClusterCustProp = `
SELECT sccp.custom_property_id,
       scp.custom_property,
	   sccp.value
FROM   soma.cluster_custom_properties sccp
JOIN   soma.custom_properties scp
ON     sccp.custom_property_id = scp.custom_property_id
AND    sccp.repository_id = scp.repository_id
WHERE  sccp.cluster_id = $1::uuid
AND    (sccp.view = $2::varchar OR sccp.view = 'any');`

const tkStmtDeployDetailNodeSysProp = `
SELECT system_property,
       value
FROM   soma.node_system_properties
WHERE  node_id = $1::uuid
AND    (view = $2::varchar OR view = 'any');`

const tkStmtDeployDetailNodeCustProp = `
SELECT sncp.custom_property_id,
       scp.custom_property,
	   sncp.value
FROM   soma.node_custom_properties sncp
JOIN   soma.custom_properties scp
ON     sncp.custom_property_id = scp.custom_property_id
AND    sncp.repository_id = scp.repository_id
WHERE  sncp.node_id = $1::uuid
AND    (sncp.view = $2::varchar OR sncp.view = 'any');`

//
// DEFAULT DATACENTER
const tkStmtDeployDetailDefaultDatacenter = `
SELECT server_datacenter_name
FROM   inventory.servers
WHERE  server_asset_id = 0
AND    server_datacenter_location = 'none'
AND    server_name = 'soma-null-server';`

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


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

// This file contains tests verifying the types associated with an AST after
// type checking.

package types

import (
	"go/ast"
	"go/parser"
	"testing"
)

const filename = "<src>"

func makePkg(t *testing.T, src string) (*Package, error) {
	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
	if err != nil {
		return nil, err
	}
	// use the package name as package path
	return Check(file.Name.Name, fset, []*ast.File{file})
}

type testEntry struct {
	src, str string
}

// dup returns a testEntry where both src and str are the same.
func dup(s string) testEntry {
	return testEntry{s, s}
}

// types that don't depend on any other type declarations
var independentTestTypes = []testEntry{
	// basic types
	dup("int"),
	dup("float32"),
	dup("string"),

	// arrays
	dup("[10]int"),

	// slices
	dup("[]int"),
	dup("[][]int"),

	// structs
	dup("struct{}"),
	dup("struct{x int}"),
	{`struct {
		x, y int
		z float32 "foo"
	}`, `struct{x int; y int; z float32 "foo"}`},
	{`struct {
		string
		elems []complex128
	}`, `struct{string; elems []complex128}`},

	// pointers
	dup("*int"),
	dup("***struct{}"),
	dup("*struct{a int; b float32}"),

	// functions
	dup("func()"),
	dup("func(x int)"),
	{"func(x, y int)", "func(x int, y int)"},
	{"func(x, y int, z string)", "func(x int, y int, z string)"},
	dup("func(int)"),
	{"func(int, string, byte)", "func(int, string, byte)"},

	dup("func() int"),
	{"func() (string)", "func() string"},
	dup("func() (u int)"),
	{"func() (u, v int, w string)", "func() (u int, v int, w string)"},

	dup("func(int) string"),
	dup("func(x int) string"),
	dup("func(x int) (u string)"),
	{"func(x, y int) (u string)", "func(x int, y int) (u string)"},

	dup("func(...int) string"),
	dup("func(x ...int) string"),
	dup("func(x ...int) (u string)"),
	{"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},

	// interfaces
	dup("interface{}"),
	dup("interface{m()}"),
	dup(`interface{String() string; m(int) float32}`),

	// maps
	dup("map[string]int"),
	{"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},

	// channels
	dup("chan int"),
	dup("chan<- func()"),
	dup("<-chan []func() int"),
}

// types that depend on other type declarations (src in TestTypes)
var dependentTestTypes = []testEntry{
	// interfaces
	dup(`interface{io.Reader; io.Writer}`),
	dup(`interface{m() int; io.Writer}`),
	{`interface{m() interface{T}}`, `interface{m() interface{p.T}}`},
}

func TestTypes(t *testing.T) {
	var tests []testEntry
	tests = append(tests, independentTestTypes...)
	tests = append(tests, dependentTestTypes...)

	for _, test := range tests {
		src := `package p; import "io"; type _ io.Writer; type T ` + test.src
		pkg, err := makePkg(t, src)
		if err != nil {
			t.Errorf("%s: %s", src, err)
			continue
		}
		typ := pkg.scope.Lookup("T").Type().Underlying()
		str := typeString(typ)
		if str != test.str {
			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
		}
	}
}

var testExprs = []testEntry{
	// basic type literals
	dup("x"),
	dup("true"),
	dup("42"),
	dup("3.1415"),
	dup("2.71828i"),
	dup(`'a'`),
	dup(`"foo"`),
	dup("`bar`"),

	// arbitrary expressions
	dup("&x"),
	dup("*&x"),
	dup("(x)"),
	dup("x + y"),
	dup("x + y * 10"),
	dup("t.foo"),
	dup("s[0]"),
	dup("s[x:y]"),
	dup("s[:y]"),
	dup("s[x:]"),
	dup("s[:]"),
	dup("f(1, 2.3)"),
	dup("-f(10, 20)"),
	dup("f(x + y, +3.1415)"),
	{"func(a, b int) {}", "(func literal)"},
	{"func(a, b int) []int {}(1, 2)[x]", "(func literal)(1, 2)[x]"},
	{"[]int{1, 2, 3}", "(composite literal)"},
	{"[]int{1, 2, 3}[x:]", "(composite literal)[x:]"},
	{"i.([]string)", "i.(<expr *ast.ArrayType>)"},
}

func TestExprs(t *testing.T) {
	for _, test := range testExprs {
		src := "package p; var _ = " + test.src + "; var (x, y int; s []string; f func(int, float32) int; i interface{}; t interface { foo() })"
		file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
		if err != nil {
			t.Errorf("%s: %s", src, err)
			continue
		}
		// TODO(gri) writing the code below w/o the decl variable will
		//           cause a 386 compiler error (out of fixed registers)
		decl := file.Decls[0].(*ast.GenDecl)
		expr := decl.Specs[0].(*ast.ValueSpec).Values[0]
		str := exprString(expr)
		if str != test.str {
			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
		}
	}
}
<commit_msg>go.tools/go/types: remove a workaround for 386 bug<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains tests verifying the types associated with an AST after
// type checking.

package types

import (
	"go/ast"
	"go/parser"
	"testing"
)

const filename = "<src>"

func makePkg(t *testing.T, src string) (*Package, error) {
	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
	if err != nil {
		return nil, err
	}
	// use the package name as package path
	return Check(file.Name.Name, fset, []*ast.File{file})
}

type testEntry struct {
	src, str string
}

// dup returns a testEntry where both src and str are the same.
func dup(s string) testEntry {
	return testEntry{s, s}
}

// types that don't depend on any other type declarations
var independentTestTypes = []testEntry{
	// basic types
	dup("int"),
	dup("float32"),
	dup("string"),

	// arrays
	dup("[10]int"),

	// slices
	dup("[]int"),
	dup("[][]int"),

	// structs
	dup("struct{}"),
	dup("struct{x int}"),
	{`struct {
		x, y int
		z float32 "foo"
	}`, `struct{x int; y int; z float32 "foo"}`},
	{`struct {
		string
		elems []complex128
	}`, `struct{string; elems []complex128}`},

	// pointers
	dup("*int"),
	dup("***struct{}"),
	dup("*struct{a int; b float32}"),

	// functions
	dup("func()"),
	dup("func(x int)"),
	{"func(x, y int)", "func(x int, y int)"},
	{"func(x, y int, z string)", "func(x int, y int, z string)"},
	dup("func(int)"),
	{"func(int, string, byte)", "func(int, string, byte)"},

	dup("func() int"),
	{"func() (string)", "func() string"},
	dup("func() (u int)"),
	{"func() (u, v int, w string)", "func() (u int, v int, w string)"},

	dup("func(int) string"),
	dup("func(x int) string"),
	dup("func(x int) (u string)"),
	{"func(x, y int) (u string)", "func(x int, y int) (u string)"},

	dup("func(...int) string"),
	dup("func(x ...int) string"),
	dup("func(x ...int) (u string)"),
	{"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},

	// interfaces
	dup("interface{}"),
	dup("interface{m()}"),
	dup(`interface{String() string; m(int) float32}`),

	// maps
	dup("map[string]int"),
	{"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},

	// channels
	dup("chan int"),
	dup("chan<- func()"),
	dup("<-chan []func() int"),
}

// types that depend on other type declarations (src in TestTypes)
var dependentTestTypes = []testEntry{
	// interfaces
	dup(`interface{io.Reader; io.Writer}`),
	dup(`interface{m() int; io.Writer}`),
	{`interface{m() interface{T}}`, `interface{m() interface{p.T}}`},
}

func TestTypes(t *testing.T) {
	var tests []testEntry
	tests = append(tests, independentTestTypes...)
	tests = append(tests, dependentTestTypes...)

	for _, test := range tests {
		src := `package p; import "io"; type _ io.Writer; type T ` + test.src
		pkg, err := makePkg(t, src)
		if err != nil {
			t.Errorf("%s: %s", src, err)
			continue
		}
		typ := pkg.scope.Lookup("T").Type().Underlying()
		str := typeString(typ)
		if str != test.str {
			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
		}
	}
}

var testExprs = []testEntry{
	// basic type literals
	dup("x"),
	dup("true"),
	dup("42"),
	dup("3.1415"),
	dup("2.71828i"),
	dup(`'a'`),
	dup(`"foo"`),
	dup("`bar`"),

	// arbitrary expressions
	dup("&x"),
	dup("*&x"),
	dup("(x)"),
	dup("x + y"),
	dup("x + y * 10"),
	dup("t.foo"),
	dup("s[0]"),
	dup("s[x:y]"),
	dup("s[:y]"),
	dup("s[x:]"),
	dup("s[:]"),
	dup("f(1, 2.3)"),
	dup("-f(10, 20)"),
	dup("f(x + y, +3.1415)"),
	{"func(a, b int) {}", "(func literal)"},
	{"func(a, b int) []int {}(1, 2)[x]", "(func literal)(1, 2)[x]"},
	{"[]int{1, 2, 3}", "(composite literal)"},
	{"[]int{1, 2, 3}[x:]", "(composite literal)[x:]"},
	{"i.([]string)", "i.(<expr *ast.ArrayType>)"},
}

func TestExprs(t *testing.T) {
	for _, test := range testExprs {
		src := "package p; var _ = " + test.src + "; var (x, y int; s []string; f func(int, float32) int; i interface{}; t interface { foo() })"
		file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
		if err != nil {
			t.Errorf("%s: %s", src, err)
			continue
		}
		str := exprString(file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0])
		if str != test.str {
			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
		}
	}
}
<|endoftext|>


<commit_before>package goat

import (
	"log"
	"net/http"
	"net/http/httptest"
	"testing"
)

// Table driven tests to iterate over and test the API router
var apiTests = []struct {
	method string
	url string
	code int
}{
	{"POST", "/api/", 405},
	{"GET", "/api/", 404},
	{"GET", "/api/files/a", 400},
	{"GET", "/api/abcdef", 404},
	{"GET", "/api/files", 200},
	{"GET", "/api/files/1", 200},
	{"GET", "/api/status", 200},
}

// TestAPIRouter verifies that the API router is working properly
func TestAPIRouter(t *testing.T) {
	log.Println("TestAPIRouter()")

	// Iterate all API tests
	for _, test := range apiTests {
		// Generate mock HTTP request
		r, err := http.NewRequest(test.method, "http://localhost:8080"+test.url, nil)
		if err != nil {
			t.Fatalf("Failed to create HTTP request")
		}

		// Capture HTTP writer response with recorder
		w := httptest.NewRecorder()

		// Invoke API router
		apiRouter(w, r)

		// Validate input
		if w.Code != test.code {
			t.Fatalf("Test %s %s, expected HTTP %d, got HTTP %d", test.method, test.url, test.code, w.Code)
		}

		log.Printf("OK - %s %s -> HTTP %d", test.method, test.url, w.Code)
		log.Println(w.Body.String())
	}
}
<commit_msg>Remove annoying newlines from API tests<commit_after>package goat

import (
	"log"
	"net/http"
	"net/http/httptest"
	"testing"
)

// Table driven tests to iterate over and test the API router
var apiTests = []struct {
	method string
	url string
	code int
}{
	{"POST", "/api/", 405},
	{"GET", "/api/", 404},
	{"GET", "/api/files/a", 400},
	{"GET", "/api/abcdef", 404},
	{"GET", "/api/files", 200},
	{"GET", "/api/files/1", 200},
	{"GET", "/api/status", 200},
}

// TestAPIRouter verifies that the API router is working properly
func TestAPIRouter(t *testing.T) {
	log.Println("TestAPIRouter()")

	// Iterate all API tests
	for _, test := range apiTests {
		// Generate mock HTTP request
		r, err := http.NewRequest(test.method, "http://localhost:8080"+test.url, nil)
		if err != nil {
			t.Fatalf("Failed to create HTTP request")
		}

		// Capture HTTP writer response with recorder
		w := httptest.NewRecorder()

		// Invoke API router
		apiRouter(w, r)

		// Validate input
		if w.Code != test.code {
			t.Fatalf("Test %s %s, expected HTTP %d, got HTTP %d", test.method, test.url, test.code, w.Code)
		}

		log.Printf("OK - %s %s -> HTTP %d", test.method, test.url, w.Code)
		log.Printf(w.Body.String())
	}
}
<|endoftext|>


<commit_before>// cmd_measurements.go

package main

import (
	"fmt"
	"github.com/keltia/ripe-atlas"
	"github.com/urfave/cli"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
)

// init injects our measurement-related commands
func init() {
	cliCommands = append(cliCommands, cli.Command{
		Name: "measurements",
		Aliases: []string{
			"measures",
			"m",
		},
		Usage:       "measurements-related keywords",
		Description: "All the commands for measurements",
		Subcommands: []cli.Command{
			{
				Name:        "list",
				Aliases:     []string{"ls"},
				Usage:       "lists all measurements",
				Description: "displays all measurements",
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:        "country, c",
						Usage:       "filter on country",
						Destination: &fCountry,
					},
					cli.StringFlag{
						Name:        "asn",
						Usage:       "filter on asn",
						Value:       "",
						Destination: &fAsn,
					},
					cli.BoolFlag{
						Name:        "A, all",
						Usage:       "all measurements even inactive ones",
						Destination: &fAllMeasurements,
					},
					cli.BoolFlag{
						Name:        "is-anchor",
						Usage:       "select anchor measurements",
						Destination: &fWantAnchor,
					},
					cli.BoolFlag{
						Name:        "mine",
						Usage:       "limit to my own measurements",
						Destination: &fWantMine,
					},
					cli.StringFlag{
						Name:        "t, type",
						Usage:       "filter on measurement type",
						Value:       "",
						Destination: &fMeasureType,
					},
				},
				Action: measurementsList,
			},
			{
				Name:        "info",
				Usage:       "info for one measurement",
				Description: "gives info for one measurement",
				Action:      measurementInfo,
			},
			{
				Name:        "results",
				Aliases:     []string{"r", "res"},
				Usage:       "results for one measurement",
				Description: "returns results for one measurement",
				Action:      measurementResults,
			},
			{
				Name:        "delete",
				Aliases:     []string{"rm", "del", "destroy"},
				Usage:       "info for one measurement",
				Description: "stops one measurement (or all)",
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:        "A",
						Usage:       "select all measurements",
						Destination: &fAllMeasurements,
					},
				},
				Action: measurementDelete,
			},
		},
	})
}

// displayMeasurement returns a string with one measurement
func displayMeasurement(m *atlas.Measurement, verbose bool) (res string) {
	if verbose {
		res = fmt.Sprintf("%v\n", m)
	} else {
		res = fmt.Sprintf("ID: %d type: %s description: %s Target: %s\n", m.ID, m.Type, m.Description, m.Target)
	}
	return
}

// displayAllMeasurements returns a string with all measurements
func displayAllMeasurements(ml *[]atlas.Measurement, verbose bool) (res string) {
	res = ""
	for _, m := range *ml {
		res += displayMeasurement(&m, verbose)
	}
	return
}

// displayResult returns a string with <obj>.Result
func displayResult(body []byte, verbose bool) (res string) {
	return string(body)
}

// measurementsList returns a list of measurements according to parameters
func measurementsList(c *cli.Context) error {
	opts := make(map[string]string)

	if fCountry != "" {
		opts["country_code"] = fCountry
	}

	if fAsn != "" {
		opts["asn"] = fAsn
	}

	if fMeasureType != "" {
		opts["type"] = fMeasureType
	}

	if fWantMine {
		opts["mine"] = "true"
	}

	// Check global parameters
	opts = checkGlobalFlags(opts)

	if fVerbose {
		displayOptions(opts)
	}

	q, err := atlas.GetMeasurements(opts)
	if err != nil {
		log.Printf("GetMeasurements err: %v - q:%v", err, q)
		os.Exit(1)
	}
	log.Printf("Got %d measurements with %v\n", len(q), opts)
	fmt.Print(displayAllMeasurements(&q, fVerbose))

	return nil
}

// measurementInfo is for one measurement only
func measurementInfo(c *cli.Context) error {
	args := c.Args()
	if args[0] == "" {
		log.Fatalf("Error: you must specify a measurement ID!")
	}

	id, _ := strconv.ParseInt(args[0], 10, 32)

	p, err := atlas.GetMeasurement(int(id))
	if err != nil {
		fmt.Printf("err: %v", err)
		os.Exit(1)
	}
	fmt.Print(displayMeasurement(p, fVerbose))

	return nil
}

// measurementResults returns the result part of the measurement
func measurementResults(c *cli.Context) error {
	args := c.Args()
	if args[0] == "" {
		log.Fatalf("Error: you must specify a measurement ID!")
	}

	id, _ := strconv.ParseInt(args[0], 10, 32)

	m, err := atlas.GetMeasurement(int(id))
	if err != nil {
		fmt.Printf("err: %v", err)
		os.Exit(1)
	}

	// m.Result is an URI pointing to results, fetch it
	if m.Result == "" {
		fmt.Println("Empty result")
	}

	resp, err := http.Get(m.Result)
	if err != nil {
		err = fmt.Errorf("bad net/http answer for %s: %v", m.Result, err)
		return err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		err = fmt.Errorf("error reading body for %s: %v", m.Result, err)
		return err
	}

	fmt.Print(displayResult(body, fVerbose))
	return nil
}

func measurementCreate(c *cli.Context) error {
	return nil
}

func measurementDelete(c *cli.Context) (err error) {
	var id int64

	if fAllMeasurements {
		opts := make(map[string]string)

		// Check global parameters
		opts = checkGlobalFlags(opts)

		list, err := atlas.GetMeasurements(opts)
		if err != nil {
			err = fmt.Errorf("Delete all failed: %v", err)
		} else {
			for _, m := range list {
				err = atlas.DeleteMeasurement(m.ID)
				if err != nil {
					err = fmt.Errorf("Error: can not delete measurement %d", m.ID)
				}
			}
			fmt.Printf("All measurements stopped.")
		}
	} else {
		args := c.Args()
		if args[0] == "" {
			log.Fatalf("Error: you must specify a measurement ID!")
		}

		id, _ = strconv.ParseInt(args[0], 10, 32)
		err = atlas.DeleteMeasurement(int(id))
	}

	return
}
<commit_msg>Add a top-level "results/r/res" command.<commit_after>// cmd_measurements.go

package main

import (
	"fmt"
	"github.com/keltia/ripe-atlas"
	"github.com/urfave/cli"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
)

// init injects our measurement-related commands
func init() {
	cliCommands = append(cliCommands, cli.Command{
		Name: "measurements",
		Aliases: []string{
			"measures",
			"m",
		},
		Usage:       "measurements-related keywords",
		Description: "All the commands for measurements",
		Subcommands: []cli.Command{
			{
				Name:        "list",
				Aliases:     []string{"ls"},
				Usage:       "lists all measurements",
				Description: "displays all measurements",
				Flags: []cli.Flag{
					cli.StringFlag{
						Name:        "country, c",
						Usage:       "filter on country",
						Destination: &fCountry,
					},
					cli.StringFlag{
						Name:        "asn",
						Usage:       "filter on asn",
						Value:       "",
						Destination: &fAsn,
					},
					cli.BoolFlag{
						Name:        "A, all",
						Usage:       "all measurements even inactive ones",
						Destination: &fAllMeasurements,
					},
					cli.BoolFlag{
						Name:        "is-anchor",
						Usage:       "select anchor measurements",
						Destination: &fWantAnchor,
					},
					cli.BoolFlag{
						Name:        "mine",
						Usage:       "limit to my own measurements",
						Destination: &fWantMine,
					},
					cli.StringFlag{
						Name:        "t, type",
						Usage:       "filter on measurement type",
						Value:       "",
						Destination: &fMeasureType,
					},
				},
				Action: measurementsList,
			},
			{
				Name:        "info",
				Usage:       "info for one measurement",
				Description: "gives info for one measurement",
				Action:      measurementInfo,
			},
			{
				Name:        "results",
				Aliases:     []string{"r", "res"},
				Usage:       "results for one measurement",
				Description: "returns results for one measurement",
				Action:      measurementResults,
			},
			{
				Name:        "delete",
				Aliases:     []string{"rm", "del", "destroy"},
				Usage:       "info for one measurement",
				Description: "stops one measurement (or all)",
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:        "A",
						Usage:       "select all measurements",
						Destination: &fAllMeasurements,
					},
				},
				Action: measurementDelete,
			},
		},
	})

	cliCommands = append(cliCommands, cli.Command{
		Name:        "results",
		Aliases:     []string{"r", "res"},
		Usage:       "results for one measurement",
		Description: "returns results for one measurement",
		Action:      measurementResults,
	})
}

// displayMeasurement returns a string with one measurement
func displayMeasurement(m *atlas.Measurement, verbose bool) (res string) {
	if verbose {
		res = fmt.Sprintf("%v\n", m)
	} else {
		res = fmt.Sprintf("ID: %d type: %s description: %s Target: %s\n", m.ID, m.Type, m.Description, m.Target)
	}
	return
}

// displayAllMeasurements returns a string with all measurements
func displayAllMeasurements(ml *[]atlas.Measurement, verbose bool) (res string) {
	res = ""
	for _, m := range *ml {
		res += displayMeasurement(&m, verbose)
	}
	return
}

// displayResult returns a string with <obj>.Result
func displayResult(body []byte, verbose bool) (res string) {
	return string(body)
}

// measurementsList returns a list of measurements according to parameters
func measurementsList(c *cli.Context) error {
	opts := make(map[string]string)

	if fCountry != "" {
		opts["country_code"] = fCountry
	}

	if fAsn != "" {
		opts["asn"] = fAsn
	}

	if fMeasureType != "" {
		opts["type"] = fMeasureType
	}

	if fWantMine {
		opts["mine"] = "true"
	}

	// Check global parameters
	opts = checkGlobalFlags(opts)

	if fVerbose {
		displayOptions(opts)
	}

	q, err := atlas.GetMeasurements(opts)
	if err != nil {
		log.Printf("GetMeasurements err: %v - q:%v", err, q)
		os.Exit(1)
	}
	log.Printf("Got %d measurements with %v\n", len(q), opts)
	fmt.Print(displayAllMeasurements(&q, fVerbose))

	return nil
}

// measurementInfo is for one measurement only
func measurementInfo(c *cli.Context) error {
	args := c.Args()
	if args[0] == "" {
		log.Fatalf("Error: you must specify a measurement ID!")
	}

	id, _ := strconv.ParseInt(args[0], 10, 32)

	p, err := atlas.GetMeasurement(int(id))
	if err != nil {
		fmt.Printf("err: %v", err)
		os.Exit(1)
	}
	fmt.Print(displayMeasurement(p, fVerbose))

	return nil
}

// measurementResults returns the result part of the measurement
func measurementResults(c *cli.Context) error {
	args := c.Args()
	if args[0] == "" {
		log.Fatalf("Error: you must specify a measurement ID!")
	}

	id, _ := strconv.ParseInt(args[0], 10, 32)

	m, err := atlas.GetMeasurement(int(id))
	if err != nil {
		fmt.Printf("err: %v", err)
		os.Exit(1)
	}

	// m.Result is an URI pointing to results, fetch it
	if m.Result == "" {
		fmt.Println("Empty result")
	}

	resp, err := http.Get(m.Result)
	if err != nil {
		err = fmt.Errorf("bad net/http answer for %s: %v", m.Result, err)
		return err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		err = fmt.Errorf("error reading body for %s: %v", m.Result, err)
		return err
	}

	fmt.Print(displayResult(body, fVerbose))
	return nil
}

func measurementCreate(c *cli.Context) error {
	return nil
}

func measurementDelete(c *cli.Context) (err error) {
	var id int64

	if fAllMeasurements {
		opts := make(map[string]string)

		// Check global parameters
		opts = checkGlobalFlags(opts)

		list, err := atlas.GetMeasurements(opts)
		if err != nil {
			err = fmt.Errorf("Delete all failed: %v", err)
		} else {
			for _, m := range list {
				err = atlas.DeleteMeasurement(m.ID)
				if err != nil {
					err = fmt.Errorf("Error: can not delete measurement %d", m.ID)
				}
			}
			fmt.Printf("All measurements stopped.")
		}
	} else {
		args := c.Args()
		if args[0] == "" {
			log.Fatalf("Error: you must specify a measurement ID!")
		}

		id, _ = strconv.ParseInt(args[0], 10, 32)
		err = atlas.DeleteMeasurement(int(id))
	}

	return
}
<|endoftext|>