<commit_before>package api

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/grafana/grafana/pkg/api/cloudwatch"
	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/metrics"
	"github.com/grafana/grafana/pkg/middleware"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/grafana/grafana/pkg/util"
)

var (
	auditLogger log.Logger = log.New("data-proxy-log")
)

func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy {
	director := func(req *http.Request) {
		req.URL.Scheme = targetUrl.Scheme
		req.URL.Host = targetUrl.Host
		req.Host = targetUrl.Host

		reqQueryVals := req.URL.Query()

		if ds.Type == m.DS_INFLUXDB_08 {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, "db/"+ds.Database+"/"+proxyPath)
			reqQueryVals.Add("u", ds.User)
			reqQueryVals.Add("p", ds.Password)
			req.URL.RawQuery = reqQueryVals.Encode()
		} else if ds.Type == m.DS_INFLUXDB {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
			req.URL.RawQuery = reqQueryVals.Encode()
			if !ds.BasicAuth {
				req.Header.Del("Authorization")
				req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.User, ds.Password))
			}
		} else {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
		}

		if ds.BasicAuth {
			req.Header.Del("Authorization")
			req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword))
		}

		dsAuth := req.Header.Get("X-DS-Authorization")
		if len(dsAuth) > 0 {
			req.Header.Del("X-DS-Authorization")
			req.Header.Del("Authorization")
			req.Header.Add("Authorization", dsAuth)
		}

		// clear cookie headers
		req.Header.Del("Cookie")
		req.Header.Del("Set-Cookie")
	}

	return &httputil.ReverseProxy{Director: director, FlushInterval: time.Millisecond * 200}
}

func getDatasource(id int64, orgId int64) (*m.DataSource, error) {
	query := m.GetDataSourceByIdQuery{Id: id, OrgId: orgId}
	if err := bus.Dispatch(&query); err != nil {
		return nil, err
	}

	return query.Result, nil
}

func ProxyDataSourceRequest(c *middleware.Context) {
	c.TimeRequest(metrics.M_DataSource_ProxyReq_Timer)

	ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId)

	if err != nil {
		c.JsonApiErr(500, "Unable to load datasource meta data", err)
		return
	}

	if ds.Type == m.DS_CLOUDWATCH {
		cloudwatch.HandleRequest(c, ds)
		return
	}

	if ds.Type == m.DS_INFLUXDB {
		if c.Query("db") != ds.Database {
			c.JsonApiErr(403, "Datasource is not configured to allow this database", nil)
			return
		}
	}

	targetUrl, _ := url.Parse(ds.Url)
	if len(setting.DataProxyWhiteList) > 0 {
		if _, exists := setting.DataProxyWhiteList[targetUrl.Host]; !exists {
			c.JsonApiErr(403, "Data proxy hostname and ip are not included in whitelist", nil)
			return
		}
	}

	proxyPath := c.Params("*")

	if ds.Type == m.DS_ES {
		if c.Req.Request.Method == "DELETE" {
			c.JsonApiErr(403, "Deletes not allowed on proxied Elasticsearch datasource", nil)
			return
		}
		if c.Req.Request.Method == "PUT" {
			c.JsonApiErr(403, "Puts not allowed on proxied Elasticsearch datasource", nil)
			return
		}
		if c.Req.Request.Method == "POST" && proxyPath != "_msearch" {
			c.JsonApiErr(403, "Posts not allowed on proxied Elasticsearch datasource except on /_msearch", nil)
			return
		}
	}

	proxy := NewReverseProxy(ds, proxyPath, targetUrl)
	proxy.Transport, err = ds.GetHttpTransport()
	if err != nil {
		c.JsonApiErr(400, "Unable to load TLS certificate", err)
		return
	}

	proxyLog(ds.Type, c)

	proxy.ServeHTTP(c.Resp, c.Req.Request)
	c.Resp.Header().Del("Set-Cookie")
}

func proxyLog(dataSourceType string, c *middleware.Context) {
	if setting.DataProxyLogging {

		var body string
		if c.Req.Request.Body != nil {
			buffer, _ := ioutil.ReadAll(c.Req.Request.Body)
			c.Req.Request.Body = ioutil.NopCloser(bytes.NewBuffer(buffer))
			body = string(buffer)
		}

		auditLogger.Info("Proxying incoming request",
			"userid", c.UserId,
			"orgid", c.OrgId,
			"username", c.Login,
			"datasource", dataSourceType,
			"uri", c.Req.RequestURI,
			"method", c.Req.Request.Method,
			"body", body)
	}
}
<commit_msg>style(dataproxy): renames log functions<commit_after>package api

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/grafana/grafana/pkg/api/cloudwatch"
	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/metrics"
	"github.com/grafana/grafana/pkg/middleware"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/grafana/grafana/pkg/util"
)

var (
	dataproxyLogger log.Logger = log.New("data-proxy-log")
)

func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy {
	director := func(req *http.Request) {
		req.URL.Scheme = targetUrl.Scheme
		req.URL.Host = targetUrl.Host
		req.Host = targetUrl.Host

		reqQueryVals := req.URL.Query()

		if ds.Type == m.DS_INFLUXDB_08 {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, "db/"+ds.Database+"/"+proxyPath)
			reqQueryVals.Add("u", ds.User)
			reqQueryVals.Add("p", ds.Password)
			req.URL.RawQuery = reqQueryVals.Encode()
		} else if ds.Type == m.DS_INFLUXDB {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
			req.URL.RawQuery = reqQueryVals.Encode()
			if !ds.BasicAuth {
				req.Header.Del("Authorization")
				req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.User, ds.Password))
			}
		} else {
			req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
		}

		if ds.BasicAuth {
			req.Header.Del("Authorization")
			req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword))
		}

		dsAuth := req.Header.Get("X-DS-Authorization")
		if len(dsAuth) > 0 {
			req.Header.Del("X-DS-Authorization")
			req.Header.Del("Authorization")
			req.Header.Add("Authorization", dsAuth)
		}

		// clear cookie headers
		req.Header.Del("Cookie")
		req.Header.Del("Set-Cookie")
	}

	return &httputil.ReverseProxy{Director: director, FlushInterval: time.Millisecond * 200}
}

func getDatasource(id int64, orgId int64) (*m.DataSource, error) {
	query := m.GetDataSourceByIdQuery{Id: id, OrgId: orgId}
	if err := bus.Dispatch(&query); err != nil {
		return nil, err
	}

	return query.Result, nil
}

func ProxyDataSourceRequest(c *middleware.Context) {
	c.TimeRequest(metrics.M_DataSource_ProxyReq_Timer)

	ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId)

	if err != nil {
		c.JsonApiErr(500, "Unable to load datasource meta data", err)
		return
	}

	if ds.Type == m.DS_CLOUDWATCH {
		cloudwatch.HandleRequest(c, ds)
		return
	}

	if ds.Type == m.DS_INFLUXDB {
		if c.Query("db") != ds.Database {
			c.JsonApiErr(403, "Datasource is not configured to allow this database", nil)
			return
		}
	}

	targetUrl, _ := url.Parse(ds.Url)
	if len(setting.DataProxyWhiteList) > 0 {
		if _, exists := setting.DataProxyWhiteList[targetUrl.Host]; !exists {
			c.JsonApiErr(403, "Data proxy hostname and ip are not included in whitelist", nil)
			return
		}
	}

	proxyPath := c.Params("*")

	if ds.Type == m.DS_ES {
		if c.Req.Request.Method == "DELETE" {
			c.JsonApiErr(403, "Deletes not allowed on proxied Elasticsearch datasource", nil)
			return
		}
		if c.Req.Request.Method == "PUT" {
			c.JsonApiErr(403, "Puts not allowed on proxied Elasticsearch datasource", nil)
			return
		}
		if c.Req.Request.Method == "POST" && proxyPath != "_msearch" {
			c.JsonApiErr(403, "Posts not allowed on proxied Elasticsearch datasource except on /_msearch", nil)
			return
		}
	}

	proxy := NewReverseProxy(ds, proxyPath, targetUrl)
	proxy.Transport, err = ds.GetHttpTransport()
	if err != nil {
		c.JsonApiErr(400, "Unable to load TLS certificate", err)
		return
	}

	logProxyRequest(ds.Type, c)
	proxy.ServeHTTP(c.Resp, c.Req.Request)
	c.Resp.Header().Del("Set-Cookie")
}

func logProxyRequest(dataSourceType string, c *middleware.Context) {
	if !setting.DataProxyLogging {
		return
	}

		var body string
		if c.Req.Request.Body != nil {
			buffer, _ := ioutil.ReadAll(c.Req.Request.Body)
			c.Req.Request.Body = ioutil.NopCloser(bytes.NewBuffer(buffer))
			body = string(buffer)
		}
	}

	dataproxyLogger.Info("Proxying incoming request",
		"userid", c.UserId,
		"orgid", c.OrgId,
		"username", c.Login,
		"datasource", dataSourceType,
		"uri", c.Req.RequestURI,
		"method", c.Req.Request.Method,
		"body", body)
}
<|endoftext|>


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

package build

import (
	"fmt"
	"os"
	"path"

	"istio.io/release-builder/pkg/model"
	"istio.io/release-builder/pkg/util"
)

