<commit_before>// Copyright 2015 The rkt 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 tar

import (
	"archive/tar"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"syscall"

	"github.com/coreos/rkt/pkg/multicall"
	"github.com/coreos/rkt/pkg/sys"
	"github.com/coreos/rkt/pkg/user"
	"github.com/hashicorp/errwrap"
)

const (
	multicallName = "extracttar"
	fileMapFdNum  = 3
)

var mcEntrypoint multicall.Entrypoint

func init() {
	mcEntrypoint = multicall.Add(multicallName, extractTarCommand)
}

// Because this function is executed by multicall in a different process, it is not possible to use errwrap to return errors
func extractTarCommand() error {
	if len(os.Args) != 5 {
		return fmt.Errorf("incorrect number of arguments. Usage: %s DIR {true|false} uidShift uidCount", multicallName)
	}
	if !sys.HasChrootCapability() {
		return fmt.Errorf("chroot capability not available.")
	}
	dir := os.Args[1]
	if !filepath.IsAbs(dir) {
		return fmt.Errorf("dir %s must be an absolute path", dir)
	}
	overwrite, err := strconv.ParseBool(os.Args[2])
	if err != nil {
		return fmt.Errorf("error parsing overwrite argument: %v", err)
	}

	us, err := strconv.ParseUint(os.Args[3], 10, 32)
	if err != nil {
		return fmt.Errorf("error parsing uidShift argument: %v", err)
	}
	uc, err := strconv.ParseUint(os.Args[4], 10, 32)
	if err != nil {
		return fmt.Errorf("error parsing uidShift argument: %v", err)
	}

	uidRange := &user.UidRange{Shift: uint32(us), Count: uint32(uc)}

	if err := syscall.Chroot(dir); err != nil {
		return fmt.Errorf("failed to chroot in %s: %v", dir, err)
	}
	if err := syscall.Chdir("/"); err != nil {
		return fmt.Errorf("failed to chdir: %v", err)
	}
	fileMapFile := os.NewFile(uintptr(fileMapFdNum), "fileMap")

	fileMap := map[string]struct{}{}
	if err := json.NewDecoder(fileMapFile).Decode(&fileMap); err != nil {
		return fmt.Errorf("error decoding fileMap: %v", err)
	}
	editor, err := NewUidShiftingFilePermEditor(uidRange)
	if err != nil {
		return fmt.Errorf("error determining current user: %v", err)
	}
	if err := ExtractTarInsecure(tar.NewReader(os.Stdin), "/", overwrite, fileMap, editor); err != nil {
		return fmt.Errorf("error extracting tar: %v", err)
	}

	// flush remaining bytes
	io.Copy(ioutil.Discard, os.Stdin)

	return nil
}

// ExtractTar extracts a tarball (from a io.Reader) into the given directory
// if pwl is not nil, only the paths in the map are extracted.
// If overwrite is true, existing files will be overwritten.
// The extraction is executed by fork/exec()ing a new process. The new process
// needs the CAP_SYS_CHROOT capability.
func ExtractTar(rs io.Reader, dir string, overwrite bool, uidRange *user.UidRange, pwl PathWhitelistMap) error {
	r, w, err := os.Pipe()
	if err != nil {
		return err
	}
	defer w.Close()
	enc := json.NewEncoder(w)
	cmd := mcEntrypoint.Cmd(dir, strconv.FormatBool(overwrite),
		strconv.FormatUint(uint64(uidRange.Shift), 10),
		strconv.FormatUint(uint64(uidRange.Count), 10))
	cmd.ExtraFiles = []*os.File{r}

	cmd.Stdin = rs
	encodeCh := make(chan error)
	go func() {
		encodeCh <- enc.Encode(pwl)
	}()

	out, err := cmd.CombinedOutput()

	// read from blocking encodeCh to release the goroutine
	encodeErr := <-encodeCh
	if err != nil {
		return fmt.Errorf("extracttar error: %v, output: %s", err, out)
	}
	if encodeErr != nil {
		return errwrap.Wrap(errors.New("extracttar failed to json encode filemap"), encodeErr)
	}
	return nil
}
<commit_msg>pkg/tar: fix variable name in error<commit_after>// Copyright 2015 The rkt 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 tar

import (
	"archive/tar"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"syscall"

	"github.com/coreos/rkt/pkg/multicall"
	"github.com/coreos/rkt/pkg/sys"
	"github.com/coreos/rkt/pkg/user"
	"github.com/hashicorp/errwrap"
)

const (
	multicallName = "extracttar"
	fileMapFdNum  = 3
)

var mcEntrypoint multicall.Entrypoint

func init() {
	mcEntrypoint = multicall.Add(multicallName, extractTarCommand)
}

// Because this function is executed by multicall in a different process, it is not possible to use errwrap to return errors
func extractTarCommand() error {
	if len(os.Args) != 5 {
		return fmt.Errorf("incorrect number of arguments. Usage: %s DIR {true|false} uidShift uidCount", multicallName)
	}
	if !sys.HasChrootCapability() {
		return fmt.Errorf("chroot capability not available.")
	}
	dir := os.Args[1]
	if !filepath.IsAbs(dir) {
		return fmt.Errorf("dir %s must be an absolute path", dir)
	}
	overwrite, err := strconv.ParseBool(os.Args[2])
	if err != nil {
		return fmt.Errorf("error parsing overwrite argument: %v", err)
	}

	us, err := strconv.ParseUint(os.Args[3], 10, 32)
	if err != nil {
		return fmt.Errorf("error parsing uidShift argument: %v", err)
	}
	uc, err := strconv.ParseUint(os.Args[4], 10, 32)
	if err != nil {
		return fmt.Errorf("error parsing uidCount argument: %v", err)
	}

	uidRange := &user.UidRange{Shift: uint32(us), Count: uint32(uc)}

	if err := syscall.Chroot(dir); err != nil {
		return fmt.Errorf("failed to chroot in %s: %v", dir, err)
	}
	if err := syscall.Chdir("/"); err != nil {
		return fmt.Errorf("failed to chdir: %v", err)
	}
	fileMapFile := os.NewFile(uintptr(fileMapFdNum), "fileMap")

	fileMap := map[string]struct{}{}
	if err := json.NewDecoder(fileMapFile).Decode(&fileMap); err != nil {
		return fmt.Errorf("error decoding fileMap: %v", err)
	}
	editor, err := NewUidShiftingFilePermEditor(uidRange)
	if err != nil {
		return fmt.Errorf("error determining current user: %v", err)
	}
	if err := ExtractTarInsecure(tar.NewReader(os.Stdin), "/", overwrite, fileMap, editor); err != nil {
		return fmt.Errorf("error extracting tar: %v", err)
	}

	// flush remaining bytes
	io.Copy(ioutil.Discard, os.Stdin)

	return nil
}

// ExtractTar extracts a tarball (from a io.Reader) into the given directory
// if pwl is not nil, only the paths in the map are extracted.
// If overwrite is true, existing files will be overwritten.
// The extraction is executed by fork/exec()ing a new process. The new process
// needs the CAP_SYS_CHROOT capability.
func ExtractTar(rs io.Reader, dir string, overwrite bool, uidRange *user.UidRange, pwl PathWhitelistMap) error {
	r, w, err := os.Pipe()
	if err != nil {
		return err
	}
	defer w.Close()
	enc := json.NewEncoder(w)
	cmd := mcEntrypoint.Cmd(dir, strconv.FormatBool(overwrite),
		strconv.FormatUint(uint64(uidRange.Shift), 10),
		strconv.FormatUint(uint64(uidRange.Count), 10))
	cmd.ExtraFiles = []*os.File{r}

	cmd.Stdin = rs
	encodeCh := make(chan error)
	go func() {
		encodeCh <- enc.Encode(pwl)
	}()

	out, err := cmd.CombinedOutput()

	// read from blocking encodeCh to release the goroutine
	encodeErr := <-encodeCh
	if err != nil {
		return fmt.Errorf("extracttar error: %v, output: %s", err, out)
	}
	if encodeErr != nil {
		return errwrap.Wrap(errors.New("extracttar failed to json encode filemap"), encodeErr)
	}
	return nil
}
<|endoftext|>


<commit_before>// +build !ignore_autogenerated

/*
Copyright 2017 The Kubernetes Authors.

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

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

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

// This file was autogenerated by defaulter-gen. Do not edit it manually!

package v1alpha1

import (
	runtime "k8s.io/apimachinery/pkg/runtime"
)

// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
	return nil
}
<commit_msg>autogenerated<commit_after>// +build !ignore_autogenerated

/*
Copyright 2017 The Kubernetes Authors.

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

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

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

// This file was autogenerated by defaulter-gen. Do not edit it manually!

package v1alpha1

import (
	runtime "k8s.io/apimachinery/pkg/runtime"
)

// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
	scheme.AddTypeDefaultingFunc(&CertificateSigningRequest{}, func(obj interface{}) { SetObjectDefaults_CertificateSigningRequest(obj.(*CertificateSigningRequest)) })
	scheme.AddTypeDefaultingFunc(&CertificateSigningRequestList{}, func(obj interface{}) {
		SetObjectDefaults_CertificateSigningRequestList(obj.(*CertificateSigningRequestList))
	})
	return nil
}

func SetObjectDefaults_CertificateSigningRequest(in *CertificateSigningRequest) {
	SetDefaults_CertificateSigningRequestSpec(&in.Spec)
}

func SetObjectDefaults_CertificateSigningRequestList(in *CertificateSigningRequestList) {
	for i := range in.Items {
		a := &in.Items[i]
		SetObjectDefaults_CertificateSigningRequest(a)
	}
}
<|endoftext|>


<commit_before>package resource

import (
	"fmt"
	"strings"

	"github.com/dokku/dokku/plugins/common"
)

func addMemorySuffixForDocker(key string, value string) string {
	if key == "memory" {
		hasSuffix := false
		suffixes := []string{"b", "k", "m", "g", "KB", "MB", "GB"}
		for _, suffix := range suffixes {
			if strings.HasSuffix(value, suffix) {
				hasSuffix = true
			}
		}
		if !hasSuffix {
			value = value + "m"
		}
	}
	return value
}

func clearByResourceType(appName string, processType string, resourceType string) {
	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}

	message := fmt.Sprintf("clearing %v %v", appName, noun)
	if processType != "_default_" && processType != "" {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	if processType == "" {
		resources, err := common.PropertyGetAll("resource", appName)
		if err != nil {
			return
		}
		for key := range resources {
			common.PropertyDelete("resource", appName, key)
		}
	} else {
		resources := []string{
			"cpu",
			"memory",
			"memory-swap",
			"network",
			"network-ingress",
			"network-egress",
			"nvidia-gpu",
		}

		for _, key := range resources {
			property := propertyKey(processType, resourceType, key)
			common.PropertyDelete("resource", appName, property)
		}
	}
}

func setResourceType(appName string, processType string, r Resource, resourceType string) error {
	if len(processType) == 0 {
		processType = "_default_"
	}

	resources := map[string]string{
		"cpu":             r.CPU,
		"memory":          r.Memory,
		"memory-swap":     r.MemorySwap,
		"network":         r.Network,
		"network-ingress": r.NetworkIngress,
		"network-egress":  r.NetworkEgress,
		"nvidia-gpu":      r.NvidiaGPU,
	}

	hasValues := false
	for _, value := range resources {
		if value != "" {
			hasValues = true
		}
	}

	if !hasValues {
		reportResourceType(appName, processType, resourceType)
		return nil
	}

	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}
	message := fmt.Sprintf("Setting resource %v for %v", noun, appName)
	if processType != "_default_" {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	for key, value := range resources {
		if value == "" {
			continue
		}

		property := propertyKey(processType, resourceType, key)
		if value == "clear" {
			common.LogVerbose(fmt.Sprintf("%v: cleared", key))
			if err := common.PropertyDelete("resource", appName, property); err != nil {
				return err
			}
			continue
		}

		common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
		if err := common.PropertyWrite("resource", appName, property, value); err != nil {
			return err
		}
	}

	return nil
}

func reportResourceType(appName string, processType string, resourceType string) {
	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}

	message := fmt.Sprintf("resource %v %v information", noun, appName)
	if processType == "_default_" {
		message = fmt.Sprintf("%v [defaults]", message)
	} else {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	resources := []string{
		"cpu",
		"memory",
		"memory-swap",
		"network",
		"network-ingress",
		"network-egress",
		"nvidia-gpu",
	}

	for _, key := range resources {
		property := propertyKey(processType, resourceType, key)
		value := common.PropertyGet("resource", appName, property)
		common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
	}
}
<commit_msg>fix: add missing B suffix to list<commit_after>package resource

import (
	"fmt"
	"strings"

	"github.com/dokku/dokku/plugins/common"
)

func addMemorySuffixForDocker(key string, value string) string {
	if key == "memory" {
		hasSuffix := false
		suffixes := []string{"b", "k", "m", "g", "KB", "MB", "GB", "B"}
		for _, suffix := range suffixes {
			if strings.HasSuffix(value, suffix) {
				hasSuffix = true
			}
		}
		if !hasSuffix {
			value = value + "m"
		}
	}
	return value
}

func clearByResourceType(appName string, processType string, resourceType string) {
	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}

	message := fmt.Sprintf("clearing %v %v", appName, noun)
	if processType != "_default_" && processType != "" {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	if processType == "" {
		resources, err := common.PropertyGetAll("resource", appName)
		if err != nil {
			return
		}
		for key := range resources {
			common.PropertyDelete("resource", appName, key)
		}
	} else {
		resources := []string{
			"cpu",
			"memory",
			"memory-swap",
			"network",
			"network-ingress",
			"network-egress",
			"nvidia-gpu",
		}

		for _, key := range resources {
			property := propertyKey(processType, resourceType, key)
			common.PropertyDelete("resource", appName, property)
		}
	}
}

func setResourceType(appName string, processType string, r Resource, resourceType string) error {
	if len(processType) == 0 {
		processType = "_default_"
	}

	resources := map[string]string{
		"cpu":             r.CPU,
		"memory":          r.Memory,
		"memory-swap":     r.MemorySwap,
		"network":         r.Network,
		"network-ingress": r.NetworkIngress,
		"network-egress":  r.NetworkEgress,
		"nvidia-gpu":      r.NvidiaGPU,
	}

	hasValues := false
	for _, value := range resources {
		if value != "" {
			hasValues = true
		}
	}

	if !hasValues {
		reportResourceType(appName, processType, resourceType)
		return nil
	}

	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}
	message := fmt.Sprintf("Setting resource %v for %v", noun, appName)
	if processType != "_default_" {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	for key, value := range resources {
		if value == "" {
			continue
		}

		property := propertyKey(processType, resourceType, key)
		if value == "clear" {
			common.LogVerbose(fmt.Sprintf("%v: cleared", key))
			if err := common.PropertyDelete("resource", appName, property); err != nil {
				return err
			}
			continue
		}

		common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
		if err := common.PropertyWrite("resource", appName, property, value); err != nil {
			return err
		}
	}

	return nil
}

func reportResourceType(appName string, processType string, resourceType string) {
	noun := "limits"
	if resourceType == "reserve" {
		noun = "reservation"
	}

	message := fmt.Sprintf("resource %v %v information", noun, appName)
	if processType == "_default_" {
		message = fmt.Sprintf("%v [defaults]", message)
	} else {
		message = fmt.Sprintf("%v (%v)", message, processType)
	}
	common.LogInfo2Quiet(message)

	resources := []string{
		"cpu",
		"memory",
		"memory-swap",
		"network",
		"network-ingress",
		"network-egress",
		"nvidia-gpu",
	}

	for _, key := range resources {
		property := propertyKey(processType, resourceType, key)
		value := common.PropertyGet("resource", appName, property)
		common.LogVerbose(fmt.Sprintf("%v: %v", key, value))
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 l3

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

// Prefixes
const (
	// VrfPrefix is the relative key prefix for VRFs.
	VrfPrefix = "vpp/config/v1/vrf/"
	// RoutesPrefix is the relative key prefix for routes.
	RoutesPrefix = VrfPrefix + "{vrf}/fib/{net}/{mask}/{next-hop}"
	// ArpPrefix is the relative key prefix for ARP.
	ArpPrefix = "vpp/config/v1/arp/"
	// ArpEntryPrefix is the relative key prefix for ARP table entries.
	ArpKey = ArpPrefix + "{if}/{ip}"
	// ProxyARPPrefix is the relative key prefix for proxy ARP configuration.
	ProxyARPPrefix = "vpp/config/v1/proxyarp/"
	// ProxyARPRangePrefix is the relative key prefix for proxy ARP ranges.
	ProxyARPRangePrefix = ProxyARPPrefix + "range/{lo_ip}/{hi_ip}"
	// ProxyARPInterfacePrefix is the relative key prefix for proxy ARP-enabled interfaces.
	ProxyARPInterfacePrefix = ProxyARPPrefix + "interface/{if}"
	// STNPrefix is the relative key prefix for STN entries.
	STNPrefix = "vpp/config/v1/stn/{ip}"
)

// VrfKeyPrefix returns the prefix used in ETCD to store VRFs for vpp instance.
func VrfKeyPrefix() string {
	return VrfPrefix
}

// RouteKeyPrefix returns the prefix used in ETCD to store vpp routes for vpp instance.
func RouteKeyPrefix() string {
	return RoutesPrefix
}

// ArpKeyPrefix returns the prefix used in ETCD to store vpp APR tables for vpp instance.
func ArpKeyPrefix() string {
	return ArpPrefix
}

// RouteKey returns the key used in ETCD to store vpp route for vpp instance.
func RouteKey(vrf uint32, dstAddr string, nextHopAddr string) string {
	_, dstNet, _ := net.ParseCIDR(dstAddr)
	dstNetAddr := dstNet.IP.String()
	dstNetMask, _ := dstNet.Mask.Size()
	key := RoutesPrefix
	key = strings.Replace(key, "{vrf}", strconv.Itoa(int(vrf)), 1)
	key = strings.Replace(key, "{net}", dstNetAddr, 1)
	key = strings.Replace(key, "{mask}", strconv.Itoa(dstNetMask), 1)
	key = strings.Replace(key, "{next-hop}", nextHopAddr, 1)
	return key
}

// ParseRouteKey parses VRF label and route address from a route key.
func ParseRouteKey(key string) (isRouteKey bool, vrfIndex string, dstNetAddr string, dstNetMask int, nextHopAddr string) {
	if strings.HasPrefix(key, VrfKeyPrefix()) {
		vrfSuffix := strings.TrimPrefix(key, VrfKeyPrefix())
		routeComps := strings.Split(vrfSuffix, "/")
		if len(routeComps) >= 5 && routeComps[1] == "fib" {
			if mask, err := strconv.Atoi(routeComps[3]); err == nil {
				return true, routeComps[0], routeComps[2], mask, routeComps[4]
			}
		}
	}
	return false, "", "", 0, ""
}

// ArpEntryKey returns the key to store ARP entry
func ArpEntryKey(iface, ipAddr string) string {
	key := ArpKey
	key = strings.Replace(key, "{if}", iface, 1)
	key = strings.Replace(key, "{ip}", ipAddr, 1)
	//key = strings.Replace(key, "{mac}", macAddr, 1)
	return key
}

// ParseArpKey parses ARP entry from a key
func ParseArpKey(key string) (iface string, ipAddr string, err error) {
	if strings.HasPrefix(key, ArpPrefix) {
		arpSuffix := strings.TrimPrefix(key, ArpPrefix)
		arpComps := strings.Split(arpSuffix, "/")
		if len(arpComps) == 2 {
			return arpComps[0], arpComps[1], nil
		}
	}
	return "", "", fmt.Errorf("invalid ARP key")
}
<commit_msg>keys and prefixes<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 l3

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

// Prefixes
const (
	// VrfPrefix is the relative key prefix for VRFs.
	VrfPrefix = "vpp/config/v1/vrf/"
	// RoutesPrefix is the relative key prefix for routes.
	RoutesPrefix = VrfPrefix + "{vrf}/fib/{net}/{mask}/{next-hop}"
	// ArpPrefix is the relative key prefix for ARP.
	ArpPrefix = "vpp/config/v1/arp/"
	// ArpEntryPrefix is the relative key prefix for ARP table entries.
	ArpKey = ArpPrefix + "{if}/{ip}"
	// ProxyARPPrefix is the relative key prefix for proxy ARP configuration.
	ProxyARPRangePrefix = "vpp/config/v1/proxyarp/range/"
	// ProxyARPPrefix is the relative key prefix for proxy ARP configuration.
	ProxyARPInterfacePrefix = "vpp/config/v1/proxyarp/interface/"
	// ProxyARPRangePrefix is the relative key prefix for proxy ARP ranges.
	ProxyARPRangeKey = ProxyARPRangePrefix + "{first}/{last}"
	// ProxyARPInterfacePrefix is the relative key prefix for proxy ARP-enabled interfaces.
	ProxyARPInterfaceKey = ProxyARPInterfacePrefix + "{if}"
)

// VrfKeyPrefix returns the prefix used in ETCD to store VRFs for vpp instance.
func VrfKeyPrefix() string {
	return VrfPrefix
}

// RouteKeyPrefix returns the prefix used in ETCD to store vpp routes for vpp instance.
func RouteKeyPrefix() string {
	return RoutesPrefix
}

// ArpKeyPrefix returns the prefix used in ETCD to store vpp APR tables for vpp instance.
func ArpKeyPrefix() string {
	return ArpPrefix
}

// ProxyArpPrefix returns the prefix used in ETCD to store proxy APR ranges for vpp instance.
func ProxyArpRangePrefix() string {
	return ProxyARPRangePrefix
}

// ProxyArpPrefix returns the prefix used in ETCD to store proxy APR interfaces for vpp instance.
func ProxyArpInterfacePrefix() string {
	return ProxyARPInterfacePrefix
}

// RouteKey returns the key used in ETCD to store vpp route for vpp instance.
func RouteKey(vrf uint32, dstAddr string, nextHopAddr string) string {
	_, dstNet, _ := net.ParseCIDR(dstAddr)
	dstNetAddr := dstNet.IP.String()
	dstNetMask, _ := dstNet.Mask.Size()
	key := RoutesPrefix
	key = strings.Replace(key, "{vrf}", strconv.Itoa(int(vrf)), 1)
	key = strings.Replace(key, "{net}", dstNetAddr, 1)
	key = strings.Replace(key, "{mask}", strconv.Itoa(dstNetMask), 1)
	key = strings.Replace(key, "{next-hop}", nextHopAddr, 1)
	return key
}

// ParseRouteKey parses VRF label and route address from a route key.
func ParseRouteKey(key string) (isRouteKey bool, vrfIndex string, dstNetAddr string, dstNetMask int, nextHopAddr string) {
	if strings.HasPrefix(key, VrfKeyPrefix()) {
		vrfSuffix := strings.TrimPrefix(key, VrfKeyPrefix())
		routeComps := strings.Split(vrfSuffix, "/")
		if len(routeComps) >= 5 && routeComps[1] == "fib" {
			if mask, err := strconv.Atoi(routeComps[3]); err == nil {
				return true, routeComps[0], routeComps[2], mask, routeComps[4]
			}
		}
	}
	return false, "", "", 0, ""
}

// ArpEntryKey returns the key to store ARP entry
func ArpEntryKey(iface, ipAddr string) string {
	key := ArpKey
	key = strings.Replace(key, "{if}", iface, 1)
	key = strings.Replace(key, "{ip}", ipAddr, 1)
	//key = strings.Replace(key, "{mac}", macAddr, 1)
	return key
}

// ParseArpKey parses ARP entry from a key
func ParseArpKey(key string) (iface string, ipAddr string, err error) {
	if strings.HasPrefix(key, ArpPrefix) {
		arpSuffix := strings.TrimPrefix(key, ArpPrefix)
		arpComps := strings.Split(arpSuffix, "/")
		if len(arpComps) == 2 {
			return arpComps[0], arpComps[1], nil
		}
	}
	return "", "", fmt.Errorf("invalid ARP key")
}

func ProxyArpRangeKey(firstIP, lastIP string) string {
	key := ProxyARPRangeKey
	key = strings.Replace(key, "{first}", firstIP, 1)
	key = strings.Replace(key, "{last}", lastIP, 1)
	return key
}

func ParseProxyArpRangeKey(key string) (firstIP, lastIP string) {
	if strings.HasPrefix(key, ProxyARPRangePrefix) {
		suffix := strings.TrimPrefix(key, ProxyARPRangePrefix)
		ips := strings.Split(suffix, "/")
		if len(ips) == 2 {
			return ips[0], ips[1]
		}
	}
	return
}

func ProxyArpInterfaceKey(ifName string) string {
	key := ProxyARPInterfaceKey
	key = strings.Replace(key, "{inf}", ifName, 1)
	return key
}

func ParseProxyArpInterfaceKey(key string) (ifName string) {
	if strings.HasPrefix(key, ProxyARPInterfacePrefix) {
		ifName = strings.TrimPrefix(key, ProxyARPInterfacePrefix)
	}
	return
}<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package e2e

import (
	"strconv"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"
	clientv1 "k8s.io/client-go/pkg/api/v1"
	"k8s.io/kubernetes/pkg/api/v1"
	batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
	batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
	"k8s.io/kubernetes/test/e2e/framework"

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

func stagingClientPod(name, value string) clientv1.Pod {
	return clientv1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": "foo",
				"time": value,
			},
		},
		Spec: clientv1.PodSpec{
			Containers: []clientv1.Container{
				{
					Name:  "nginx",
					Image: "gcr.io/google_containers/nginx-slim:0.7",
					Ports: []clientv1.ContainerPort{{ContainerPort: 80}},
				},
			},
		},
	}
}

func testingPod(name, value string) v1.Pod {
	return v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": "foo",
				"time": value,
			},
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  "nginx",
					Image: "gcr.io/google_containers/nginx-slim:0.7",
					Ports: []v1.ContainerPort{{ContainerPort: 80}},
					LivenessProbe: &v1.Probe{
						Handler: v1.Handler{
							HTTPGet: &v1.HTTPGetAction{
								Path: "/index.html",
								Port: intstr.FromInt(8080),
							},
						},
						InitialDelaySeconds: 30,
					},
				},
			},
		},
	}
}

func observeCreation(w watch.Interface) {
	select {
	case event, _ := <-w.ResultChan():
		if event.Type != watch.Added {
			framework.Failf("Failed to observe the creation: %v", event)
		}
	case <-time.After(30 * time.Second):
		framework.Failf("Timeout while waiting for observing the creation")
	}
}

func observeObjectDeletion(w watch.Interface) (obj runtime.Object) {
	deleted := false
	timeout := false
	timer := time.After(60 * time.Second)
	for !deleted && !timeout {
		select {
		case event, _ := <-w.ResultChan():
			if event.Type == watch.Deleted {
				obj = event.Object
				deleted = true
			}
		case <-timer:
			timeout = true
		}
	}
	if !deleted {
		framework.Failf("Failed to observe pod deletion")
	}
	return
}

var _ = framework.KubeDescribe("Generated release_1_5 clientset", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create pods, delete pods, watch pods", func() {
		podClient := f.ClientSet.Core().Pods(f.Namespace.Name)
		By("constructing the pod")
		name := "pod" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		podCopy := testingPod(name, value)
		pod := &podCopy
		By("setting up watch")
		selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String()
		options := metav1.ListOptions{LabelSelector: selector}
		pods, err := podClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: pods.ListMeta.ResourceVersion,
		}
		w, err := podClient.Watch(options)
		if err != nil {
			framework.Failf("Failed to set up watch: %v", err)
		}

		By("creating the pod")
		pod, err = podClient.Create(pod)
		if err != nil {
			framework.Failf("Failed to create pod: %v", err)
		}

		By("verifying the pod is in kubernetes")
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: pod.ResourceVersion,
		}
		pods, err = podClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(1))

		By("verifying pod creation was observed")
		observeCreation(w)

		// We need to wait for the pod to be scheduled, otherwise the deletion
		// will be carried out immediately rather than gracefully.
		framework.ExpectNoError(f.WaitForPodRunning(pod.Name))

		By("deleting the pod gracefully")
		if err := podClient.Delete(pod.Name, metav1.NewDeleteOptions(30)); err != nil {
			framework.Failf("Failed to delete pod: %v", err)
		}

		By("verifying pod deletion was observed")
		obj := observeObjectDeletion(w)
		lastPod := obj.(*v1.Pod)
		Expect(lastPod.DeletionTimestamp).ToNot(BeNil())
		Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero())

		options = metav1.ListOptions{LabelSelector: selector}
		pods, err = podClient.List(options)
		if err != nil {
			framework.Failf("Failed to list pods to verify deletion: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
	})
})

func newTestingCronJob(name string, value string) *batchv2alpha1.CronJob {
	parallelism := int32(1)
	completions := int32(1)
	return &batchv2alpha1.CronJob{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"time": value,
			},
		},
		Spec: batchv2alpha1.CronJobSpec{
			Schedule:          "*/1 * * * ?",
			ConcurrencyPolicy: batchv2alpha1.AllowConcurrent,
			JobTemplate: batchv2alpha1.JobTemplateSpec{
				Spec: batchv1.JobSpec{
					Parallelism: &parallelism,
					Completions: &completions,
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							RestartPolicy: v1.RestartPolicyOnFailure,
							Volumes: []v1.Volume{
								{
									Name: "data",
									VolumeSource: v1.VolumeSource{
										EmptyDir: &v1.EmptyDirVolumeSource{},
									},
								},
							},
							Containers: []v1.Container{
								{
									Name:  "c",
									Image: "gcr.io/google_containers/busybox:1.24",
									VolumeMounts: []v1.VolumeMount{
										{
											MountPath: "/data",
											Name:      "data",
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

var _ = framework.KubeDescribe("Generated release_1_5 clientset", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create v2alpha1 cronJobs, delete cronJobs, watch cronJobs", func() {
		var enabled bool
		groupList, err := f.ClientSet.Discovery().ServerGroups()
		framework.ExpectNoError(err)
		for _, group := range groupList.Groups {
			if group.Name == batchv2alpha1.GroupName {
				for _, version := range group.Versions {
					if version.Version == batchv2alpha1.SchemeGroupVersion.Version {
						enabled = true
						break
					}
				}
			}
		}
		if !enabled {
			framework.Logf("%s is not enabled, test skipped", batchv2alpha1.SchemeGroupVersion)
			return
		}
		cronJobClient := f.ClientSet.BatchV2alpha1().CronJobs(f.Namespace.Name)
		By("constructing the cronJob")
		name := "cronjob" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		cronJob := newTestingCronJob(name, value)
		By("setting up watch")
		selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String()
		options := metav1.ListOptions{LabelSelector: selector}
		cronJobs, err := cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for cronJobs: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(0))
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: cronJobs.ListMeta.ResourceVersion,
		}
		w, err := cronJobClient.Watch(options)
		if err != nil {
			framework.Failf("Failed to set up watch: %v", err)
		}

		By("creating the cronJob")
		cronJob, err = cronJobClient.Create(cronJob)
		if err != nil {
			framework.Failf("Failed to create cronJob: %v", err)
		}

		By("verifying the cronJob is in kubernetes")
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: cronJob.ResourceVersion,
		}
		cronJobs, err = cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for cronJobs: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(1))

		By("verifying cronJob creation was observed")
		observeCreation(w)

		By("deleting the cronJob")
		if err := cronJobClient.Delete(cronJob.Name, nil); err != nil {
			framework.Failf("Failed to delete cronJob: %v", err)
		}

		options = metav1.ListOptions{LabelSelector: selector}
		cronJobs, err = cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to list cronJobs to verify deletion: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(0))
	})
})