// Archive creates the release archive that users will download. This includes the installation templates,
// istioctl, and various tools.
func Archive(manifest model.Manifest) error {
	// First, build all variants of istioctl (linux, osx, windows)
	if err := util.RunMake(manifest, "istio", nil, "istioctl-all", "istioctl.completion"); err != nil {
		return fmt.Errorf("failed to make istioctl: %v", err)
	}
	// Generate the demo rendered yaml file
	if err := util.RunMake(manifest, "istio", nil, "istio-demo.yaml"); err != nil {
		return fmt.Errorf("failed to make istio-demo.yaml: %v", err)
	}

	// We build archives for each arch. These contain the same thing except arch specific istioctl
	for _, arch := range []string{"linux", "osx", "win"} {
		out := path.Join(manifest.Directory, "work", "archive", arch, fmt.Sprintf("istio-%s", manifest.Version))
		if err := os.MkdirAll(out, 0750); err != nil {
			return err
		}

		// Some files we just directly copy into the release archive
		directCopies := []string{
			"LICENSE",
			"README.md",

			// Setup tools. The tools/ folder contains a bunch of extra junk, so just select exactly what we want
			"tools/convert_RbacConfig_to_ClusterRbacConfig.sh",
			"tools/dump_kubernetes.sh",
		}
		for _, file := range directCopies {
			if err := util.CopyFile(path.Join(manifest.RepoDir("istio"), file), path.Join(out, file)); err != nil {
				return err
			}
		}

		// Set up install and samples. We filter down to only some file patterns
		// TODO - clean this up. We probably include files we don't want and exclude files we do want.
		includePatterns := []string{"*.yaml", "*.md", "cleanup.sh", "*.txt", "*.pem", "*.conf", "*.tpl", "*.json"}
		if err := util.CopyDirFiltered(path.Join(manifest.RepoDir("istio"), "samples"), path.Join(out, "samples"), includePatterns); err != nil {
			return err
		}
		if err := util.CopyDirFiltered(path.Join(manifest.RepoDir("istio"), "install"), path.Join(out, "install"), includePatterns); err != nil {
			return err
		}

		cniSource := path.Join(manifest.RepoDir("cni"), "deployments/kubernetes/install/helm/istio-cni")
		if err := util.CopyDirFiltered(cniSource, path.Join(out, "install/kubernetes/helm"), includePatterns); err != nil {
			return err
		}

		cmd := util.VerboseCommand("./release/create_release_charts.sh", "-o", path.Join(out, "install/kubernetes/operator"))
		cmd.Dir = manifest.RepoDir("operator")
		cmd.Env = util.StandardEnv(manifest)
		if err := cmd.Run(); err != nil {
			return err
		}
		if err := sanitizeTemplate(manifest, path.Join(out, "install/kubernetes/operator/profiles/default.yaml")); err != nil {
			return fmt.Errorf("failed to sanitize charts")
		}
		if err := util.CopyDir(path.Join(manifest.RepoDir("operator"), "deploy"), path.Join(out, "install/kubernetes/operator/deploy")); err != nil {
			return err
		}
		if err := sanitizeTemplate(manifest, path.Join(out, "install/kubernetes/operator/deploy/operator.yaml")); err != nil {
			return fmt.Errorf("failed to sanitize operator manifest")
		}
		if err := util.CopyDir(path.Join(manifest.RepoDir("operator"), "samples"), path.Join(out, "samples/operator")); err != nil {
			return err
		}

		// Write manifest
		if err := writeManifest(manifest, out); err != nil {
			return fmt.Errorf("failed to write manifest: %v", err)
		}

		// Copy the istioctl binary over
		istioctlBinary := fmt.Sprintf("istioctl-%s", arch)
		istioctlDest := "istioctl"
		if arch == "win" {
			istioctlBinary += ".exe"
			istioctlDest += ".exe"
		}
		if err := util.CopyFile(path.Join(manifest.GoOutDir(), istioctlBinary), path.Join(out, "bin", istioctlDest)); err != nil {
			return err
		}
		if err := os.Chmod(path.Join(out, "bin", istioctlDest), 0755); err != nil {
			return err
		}

		// Copy the istioctl completions files to the tools directory
		completionFiles := []string{"istioctl.bash", "_istioctl"}
		for _, file := range completionFiles {
			if err := util.CopyFile(path.Join(manifest.GoOutDir(), file), path.Join(out, "tools", file)); err != nil {
				return err
			}
		}

		if err := createArchive(arch, manifest, out); err != nil {
			return err
		}

		if err := createStandaloneIstioctl(arch, manifest, out); err != nil {
			return err
		}
	}
	return nil
}

func createStandaloneIstioctl(arch string, manifest model.Manifest, out string) error {
	var istioctlArchive string
	// Create a stand alone archive for istioctl
	// Windows should use zip, linux and osx tar
	if arch == "win" {
		istioctlArchive = fmt.Sprintf("istioctl-%s-%s.zip", manifest.Version, arch)
		if err := util.ZipFolder(path.Join(out, "bin", "istioctl.exe"), path.Join(out, "bin", istioctlArchive)); err != nil {
			return fmt.Errorf("failed to zip istioctl: %v", err)
		}
	} else {
		istioctlArchive = fmt.Sprintf("istioctl-%s-%s.tar.gz", manifest.Version, arch)
		icmd := util.VerboseCommand("tar", "-czf", istioctlArchive, fmt.Sprintf("istioctl"))
		icmd.Dir = path.Join(out, "bin")
		if err := icmd.Run(); err != nil {
			return fmt.Errorf("failed to tar istioctl: %v", err)
		}
	}
	// Copy files over to the output directory
	archivePath := path.Join(out, "bin", istioctlArchive)
	dest := path.Join(manifest.OutDir(), istioctlArchive)
	if err := util.CopyFile(archivePath, dest); err != nil {
		return fmt.Errorf("failed to package %v release archive: %v", arch, err)
	}

	// Create a SHA of the archive
	if err := util.CreateSha(dest); err != nil {
		return fmt.Errorf("failed to package %v: %v", dest, err)
	}
	return nil
}