var _ = framework.KubeDescribe("Staging client repo client", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create pods, delete pods, watch pods", func() {
		podClient := f.StagingClient.Core().Pods(f.Namespace.Name)
		By("constructing the pod")
		name := "pod" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		podCopy := stagingClientPod(name, value)
		pod := &podCopy
		By("verifying no pod exists before the test")
		pods, err := podClient.List(metav1.ListOptions{})
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
		By("creating the pod")
		pod, err = podClient.Create(pod)
		if err != nil {
			framework.Failf("Failed to create pod: %v", err)
		}

		By("verifying the pod is in kubernetes")
		timeout := 1 * time.Minute
		if err := wait.PollImmediate(time.Second, timeout, func() (bool, error) {
			pods, err = podClient.List(metav1.ListOptions{})
			if err != nil {
				return false, err
			}
			if len(pods.Items) == 1 {
				return true, nil
			}
			return false, nil
		}); err != nil {
			framework.Failf("Err : %s\n. Failed to wait for 1 pod to be created", err)
		}
	})
})
<commit_msg>add debugging to the client watch test<commit_after>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package e2e

import (
	"strconv"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"
	clientv1 "k8s.io/client-go/pkg/api/v1"
	"k8s.io/kubernetes/pkg/api/v1"
	batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
	batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
	"k8s.io/kubernetes/test/e2e/framework"

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

func stagingClientPod(name, value string) clientv1.Pod {
	return clientv1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": "foo",
				"time": value,
			},
		},
		Spec: clientv1.PodSpec{
			Containers: []clientv1.Container{
				{
					Name:  "nginx",
					Image: "gcr.io/google_containers/nginx-slim:0.7",
					Ports: []clientv1.ContainerPort{{ContainerPort: 80}},
				},
			},
		},
	}
}

func testingPod(name, value string) v1.Pod {
	return v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": "foo",
				"time": value,
			},
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:  "nginx",
					Image: "gcr.io/google_containers/nginx-slim:0.7",
					Ports: []v1.ContainerPort{{ContainerPort: 80}},
					LivenessProbe: &v1.Probe{
						Handler: v1.Handler{
							HTTPGet: &v1.HTTPGetAction{
								Path: "/index.html",
								Port: intstr.FromInt(8080),
							},
						},
						InitialDelaySeconds: 30,
					},
				},
			},
		},
	}
}

func observeCreation(w watch.Interface) {
	select {
	case event, _ := <-w.ResultChan():
		if event.Type != watch.Added {
			framework.Failf("Failed to observe the creation: %v", event)
		}
	case <-time.After(30 * time.Second):
		framework.Failf("Timeout while waiting for observing the creation")
	}
}

func observeObjectDeletion(w watch.Interface) (obj runtime.Object) {
	// output to give us a duration to failure.  Maybe we aren't getting the
	// full timeout for some reason.  My guess would be watch failure
	framework.Logf("Starting to observe pod deletion")
	deleted := false
	timeout := false
	timer := time.After(60 * time.Second)
	for !deleted && !timeout {
		select {
		case event, normal := <-w.ResultChan():
			if !normal {
				framework.Failf("The channel was closed unexpectedly")
				return
			}
			if event.Type == watch.Deleted {
				obj = event.Object
				deleted = true
			}
		case <-timer:
			timeout = true
		}
	}
	if !deleted {
		framework.Failf("Failed to observe pod deletion")
	}
	return
}

var _ = framework.KubeDescribe("Generated release_1_5 clientset", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create pods, delete pods, watch pods", func() {
		podClient := f.ClientSet.Core().Pods(f.Namespace.Name)
		By("constructing the pod")
		name := "pod" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		podCopy := testingPod(name, value)
		pod := &podCopy
		By("setting up watch")
		selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String()
		options := metav1.ListOptions{LabelSelector: selector}
		pods, err := podClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: pods.ListMeta.ResourceVersion,
		}
		w, err := podClient.Watch(options)
		if err != nil {
			framework.Failf("Failed to set up watch: %v", err)
		}

		By("creating the pod")
		pod, err = podClient.Create(pod)
		if err != nil {
			framework.Failf("Failed to create pod: %v", err)
		}

		By("verifying the pod is in kubernetes")
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: pod.ResourceVersion,
		}
		pods, err = podClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(1))

		By("verifying pod creation was observed")
		observeCreation(w)

		// We need to wait for the pod to be scheduled, otherwise the deletion
		// will be carried out immediately rather than gracefully.
		framework.ExpectNoError(f.WaitForPodRunning(pod.Name))

		By("deleting the pod gracefully")
		if err := podClient.Delete(pod.Name, metav1.NewDeleteOptions(30)); err != nil {
			framework.Failf("Failed to delete pod: %v", err)
		}

		By("verifying pod deletion was observed")
		obj := observeObjectDeletion(w)
		lastPod := obj.(*v1.Pod)
		Expect(lastPod.DeletionTimestamp).ToNot(BeNil())
		Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero())

		options = metav1.ListOptions{LabelSelector: selector}
		pods, err = podClient.List(options)
		if err != nil {
			framework.Failf("Failed to list pods to verify deletion: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
	})
})