func createArchive(arch string, manifest model.Manifest, out string) error {
	var archive string
	// Create the archive from all the above files
	// Windows should use zip, linux and osx tar
	if arch == "win" {
		archive = fmt.Sprintf("istio-%s-%s.zip", manifest.Version, arch)
		if err := util.ZipFolder(path.Join(out, "..", fmt.Sprintf("istio-%s", manifest.Version)), path.Join(out, "..", archive)); err != nil {
			return fmt.Errorf("failed to zip istioctl: %v", err)
		}
	} else {
		archive = fmt.Sprintf("istio-%s-%s.tar.gz", manifest.Version, arch)
		cmd := util.VerboseCommand("tar", "-czf", archive, fmt.Sprintf("istio-%s", manifest.Version))
		cmd.Dir = path.Join(out, "..")
		if err := cmd.Run(); err != nil {
			return err
		}
	}

	// Copy files over to the output directory
	archivePath := path.Join(manifest.WorkDir(), "archive", arch, archive)
	dest := path.Join(manifest.OutDir(), archive)
	if err := util.CopyFile(archivePath, dest); err != nil {
		return fmt.Errorf("failed to package %v release archive: %v", arch, err)
	}
	// Create a SHA of the archive
	if err := util.CreateSha(dest); err != nil {
		return fmt.Errorf("failed to package %v: %v", dest, err)
	}
	return nil
}
<commit_msg>Package istioctl in new makefile model (#106)<commit_after>// Copyright Istio Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package build

import (
	"fmt"
	"os"
	"path"

	"istio.io/release-builder/pkg/model"
	"istio.io/release-builder/pkg/util"
)

// Archive creates the release archive that users will download. This includes the installation templates,
// istioctl, and various tools.
func Archive(manifest model.Manifest) error {
	// First, build all variants of istioctl (linux, osx, windows)
	if err := util.RunMake(manifest, "istio", nil, "istioctl-all", "istioctl.completion"); err != nil {
		return fmt.Errorf("failed to make istioctl: %v", err)
	}
	// Generate the demo rendered yaml file
	if err := util.RunMake(manifest, "istio", nil, "istio-demo.yaml"); err != nil {
		return fmt.Errorf("failed to make istio-demo.yaml: %v", err)
	}

	// We build archives for each arch. These contain the same thing except arch specific istioctl
	for _, arch := range []string{"linux", "osx", "win"} {
		out := path.Join(manifest.Directory, "work", "archive", arch, fmt.Sprintf("istio-%s", manifest.Version))
		if err := os.MkdirAll(out, 0750); err != nil {
			return err
		}

		// Some files we just directly copy into the release archive
		directCopies := []string{
			"LICENSE",
			"README.md",

			// Setup tools. The tools/ folder contains a bunch of extra junk, so just select exactly what we want
			"tools/convert_RbacConfig_to_ClusterRbacConfig.sh",
			"tools/dump_kubernetes.sh",
		}
		for _, file := range directCopies {
			if err := util.CopyFile(path.Join(manifest.RepoDir("istio"), file), path.Join(out, file)); err != nil {
				return err
			}
		}

		// Set up install and samples. We filter down to only some file patterns
		// TODO - clean this up. We probably include files we don't want and exclude files we do want.
		includePatterns := []string{"*.yaml", "*.md", "cleanup.sh", "*.txt", "*.pem", "*.conf", "*.tpl", "*.json"}
		if err := util.CopyDirFiltered(path.Join(manifest.RepoDir("istio"), "samples"), path.Join(out, "samples"), includePatterns); err != nil {
			return err
		}
		if err := util.CopyDirFiltered(path.Join(manifest.RepoDir("istio"), "install"), path.Join(out, "install"), includePatterns); err != nil {
			return err
		}

		cniSource := path.Join(manifest.RepoDir("cni"), "deployments/kubernetes/install/helm/istio-cni")
		if err := util.CopyDirFiltered(cniSource, path.Join(out, "install/kubernetes/helm"), includePatterns); err != nil {
			return err
		}

		cmd := util.VerboseCommand("./release/create_release_charts.sh", "-o", path.Join(out, "install/kubernetes/operator"))
		cmd.Dir = manifest.RepoDir("operator")
		cmd.Env = util.StandardEnv(manifest)
		if err := cmd.Run(); err != nil {
			return err
		}
		if err := sanitizeTemplate(manifest, path.Join(out, "install/kubernetes/operator/profiles/default.yaml")); err != nil {
			return fmt.Errorf("failed to sanitize charts")
		}
		if err := util.CopyDir(path.Join(manifest.RepoDir("operator"), "deploy"), path.Join(out, "install/kubernetes/operator/deploy")); err != nil {
			return err
		}
		if err := sanitizeTemplate(manifest, path.Join(out, "install/kubernetes/operator/deploy/operator.yaml")); err != nil {
			return fmt.Errorf("failed to sanitize operator manifest")
		}
		if err := util.CopyDir(path.Join(manifest.RepoDir("operator"), "samples"), path.Join(out, "samples/operator")); err != nil {
			return err
		}

		// Write manifest
		if err := writeManifest(manifest, out); err != nil {
			return fmt.Errorf("failed to write manifest: %v", err)
		}

		// Copy the istioctl binary over
		istioctlBinary := fmt.Sprintf("istioctl-%s", arch)
		istioctlDest := "istioctl"
		if arch == "win" {
			istioctlBinary += ".exe"
			istioctlDest += ".exe"
		}
		if err := util.CopyFile(path.Join(manifest.RepoOutDir("istio"), istioctlBinary), path.Join(out, "bin", istioctlDest)); err != nil {
			return err
		}
		if err := os.Chmod(path.Join(out, "bin", istioctlDest), 0755); err != nil {
			return err
		}

		// Copy the istioctl completions files to the tools directory
		completionFiles := []string{"istioctl.bash", "_istioctl"}
		for _, file := range completionFiles {
			if err := util.CopyFile(path.Join(manifest.GoOutDir(), file), path.Join(out, "tools", file)); err != nil {
				return err
			}
		}

		if err := createArchive(arch, manifest, out); err != nil {
			return err
		}

		if err := createStandaloneIstioctl(arch, manifest, out); err != nil {
			return err
		}
	}
	return nil
}

func createStandaloneIstioctl(arch string, manifest model.Manifest, out string) error {
	var istioctlArchive string
	// Create a stand alone archive for istioctl
	// Windows should use zip, linux and osx tar
	if arch == "win" {
		istioctlArchive = fmt.Sprintf("istioctl-%s-%s.zip", manifest.Version, arch)
		if err := util.ZipFolder(path.Join(out, "bin", "istioctl.exe"), path.Join(out, "bin", istioctlArchive)); err != nil {
			return fmt.Errorf("failed to zip istioctl: %v", err)
		}
	} else {
		istioctlArchive = fmt.Sprintf("istioctl-%s-%s.tar.gz", manifest.Version, arch)
		icmd := util.VerboseCommand("tar", "-czf", istioctlArchive, fmt.Sprintf("istioctl"))
		icmd.Dir = path.Join(out, "bin")
		if err := icmd.Run(); err != nil {
			return fmt.Errorf("failed to tar istioctl: %v", err)
		}
	}
	// Copy files over to the output directory
	archivePath := path.Join(out, "bin", istioctlArchive)
	dest := path.Join(manifest.OutDir(), istioctlArchive)
	if err := util.CopyFile(archivePath, dest); err != nil {
		return fmt.Errorf("failed to package %v release archive: %v", arch, err)
	}

	// Create a SHA of the archive
	if err := util.CreateSha(dest); err != nil {
		return fmt.Errorf("failed to package %v: %v", dest, err)
	}
	return nil
}

func createArchive(arch string, manifest model.Manifest, out string) error {
	var archive string
	// Create the archive from all the above files
	// Windows should use zip, linux and osx tar
	if arch == "win" {
		archive = fmt.Sprintf("istio-%s-%s.zip", manifest.Version, arch)
		if err := util.ZipFolder(path.Join(out, "..", fmt.Sprintf("istio-%s", manifest.Version)), path.Join(out, "..", archive)); err != nil {
			return fmt.Errorf("failed to zip istioctl: %v", err)
		}
	} else {
		archive = fmt.Sprintf("istio-%s-%s.tar.gz", manifest.Version, arch)
		cmd := util.VerboseCommand("tar", "-czf", archive, fmt.Sprintf("istio-%s", manifest.Version))
		cmd.Dir = path.Join(out, "..")
		if err := cmd.Run(); err != nil {
			return err
		}
	}

	// Copy files over to the output directory
	archivePath := path.Join(manifest.WorkDir(), "archive", arch, archive)
	dest := path.Join(manifest.OutDir(), archive)
	if err := util.CopyFile(archivePath, dest); err != nil {
		return fmt.Errorf("failed to package %v release archive: %v", arch, err)
	}
	// Create a SHA of the archive
	if err := util.CreateSha(dest); err != nil {
		return fmt.Errorf("failed to package %v: %v", dest, err)
	}
	return nil
}
<|endoftext|>


<commit_before>package build

import (
	"github.com/openshift/source-to-image/pkg/api"
	"github.com/openshift/source-to-image/pkg/docker"
	"github.com/openshift/source-to-image/pkg/util"
	utilglog "github.com/openshift/source-to-image/pkg/util/glog"
)

var glog = utilglog.StderrLog

// DefaultCleaner provides a cleaner for most STI build use-cases. It cleans the
// temporary directories created by STI build and it also cleans the temporary
// Docker images produced by LayeredBuild
type DefaultCleaner struct {
	fs     util.FileSystem
	docker docker.Docker
}

// NewDefaultCleaner creates a new instance of the default Cleaner implementation
func NewDefaultCleaner(fs util.FileSystem, docker docker.Docker) Cleaner {
	return &DefaultCleaner{
		fs:     fs,
		docker: docker,
	}
}

// Cleanup removes the temporary directories where the sources were stored for build.
func (c *DefaultCleaner) Cleanup(config *api.Config) {
	if config.PreserveWorkingDir {
		glog.Infof("Temporary directory %q will be saved, not deleted", config.WorkingDir)
	} else {
		glog.V(2).Infof("Removing temporary directory %s", config.WorkingDir)
		if err := c.fs.RemoveDirectory(config.WorkingDir); err != nil {
			glog.Warningf("Error removing temporary directory %q: %v", config.WorkingDir, err)
		}
	}
	if config.LayeredBuild {
		// config.LayeredBuild is true only when layered build was finished successfully.
		// Also in this case config.BuilderImage contains name of the new just built image,
		// not the original one that was specified by the user.
		glog.V(2).Infof("Removing temporary image %s", config.BuilderImage)
		if err := c.docker.RemoveImage(config.BuilderImage); err != nil {
			glog.Warningf("Error removing temporary image %s: %v", config.BuilderImage, err)
		}
	}
}
<commit_msg>reduce loglevel of temp directory cleanup message<commit_after>package build

import (
	"github.com/openshift/source-to-image/pkg/api"
	"github.com/openshift/source-to-image/pkg/docker"
	"github.com/openshift/source-to-image/pkg/util"
	utilglog "github.com/openshift/source-to-image/pkg/util/glog"
)

var glog = utilglog.StderrLog

// DefaultCleaner provides a cleaner for most STI build use-cases. It cleans the
// temporary directories created by STI build and it also cleans the temporary
// Docker images produced by LayeredBuild
type DefaultCleaner struct {
	fs     util.FileSystem
	docker docker.Docker
}

// NewDefaultCleaner creates a new instance of the default Cleaner implementation
func NewDefaultCleaner(fs util.FileSystem, docker docker.Docker) Cleaner {
	return &DefaultCleaner{
		fs:     fs,
		docker: docker,
	}
}

// Cleanup removes the temporary directories where the sources were stored for build.
func (c *DefaultCleaner) Cleanup(config *api.Config) {
	if config.PreserveWorkingDir {
		glog.V(2).Infof("Temporary directory %q will be saved, not deleted", config.WorkingDir)
	} else {
		glog.V(2).Infof("Removing temporary directory %s", config.WorkingDir)
		if err := c.fs.RemoveDirectory(config.WorkingDir); err != nil {
			glog.Warningf("Error removing temporary directory %q: %v", config.WorkingDir, err)
		}
	}
	if config.LayeredBuild {
		// config.LayeredBuild is true only when layered build was finished successfully.
		// Also in this case config.BuilderImage contains name of the new just built image,
		// not the original one that was specified by the user.
		glog.V(2).Infof("Removing temporary image %s", config.BuilderImage)
		if err := c.docker.RemoveImage(config.BuilderImage); err != nil {
			glog.Warningf("Error removing temporary image %s: %v", config.BuilderImage, err)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package build

import (
	"fmt"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/google/syzkaller/pkg/osutil"
)

type freebsd struct{}

func (ctx freebsd) build(params *Params) error {
	confDir := fmt.Sprintf("%v/sys/%v/conf/", params.KernelDir, params.TargetArch)
	confFile := "SYZKALLER"

	config := params.Config
	if config == nil {
		config = []byte(`
include "./GENERIC"

ident		SYZKALLER
options 	COVERAGE
options 	KCOV

options 	TCPHPTS
options 	RATELIMIT

options 	DEBUG_VFS_LOCKS
options 	DIAGNOSTIC
options 	DEBUG_REDZONE
`)
	}
	if err := osutil.WriteFile(filepath.Join(confDir, confFile), config); err != nil {
		return err
	}

	objPrefix := filepath.Join(params.KernelDir, "obj")
	if err := ctx.make(params.KernelDir, objPrefix, "kernel-toolchain", "-DNO_CLEAN"); err != nil {
		return err
	}
	if err := ctx.make(params.KernelDir, objPrefix, "buildkernel", "WITH_EXTRA_TCP_STACKS=",
		fmt.Sprintf("KERNCONF=%v", confFile)); err != nil {
		return err
	}

	kernelObjDir := filepath.Join(objPrefix, params.KernelDir,
		fmt.Sprintf("%v.%v", params.TargetArch, params.TargetArch), "sys", confFile)
	for _, s := range []struct{ dir, src, dst string }{
		{params.UserspaceDir, "image", "image"},
		{params.UserspaceDir, "key", "key"},
		{kernelObjDir, "kernel.full", "obj/kernel.full"},
	} {
		fullSrc := filepath.Join(s.dir, s.src)
		fullDst := filepath.Join(params.OutputDir, s.dst)
		if err := osutil.CopyFile(fullSrc, fullDst); err != nil {
			return fmt.Errorf("failed to copy %v -> %v: %v", fullSrc, fullDst, err)
		}
	}

	script := fmt.Sprintf(`
set -eux
md=$(sudo mdconfig -a -t vnode image)
partn=$(gpart show /dev/${md} | awk '/freebsd-ufs/{print $3}' | head -n 1)
tmpdir=$(mktemp -d)
sudo mount /dev/${md}p${partn} $tmpdir

sudo MAKEOBJDIRPREFIX=%s make -C %s installkernel WITH_EXTRA_TCP_STACKS= KERNCONF=%s DESTDIR=$tmpdir

cat | sudo tee ${tmpdir}/boot/loader.conf.local <<__EOF__
ipsec_load="YES"
pf_load="YES"
sctp_load="YES"
tcp_bbr_load="YES"
tcp_rack_load="YES"
sem_load="YES"
mqueuefs_load="YES"
cryptodev_load="YES"
cc_cdg_load="YES"
cc_chd_load="YES"
cc_cubic_load="YES"
cc_dctcp_load="YES"
cc_hd_load="YES"
cc_htcp_load="YES"
cc_vegas_load="YES"

kern.ipc.tls.enable="1"
vm.panic_on_oom="1"
__EOF__

cat | sudo tee -a ${tmpdir}/etc/sysctl.conf <<__EOF__
net.inet.sctp.udp_tunneling_port=9899
net.inet.tcp.udp_tunneling_port=9811
vm.redzone.panic=1
__EOF__

sudo umount $tmpdir
sudo mdconfig -d -u ${md#md}
`, objPrefix, params.KernelDir, confFile)

	if debugOut, err := osutil.RunCmd(10*time.Minute, params.OutputDir, "/bin/sh", "-c", script); err != nil {
		return fmt.Errorf("error copying kernel: %v\n%v", err, debugOut)
	}
	return nil
}

func (ctx freebsd) clean(kernelDir, targetArch string) error {
	objPrefix := filepath.Join(kernelDir, "obj")
	return ctx.make(kernelDir, objPrefix, "cleanworld")
}

func (ctx freebsd) make(kernelDir, objPrefix string, makeArgs ...string) error {
	args := append([]string{
		fmt.Sprintf("MAKEOBJDIRPREFIX=%v", objPrefix),
		"make",
		"-C", kernelDir,
		"-j", strconv.Itoa(runtime.NumCPU()),
	}, makeArgs...)
	_, err := osutil.RunCmd(3*time.Hour, kernelDir, "sh", "-c", strings.Join(args, " "))
	return err
}
<commit_msg>pkg/build: enable KASAN in the default FreeBSD kernel config<commit_after>// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package build

import (
	"fmt"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/google/syzkaller/pkg/osutil"
)

type freebsd struct{}

func (ctx freebsd) build(params *Params) error {
	confDir := fmt.Sprintf("%v/sys/%v/conf/", params.KernelDir, params.TargetArch)
	confFile := "SYZKALLER"

	config := params.Config
	if config == nil {
		config = []byte(`
include "./GENERIC"

ident		SYZKALLER
options 	COVERAGE
options 	KCOV
options 	KASAN

options 	TCPHPTS
options 	RATELIMIT

options 	DEBUG_VFS_LOCKS
options 	DIAGNOSTIC
options 	DEBUG_REDZONE
`)
	}
	if err := osutil.WriteFile(filepath.Join(confDir, confFile), config); err != nil {
		return err
	}

	objPrefix := filepath.Join(params.KernelDir, "obj")
	if err := ctx.make(params.KernelDir, objPrefix, "kernel-toolchain", "-DNO_CLEAN"); err != nil {
		return err
	}
	if err := ctx.make(params.KernelDir, objPrefix, "buildkernel", "WITH_EXTRA_TCP_STACKS=",
		fmt.Sprintf("KERNCONF=%v", confFile)); err != nil {
		return err
	}

	kernelObjDir := filepath.Join(objPrefix, params.KernelDir,
		fmt.Sprintf("%v.%v", params.TargetArch, params.TargetArch), "sys", confFile)
	for _, s := range []struct{ dir, src, dst string }{
		{params.UserspaceDir, "image", "image"},
		{params.UserspaceDir, "key", "key"},
		{kernelObjDir, "kernel.full", "obj/kernel.full"},
	} {
		fullSrc := filepath.Join(s.dir, s.src)
		fullDst := filepath.Join(params.OutputDir, s.dst)
		if err := osutil.CopyFile(fullSrc, fullDst); err != nil {
			return fmt.Errorf("failed to copy %v -> %v: %v", fullSrc, fullDst, err)
		}
	}

	script := fmt.Sprintf(`
set -eux
md=$(sudo mdconfig -a -t vnode image)
partn=$(gpart show /dev/${md} | awk '/freebsd-ufs/{print $3}' | head -n 1)
tmpdir=$(mktemp -d)
sudo mount /dev/${md}p${partn} $tmpdir

sudo MAKEOBJDIRPREFIX=%s make -C %s installkernel WITH_EXTRA_TCP_STACKS= KERNCONF=%s DESTDIR=$tmpdir

cat | sudo tee ${tmpdir}/boot/loader.conf.local <<__EOF__
ipsec_load="YES"
pf_load="YES"
sctp_load="YES"
tcp_bbr_load="YES"
tcp_rack_load="YES"
sem_load="YES"
mqueuefs_load="YES"
cryptodev_load="YES"
cc_cdg_load="YES"
cc_chd_load="YES"
cc_cubic_load="YES"
cc_dctcp_load="YES"
cc_hd_load="YES"
cc_htcp_load="YES"
cc_vegas_load="YES"

kern.ipc.tls.enable="1"
vm.panic_on_oom="1"
__EOF__

cat | sudo tee -a ${tmpdir}/etc/sysctl.conf <<__EOF__
net.inet.sctp.udp_tunneling_port=9899
net.inet.tcp.udp_tunneling_port=9811
vm.redzone.panic=1
__EOF__

sudo umount $tmpdir
sudo mdconfig -d -u ${md#md}
`, objPrefix, params.KernelDir, confFile)

	if debugOut, err := osutil.RunCmd(10*time.Minute, params.OutputDir, "/bin/sh", "-c", script); err != nil {
		return fmt.Errorf("error copying kernel: %v\n%v", err, debugOut)
	}
	return nil
}

func (ctx freebsd) clean(kernelDir, targetArch string) error {
	objPrefix := filepath.Join(kernelDir, "obj")
	return ctx.make(kernelDir, objPrefix, "cleanworld")
}

func (ctx freebsd) make(kernelDir, objPrefix string, makeArgs ...string) error {
	args := append([]string{
		fmt.Sprintf("MAKEOBJDIRPREFIX=%v", objPrefix),
		"make",
		"-C", kernelDir,
		"-j", strconv.Itoa(runtime.NumCPU()),
	}, makeArgs...)
	_, err := osutil.RunCmd(3*time.Hour, kernelDir, "sh", "-c", strings.Join(args, " "))
	return err
}
<|endoftext|>


<commit_before>package cli

import (
	"encoding/json"

	"github.com/mobingilabs/mocli/pkg/iohelper"
	"github.com/mobingilabs/mocli/pkg/pretty"
)

type cliConfig struct {
	RunEnv  string `json:"runenv"`
	Verbose bool   `json:"verbose"`
}

func SetDefaultCliConfig(f string) error {
	defcfg := cliConfig{RunEnv: "prod"}
	contents, err := json.MarshalIndent(defcfg, "", pretty.Indent(3))
	if err != nil {
		return err
	}

	return iohelper.WriteToFile(f, contents)
}
<commit_msg>Make config public.<commit_after>package cli

import (
	"encoding/json"

	"github.com/mobingilabs/mocli/pkg/iohelper"
	"github.com/mobingilabs/mocli/pkg/pretty"
)

type CliConfig struct {
	RunEnv  string `json:"runenv"`
	Verbose bool   `json:"verbose"`
}

func SetDefaultCliConfig(f string) error {
	defcfg := CliConfig{RunEnv: "prod"}
	contents, err := json.MarshalIndent(defcfg, "", pretty.Indent(3))
	if err != nil {
		return err
	}

	return iohelper.WriteToFile(f, contents)
}
<|endoftext|>


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

package command

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
	"go.opencensus.io/trace"
	"go.uber.org/zap"

	"github.com/zchee/nvim-go/pkg/config"
	"github.com/zchee/nvim-go/pkg/fs"
	"github.com/zchee/nvim-go/pkg/logger"
	"github.com/zchee/nvim-go/pkg/monitoring"
	"github.com/zchee/nvim-go/pkg/nvimutil"
)

// CmdBuildEval struct type for Eval of GoBuild command.
type CmdBuildEval struct {
	Cwd  string `msgpack:",array"`
	File string
}

func (c *Command) cmdBuild(ctx context.Context, args []string, bang bool, eval *CmdBuildEval) {
	errch := make(chan interface{}, 1)
	go func() {
		errch <- c.Build(ctx, args, bang, eval)
	}()

	select {
	case <-ctx.Done():
		return
	case err := <-errch:
		switch e := err.(type) {
		case error:
			nvimutil.ErrorWrap(c.Nvim, e)
		case []*nvim.QuickfixError:
			c.errs.Store("Build", e)
			errlist := make(map[string][]*nvim.QuickfixError)
			c.errs.Range(func(ki, vi interface{}) bool {
				k, v := ki.(string), vi.([]*nvim.QuickfixError)
				errlist[k] = append(errlist[k], v...)
				return true
			})
			nvimutil.ErrorList(c.Nvim, errlist, true)
		case nil:
			// nothing to do
		}
	}
}

// Build builds the current buffers package use compile tool that determined
// from the package directory structure.
func (c *Command) Build(pctx context.Context, args []string, bang bool, eval *CmdBuildEval) interface{} {
	ctx, span := monitoring.StartSpan(pctx, "Build")
	defer span.End()

	log := logger.FromContext(ctx).With(zap.Strings("args", args), zap.Bool("bang", bang), zap.Any("CmdBuildEval", eval))
	if !bang {
		bang = config.BuildForce
	}

	cmd, err := c.compileCmd(ctx, args, bang, eval.Cwd)
	if err != nil {
		span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: err.Error()})
		return errors.WithStack(err)
	}
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	log.Debug("command.Build",
		zap.Strings("cmd.Args", cmd.Args),
		zap.String("cmd.Path", cmd.Path),
		zap.String("cmd.Dir", cmd.Dir),
		zap.Any("cmd.SysProcAttr", cmd.SysProcAttr),
		zap.Any("cmd.Process", cmd.Process),
		zap.Any("cmd.ProcessState", cmd.ProcessState))

	os.Unsetenv("GO111MODULE")

	if buildErr := cmd.Run(); buildErr != nil {
		if err, ok := buildErr.(*exec.ExitError); ok && err != nil {
			errlist, err := nvimutil.ParseError(ctx, stderr.Bytes(), eval.Cwd, &c.buildContext.Build, nil)
			if err != nil {
				span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: err.Error()})
				return errors.WithStack(err)
			}
			return errlist
		}
		span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: buildErr.Error()})
		return errors.WithStack(buildErr)
	}

	return nvimutil.EchoSuccess(c.Nvim, "GoBuild", fmt.Sprintf("compiler: %s", c.buildContext.Build.Tool))
}