func newTestingCronJob(name string, value string) *batchv2alpha1.CronJob {
	parallelism := int32(1)
	completions := int32(1)
	return &batchv2alpha1.CronJob{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"time": value,
			},
		},
		Spec: batchv2alpha1.CronJobSpec{
			Schedule:          "*/1 * * * ?",
			ConcurrencyPolicy: batchv2alpha1.AllowConcurrent,
			JobTemplate: batchv2alpha1.JobTemplateSpec{
				Spec: batchv1.JobSpec{
					Parallelism: &parallelism,
					Completions: &completions,
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							RestartPolicy: v1.RestartPolicyOnFailure,
							Volumes: []v1.Volume{
								{
									Name: "data",
									VolumeSource: v1.VolumeSource{
										EmptyDir: &v1.EmptyDirVolumeSource{},
									},
								},
							},
							Containers: []v1.Container{
								{
									Name:  "c",
									Image: "gcr.io/google_containers/busybox:1.24",
									VolumeMounts: []v1.VolumeMount{
										{
											MountPath: "/data",
											Name:      "data",
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

var _ = framework.KubeDescribe("Generated release_1_5 clientset", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create v2alpha1 cronJobs, delete cronJobs, watch cronJobs", func() {
		var enabled bool
		groupList, err := f.ClientSet.Discovery().ServerGroups()
		framework.ExpectNoError(err)
		for _, group := range groupList.Groups {
			if group.Name == batchv2alpha1.GroupName {
				for _, version := range group.Versions {
					if version.Version == batchv2alpha1.SchemeGroupVersion.Version {
						enabled = true
						break
					}
				}
			}
		}
		if !enabled {
			framework.Logf("%s is not enabled, test skipped", batchv2alpha1.SchemeGroupVersion)
			return
		}
		cronJobClient := f.ClientSet.BatchV2alpha1().CronJobs(f.Namespace.Name)
		By("constructing the cronJob")
		name := "cronjob" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		cronJob := newTestingCronJob(name, value)
		By("setting up watch")
		selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String()
		options := metav1.ListOptions{LabelSelector: selector}
		cronJobs, err := cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for cronJobs: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(0))
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: cronJobs.ListMeta.ResourceVersion,
		}
		w, err := cronJobClient.Watch(options)
		if err != nil {
			framework.Failf("Failed to set up watch: %v", err)
		}

		By("creating the cronJob")
		cronJob, err = cronJobClient.Create(cronJob)
		if err != nil {
			framework.Failf("Failed to create cronJob: %v", err)
		}

		By("verifying the cronJob is in kubernetes")
		options = metav1.ListOptions{
			LabelSelector:   selector,
			ResourceVersion: cronJob.ResourceVersion,
		}
		cronJobs, err = cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to query for cronJobs: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(1))

		By("verifying cronJob creation was observed")
		observeCreation(w)

		By("deleting the cronJob")
		if err := cronJobClient.Delete(cronJob.Name, nil); err != nil {
			framework.Failf("Failed to delete cronJob: %v", err)
		}

		options = metav1.ListOptions{LabelSelector: selector}
		cronJobs, err = cronJobClient.List(options)
		if err != nil {
			framework.Failf("Failed to list cronJobs to verify deletion: %v", err)
		}
		Expect(len(cronJobs.Items)).To(Equal(0))
	})
})

var _ = framework.KubeDescribe("Staging client repo client", func() {
	f := framework.NewDefaultFramework("clientset")
	It("should create pods, delete pods, watch pods", func() {
		podClient := f.StagingClient.Core().Pods(f.Namespace.Name)
		By("constructing the pod")
		name := "pod" + string(uuid.NewUUID())
		value := strconv.Itoa(time.Now().Nanosecond())
		podCopy := stagingClientPod(name, value)
		pod := &podCopy
		By("verifying no pod exists before the test")
		pods, err := podClient.List(metav1.ListOptions{})
		if err != nil {
			framework.Failf("Failed to query for pods: %v", err)
		}
		Expect(len(pods.Items)).To(Equal(0))
		By("creating the pod")
		pod, err = podClient.Create(pod)
		if err != nil {
			framework.Failf("Failed to create pod: %v", err)
		}

		By("verifying the pod is in kubernetes")
		timeout := 1 * time.Minute
		if err := wait.PollImmediate(time.Second, timeout, func() (bool, error) {
			pods, err = podClient.List(metav1.ListOptions{})
			if err != nil {
				return false, err
			}
			if len(pods.Items) == 1 {
				return true, nil
			}
			return false, nil
		}); err != nil {
			framework.Failf("Err : %s\n. Failed to wait for 1 pod to be created", err)
		}
	})
})
<|endoftext|>


<commit_before>package alert

import (
	"context"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	"github.com/prometheus/common/model"

	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/disruption"
	helper "github.com/openshift/origin/test/extended/util/prometheus"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/e2e/upgrades"
)

// UpgradeTest runs verifies invariants regarding what alerts are allowed to fire
// during the upgrade process.
type UpgradeTest struct {
	url         string
	bearerToken string
	oc          *exutil.CLI
}

func (UpgradeTest) Name() string { return "check-for-alerts" }
func (UpgradeTest) DisplayName() string {
	return "[sig-arch] Check if alerts are firing during or after upgrade success"
}

// Setup creates parameters to query Prometheus
func (t *UpgradeTest) Setup(f *framework.Framework) {
	g.By("Setting up upgrade alert test")

	oc := exutil.NewCLIWithFramework(f)
	url, _, bearerToken, ok := helper.LocatePrometheus(oc)
	if !ok {
		framework.Failf("Prometheus could not be located on this cluster, failing test %s", t.Name())
	}
	t.url = url
	t.bearerToken = bearerToken
	t.oc = oc
	framework.Logf("Post-upgrade alert test setup complete")
}

// Test checks if alerts are firing at various points during upgrade.
// An alert firing during an upgrade is a high severity bug - it either points to a real issue in
// a dependency, or a failure of the component, and therefore must be fixed.
func (t *UpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	tolerateDuringSkew := exutil.TolerateVersionSkewInTests()
	firingAlertsWithBugs := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "KubePodNotReady", "namespace": "openshift-kube-apiserver-operator"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "KubePodNotReady", "namespace": "openshift-kube-apiserver-operator"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDegraded", "name": "openshift-apiserver"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDown", "name": "authentication"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDown", "name": "machine-config"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1955300",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDegraded", "name": "authentication"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "KubeDaemonSetRolloutStuck"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1943667",
		},
		{
			Selector: map[string]string{"alertname": "KubeAPIErrorBudgetBurn"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1953798",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
		{
			Selector: map[string]string{"alertname": "AggregatedAPIDown", "namespace": "default", "name": "v1beta1.metrics.k8s.io"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1970624",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
		{
			// Should be removed one release after the attached bugzilla is fixed.
			Selector: map[string]string{"alertname": "HighlyAvailableWorkloadIncorrectlySpread", "namespace": "openshift-monitoring", "workload": "prometheus-k8s"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1949262",
		},
		{
			// Should be removed one release after the attached bugzilla is fixed.
			Selector: map[string]string{"alertname": "HighlyAvailableWorkloadIncorrectlySpread", "namespace": "openshift-monitoring", "workload": "alertmanager-main"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1955489",
		},
		{
			// Should be removed one release after the attached bugzilla is fixed, or after that bug is fixed in a backport to the previous minor.
			Selector: map[string]string{"alertname": "HighOverallControlPlaneCPU"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1985073",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
	}

	pendingAlertsWithBugs := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "ClusterMonitoringOperatorReconciliationErrors"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1932624",
		},
		{
			Selector: map[string]string{"alertname": "KubeClientErrors"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1925698",
		},
	}
	allowedPendingAlerts := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "etcdMemberCommunicationSlow"},
			Text:     "Excluded because it triggers during upgrade (detects ~5m of high latency immediately preceeding the end of the test), and we don't want to change the alert because it is correct",
		},
	}

	knownViolations := sets.NewString()
	unexpectedViolations := sets.NewString()
	unexpectedViolationsAsFlakes := sets.NewString()
	debug := sets.NewString()

	g.By("Checking for alerts")

	start := time.Now()

	// Block until upgrade is done
	g.By("Waiting for upgrade to finish before checking for alerts")
	<-done

	// Additonal delay after upgrade completion to allow pending alerts to settle
	g.By("Waiting before checking for alerts")
	time.Sleep(1 * time.Minute)

	ns := t.oc.SetupNamespace()
	execPod := exutil.CreateExecPodOrFail(t.oc.AdminKubeClient(), ns, "execpod")
	defer func() {
		t.oc.AdminKubeClient().CoreV1().Pods(ns).Delete(context.Background(), execPod.Name, *metav1.NewDeleteOptions(1))
	}()

	testDuration := time.Now().Sub(start).Truncate(time.Second)

	// Invariant: The watchdog alert should be firing continuously during the whole upgrade via the thanos
	// querier (which should have no gaps when it queries the individual stores). Allow zero or one changes
	// to the presence of this series (zero if data is preserved over upgrade, one if data is lost on upgrade).
	// This would not catch the alert stopping firing, but we catch that in other places and tests.
	watchdogQuery := fmt.Sprintf(`changes((max((ALERTS{alertstate="firing",alertname="Watchdog",severity="none"}) or (absent(ALERTS{alertstate="firing",alertname="Watchdog",severity="none"})*0)))[%s:1s]) > 1`, testDuration)
	result, err := helper.RunQuery(watchdogQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check watchdog alert over upgrade window")
	if len(result.Data.Result) > 0 {
		if result.Data.Result[0].Value <= 8 {
			unexpectedViolations.Insert(fmt.Sprintf("Watchdog alert had %s changes during the run, which may be a sign of a Prometheus outage in violation of the prometheus query SLO of 100%% uptime during upgrade", result.Data.Result[0].Value))
		} else {
			knownViolations.Insert(fmt.Sprintf("Watchdog alert had %s changes during the run, which may be a sign of a Prometheus outage in violation of the prometheus query SLO of 100%% uptime during upgrade, but is being tracked in https://bugzilla.redhat.com/show_bug.cgi?id=1949262 and is acceptable while that is open", result.Data.Result[0].Value))
		}
	}

	// Invariant: No non-info level alerts should have fired during the upgrade
	firingAlertQuery := fmt.Sprintf(`
sort_desc(
count_over_time(ALERTS{alertstate="firing",severity!="info",alertname!~"Watchdog|AlertmanagerReceiversNotConfigured"}[%[1]s:1s])
) > 0
`, testDuration)
	result, err = helper.RunQuery(firingAlertQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check firing alerts during upgrade")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s fired for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := firingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s (open bug: %s)", violation, cause.Text))
		} else {
			unexpectedViolations.Insert(violation)
		}
	}

	// Invariant: There should be no pending alerts 1m after the upgrade completes
	pendingAlertQuery := fmt.Sprintf(`
sort_desc(
  time() * ALERTS + 1
  -
  last_over_time((
    time() * ALERTS{alertname!~"Watchdog|AlertmanagerReceiversNotConfigured",alertstate="pending",severity!="info"}
    unless
    ALERTS offset 1s
  )[%[1]s:1s])
)
`, testDuration)
	result, err = helper.RunQuery(pendingAlertQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to retrieve pending alerts after upgrade")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s pending for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedPendingAlerts.Matches(series); cause != nil {
			debug.Insert(fmt.Sprintf("%s (allowed: %s)", violation, cause.Text))
			continue
		}
		if cause := pendingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s (open bug: %s)", violation, cause.Text))
		} else {
			// treat pending errors as a flake right now because we are still trying to determine the scope
			// TODO: move this to unexpectedViolations later
			unexpectedViolationsAsFlakes.Insert(violation)
		}
	}

	if len(debug) > 0 {
		framework.Logf("Alerts were detected during upgrade which are allowed:\n\n%s", strings.Join(debug.List(), "\n"))
	}
	if len(unexpectedViolations) > 0 {
		if !tolerateDuringSkew {
			framework.Failf("Unexpected alerts fired or pending during the upgrade:\n\n%s", strings.Join(unexpectedViolations.List(), "\n"))
		}
	}
	if flakes := sets.NewString().Union(knownViolations).Union(unexpectedViolations).Union(unexpectedViolationsAsFlakes); len(flakes) > 0 {
		disruption.FrameworkFlakef(f, "Unexpected alert behavior during upgrade:\n\n%s", strings.Join(flakes.List(), "\n"))
	}
	framework.Logf("No alerts fired during upgrade")
}

// Teardown cleans up any remaining resources.
func (t *UpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}
<commit_msg>test/e2e/upgrade/alert: Temporarily allow ExtremelyHighIndividualControlPlaneCPU<commit_after>package alert

import (
	"context"
	"fmt"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	"github.com/prometheus/common/model"

	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/disruption"
	helper "github.com/openshift/origin/test/extended/util/prometheus"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/e2e/upgrades"
)

// UpgradeTest runs verifies invariants regarding what alerts are allowed to fire
// during the upgrade process.
type UpgradeTest struct {
	url         string
	bearerToken string
	oc          *exutil.CLI
}

func (UpgradeTest) Name() string { return "check-for-alerts" }
func (UpgradeTest) DisplayName() string {
	return "[sig-arch] Check if alerts are firing during or after upgrade success"
}

// Setup creates parameters to query Prometheus
func (t *UpgradeTest) Setup(f *framework.Framework) {
	g.By("Setting up upgrade alert test")

	oc := exutil.NewCLIWithFramework(f)
	url, _, bearerToken, ok := helper.LocatePrometheus(oc)
	if !ok {
		framework.Failf("Prometheus could not be located on this cluster, failing test %s", t.Name())
	}
	t.url = url
	t.bearerToken = bearerToken
	t.oc = oc
	framework.Logf("Post-upgrade alert test setup complete")
}

// Test checks if alerts are firing at various points during upgrade.
// An alert firing during an upgrade is a high severity bug - it either points to a real issue in
// a dependency, or a failure of the component, and therefore must be fixed.
func (t *UpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	tolerateDuringSkew := exutil.TolerateVersionSkewInTests()
	firingAlertsWithBugs := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "KubePodNotReady", "namespace": "openshift-kube-apiserver-operator"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "KubePodNotReady", "namespace": "openshift-kube-apiserver-operator"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDegraded", "name": "openshift-apiserver"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDown", "name": "authentication"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDown", "name": "machine-config"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1955300",
		},
		{
			Selector: map[string]string{"alertname": "ClusterOperatorDegraded", "name": "authentication"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1939580",
		},
		{
			Selector: map[string]string{"alertname": "KubeDaemonSetRolloutStuck"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1943667",
		},
		{
			Selector: map[string]string{"alertname": "KubeAPIErrorBudgetBurn"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1953798",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
		{
			Selector: map[string]string{"alertname": "AggregatedAPIDown", "namespace": "default", "name": "v1beta1.metrics.k8s.io"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1970624",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
		{
			// Should be removed one release after the attached bugzilla is fixed.
			Selector: map[string]string{"alertname": "HighlyAvailableWorkloadIncorrectlySpread", "namespace": "openshift-monitoring", "workload": "prometheus-k8s"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1949262",
		},
		{
			// Should be removed one release after the attached bugzilla is fixed.
			Selector: map[string]string{"alertname": "HighlyAvailableWorkloadIncorrectlySpread", "namespace": "openshift-monitoring", "workload": "alertmanager-main"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1955489",
		},
		{
			// Should be removed one release after the attached bugzilla is fixed, or after that bug is fixed in a backport to the previous minor.
			Selector: map[string]string{"alertname": "ExtremelyHighIndividualControlPlaneCPU"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1985073",
			Matches: func(_ *model.Sample) bool {
				return framework.ProviderIs("gce")
			},
		},
	}

	pendingAlertsWithBugs := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "ClusterMonitoringOperatorReconciliationErrors"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1932624",
		},
		{
			Selector: map[string]string{"alertname": "KubeClientErrors"},
			Text:     "https://bugzilla.redhat.com/show_bug.cgi?id=1925698",
		},
	}
	allowedPendingAlerts := helper.MetricConditions{
		{
			Selector: map[string]string{"alertname": "etcdMemberCommunicationSlow"},
			Text:     "Excluded because it triggers during upgrade (detects ~5m of high latency immediately preceeding the end of the test), and we don't want to change the alert because it is correct",
		},
	}

	knownViolations := sets.NewString()
	unexpectedViolations := sets.NewString()
	unexpectedViolationsAsFlakes := sets.NewString()
	debug := sets.NewString()

	g.By("Checking for alerts")

	start := time.Now()

	// Block until upgrade is done
	g.By("Waiting for upgrade to finish before checking for alerts")
	<-done

	// Additonal delay after upgrade completion to allow pending alerts to settle
	g.By("Waiting before checking for alerts")
	time.Sleep(1 * time.Minute)

	ns := t.oc.SetupNamespace()
	execPod := exutil.CreateExecPodOrFail(t.oc.AdminKubeClient(), ns, "execpod")
	defer func() {
		t.oc.AdminKubeClient().CoreV1().Pods(ns).Delete(context.Background(), execPod.Name, *metav1.NewDeleteOptions(1))
	}()

	testDuration := time.Now().Sub(start).Truncate(time.Second)

	// Invariant: The watchdog alert should be firing continuously during the whole upgrade via the thanos
	// querier (which should have no gaps when it queries the individual stores). Allow zero or one changes
	// to the presence of this series (zero if data is preserved over upgrade, one if data is lost on upgrade).
	// This would not catch the alert stopping firing, but we catch that in other places and tests.
	watchdogQuery := fmt.Sprintf(`changes((max((ALERTS{alertstate="firing",alertname="Watchdog",severity="none"}) or (absent(ALERTS{alertstate="firing",alertname="Watchdog",severity="none"})*0)))[%s:1s]) > 1`, testDuration)
	result, err := helper.RunQuery(watchdogQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check watchdog alert over upgrade window")
	if len(result.Data.Result) > 0 {
		if result.Data.Result[0].Value <= 8 {
			unexpectedViolations.Insert(fmt.Sprintf("Watchdog alert had %s changes during the run, which may be a sign of a Prometheus outage in violation of the prometheus query SLO of 100%% uptime during upgrade", result.Data.Result[0].Value))
		} else {
			knownViolations.Insert(fmt.Sprintf("Watchdog alert had %s changes during the run, which may be a sign of a Prometheus outage in violation of the prometheus query SLO of 100%% uptime during upgrade, but is being tracked in https://bugzilla.redhat.com/show_bug.cgi?id=1949262 and is acceptable while that is open", result.Data.Result[0].Value))
		}
	}

	// Invariant: No non-info level alerts should have fired during the upgrade
	firingAlertQuery := fmt.Sprintf(`
sort_desc(
count_over_time(ALERTS{alertstate="firing",severity!="info",alertname!~"Watchdog|AlertmanagerReceiversNotConfigured"}[%[1]s:1s])
) > 0
`, testDuration)
	result, err = helper.RunQuery(firingAlertQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check firing alerts during upgrade")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s fired for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := firingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s (open bug: %s)", violation, cause.Text))
		} else {
			unexpectedViolations.Insert(violation)
		}
	}

	// Invariant: There should be no pending alerts 1m after the upgrade completes
	pendingAlertQuery := fmt.Sprintf(`
sort_desc(
  time() * ALERTS + 1
  -
  last_over_time((
    time() * ALERTS{alertname!~"Watchdog|AlertmanagerReceiversNotConfigured",alertstate="pending",severity!="info"}
    unless
    ALERTS offset 1s
  )[%[1]s:1s])
)
`, testDuration)
	result, err = helper.RunQuery(pendingAlertQuery, ns, execPod.Name, t.url, t.bearerToken)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to retrieve pending alerts after upgrade")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s pending for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedPendingAlerts.Matches(series); cause != nil {
			debug.Insert(fmt.Sprintf("%s (allowed: %s)", violation, cause.Text))
			continue
		}
		if cause := pendingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s (open bug: %s)", violation, cause.Text))
		} else {
			// treat pending errors as a flake right now because we are still trying to determine the scope
			// TODO: move this to unexpectedViolations later
			unexpectedViolationsAsFlakes.Insert(violation)
		}
	}

	if len(debug) > 0 {
		framework.Logf("Alerts were detected during upgrade which are allowed:\n\n%s", strings.Join(debug.List(), "\n"))
	}
	if len(unexpectedViolations) > 0 {
		if !tolerateDuringSkew {
			framework.Failf("Unexpected alerts fired or pending during the upgrade:\n\n%s", strings.Join(unexpectedViolations.List(), "\n"))
		}
	}
	if flakes := sets.NewString().Union(knownViolations).Union(unexpectedViolations).Union(unexpectedViolationsAsFlakes); len(flakes) > 0 {
		disruption.FrameworkFlakef(f, "Unexpected alert behavior during upgrade:\n\n%s", strings.Join(flakes.List(), "\n"))
	}
	framework.Logf("No alerts fired during upgrade")
}

// Teardown cleans up any remaining resources.
func (t *UpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}
<|endoftext|>


<commit_before>package pkgwork

import (
	"log"
	"sync"
	"time"
)

type Worker struct {
	Fn       func(string) error
	Cooldown time.Duration

	sync.Mutex

	inited  bool
	running map[string]time.Time
	again   map[string]bool
}

func (w *Worker) Init() {
	if w.inited {
		return
	}

	w.running = map[string]time.Time{}
	w.again = map[string]bool{}
	w.inited = true
}

func (w *Worker) Run(pkg string) error {
	w.Init()

	if !w.shouldStart(pkg) {
		return nil
	}

	defer w.finish(pkg)
	log.Printf("starting work on %s", pkg)

	err := w.Fn(pkg)
	if err != nil {
		return err
	}

	for w.shouldRunAgain(pkg) {
		err := w.Fn(pkg)
		if err != nil {
			return err
		}
	}
	return nil
}

func (w *Worker) finish(pkg string) {
	w.Lock()
	delete(w.running, pkg)
	delete(w.again, pkg)
	w.Unlock()
}

func (w *Worker) shouldRunAgain(pkg string) bool {
	w.Lock()
	again, _ := w.again[pkg]
	w.again[pkg] = false
	w.Unlock()
	return again
}

func (w *Worker) shouldStart(pkg string) bool {
	w.Lock()

	startedAt, alreadyRunning := w.running[pkg]
	if alreadyRunning {

		// If the cooldown has elapsed since the last start of the work for this
		// pkg, requeue the pkg to run again after the current process is complete
		if time.Since(startedAt) > w.Cooldown {
			log.Printf("requeuing %s", pkg)
			w.again[pkg] = true
		}

		w.Unlock()
		return false
	}

	w.running[pkg] = time.Now()
	w.Unlock()
	return true
}
<commit_msg>extract `run` func, with done logline<commit_after>package pkgwork

import (
	"log"
	"sync"
	"time"
)

type Worker struct {
	Fn       func(string) error
	Cooldown time.Duration

	sync.Mutex

	inited  bool
	running map[string]time.Time
	again   map[string]bool
}

func (w *Worker) Init() {
	if w.inited {
		return
	}

	w.running = map[string]time.Time{}
	w.again = map[string]bool{}
	w.inited = true
}

func (w *Worker) Run(pkg string) error {
	w.Init()

	if !w.shouldStart(pkg) {
		return nil
	}

	defer w.finish(pkg)

	err := w.run(pkg)
	if err != nil {
		return err
	}

	for w.shouldRunAgain(pkg) {
		err := w.run(pkg)
		if err != nil {
			return err
		}
	}
	return nil
}

func (w *Worker) run(pkg string) error {
	log.Printf("starting: %s", pkg)
	defer log.Printf("done: %s", pkg)
	return w.Fn(pkg)
}

func (w *Worker) finish(pkg string) {
	w.Lock()
	delete(w.running, pkg)
	delete(w.again, pkg)
	w.Unlock()
}

func (w *Worker) shouldRunAgain(pkg string) bool {
	w.Lock()
	again, _ := w.again[pkg]
	w.again[pkg] = false
	w.Unlock()
	return again
}

func (w *Worker) shouldStart(pkg string) bool {
	w.Lock()

	startedAt, alreadyRunning := w.running[pkg]
	if alreadyRunning {

		// If the cooldown has elapsed since the last start of the work for this
		// pkg, requeue the pkg to run again after the current process is complete
		if time.Since(startedAt) > w.Cooldown {
			log.Printf("requeuing %s", pkg)
			w.again[pkg] = true
		}

		w.Unlock()
		return false
	}

	w.running[pkg] = time.Now()
	w.Unlock()
	return true
}
<|endoftext|>


<commit_before>package ethui

import (
	"bytes"
	"fmt"
	"github.com/ethereum/eth-go"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethdb"
	"github.com/ethereum/eth-go/ethpub"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/go-qml/qml"
	"github.com/obscuren/mutan"
	"math/big"
	"strings"
)

type Gui struct {
	// The main application window
	win *qml.Window
	// QML Engine
	engine    *qml.Engine
	component *qml.Common
	// The ethereum interface
	eth *eth.Ethereum

	// The public Ethereum library
	lib   *EthLib
	uiLib *UiLib

	txDb *ethdb.LDBDatabase

	addr []byte

	pub *ethpub.PEthereum
}

// Create GUI, but doesn't start it
func New(ethereum *eth.Ethereum) *Gui {
	lib := &EthLib{stateManager: ethereum.StateManager(), blockChain: ethereum.BlockChain(), txPool: ethereum.TxPool()}
	db, err := ethdb.NewLDBDatabase("tx_database")
	if err != nil {
		panic(err)
	}

	data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
	// On first run we won't have any keys yet, so this would crash.
	// Therefor we check if we are ready to actually start this process
	var addr []byte
	if len(data) > 0 {
		key := ethutil.Config.Db.GetKeys()[0]
		addr = key.Address()

		//ethereum.StateManager().WatchAddr(addr)
	}

	pub := ethpub.NewPEthereum(ethereum)

	return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub}
}

func (gui *Gui) Start(assetPath string) {
	defer gui.txDb.Close()

	// Register ethereum functions
	qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{
		Init: func(p *ethpub.PBlock, obj qml.Object) { p.Number = 0; p.Hash = "" },
	}, {
		Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" },
	}})

	ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC3"))
	ethutil.Config.Log.Infoln("[GUI] Starting GUI")
	// Create a new QML engine
	gui.engine = qml.NewEngine()
	context := gui.engine.Context()

	// Expose the eth library and the ui library to QML
	context.SetVar("eth", gui)
	gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
	context.SetVar("ui", gui.uiLib)

	// Load the main QML interface
	data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
	/*
		var err error
		var component qml.Object
		firstRun := len(data) == 0

		if firstRun {
			component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml"))
		} else {
			component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml"))
		}
		if err != nil {
			ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'")

			panic(err)
		}

		gui.win = component.CreateWindow(nil)
		uiLib.win = gui.win
		db := &Debugger{gui.win, make(chan bool)}
		gui.lib.Db = db
		uiLib.Db = db

		// Add the ui as a log system so we can log directly to the UGI
		ethutil.Config.Log.AddLogSystem(gui)

		// Loads previous blocks
		if firstRun == false {
			go gui.setInitialBlockChain()
			go gui.readPreviousTransactions()
			go gui.update()
		}

		gui.win.Show()
		gui.win.Wait()

		gui.eth.Stop()
	*/

	var win *qml.Window
	var err error
	if len(data) == 0 {
		win, err = gui.showKeyImport(context)
	} else {
		win, err = gui.showWallet(context)
	}
	if err != nil {
		ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'")

		panic(err)
	}

	win.Show()
	win.Wait()

	gui.eth.Stop()
}