// compileCmd returns the *exec.Cmd corresponding to the compile tool.
func (c *Command) compileCmd(pctx context.Context, args []string, bang bool, dir string) (*exec.Cmd, error) {
	ctx, span := monitoring.StartSpan(pctx, "compileCmd")
	defer span.End()

	bin, err := exec.LookPath(c.buildContext.Build.Tool)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	cmd := exec.CommandContext(ctx, bin, "build")
	cmd.Env = os.Environ()

	if len(config.BuildFlags) > 0 {
		args = append(args, config.BuildFlags...)
	}
	switch c.buildContext.Build.Tool {
	case "go":
		cmd.Dir = dir

		// Outputs the binary to DevNull if without bang
		if !bang || !matchSlice("-o", args) {
			args = append(args, "-o", os.DevNull)
		}
		// add "app" suffix to binary name if enable app-engine build
		if config.BuildAppengine {
			cmd.Args[0] += "app"
		}
	case "gb":
		cmd.Dir = c.buildContext.Build.ProjectRoot

		if config.BuildAppengine {
			cmd.Args = append([]string{cmd.Args[0], "gae"}, cmd.Args[1:]...)
			pkgs, err := fs.GbPackages(cmd.Dir)
			if err != nil {
				return nil, err
			}
			for _, pkg := range pkgs {
				// "gb gae build" doesn't compatible "gb build" arg. actually, "goapp build ..."
				cmd.Args = append(cmd.Args, pkg+string(filepath.Separator)+"...")
			}
		}
	}

	args = append(args, "./...")
	cmd.Args = append(cmd.Args, args...)

	return cmd, nil
}

func matchSlice(s string, ss []string) bool {
	for _, str := range ss {
		if s == str {
			return true
		}
	}
	return false
}
<commit_msg>pkg/command: move os.Unsetenv GO111MODULE to compileCmd<commit_after>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package command

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
	"go.opencensus.io/trace"
	"go.uber.org/zap"

	"github.com/zchee/nvim-go/pkg/config"
	"github.com/zchee/nvim-go/pkg/fs"
	"github.com/zchee/nvim-go/pkg/logger"
	"github.com/zchee/nvim-go/pkg/monitoring"
	"github.com/zchee/nvim-go/pkg/nvimutil"
)

// CmdBuildEval struct type for Eval of GoBuild command.
type CmdBuildEval struct {
	Cwd  string `msgpack:",array"`
	File string
}

func (c *Command) cmdBuild(ctx context.Context, args []string, bang bool, eval *CmdBuildEval) {
	errch := make(chan interface{}, 1)
	go func() {
		errch <- c.Build(ctx, args, bang, eval)
	}()

	select {
	case <-ctx.Done():
		return
	case err := <-errch:
		switch e := err.(type) {
		case error:
			nvimutil.ErrorWrap(c.Nvim, e)
		case []*nvim.QuickfixError:
			c.errs.Store("Build", e)
			errlist := make(map[string][]*nvim.QuickfixError)
			c.errs.Range(func(ki, vi interface{}) bool {
				k, v := ki.(string), vi.([]*nvim.QuickfixError)
				errlist[k] = append(errlist[k], v...)
				return true
			})
			nvimutil.ErrorList(c.Nvim, errlist, true)
		case nil:
			// nothing to do
		}
	}
}