func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml"))
	if err != nil {
		return nil, err
	}

	win := gui.createWindow(component)

	go gui.setInitialBlockChain()
	go gui.readPreviousTransactions()
	go gui.update()

	return win, nil
}

func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
	context.SetVar("lib", gui.lib)
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
	if err != nil {
		return nil, err
	}

	return gui.createWindow(component), nil
}

func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
	win := comp.CreateWindow(nil)

	gui.win = win
	gui.uiLib.win = win

	db := &Debugger{gui.win, make(chan bool)}
	gui.lib.Db = db
	gui.uiLib.Db = db

	return gui.win
}

func (gui *Gui) setInitialBlockChain() {
	// Load previous 10 blocks
	chain := gui.eth.BlockChain().GetChain(gui.eth.BlockChain().CurrentBlock.Hash(), 10)
	for _, block := range chain {
		gui.processBlock(block)
	}

}

func (gui *Gui) readPreviousTransactions() {
	it := gui.txDb.Db().NewIterator(nil, nil)
	for it.Next() {
		tx := ethchain.NewTransactionFromBytes(it.Value())

		gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
	}
	it.Release()
}

func (gui *Gui) processBlock(block *ethchain.Block) {
	gui.win.Root().Call("addBlock", ethpub.NewPBlock(block))
}

// Simple go routine function that updates the list of peers in the GUI
func (gui *Gui) update() {
	txChan := make(chan ethchain.TxMsg, 1)
	gui.eth.TxPool().Subscribe(txChan)

	state := gui.eth.StateManager().TransState()

	unconfirmedFunds := new(big.Int)
	gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.addr).Amount)))

	for {
		select {
		case txMsg := <-txChan:
			tx := txMsg.Tx

			if txMsg.Type == ethchain.TxPre {
				object := state.GetAccount(gui.addr)

				if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce {
					gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())

					object.Nonce += 1
					state.SetStateObject(object)

					unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
				} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
					gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())

					unconfirmedFunds.Add(unconfirmedFunds, tx.Value)
				}

				pos := "+"
				if unconfirmedFunds.Cmp(big.NewInt(0)) >= 0 {
					pos = "-"
				}
				val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
				str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(object.Amount), pos, val)

				gui.win.Root().Call("setWalletValue", str)
			} else {
				object := state.GetAccount(gui.addr)
				if bytes.Compare(tx.Sender(), gui.addr) == 0 {
					object.SubAmount(tx.Value)
				} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
					object.AddAmount(tx.Value)
				}

				gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(object.Amount)))

				state.SetStateObject(object)
			}
		}
	}
}

// Logging functions that log directly to the GUI interface
func (gui *Gui) Println(v ...interface{}) {
	str := strings.TrimRight(fmt.Sprintln(v...), "\n")
	lines := strings.Split(str, "\n")
	for _, line := range lines {
		gui.win.Root().Call("addLog", line)
	}
}

func (gui *Gui) Printf(format string, v ...interface{}) {
	str := strings.TrimRight(fmt.Sprintf(format, v...), "\n")
	lines := strings.Split(str, "\n")
	for _, line := range lines {
		gui.win.Root().Call("addLog", line)
	}
}

func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
	keyPair := ethutil.Config.Db.GetKeys()[0]

	return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
}

func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
	keyPair := ethutil.Config.Db.GetKeys()[0]

	mainInput, initInput := mutan.PreParse(data)

	return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, initInput, mainInput)
}
<commit_msg>Bumped<commit_after>package ethui

import (
	"bytes"
	"fmt"
	"github.com/ethereum/eth-go"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethdb"
	"github.com/ethereum/eth-go/ethpub"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/go-qml/qml"
	"github.com/obscuren/mutan"
	"math/big"
	"strings"
)

type Gui struct {
	// The main application window
	win *qml.Window
	// QML Engine
	engine    *qml.Engine
	component *qml.Common
	// The ethereum interface
	eth *eth.Ethereum

	// The public Ethereum library
	lib   *EthLib
	uiLib *UiLib

	txDb *ethdb.LDBDatabase

	addr []byte

	pub *ethpub.PEthereum
}

// Create GUI, but doesn't start it
func New(ethereum *eth.Ethereum) *Gui {
	lib := &EthLib{stateManager: ethereum.StateManager(), blockChain: ethereum.BlockChain(), txPool: ethereum.TxPool()}
	db, err := ethdb.NewLDBDatabase("tx_database")
	if err != nil {
		panic(err)
	}

	data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
	// On first run we won't have any keys yet, so this would crash.
	// Therefor we check if we are ready to actually start this process
	var addr []byte
	if len(data) > 0 {
		key := ethutil.Config.Db.GetKeys()[0]
		addr = key.Address()

		//ethereum.StateManager().WatchAddr(addr)
	}

	pub := ethpub.NewPEthereum(ethereum)

	return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub}
}

func (gui *Gui) Start(assetPath string) {
	defer gui.txDb.Close()

	// Register ethereum functions
	qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{
		Init: func(p *ethpub.PBlock, obj qml.Object) { p.Number = 0; p.Hash = "" },
	}, {
		Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" },
	}})

	ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC4"))
	ethutil.Config.Log.Infoln("[GUI] Starting GUI")
	// Create a new QML engine
	gui.engine = qml.NewEngine()
	context := gui.engine.Context()

	// Expose the eth library and the ui library to QML
	context.SetVar("eth", gui)
	gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
	context.SetVar("ui", gui.uiLib)

	// Load the main QML interface
	data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
	/*
		var err error
		var component qml.Object
		firstRun := len(data) == 0

		if firstRun {
			component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml"))
		} else {
			component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml"))
		}
		if err != nil {
			ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'")

			panic(err)
		}

		gui.win = component.CreateWindow(nil)
		uiLib.win = gui.win
		db := &Debugger{gui.win, make(chan bool)}
		gui.lib.Db = db
		uiLib.Db = db

		// Add the ui as a log system so we can log directly to the UGI
		ethutil.Config.Log.AddLogSystem(gui)

		// Loads previous blocks
		if firstRun == false {
			go gui.setInitialBlockChain()
			go gui.readPreviousTransactions()
			go gui.update()
		}

		gui.win.Show()
		gui.win.Wait()

		gui.eth.Stop()
	*/

	var win *qml.Window
	var err error
	if len(data) == 0 {
		win, err = gui.showKeyImport(context)
	} else {
		win, err = gui.showWallet(context)
	}
	if err != nil {
		ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'")

		panic(err)
	}

	win.Show()
	win.Wait()

	gui.eth.Stop()
}

func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml"))
	if err != nil {
		return nil, err
	}

	win := gui.createWindow(component)

	go gui.setInitialBlockChain()
	go gui.readPreviousTransactions()
	go gui.update()

	return win, nil
}

func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
	context.SetVar("lib", gui.lib)
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
	if err != nil {
		return nil, err
	}

	return gui.createWindow(component), nil
}

func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
	win := comp.CreateWindow(nil)

	gui.win = win
	gui.uiLib.win = win

	db := &Debugger{gui.win, make(chan bool)}
	gui.lib.Db = db
	gui.uiLib.Db = db

	return gui.win
}

func (gui *Gui) setInitialBlockChain() {
	// Load previous 10 blocks
	chain := gui.eth.BlockChain().GetChain(gui.eth.BlockChain().CurrentBlock.Hash(), 10)
	for _, block := range chain {
		gui.processBlock(block)
	}

}

func (gui *Gui) readPreviousTransactions() {
	it := gui.txDb.Db().NewIterator(nil, nil)
	for it.Next() {
		tx := ethchain.NewTransactionFromBytes(it.Value())

		gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
	}
	it.Release()
}

func (gui *Gui) processBlock(block *ethchain.Block) {
	gui.win.Root().Call("addBlock", ethpub.NewPBlock(block))
}

// Simple go routine function that updates the list of peers in the GUI
func (gui *Gui) update() {
	txChan := make(chan ethchain.TxMsg, 1)
	gui.eth.TxPool().Subscribe(txChan)

	state := gui.eth.StateManager().TransState()

	unconfirmedFunds := new(big.Int)
	gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.addr).Amount)))

	for {
		select {
		case txMsg := <-txChan:
			tx := txMsg.Tx

			if txMsg.Type == ethchain.TxPre {
				object := state.GetAccount(gui.addr)

				if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce {
					gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())

					object.Nonce += 1
					state.SetStateObject(object)

					unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
				} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
					gui.win.Root().Call("addTx", ethpub.NewPTx(tx))
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())

					unconfirmedFunds.Add(unconfirmedFunds, tx.Value)
				}

				pos := "+"
				if unconfirmedFunds.Cmp(big.NewInt(0)) >= 0 {
					pos = "-"
				}
				val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
				str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(object.Amount), pos, val)

				gui.win.Root().Call("setWalletValue", str)
			} else {
				object := state.GetAccount(gui.addr)
				if bytes.Compare(tx.Sender(), gui.addr) == 0 {
					object.SubAmount(tx.Value)
				} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
					object.AddAmount(tx.Value)
				}

				gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(object.Amount)))

				state.SetStateObject(object)
			}
		}
	}
}

// Logging functions that log directly to the GUI interface
func (gui *Gui) Println(v ...interface{}) {
	str := strings.TrimRight(fmt.Sprintln(v...), "\n")
	lines := strings.Split(str, "\n")
	for _, line := range lines {
		gui.win.Root().Call("addLog", line)
	}
}

func (gui *Gui) Printf(format string, v ...interface{}) {
	str := strings.TrimRight(fmt.Sprintf(format, v...), "\n")
	lines := strings.Split(str, "\n")
	for _, line := range lines {
		gui.win.Root().Call("addLog", line)
	}
}

func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
	keyPair := ethutil.Config.Db.GetKeys()[0]

	return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
}

func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
	keyPair := ethutil.Config.Db.GetKeys()[0]

	mainInput, initInput := mutan.PreParse(data)

	return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, initInput, mainInput)
}
<|endoftext|>


<commit_before>package ethrpc

import (
	"encoding/json"
	"errors"
	"github.com/ethereum/eth-go/ethpub"
	"github.com/ethereum/eth-go/ethutil"
	"math/big"
)

type EthereumApi struct {
	ethp *ethpub.PEthereum
}

type JsonArgs interface {
	requirements() error
}

type BlockResponse struct {
	JsonResponse
}
type GetBlockArgs struct {
	BlockNumber int
	Hash        string
}

type ErrorResponse struct {
	Error     bool   `json:"error"`
	ErrorText string `json:"errorText"`
}

type JsonResponse interface {
}

type SuccessRes struct {
	Error  bool         `json:"error"`
	Result JsonResponse `json:"result"`
}