// Build builds the current buffers package use compile tool that determined
// from the package directory structure.
func (c *Command) Build(pctx context.Context, args []string, bang bool, eval *CmdBuildEval) interface{} {
	ctx, span := monitoring.StartSpan(pctx, "Build")
	defer span.End()

	log := logger.FromContext(ctx).With(zap.Strings("args", args), zap.Bool("bang", bang), zap.Any("CmdBuildEval", eval))
	if !bang {
		bang = config.BuildForce
	}

	cmd, err := c.compileCmd(ctx, args, bang, eval.Cwd)
	if err != nil {
		span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: err.Error()})
		return errors.WithStack(err)
	}
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	log.Debug("command.Build",
		zap.Strings("cmd.Args", cmd.Args),
		zap.String("cmd.Path", cmd.Path),
		zap.String("cmd.Dir", cmd.Dir),
		zap.Any("cmd.SysProcAttr", cmd.SysProcAttr),
		zap.Any("cmd.Process", cmd.Process),
		zap.Any("cmd.ProcessState", cmd.ProcessState))

	if buildErr := cmd.Run(); buildErr != nil {
		if err, ok := buildErr.(*exec.ExitError); ok && err != nil {
			errlist, err := nvimutil.ParseError(ctx, stderr.Bytes(), eval.Cwd, &c.buildContext.Build, nil)
			if err != nil {
				span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: err.Error()})
				return errors.WithStack(err)
			}
			return errlist
		}
		span.SetStatus(trace.Status{Code: trace.StatusCodeInternal, Message: buildErr.Error()})
		return errors.WithStack(buildErr)
	}

	return nvimutil.EchoSuccess(c.Nvim, "GoBuild", fmt.Sprintf("compiler: %s", c.buildContext.Build.Tool))
}

// compileCmd returns the *exec.Cmd corresponding to the compile tool.
func (c *Command) compileCmd(pctx context.Context, args []string, bang bool, dir string) (*exec.Cmd, error) {
	ctx, span := monitoring.StartSpan(pctx, "compileCmd")
	defer span.End()

	bin, err := exec.LookPath(c.buildContext.Build.Tool)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	cmd := exec.CommandContext(ctx, bin, "build")
	cmd.Env = os.Environ()

	if len(config.BuildFlags) > 0 {
		args = append(args, config.BuildFlags...)
	}
	switch c.buildContext.Build.Tool {
	case "go":
		cmd.Dir = dir

		// Outputs the binary to DevNull if without bang
		if !bang || !matchSlice("-o", args) {
			args = append(args, "-o", os.DevNull)
		}
		// add "app" suffix to binary name if enable app-engine build
		if config.BuildAppengine {
			cmd.Args[0] += "app"
		}
		os.Unsetenv("GO111MODULE")
	case "gb":
		cmd.Dir = c.buildContext.Build.ProjectRoot

		if config.BuildAppengine {
			cmd.Args = append([]string{cmd.Args[0], "gae"}, cmd.Args[1:]...)
			pkgs, err := fs.GbPackages(cmd.Dir)
			if err != nil {
				return nil, err
			}
			for _, pkg := range pkgs {
				// "gb gae build" doesn't compatible "gb build" arg. actually, "goapp build ..."
				cmd.Args = append(cmd.Args, pkg+string(filepath.Separator)+"...")
			}
		}
	}

	args = append(args, "./...")
	cmd.Args = append(cmd.Args, args...)

	return cmd, nil
}

func matchSlice(s string, ss []string) bool {
	for _, str := range ss {
		if s == str {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google LLC

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

    https://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 config manages configuration of the whole application.
package config

import (
	"fmt"
	"os"
	"time"

	"cloud.google.com/go/compute/metadata"
	"github.com/golang/glog"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	compute "google.golang.org/api/compute/v0.beta"
	gcfg "gopkg.in/gcfg.v1"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
)

const (
	managedActive                        = "Active"
	managedEmpty                         = ""
	managedFailedCaaChecking             = "FailedCaaChecking"
	managedFailedCaaForbidden            = "FailedCaaForbidden"
	managedFailedNotVisible              = "FailedNotVisible"
	managedFailedRateLimited             = "FailedRateLimited"
	managedProvisioning                  = "Provisioning"
	managedProvisioningFailed            = "ProvisioningFailed"
	managedProvisioningFailedPermanently = "ProvisioningFailedPermanently"
	managedRenewalFailed                 = "RenewalFailed"

	SslCertificateNamePrefix = "mcrt-"

	sslActive                              = "ACTIVE"
	sslEmpty                               = ""
	sslFailedCaaChecking                   = "FAILED_CAA_CHECKING"
	sslFailedCaaForbidden                  = "FAILED_CAA_FORBIDDEN"
	sslFailedNotVisible                    = "FAILED_NOT_VISIBLE"
	sslFailedRateLimited                   = "FAILED_RATE_LIMITED"
	sslManagedCertificateStatusUnspecified = "MANAGED_CERTIFICATE_STATUS_UNSPECIFIED"
	sslProvisioning                        = "PROVISIONING"
	sslProvisioningFailed                  = "PROVISIONING_FAILED"
	sslProvisioningFailedPermanently       = "PROVISIONING_FAILED_PERMANENTLY"
	sslRenewalFailed                       = "RENEWAL_FAILED"
)

type computeConfig struct {
	TokenSource oauth2.TokenSource
	ProjectID   string
	Timeout     time.Duration
}

type certificateStatusConfig struct {
	// Certificate is a mapping from SslCertificate status to ManagedCertificate status
	Certificate map[string]string
	// Domain is a mapping from SslCertificate domain status to ManagedCertificate domain status
	Domain map[string]string
}

type Config struct {
	// CertificateStatus holds mappings of SslCertificate statuses to ManagedCertificate statuses
	CertificateStatus certificateStatusConfig
	// Compute is GCP-specific configuration
	Compute computeConfig
	// SslCertificateNamePrefix is a prefix prepended to SslCertificate resources created by the controller
	SslCertificateNamePrefix string
}

func New(gceConfigFilePath string) (*Config, error) {
	tokenSource, projectID, err := getTokenSourceAndProjectID(gceConfigFilePath)
	if err != nil {
		return nil, err
	}

	glog.Infof("TokenSource: %#v, projectID: %s", tokenSource, projectID)

	domainStatuses := make(map[string]string, 0)
	domainStatuses[sslActive] = managedActive
	domainStatuses[sslFailedCaaChecking] = managedFailedCaaChecking
	domainStatuses[sslFailedCaaForbidden] = managedFailedCaaForbidden
	domainStatuses[sslFailedNotVisible] = managedFailedNotVisible
	domainStatuses[sslFailedRateLimited] = managedFailedRateLimited
	domainStatuses[sslProvisioning] = managedProvisioning

	certificateStatuses := make(map[string]string, 0)
	certificateStatuses[sslActive] = managedActive
	certificateStatuses[sslEmpty] = managedEmpty
	certificateStatuses[sslManagedCertificateStatusUnspecified] = managedEmpty
	certificateStatuses[sslProvisioning] = managedProvisioning
	certificateStatuses[sslProvisioningFailed] = managedProvisioningFailed
	certificateStatuses[sslProvisioningFailedPermanently] = managedProvisioningFailedPermanently
	certificateStatuses[sslRenewalFailed] = managedRenewalFailed

	return &Config{
		CertificateStatus: certificateStatusConfig{
			Certificate: certificateStatuses,
			Domain:      domainStatuses,
		},
		Compute: computeConfig{
			TokenSource: tokenSource,
			ProjectID:   projectID,
			Timeout:     30 * time.Second,
		},
		SslCertificateNamePrefix: SslCertificateNamePrefix,
	}, nil
}

func getTokenSourceAndProjectID(gceConfigFilePath string) (oauth2.TokenSource, string, error) {
	if gceConfigFilePath != "" {
		glog.V(1).Info("In a GKE cluster")

		config, err := os.Open(gceConfigFilePath)
		if err != nil {
			return nil, "", fmt.Errorf("Could not open cloud provider configuration %s: %v", gceConfigFilePath, err)
		}
		defer config.Close()

		var cfg gce.ConfigFile
		if err := gcfg.ReadInto(&cfg, config); err != nil {
			return nil, "", fmt.Errorf("Could not read config %v", err)
		}
		glog.Infof("Using GCE provider config %+v", cfg)

		return gce.NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody), cfg.Global.ProjectID, nil
	}

	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil, "", fmt.Errorf("Could not fetch project id: %v", err)
	}

	if len(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) > 0 {
		glog.V(1).Info("In a GCP cluster")
		tokenSource, err := google.DefaultTokenSource(oauth2.NoContext, compute.ComputeScope)
		return tokenSource, projectID, err
	} else {
		glog.V(1).Info("Using default TokenSource")
		return google.ComputeTokenSource(""), projectID, nil
	}
}
<commit_msg>Only fail on fatal errors from gcfg parser (fix support for regional clusters)<commit_after>/*
Copyright 2018 Google LLC

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

    https://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 config manages configuration of the whole application.
package config

import (
	"fmt"
	"os"
	"time"

	"cloud.google.com/go/compute/metadata"
	"github.com/golang/glog"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	compute "google.golang.org/api/compute/v0.beta"
	gcfg "gopkg.in/gcfg.v1"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
)

const (
	managedActive                        = "Active"
	managedEmpty                         = ""
	managedFailedCaaChecking             = "FailedCaaChecking"
	managedFailedCaaForbidden            = "FailedCaaForbidden"
	managedFailedNotVisible              = "FailedNotVisible"
	managedFailedRateLimited             = "FailedRateLimited"
	managedProvisioning                  = "Provisioning"
	managedProvisioningFailed            = "ProvisioningFailed"
	managedProvisioningFailedPermanently = "ProvisioningFailedPermanently"
	managedRenewalFailed                 = "RenewalFailed"

	SslCertificateNamePrefix = "mcrt-"

	sslActive                              = "ACTIVE"
	sslEmpty                               = ""
	sslFailedCaaChecking                   = "FAILED_CAA_CHECKING"
	sslFailedCaaForbidden                  = "FAILED_CAA_FORBIDDEN"
	sslFailedNotVisible                    = "FAILED_NOT_VISIBLE"
	sslFailedRateLimited                   = "FAILED_RATE_LIMITED"
	sslManagedCertificateStatusUnspecified = "MANAGED_CERTIFICATE_STATUS_UNSPECIFIED"
	sslProvisioning                        = "PROVISIONING"
	sslProvisioningFailed                  = "PROVISIONING_FAILED"
	sslProvisioningFailedPermanently       = "PROVISIONING_FAILED_PERMANENTLY"
	sslRenewalFailed                       = "RENEWAL_FAILED"
)

type computeConfig struct {
	TokenSource oauth2.TokenSource
	ProjectID   string
	Timeout     time.Duration
}

type certificateStatusConfig struct {
	// Certificate is a mapping from SslCertificate status to ManagedCertificate status
	Certificate map[string]string
	// Domain is a mapping from SslCertificate domain status to ManagedCertificate domain status
	Domain map[string]string
}

type Config struct {
	// CertificateStatus holds mappings of SslCertificate statuses to ManagedCertificate statuses
	CertificateStatus certificateStatusConfig
	// Compute is GCP-specific configuration
	Compute computeConfig
	// SslCertificateNamePrefix is a prefix prepended to SslCertificate resources created by the controller
	SslCertificateNamePrefix string
}

func New(gceConfigFilePath string) (*Config, error) {
	tokenSource, projectID, err := getTokenSourceAndProjectID(gceConfigFilePath)
	if err != nil {
		return nil, err
	}

	glog.Infof("TokenSource: %#v, projectID: %s", tokenSource, projectID)

	domainStatuses := make(map[string]string, 0)
	domainStatuses[sslActive] = managedActive
	domainStatuses[sslFailedCaaChecking] = managedFailedCaaChecking
	domainStatuses[sslFailedCaaForbidden] = managedFailedCaaForbidden
	domainStatuses[sslFailedNotVisible] = managedFailedNotVisible
	domainStatuses[sslFailedRateLimited] = managedFailedRateLimited
	domainStatuses[sslProvisioning] = managedProvisioning

	certificateStatuses := make(map[string]string, 0)
	certificateStatuses[sslActive] = managedActive
	certificateStatuses[sslEmpty] = managedEmpty
	certificateStatuses[sslManagedCertificateStatusUnspecified] = managedEmpty
	certificateStatuses[sslProvisioning] = managedProvisioning
	certificateStatuses[sslProvisioningFailed] = managedProvisioningFailed
	certificateStatuses[sslProvisioningFailedPermanently] = managedProvisioningFailedPermanently
	certificateStatuses[sslRenewalFailed] = managedRenewalFailed

	return &Config{
		CertificateStatus: certificateStatusConfig{
			Certificate: certificateStatuses,
			Domain:      domainStatuses,
		},
		Compute: computeConfig{
			TokenSource: tokenSource,
			ProjectID:   projectID,
			Timeout:     30 * time.Second,
		},
		SslCertificateNamePrefix: SslCertificateNamePrefix,
	}, nil
}

func getTokenSourceAndProjectID(gceConfigFilePath string) (oauth2.TokenSource, string, error) {
	if gceConfigFilePath != "" {
		glog.V(1).Info("In a GKE cluster")

		config, err := os.Open(gceConfigFilePath)
		if err != nil {
			return nil, "", fmt.Errorf("Could not open cloud provider configuration %s: %v", gceConfigFilePath, err)
		}
		defer config.Close()

		var cfg gce.ConfigFile
		if err := gcfg.FatalOnly(gcfg.ReadInto(&cfg, config)); err != nil {
			return nil, "", fmt.Errorf("Could not read config %v", err)
		}
		glog.Infof("Using GCE provider config %+v", cfg)

		return gce.NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody), cfg.Global.ProjectID, nil
	}

	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil, "", fmt.Errorf("Could not fetch project id: %v", err)
	}

	if len(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) > 0 {
		glog.V(1).Info("In a GCP cluster")
		tokenSource, err := google.DefaultTokenSource(oauth2.NoContext, compute.ComputeScope)
		return tokenSource, projectID, err
	} else {
		glog.V(1).Info("Using default TokenSource")
		return google.ComputeTokenSource(""), projectID, nil
	}
}
<|endoftext|>


<commit_before>package kates

import (
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	netv1beta1 "k8s.io/api/networking/v1beta1"
	rbacv1 "k8s.io/api/rbac/v1"
	xv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/version"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	metrics "k8s.io/metrics/pkg/apis/metrics/v1beta1"
)

// The kubernetes client libraries and core protobufs are split across so many different packages
// that it is extremely difficult to keep them straight. The naming conventions are also very poorly
// chosen resulting in frequent name collisions under even simple uses. Case in point, there are a
// whole lot of v1 packages (core/v1, apiextensions/v1, meta/v1, apps/v1) just to name a few, and
// you need to use at least 3 of these together in order to accomplish almost anything. The types
// within packages are often horribly named as well (e.g. dynamic.Interface, rest.Config,
// version.Info are not super description when you omit the packages).
//
// The aliases in this file are intended to do several things:
//
//   1. Make our kubernetes code easier to read by providing a standard set of aliases instead of
//      requiring developers to make up potentially different aliases at the point of use.
//
//   2. Make for a simpler and easier Quickstart for our kubernetes library by providing a single
//      entry point.
//
//   3. Allow us to build a set of simpler and easier to use APIs on top of client-go while using
//      types that are compatible with client-go so we have a good escape hatch for directly using
//      client-go.
//
//   4. Provide a single file that helps me (rhs@datawire.io) remember where the hell everything is.

// type related aliases

type TypeMeta = metav1.TypeMeta
type ObjectMeta = metav1.ObjectMeta
type APIResource = metav1.APIResource

type Namespace = corev1.Namespace

type LocalObjectReference = corev1.LocalObjectReference

type Event = corev1.Event
type ConfigMap = corev1.ConfigMap

type Secret = corev1.Secret

const SecretTypeServiceAccountToken = corev1.SecretTypeServiceAccountToken
const SecretTypeTLS = corev1.SecretTypeTLS

type Ingress = netv1beta1.Ingress
type IngressClass = netv1beta1.IngressClass

type Service = corev1.Service
type ServiceSpec = corev1.ServiceSpec
type ServicePort = corev1.ServicePort
type Endpoints = corev1.Endpoints
type EndpointSubset = corev1.EndpointSubset
type EndpointAddress = corev1.EndpointAddress
type EndpointPort = corev1.EndpointPort

type Protocol = corev1.Protocol

var ProtocolTCP = corev1.ProtocolTCP
var ProtocolUDP = corev1.ProtocolUDP
var ProtocolSCTP = corev1.ProtocolSCTP

var ServiceTypeLoadBalancer = corev1.ServiceTypeLoadBalancer
var ServiceTypeClusterIP = corev1.ServiceTypeClusterIP

type ServiceAccount = corev1.ServiceAccount

type Role = rbacv1.Role
type RoleBinding = rbacv1.RoleBinding
type ClusterRole = rbacv1.ClusterRole
type ClusterRoleBinding = rbacv1.ClusterRoleBinding

type Pod = corev1.Pod
type PodSpec = corev1.PodSpec
type Container = corev1.Container
type EnvVar = corev1.EnvVar
type SecurityContext = corev1.SecurityContext
type PodCondition = corev1.PodCondition
type PodLogOptions = corev1.PodLogOptions
type Toleration = corev1.Toleration
type TolerationOperator = corev1.TolerationOperator

var TolerationOpExists = corev1.TolerationOpExists
var TolerationOpEqual = corev1.TolerationOpEqual

var PodSucceeded = corev1.PodSucceeded
var PodFailed = corev1.PodFailed
var PodReady = corev1.PodReady
var CoreConditionTrue = corev1.ConditionTrue

type Node = corev1.Node

const NodeUnreachablePodReason = "NodeLost" // k8s.io/kubernetes/pkg/util/node.NodeUnreachablePodReason

type Volume = corev1.Volume
type VolumeSource = corev1.VolumeSource
type PersistentVolumeClaimVolumeSource = corev1.PersistentVolumeClaimVolumeSource
type VolumeMount = corev1.VolumeMount

type ResourceRequirements = corev1.ResourceRequirements
type ResourceList = corev1.ResourceList

const ResourceCPU = corev1.ResourceCPU
const ResourceMemory = corev1.ResourceMemory

type PersistentVolumeClaim = corev1.PersistentVolumeClaim

type Deployment = appsv1.Deployment

type CustomResourceDefinition = xv1.CustomResourceDefinition

var NamesAccepted = xv1.NamesAccepted
var Established = xv1.Established
var ConditionTrue = xv1.ConditionTrue

type NodeMetrics = metrics.NodeMetrics
type PodMetrics = metrics.PodMetrics
type ContainerMetrics = metrics.ContainerMetrics

type Unstructured = unstructured.Unstructured

var MustParseQuantity = resource.MustParse

type Quantity = resource.Quantity
type IntOrString = intstr.IntOrString
type Time = metav1.Time

var Int = intstr.Int

// client related aliases

type ConfigFlags = genericclioptions.ConfigFlags

var NewConfigFlags = genericclioptions.NewConfigFlags

type VersionInfo = version.Info

type PatchType = types.PatchType

var (
	JSONPatchType           = types.JSONPatchType
	MergePatchType          = types.MergePatchType
	StrategicMergePatchType = types.StrategicMergePatchType
	ApplyPatchType          = types.ApplyPatchType
)

type GetOptions = metav1.GetOptions
type ListOptions = metav1.ListOptions
type CreateOptions = metav1.CreateOptions
type UpdateOptions = metav1.UpdateOptions
type PatchOptions = metav1.PatchOptions
type DeleteOptions = metav1.DeleteOptions

var NamespaceAll = metav1.NamespaceAll
var NamespaceNone = metav1.NamespaceNone

type LabelSelector = metav1.LabelSelector

type Selector = labels.Selector
type LabelSet = labels.Set

var ParseSelector = labels.Parse

// error related aliases

var IsNotFound = apierrors.IsNotFound
var IsConflict = apierrors.IsConflict

//

type Object interface {
	runtime.Object
	metav1.Object
}
<commit_msg>Adding ReplicaSet + PodTemplateSpec aliases to kates<commit_after>package kates

import (
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	netv1beta1 "k8s.io/api/networking/v1beta1"
	rbacv1 "k8s.io/api/rbac/v1"
	xv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/version"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	metrics "k8s.io/metrics/pkg/apis/metrics/v1beta1"
)

// The kubernetes client libraries and core protobufs are split across so many different packages
// that it is extremely difficult to keep them straight. The naming conventions are also very poorly
// chosen resulting in frequent name collisions under even simple uses. Case in point, there are a
// whole lot of v1 packages (core/v1, apiextensions/v1, meta/v1, apps/v1) just to name a few, and
// you need to use at least 3 of these together in order to accomplish almost anything. The types
// within packages are often horribly named as well (e.g. dynamic.Interface, rest.Config,
// version.Info are not super description when you omit the packages).
//
// The aliases in this file are intended to do several things:
//
//   1. Make our kubernetes code easier to read by providing a standard set of aliases instead of
//      requiring developers to make up potentially different aliases at the point of use.
//
//   2. Make for a simpler and easier Quickstart for our kubernetes library by providing a single
//      entry point.
//
//   3. Allow us to build a set of simpler and easier to use APIs on top of client-go while using
//      types that are compatible with client-go so we have a good escape hatch for directly using
//      client-go.
//
//   4. Provide a single file that helps me (rhs@datawire.io) remember where the hell everything is.

// type related aliases

type TypeMeta = metav1.TypeMeta
type ObjectMeta = metav1.ObjectMeta
type APIResource = metav1.APIResource

type Namespace = corev1.Namespace

type LocalObjectReference = corev1.LocalObjectReference

type Event = corev1.Event
type ConfigMap = corev1.ConfigMap

type Secret = corev1.Secret

const SecretTypeServiceAccountToken = corev1.SecretTypeServiceAccountToken
const SecretTypeTLS = corev1.SecretTypeTLS

type Ingress = netv1beta1.Ingress
type IngressClass = netv1beta1.IngressClass

type Service = corev1.Service
type ServiceSpec = corev1.ServiceSpec
type ServicePort = corev1.ServicePort
type Endpoints = corev1.Endpoints
type EndpointSubset = corev1.EndpointSubset
type EndpointAddress = corev1.EndpointAddress
type EndpointPort = corev1.EndpointPort

type Protocol = corev1.Protocol

var ProtocolTCP = corev1.ProtocolTCP
var ProtocolUDP = corev1.ProtocolUDP
var ProtocolSCTP = corev1.ProtocolSCTP

var ServiceTypeLoadBalancer = corev1.ServiceTypeLoadBalancer
var ServiceTypeClusterIP = corev1.ServiceTypeClusterIP

type ServiceAccount = corev1.ServiceAccount

type Role = rbacv1.Role
type RoleBinding = rbacv1.RoleBinding
type ClusterRole = rbacv1.ClusterRole
type ClusterRoleBinding = rbacv1.ClusterRoleBinding

type Pod = corev1.Pod
type PodSpec = corev1.PodSpec
type PodTemplateSpec = corev1.PodTemplateSpec
type Container = corev1.Container
type EnvVar = corev1.EnvVar
type SecurityContext = corev1.SecurityContext
type PodCondition = corev1.PodCondition
type PodLogOptions = corev1.PodLogOptions
type Toleration = corev1.Toleration
type TolerationOperator = corev1.TolerationOperator

var TolerationOpExists = corev1.TolerationOpExists
var TolerationOpEqual = corev1.TolerationOpEqual

var PodSucceeded = corev1.PodSucceeded
var PodFailed = corev1.PodFailed
var PodReady = corev1.PodReady
var CoreConditionTrue = corev1.ConditionTrue

type Node = corev1.Node

const NodeUnreachablePodReason = "NodeLost" // k8s.io/kubernetes/pkg/util/node.NodeUnreachablePodReason

type Volume = corev1.Volume
type VolumeSource = corev1.VolumeSource
type PersistentVolumeClaimVolumeSource = corev1.PersistentVolumeClaimVolumeSource
type VolumeMount = corev1.VolumeMount

type ResourceRequirements = corev1.ResourceRequirements
type ResourceList = corev1.ResourceList

const ResourceCPU = corev1.ResourceCPU
const ResourceMemory = corev1.ResourceMemory

type PersistentVolumeClaim = corev1.PersistentVolumeClaim

type Deployment = appsv1.Deployment
type ReplicaSet = appsv1.ReplicaSet

type CustomResourceDefinition = xv1.CustomResourceDefinition

var NamesAccepted = xv1.NamesAccepted
var Established = xv1.Established
var ConditionTrue = xv1.ConditionTrue

type NodeMetrics = metrics.NodeMetrics
type PodMetrics = metrics.PodMetrics
type ContainerMetrics = metrics.ContainerMetrics

type Unstructured = unstructured.Unstructured

var MustParseQuantity = resource.MustParse

type Quantity = resource.Quantity
type IntOrString = intstr.IntOrString
type Time = metav1.Time

var Int = intstr.Int

// client related aliases

type ConfigFlags = genericclioptions.ConfigFlags

var NewConfigFlags = genericclioptions.NewConfigFlags

type VersionInfo = version.Info

type PatchType = types.PatchType

var (
	JSONPatchType           = types.JSONPatchType
	MergePatchType          = types.MergePatchType
	StrategicMergePatchType = types.StrategicMergePatchType
	ApplyPatchType          = types.ApplyPatchType
)

type GetOptions = metav1.GetOptions
type ListOptions = metav1.ListOptions
type CreateOptions = metav1.CreateOptions
type UpdateOptions = metav1.UpdateOptions
type PatchOptions = metav1.PatchOptions
type DeleteOptions = metav1.DeleteOptions

var NamespaceAll = metav1.NamespaceAll
var NamespaceNone = metav1.NamespaceNone

type LabelSelector = metav1.LabelSelector

type Selector = labels.Selector
type LabelSet = labels.Set

var ParseSelector = labels.Parse

// error related aliases

var IsNotFound = apierrors.IsNotFound
var IsConflict = apierrors.IsConflict

//

type Object interface {
	runtime.Object
	metav1.Object
}
<|endoftext|>


<commit_before>
package paxos

import (
    "fmt"
    "strconv"
    "strings"
)

const (
	mSeqn = iota
	mFrom
	mTo
	mCmd
	mBody
	mNumParts
)

const (
	Nop = iota
	Invite
	Rsvp
	Nominate
	Vote
)

type Message interface {
    From() int
    Cmd() int
    Seqn() uint64
    Body() string // soon to be []byte

	SetFrom(byte)
	SetSeqn(uint64)
}

func NewMessage(s string) Message {
	parts := strings.Split(s, ":", mNumParts)
	if len(parts) != mNumParts {
		panic(s)
	}

	seqn, err := strconv.Btoui64(parts[mSeqn], 10)
	if err != nil {
		panic(s)
	}

	from, err := strconv.Atoi(parts[mFrom])
	if err != nil {
		panic(s)
	}

	cmd, err := strconv.Atoi(parts[mCmd])
	if err != nil {
		panic(s)
	}

	return &Msg{byte(from), cmd, seqn, parts[mBody]}
}

func NewInvite(crnd uint64) Message {
	return &Msg{
		cmd:  Invite,
		body: fmt.Sprintf("%d", crnd),
	}
}

// Returns the info for `m`. If `m` is not an invite, the result is undefined.
func InviteParts(m Message) (crnd uint64) {
	crnd, _ = strconv.Atoui64(m.Body())
	return
}

func NewNominate(crnd uint64, v string) Message {
	return &Msg{
		cmd:  Nominate,
		body: fmt.Sprintf("%d:%s", crnd, v),
	}
}

// Returns the info for `m`. If `m` is not a nominate, the result is undefined.
func NominateParts(m Message) (crnd uint64, v string) {
	parts := strings.Split(m.Body(), ":", 2)
	crnd, _ = strconv.Atoui64(parts[0])
	v = parts[1]
	return
}

func NewRsvp(i, vrnd uint64, vval string) Message {
	return &Msg{
		cmd: Rsvp,
		body: fmt.Sprintf("%d:%d:%s", i, vrnd, vval),
	}
}

// Returns the info for `m`. If `m` is not an rsvp, the result is undefined.
func RsvpParts(m Message) (i, vrnd uint64, vval string) {
	parts := strings.Split(m.Body(), ":", 3)
	i, _ = strconv.Atoui64(parts[0])
	vrnd, _ = strconv.Atoui64(parts[1])
	vval = parts[2]
	return
}

func NewVote(i uint64, vval string) Message {
	return &Msg{
		cmd: Vote,
		body: fmt.Sprintf("%d:%s", i, vval),
	}
}

// Returns the info for `m`. If `m` is not a vote, the result is undefined.
func VoteParts(m Message) (i uint64, vval string) {
	parts := strings.Split(m.Body(), ":", 2)
	i, _ = strconv.Atoui64(parts[0])
	vval = parts[1]
	return
}

// In-memory format:
//
//     0    -- index of sender
//     1    -- cmd
//     2..9 -- seqn
//     10.. -- body -- format depends on command
//
// Wire format is same as in-memory format, but without the first byte (the
// sender index). Here it is for clarity:
//
//     0    -- cmd
//     1..8 -- seqn
//     9..  -- body -- format depends on command
//type Msg []byte

type Msg struct {
	from byte
	cmd int
	seqn uint64
	body string
}

func (m Msg) Seqn() uint64 {
	return m.seqn
}

func (m Msg) From() int {
	return int(m.from)
}

func (m Msg) Cmd() int {
	return m.cmd
}

func (m Msg) Body() string {
	return m.body
}

func (m *Msg) SetFrom(from byte) {
	m.from = from
}

func (m *Msg) SetSeqn(seqn uint64) {
	m.seqn = seqn
}
<commit_msg>tweak numeric types<commit_after>
package paxos

import (
    "fmt"
    "strconv"
    "strings"
)

const (
	mSeqn = iota
	mFrom
	mTo
	mCmd
	mBody
	mNumParts
)

const (
	Nop = iota
	Invite
	Rsvp
	Nominate
	Vote
)

type Message interface {
    From() int
    Cmd() int
    Seqn() uint64
    Body() string // soon to be []byte

	SetFrom(byte)
	SetSeqn(uint64)
}

func NewMessage(s string) Message {
	parts := strings.Split(s, ":", mNumParts)
	if len(parts) != mNumParts {
		panic(s)
	}

	seqn, err := strconv.Btoui64(parts[mSeqn], 10)
	if err != nil {
		panic(s)
	}

	from, err := strconv.Atoi(parts[mFrom])
	if err != nil {
		panic(s)
	}

	cmd, err := strconv.Atoi(parts[mCmd])
	if err != nil {
		panic(s)
	}

	return &Msg{byte(from), byte(cmd), seqn, parts[mBody]}
}

func NewInvite(crnd uint64) Message {
	return &Msg{
		cmd:  Invite,
		body: fmt.Sprintf("%d", crnd),
	}
}

// Returns the info for `m`. If `m` is not an invite, the result is undefined.
func InviteParts(m Message) (crnd uint64) {
	crnd, _ = strconv.Atoui64(m.Body())
	return
}

func NewNominate(crnd uint64, v string) Message {
	return &Msg{
		cmd:  Nominate,
		body: fmt.Sprintf("%d:%s", crnd, v),
	}
}

// Returns the info for `m`. If `m` is not a nominate, the result is undefined.
func NominateParts(m Message) (crnd uint64, v string) {
	parts := strings.Split(m.Body(), ":", 2)
	crnd, _ = strconv.Atoui64(parts[0])
	v = parts[1]
	return
}

func NewRsvp(i, vrnd uint64, vval string) Message {
	return &Msg{
		cmd: Rsvp,
		body: fmt.Sprintf("%d:%d:%s", i, vrnd, vval),
	}
}

// Returns the info for `m`. If `m` is not an rsvp, the result is undefined.
func RsvpParts(m Message) (i, vrnd uint64, vval string) {
	parts := strings.Split(m.Body(), ":", 3)
	i, _ = strconv.Atoui64(parts[0])
	vrnd, _ = strconv.Atoui64(parts[1])
	vval = parts[2]
	return
}

func NewVote(i uint64, vval string) Message {
	return &Msg{
		cmd: Vote,
		body: fmt.Sprintf("%d:%s", i, vval),
	}
}

// Returns the info for `m`. If `m` is not a vote, the result is undefined.
func VoteParts(m Message) (i uint64, vval string) {
	parts := strings.Split(m.Body(), ":", 2)
	i, _ = strconv.Atoui64(parts[0])
	vval = parts[1]
	return
}

// In-memory format:
//
//     0    -- index of sender
//     1    -- cmd
//     2..9 -- seqn
//     10.. -- body -- format depends on command
//
// Wire format is same as in-memory format, but without the first byte (the
// sender index). Here it is for clarity:
//
//     0    -- cmd
//     1..8 -- seqn
//     9..  -- body -- format depends on command
//type Msg []byte

type Msg struct {
	from byte
	cmd byte
	seqn uint64
	body string
}

func (m Msg) Seqn() uint64 {
	return m.seqn
}

func (m Msg) From() int {
	return int(m.from)
}

func (m Msg) Cmd() int {
	return int(m.cmd)
}

func (m Msg) Body() string {
	return m.body
}

func (m *Msg) SetFrom(from byte) {
	m.from = from
}

func (m *Msg) SetSeqn(seqn uint64) {
	m.seqn = seqn
}
<|endoftext|>


<commit_before>package router

import (
	"crypto"

	"nimona.io/pkg/object"
	"nimona.io/pkg/peer"
)

type (
	Envelope struct {
		Sender  crypto.PublicKey
		Payload object.Object
	}
	Router interface {
		Send(*peer.Peer, object.Object) error
		Handle() <-chan Envelope
	}
)

func New() Router {
	return nil
}
<commit_msg>chore(router): remove unused<commit_after><|endoftext|>


<commit_before>package search

import (
	"fmt"

	"log"

	"github.com/cridenour/go-postgis"
	"github.com/devinmcgloin/clr/clr"
	"github.com/devinmcgloin/fokal/pkg/handler"
	"github.com/devinmcgloin/fokal/pkg/model"
	"github.com/devinmcgloin/fokal/pkg/retrieval"
	"github.com/jmoiron/sqlx"
	"github.com/lib/pq"
)

func Color(state *handler.State, color clr.Color, pixelFraction float64, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	l, a, b := color.CIELAB()
	cube := fmt.Sprintf("(%f, %f, %f)", l, a, b)

	log.Println(cube)
	err := state.DB.Select(&ids, `
			SELECT bridge.image_id
			FROM content.colors AS colors
  				INNER JOIN content.image_color_bridge AS bridge ON colors.id = bridge.color_id
  				INNER JOIN permissions.can_view AS view ON view.o_id = bridge.image_id
  				WHERE view.user_id = -1 AND bridge.pixel_fraction >= $4
				AND ($1::cube <-> cielab) < 50
			ORDER BY $1::cube <-> cielab
			OFFSET $2 LIMIT $3;`, cube, offset, limit, pixelFraction)
	if err != nil {
		return []model.Image{}, err
	}

	return retrieval.GetImages(state, ids)
}

func Text(state *handler.State, query string, limit, offset int) ([]model.Image, error) {
	ids := []struct {
		Id   int64 `db:"image_id"`
		Rank float64
	}{}

	//images := []struct {
	//	Image model.Image
	//	Rank  float64
	//}{}

	err := state.DB.Select(&ids, `
SELECT
    scores.image_id,
    sum(scores.rank) AS rank
 FROM (SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(landmark.description), to_tsquery($1)) AS rank
        FROM content.landmarks AS landmark
          JOIN content.image_landmark_bridge AS bridge ON landmark.id = bridge.landmark_id
        WHERE to_tsvector(landmark.description) @@ to_tsquery($1)
        UNION ALL
        SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(labels.description), to_tsquery($1)) AS rank
        FROM content.labels AS labels
          JOIN content.image_label_bridge AS bridge ON labels.id = bridge.label_id
        WHERE to_tsvector(labels.description) @@ to_tsquery($1)
        UNION ALL
        SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(tags.description), to_tsquery($1)) AS rank
        FROM content.image_tags AS tags
          JOIN content.image_tag_bridge AS bridge ON tags.id = bridge.tag_id
        WHERE to_tsvector(tags.description) @@ to_tsquery($1)) AS scores
  GROUP BY scores.image_id
  ORDER BY rank DESC
  OFFSET $2
  LIMIT $3;
	`, query, offset, limit)
	if err != nil {
		return []model.Image{}, err
	}

	imageIds := make([]int64, len(ids))
	for i, v := range ids {
		imageIds[i] = v.Id
		//images[i].Rank = v.Rank
	}

	return retrieval.GetImages(state, imageIds)

}

func GeoRadius(state *handler.State, point postgis.PointS, radius float64, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	err := state.DB.Select(&ids, `
	SELECT geo.image_id
	FROM content.image_geo AS geo
	WHERE ST_Distance($1, geo.loc) < $2
	ORDER BY $1 <-> geo.loc
	OFFSET $3 LIMIT $4
	`, point, radius, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, ids)
}

func Hot(state *handler.State, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	err := state.DB.Select(&ids, `
	SELECT id FROM content.images
	ORDER BY ranking(id, views + favorites , featured::int + 3) DESC
	OFFSET $1 LIMIT $2
	`, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, ids)

}

func FeaturedImages(state *handler.State, userId int64, limit, offset int) ([]model.Image, error) {
	imgs := []int64{}
	var stmt *sqlx.Stmt
	var err error
	if userId == 0 {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE (view.user_id = -1 OR view.user_id = $1) AND images.featured = TRUE
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	} else {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE view.user_id = -1 AND images.featured = TRUE
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	}
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	err = stmt.Select(&imgs,
		userId, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, imgs)
}

func RecentImages(state *handler.State, userId int64, limit, offset int) ([]model.Image, error) {
	imageIds := []int64{}
	var stmt *sqlx.Stmt
	var err error
	if userId == 0 {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE view.user_id = -1 OR view.user_id = $1
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	} else {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE (view.user_id = -1 OR view.user_id = $1) AND images.user_id = $1
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	}
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, err)
		}
		return []model.Image{}, err
	}
	err = stmt.Select(&imageIds,
		userId, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, err)
		}
		return []model.Image{}, err
	}
	log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, imageIds)

	return retrieval.GetImages(state, imageIds)
}
<commit_msg>Improved Color Search Query<commit_after>package search

import (
	"fmt"

	"log"

	"github.com/cridenour/go-postgis"
	"github.com/devinmcgloin/clr/clr"
	"github.com/devinmcgloin/fokal/pkg/handler"
	"github.com/devinmcgloin/fokal/pkg/model"
	"github.com/devinmcgloin/fokal/pkg/retrieval"
	"github.com/jmoiron/sqlx"
	"github.com/lib/pq"
)

func Color(state *handler.State, color clr.Color, pixelFraction float64, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	l, a, b := color.CIELAB()
	cube := fmt.Sprintf("(%f, %f, %f)", l, a, b)

	log.Println(cube)
	err := state.DB.Select(&ids, `
	SELECT
	  id
	FROM (SELECT
			bridge.image_id                                         AS id,
			$1 :: CUBE <-> cielab AS score
		  FROM content.colors AS COLORS
			INNER JOIN content.image_color_bridge AS bridge ON COLORS.id = bridge.color_id
			INNER JOIN permissions.can_view AS view ON view.o_id = bridge.image_id
		  WHERE view.user_id = -1 AND bridge.pixel_fraction >= $4
		  ORDER BY score
		  OFFSET $2
		  LIMIT $3) AS scores
	WHERE score < 50
	GROUP BY id
	ORDER BY min(score);
	`, cube, offset, limit, pixelFraction)
	if err != nil {
		return []model.Image{}, err
	}

	return retrieval.GetImages(state, ids)
}

func Text(state *handler.State, query string, limit, offset int) ([]model.Image, error) {
	ids := []struct {
		Id   int64 `db:"image_id"`
		Rank float64
	}{}

	//images := []struct {
	//	Image model.Image
	//	Rank  float64
	//}{}

	err := state.DB.Select(&ids, `
SELECT
    scores.image_id,
    sum(scores.rank) AS rank
 FROM (SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(landmark.description), to_tsquery($1)) AS rank
        FROM content.landmarks AS landmark
          JOIN content.image_landmark_bridge AS bridge ON landmark.id = bridge.landmark_id
        WHERE to_tsvector(landmark.description) @@ to_tsquery($1)
        UNION ALL
        SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(labels.description), to_tsquery($1)) AS rank
        FROM content.labels AS labels
          JOIN content.image_label_bridge AS bridge ON labels.id = bridge.label_id
        WHERE to_tsvector(labels.description) @@ to_tsquery($1)
        UNION ALL
        SELECT
          bridge.image_id,
          ts_rank_cd(to_tsvector(tags.description), to_tsquery($1)) AS rank
        FROM content.image_tags AS tags
          JOIN content.image_tag_bridge AS bridge ON tags.id = bridge.tag_id
        WHERE to_tsvector(tags.description) @@ to_tsquery($1)) AS scores
  GROUP BY scores.image_id
  ORDER BY rank DESC
  OFFSET $2
  LIMIT $3;
	`, query, offset, limit)
	if err != nil {
		return []model.Image{}, err
	}

	imageIds := make([]int64, len(ids))
	for i, v := range ids {
		imageIds[i] = v.Id
		//images[i].Rank = v.Rank
	}

	return retrieval.GetImages(state, imageIds)

}

func GeoRadius(state *handler.State, point postgis.PointS, radius float64, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	err := state.DB.Select(&ids, `
	SELECT geo.image_id
	FROM content.image_geo AS geo
	WHERE ST_Distance($1, geo.loc) < $2
	ORDER BY $1 <-> geo.loc
	OFFSET $3 LIMIT $4
	`, point, radius, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, ids)
}

func Hot(state *handler.State, limit, offset int) ([]model.Image, error) {
	ids := []int64{}

	err := state.DB.Select(&ids, `
	SELECT id FROM content.images
	ORDER BY ranking(id, views + favorites , featured::int + 3) DESC
	OFFSET $1 LIMIT $2
	`, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, ids)

}

func FeaturedImages(state *handler.State, userId int64, limit, offset int) ([]model.Image, error) {
	imgs := []int64{}
	var stmt *sqlx.Stmt
	var err error
	if userId == 0 {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE (view.user_id = -1 OR view.user_id = $1) AND images.featured = TRUE
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	} else {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE view.user_id = -1 AND images.featured = TRUE
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	}
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	err = stmt.Select(&imgs,
		userId, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("%+v", err)
		}
		return []model.Image{}, err
	}
	return retrieval.GetImages(state, imgs)
}

func RecentImages(state *handler.State, userId int64, limit, offset int) ([]model.Image, error) {
	imageIds := []int64{}
	var stmt *sqlx.Stmt
	var err error
	if userId == 0 {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE view.user_id = -1 OR view.user_id = $1
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	} else {
		stmt, err = state.DB.Preparex(`
		SELECT images.id
		FROM content.images AS images
		INNER JOIN permissions.can_view AS view ON view.o_id = images.id
		WHERE (view.user_id = -1 OR view.user_id = $1) AND images.user_id = $1
		ORDER BY publish_time DESC
		OFFSET $2 LIMIT $3
		`)
	}
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, err)
		}
		return []model.Image{}, err
	}
	err = stmt.Select(&imageIds,
		userId, offset, limit)
	if err != nil {
		if err, ok := err.(*pq.Error); ok {
			log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, err)
		}
		return []model.Image{}, err
	}
	log.Printf("GetRecentImages userId: %d limit: %d offset: %d %+v", userId, limit, offset, imageIds)

	return retrieval.GetImages(state, imageIds)
}
<|endoftext|>