func NewSuccessRes(object JsonResponse) string {
	e := SuccessRes{Error: false, Result: object}
	res, err := json.Marshal(e)
	if err != nil {
		// This should never happen
		panic("Creating json error response failed, help")
	}
	success := string(res)
	return success
}

func NewErrorResponse(msg string) error {
	e := ErrorResponse{Error: true, ErrorText: msg}
	res, err := json.Marshal(e)
	if err != nil {
		// This should never happen
		panic("Creating json error response failed, help")
	}
	newErr := errors.New(string(res))
	return newErr
}

func (b *GetBlockArgs) requirements() error {
	if b.BlockNumber == 0 && b.Hash == "" {
		return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
	}
	return nil
}

func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	// Do something
	block := p.ethp.GetBlock(args.Hash)
	*reply = NewSuccessRes(block)
	return nil
}

type NewTxArgs struct {
	Sec       string
	Recipient string
	Value     string
	Gas       string
	GasPrice  string
	Init      string
	Body      string
}
type TxResponse struct {
	Hash string
}

func (a *NewTxArgs) requirements() error {
	if a.Recipient == "" {
		return NewErrorResponse("Transact requires a 'recipient' address as argument")
	}
	if a.Value == "" {
		return NewErrorResponse("Transact requires a 'value' as argument")
	}
	if a.Gas == "" {
		return NewErrorResponse("Transact requires a 'gas' value as argument")
	}
	if a.GasPrice == "" {
		return NewErrorResponse("Transact requires a 'gasprice' value as argument")
	}
	return nil
}

func (a *NewTxArgs) requirementsContract() error {
	if a.Value == "" {
		return NewErrorResponse("Create requires a 'value' as argument")
	}
	if a.Gas == "" {
		return NewErrorResponse("Create requires a 'gas' value as argument")
	}
	if a.GasPrice == "" {
		return NewErrorResponse("Create requires a 'gasprice' value as argument")
	}
	if a.Body == "" {
		return NewErrorResponse("Create requires a 'body' value as argument")
	}
	return nil
}

func (p *EthereumApi) Transact(args *NewTxArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	result, _ := p.ethp.Transact(p.ethp.GetKey().PrivateKey, args.Recipient, args.Value, args.Gas, args.GasPrice, args.Body)
	*reply = NewSuccessRes(result)
	return nil
}

func (p *EthereumApi) Create(args *NewTxArgs, reply *string) error {
	err := args.requirementsContract()
	if err != nil {
		return err
	}
	result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Init, args.Body)
	*reply = NewSuccessRes(result)
	return nil
}

func (p *EthereumApi) GetKey(args interface{}, reply *string) error {
	*reply = NewSuccessRes(p.ethp.GetKey())
	return nil
}

type GetStorageArgs struct {
	Address string
	Key     string
}

func (a *GetStorageArgs) requirements() error {
	if a.Address == "" {
		return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
	}
	if a.Key == "" {
		return NewErrorResponse("GetStorageAt requires an 'key' value as argument")
	}
	return nil
}

type GetStorageAtRes struct {
	Key     string `json:"key"`
	Value   string `json:"value"`
	Address string `json:"address"`
}

func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	state := p.ethp.GetStateObject(args.Address)
	// Convert the incoming string (which is a bigint) into hex
	i, _ := new(big.Int).SetString(args.Key, 10)
	hx := ethutil.Hex(i.Bytes())
	value := state.GetStorage(hx)
	*reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value})
	return nil
}

type GetBalanceArgs struct {
	Address string
}

func (a *GetBalanceArgs) requirements() error {
	if a.Address == "" {
		return NewErrorResponse("GetBalanceAt requires an 'address' value as argument")
	}
	return nil
}

type BalanceRes struct {
	Balance string `json:"balance"`
	Address string `json:"address"`
}

func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	state := p.ethp.GetStateObject(args.Address)
	*reply = NewSuccessRes(BalanceRes{Balance: state.Value(), Address: args.Address})
	return nil
}

type TestRes struct {
	JsonResponse `json:"-"`
	Answer       int `json:"answer"`
}

func (p *EthereumApi) Test(args *GetBlockArgs, reply *string) error {
	*reply = NewSuccessRes(TestRes{Answer: 15})
	return nil
}
<commit_msg>Implemented missing EthPub calls in RPC server<commit_after>package ethrpc

import (
	"encoding/json"
	"errors"
	"github.com/ethereum/eth-go/ethpub"
	"github.com/ethereum/eth-go/ethutil"
	"math/big"
)

type EthereumApi struct {
	ethp *ethpub.PEthereum
}

type JsonArgs interface {
	requirements() error
}

type BlockResponse struct {
	JsonResponse
}
type GetBlockArgs struct {
	BlockNumber int
	Hash        string
}

type ErrorResponse struct {
	Error     bool   `json:"error"`
	ErrorText string `json:"errorText"`
}

type JsonResponse interface {
}

type SuccessRes struct {
	Error  bool         `json:"error"`
	Result JsonResponse `json:"result"`
}

func NewSuccessRes(object JsonResponse) string {
	e := SuccessRes{Error: false, Result: object}
	res, err := json.Marshal(e)
	if err != nil {
		// This should never happen
		panic("Creating json error response failed, help")
	}
	success := string(res)
	return success
}

func NewErrorResponse(msg string) error {
	e := ErrorResponse{Error: true, ErrorText: msg}
	res, err := json.Marshal(e)
	if err != nil {
		// This should never happen
		panic("Creating json error response failed, help")
	}
	newErr := errors.New(string(res))
	return newErr
}

func (b *GetBlockArgs) requirements() error {
	if b.BlockNumber == 0 && b.Hash == "" {
		return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
	}
	return nil
}

func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	// Do something
	block := p.ethp.GetBlock(args.Hash)
	*reply = NewSuccessRes(block)
	return nil
}

type NewTxArgs struct {
	Sec       string
	Recipient string
	Value     string
	Gas       string
	GasPrice  string
	Init      string
	Body      string
}
type TxResponse struct {
	Hash string
}

func (a *NewTxArgs) requirements() error {
	if a.Recipient == "" {
		return NewErrorResponse("Transact requires a 'recipient' address as argument")
	}
	if a.Value == "" {
		return NewErrorResponse("Transact requires a 'value' as argument")
	}
	if a.Gas == "" {
		return NewErrorResponse("Transact requires a 'gas' value as argument")
	}
	if a.GasPrice == "" {
		return NewErrorResponse("Transact requires a 'gasprice' value as argument")
	}
	return nil
}

func (a *NewTxArgs) requirementsContract() error {
	if a.Value == "" {
		return NewErrorResponse("Create requires a 'value' as argument")
	}
	if a.Gas == "" {
		return NewErrorResponse("Create requires a 'gas' value as argument")
	}
	if a.GasPrice == "" {
		return NewErrorResponse("Create requires a 'gasprice' value as argument")
	}
	if a.Body == "" {
		return NewErrorResponse("Create requires a 'body' value as argument")
	}
	return nil
}

func (p *EthereumApi) Transact(args *NewTxArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	result, _ := p.ethp.Transact(p.ethp.GetKey().PrivateKey, args.Recipient, args.Value, args.Gas, args.GasPrice, args.Body)
	*reply = NewSuccessRes(result)
	return nil
}

func (p *EthereumApi) Create(args *NewTxArgs, reply *string) error {
	err := args.requirementsContract()
	if err != nil {
		return err
	}
	result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Init, args.Body)
	*reply = NewSuccessRes(result)
	return nil
}

func (p *EthereumApi) GetKey(args interface{}, reply *string) error {
	*reply = NewSuccessRes(p.ethp.GetKey())
	return nil
}

type GetStorageArgs struct {
	Address string
	Key     string
}

func (a *GetStorageArgs) requirements() error {
	if a.Address == "" {
		return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
	}
	if a.Key == "" {
		return NewErrorResponse("GetStorageAt requires an 'key' value as argument")
	}
	return nil
}

type GetStorageAtRes struct {
	Key     string `json:"key"`
	Value   string `json:"value"`
	Address string `json:"address"`
}

func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	state := p.ethp.GetStateObject(args.Address)
	// Convert the incoming string (which is a bigint) into hex
	i, _ := new(big.Int).SetString(args.Key, 10)
	hx := ethutil.Hex(i.Bytes())
	value := state.GetStorage(hx)
	*reply = NewSuccessRes(GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value})
	return nil
}

type GetTxCountArgs struct {
	Address string `json:"address"`
}
type GetTxCountRes struct {
	Nonce int `json:"nonce"`
}

func (a *GetTxCountArgs) requirements() error {
	if a.Address == "" {
		return NewErrorResponse("GetTxCountAt requires an 'address' value as argument")
	}
	return nil
}

type GetPeerCountRes struct {
	PeerCount int `json:"peerCount"`
}

func (p *EthereumApi) GetPeerCount(args *interface{}, reply *string) error {
	*reply = NewSuccessRes(GetPeerCountRes{PeerCount: p.ethp.GetPeerCount()})
	return nil
}

type GetListeningRes struct {
	IsListening bool `json:"isListening"`
}

func (p *EthereumApi) GetIsListening(args *interface{}, reply *string) error {
	*reply = NewSuccessRes(GetListeningRes{IsListening: p.ethp.GetIsListening()})
	return nil
}

type GetCoinbaseRes struct {
	Coinbase string `json:"coinbase"`
}

func (p *EthereumApi) GetCoinbase(args *interface{}, reply *string) error {
	*reply = NewSuccessRes(GetCoinbaseRes{Coinbase: p.ethp.GetCoinBase()})
	return nil
}

type GetMiningRes struct {
	IsMining bool `json:"isMining"`
}

func (p *EthereumApi) GetIsMining(args *interface{}, reply *string) error {
	*reply = NewSuccessRes(GetMiningRes{IsMining: p.ethp.GetIsMining()})
	return nil
}

func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	state := p.ethp.GetTxCountAt(args.Address)
	*reply = NewSuccessRes(GetTxCountRes{Nonce: state})
	return nil
}

type GetBalanceArgs struct {
	Address string
}

func (a *GetBalanceArgs) requirements() error {
	if a.Address == "" {
		return NewErrorResponse("GetBalanceAt requires an 'address' value as argument")
	}
	return nil
}

type BalanceRes struct {
	Balance string `json:"balance"`
	Address string `json:"address"`
}

func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *string) error {
	err := args.requirements()
	if err != nil {
		return err
	}
	state := p.ethp.GetStateObject(args.Address)
	*reply = NewSuccessRes(BalanceRes{Balance: state.Value(), Address: args.Address})
	return nil
}

type TestRes struct {
	JsonResponse `json:"-"`
	Answer       int `json:"answer"`
}

func (p *EthereumApi) Test(args *GetBlockArgs, reply *string) error {
	*reply = NewSuccessRes(TestRes{Answer: 15})
	return nil
}
<|endoftext|>