<commit_before>/*
Copyright IBM Corp 2016 All Rights Reserved.

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

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

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

package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"
	"time"
	"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	// if function == "read" {                            //read a variable
	// 	return t.read(stub, args)
	// }
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error election")
			return nil, errors.New("Invalid election")
		}

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return nil, errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error creating election");
			return nil, errors.New("Error creating election")
		}

		return nil, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
  // strings
	return nil, nil
}
<commit_msg>chaincode V1<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.

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

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

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

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	// if function == "read" {                            //read a variable
	// 	return t.read(stub, args)
	// }
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {
	// if election != nil {
	// 		fmt.Println("error invalid arguments")
	// 		return nil, errors.New("Incorrect number of arguments. Expecting election record")
	// 	}

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error election")
			return nil, errors.New("Invalid election")
		}

		t.saveElection(stub, election)

		return nil, nil
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

//go:build !privileged_tests

package ipam

import (
	"net"
	"time"

	. "gopkg.in/check.v1"

	"github.com/cilium/cilium/pkg/addressing"
	"github.com/cilium/cilium/pkg/cidr"
	"github.com/cilium/cilium/pkg/datapath/fake"
	"github.com/cilium/cilium/pkg/k8s/watchers/subscriber"
	"github.com/cilium/cilium/pkg/mtu"
)

type ownerMock struct{}

func (o *ownerMock) K8sEventReceived(resourceApiGroup, scope string, action string, valid, equal bool) {
}
func (o *ownerMock) K8sEventProcessed(scope string, action string, status bool) {}
func (o *ownerMock) RegisterCiliumNodeSubscriber(s subscriber.CiliumNode)       {}

func (o *ownerMock) UpdateCiliumNodeResource()                                          {}
func (o *ownerMock) LocalAllocCIDRsUpdated(ipv4AllocCIDRs, ipv6AllocCIDRs []*cidr.CIDR) {}

var mtuMock = mtu.NewConfiguration(0, false, false, false, 1500, nil)

func (s *IPAMSuite) TestAllocatedIPDump(c *C) {
	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	ipv4 := fakeIPv4AllocCIDRIP(fakeAddressing)
	ipv6 := fakeIPv6AllocCIDRIP(fakeAddressing)

	for i := 0; i < 10; i++ {
		_, err := addressing.NewCiliumIPv4(ipv4.String())
		c.Assert(err, IsNil)
		nextIP(ipv4)

		_, err = addressing.NewCiliumIPv6(ipv6.String())
		c.Assert(err, IsNil)
		nextIP(ipv6)
	}

	allocv4, allocv6, status := ipam.Dump()
	c.Assert(status, Not(Equals), "")

	// Test the format of the dumped ip addresses
	for ip := range allocv4 {
		c.Assert(net.ParseIP(ip), NotNil)
	}
	for ip := range allocv6 {
		c.Assert(net.ParseIP(ip), NotNil)
	}
}

func (s *IPAMSuite) TestExpirationTimer(c *C) {
	ip := net.ParseIP("1.1.1.1")
	timeout := 50 * time.Millisecond

	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	err := ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)

	uuid, err := ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// must fail, already registered
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, Not(IsNil))
	c.Assert(uuid, Equals, "")
	// must fail, already in use
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, Not(IsNil))
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// Must succeed, IP must be released again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register new expiration timer
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// attempt to stop with an invalid uuid, must fail
	err = ipam.StopExpirationTimer(ip, "unknown-uuid")
	c.Assert(err, Not(IsNil))
	// stop expiration with valid uuid
	err = ipam.StopExpirationTimer(ip, uuid)
	c.Assert(err, IsNil)
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// must fail as IP is properly in use now
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, Not(IsNil))
	// release IP for real
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)

	// allocate IP again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register expiration timer
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// release IP, must also stop expiration timer
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)
	// allocate same IP again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register expiration timer must succeed even though stop was never called
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// release IP
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)

}

func (s *IPAMSuite) TestAllocateNextWithExpiration(c *C) {
	timeout := 50 * time.Millisecond

	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	ipv4, ipv6, err := ipam.AllocateNextWithExpiration("", "foo", timeout)
	c.Assert(err, IsNil)

	// IPv4 address must be in use
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, Not(IsNil))
	// IPv6 address must be in use
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, Not(IsNil))
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// IPv4 address must be available again
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, IsNil)
	// IPv6 address must be available again
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, IsNil)
	// Release IPs
	err = ipam.ReleaseIP(ipv4.IP)
	c.Assert(err, IsNil)
	err = ipam.ReleaseIP(ipv6.IP)
	c.Assert(err, IsNil)

	// Allocate IPs again and test stopping the expiration timer
	ipv4, ipv6, err = ipam.AllocateNextWithExpiration("", "foo", timeout)
	c.Assert(err, IsNil)

	// Stop expiration timer for IPv4 address
	err = ipam.StopExpirationTimer(ipv4.IP, ipv4.ExpirationUUID)
	c.Assert(err, IsNil)

	// Let expiration timer expire
	time.Sleep(2 * timeout)

	// IPv4 address must be in use
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, Not(IsNil))
	// IPv6 address must be available again
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, IsNil)
	// Release IPv4 address
	err = ipam.ReleaseIP(ipv4.IP)
	c.Assert(err, IsNil)
}
<commit_msg>ipam: remove unused code in TestAllocatedIPDump<commit_after>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

//go:build !privileged_tests

package ipam

import (
	"net"
	"time"

	. "gopkg.in/check.v1"

	"github.com/cilium/cilium/pkg/cidr"
	"github.com/cilium/cilium/pkg/datapath/fake"
	"github.com/cilium/cilium/pkg/k8s/watchers/subscriber"
	"github.com/cilium/cilium/pkg/mtu"
)

type ownerMock struct{}

func (o *ownerMock) K8sEventReceived(resourceApiGroup, scope string, action string, valid, equal bool) {
}
func (o *ownerMock) K8sEventProcessed(scope string, action string, status bool) {}
func (o *ownerMock) RegisterCiliumNodeSubscriber(s subscriber.CiliumNode)       {}

func (o *ownerMock) UpdateCiliumNodeResource()                                          {}
func (o *ownerMock) LocalAllocCIDRsUpdated(ipv4AllocCIDRs, ipv6AllocCIDRs []*cidr.CIDR) {}

var mtuMock = mtu.NewConfiguration(0, false, false, false, 1500, nil)

func (s *IPAMSuite) TestAllocatedIPDump(c *C) {
	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	allocv4, allocv6, status := ipam.Dump()
	c.Assert(status, Not(Equals), "")

	// Test the format of the dumped ip addresses
	for ip := range allocv4 {
		c.Assert(net.ParseIP(ip), NotNil)
	}
	for ip := range allocv6 {
		c.Assert(net.ParseIP(ip), NotNil)
	}
}

func (s *IPAMSuite) TestExpirationTimer(c *C) {
	ip := net.ParseIP("1.1.1.1")
	timeout := 50 * time.Millisecond

	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	err := ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)

	uuid, err := ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// must fail, already registered
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, Not(IsNil))
	c.Assert(uuid, Equals, "")
	// must fail, already in use
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, Not(IsNil))
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// Must succeed, IP must be released again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register new expiration timer
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// attempt to stop with an invalid uuid, must fail
	err = ipam.StopExpirationTimer(ip, "unknown-uuid")
	c.Assert(err, Not(IsNil))
	// stop expiration with valid uuid
	err = ipam.StopExpirationTimer(ip, uuid)
	c.Assert(err, IsNil)
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// must fail as IP is properly in use now
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, Not(IsNil))
	// release IP for real
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)

	// allocate IP again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register expiration timer
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// release IP, must also stop expiration timer
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)
	// allocate same IP again
	err = ipam.AllocateIP(ip, "foo")
	c.Assert(err, IsNil)
	// register expiration timer must succeed even though stop was never called
	uuid, err = ipam.StartExpirationTimer(ip, timeout)
	c.Assert(err, IsNil)
	c.Assert(uuid, Not(Equals), "")
	// release IP
	err = ipam.ReleaseIP(ip)
	c.Assert(err, IsNil)

}

func (s *IPAMSuite) TestAllocateNextWithExpiration(c *C) {
	timeout := 50 * time.Millisecond

	fakeAddressing := fake.NewNodeAddressing()
	ipam := NewIPAM(fakeAddressing, &testConfiguration{}, &ownerMock{}, &ownerMock{}, &mtuMock)

	ipv4, ipv6, err := ipam.AllocateNextWithExpiration("", "foo", timeout)
	c.Assert(err, IsNil)

	// IPv4 address must be in use
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, Not(IsNil))
	// IPv6 address must be in use
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, Not(IsNil))
	// Let expiration timer expire
	time.Sleep(2 * timeout)
	// IPv4 address must be available again
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, IsNil)
	// IPv6 address must be available again
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, IsNil)
	// Release IPs
	err = ipam.ReleaseIP(ipv4.IP)
	c.Assert(err, IsNil)
	err = ipam.ReleaseIP(ipv6.IP)
	c.Assert(err, IsNil)

	// Allocate IPs again and test stopping the expiration timer
	ipv4, ipv6, err = ipam.AllocateNextWithExpiration("", "foo", timeout)
	c.Assert(err, IsNil)

	// Stop expiration timer for IPv4 address
	err = ipam.StopExpirationTimer(ipv4.IP, ipv4.ExpirationUUID)
	c.Assert(err, IsNil)

	// Let expiration timer expire
	time.Sleep(2 * timeout)

	// IPv4 address must be in use
	err = ipam.AllocateIP(ipv4.IP, "foo")
	c.Assert(err, Not(IsNil))
	// IPv6 address must be available again
	err = ipam.AllocateIP(ipv6.IP, "foo")
	c.Assert(err, IsNil)
	// Release IPv4 address
	err = ipam.ReleaseIP(ipv4.IP)
	c.Assert(err, IsNil)
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Kubernetes Authors All rights reserved.

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

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

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

package node

import (
	"os"
	"runtime"
	"strings"

	"github.com/golang/glog"
	"github.com/spf13/viper"
	"golang.org/x/sync/errgroup"
	cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
	"k8s.io/minikube/pkg/drivers/kic"
	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/download"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/image"
	"k8s.io/minikube/pkg/minikube/localpath"
	"k8s.io/minikube/pkg/minikube/machine"
	"k8s.io/minikube/pkg/minikube/out"
)

const (
	cacheImages         = "cache-images"
	cacheImageConfigKey = "cache"
)

// BeginCacheKubernetesImages caches images required for kubernetes version in the background
func beginCacheKubernetesImages(g *errgroup.Group, imageRepository string, k8sVersion string, cRuntime string) {
	if download.PreloadExists(k8sVersion, cRuntime) {
		glog.Info("Caching tarball of preloaded images")
		err := download.Preload(k8sVersion, cRuntime)
		if err == nil {
			glog.Infof("Finished downloading the preloaded tar for %s on %s", k8sVersion, cRuntime)
			return // don't cache individual images if preload is successful.
		}
		glog.Warningf("Error downloading preloaded artifacts will continue without preload: %v", err)
	}

	if !viper.GetBool(cacheImages) {
		return
	}

	g.Go(func() error {
		return machine.CacheImagesForBootstrapper(imageRepository, k8sVersion, viper.GetString(cmdcfg.Bootstrapper))
	})
}

// HandleDownloadOnly caches appropariate binaries and images
func handleDownloadOnly(cacheGroup, kicGroup *errgroup.Group, k8sVersion string) {
	// If --download-only, complete the remaining downloads and exit.
	if !viper.GetBool("download-only") {
		return
	}
	if err := doCacheBinaries(k8sVersion); err != nil {
		exit.WithError("Failed to cache binaries", err)
	}
	if _, err := CacheKubectlBinary(k8sVersion); err != nil {
		exit.WithError("Failed to cache kubectl", err)
	}
	waitCacheRequiredImages(cacheGroup)
	waitDownloadKicArtifacts(kicGroup)
	if err := saveImagesToTarFromConfig(); err != nil {
		exit.WithError("Failed to cache images to tar", err)
	}
	out.T(out.Check, "Download complete!")
	os.Exit(0)

}

// CacheKubectlBinary caches the kubectl binary
func CacheKubectlBinary(k8sVerison string) (string, error) {
	binary := "kubectl"
	if runtime.GOOS == "windows" {
		binary = "kubectl.exe"
	}

	return download.Binary(binary, k8sVerison, runtime.GOOS, runtime.GOARCH)
}

// doCacheBinaries caches Kubernetes binaries in the foreground
func doCacheBinaries(k8sVersion string) error {
	return machine.CacheBinariesForBootstrapper(k8sVersion, viper.GetString(cmdcfg.Bootstrapper))
}

// BeginDownloadKicArtifacts downloads the kic image + preload tarball, returns true if preload is available
func beginDownloadKicArtifacts(g *errgroup.Group) {
	out.T(out.Pulling, "Pulling base image ...")
	glog.Info("Beginning downloading kic artifacts")
	g.Go(func() error {
		glog.Infof("Downloading %s to local daemon", kic.BaseImage)
		return image.WriteImageToDaemon(kic.BaseImage)
	})
}

// WaitDownloadKicArtifacts blocks until the required artifacts for KIC are downloaded.
func waitDownloadKicArtifacts(g *errgroup.Group) {
	if err := g.Wait(); err != nil {
		if strings.Contains(err.Error(), "Cannot connect to the Docker daemon") {
			out.WarningT("Failed to connect to docker daemon : {{.error}}", out.V{"error": err.Error()})
			exit.UsageT("Please make sure Docker service is running.")
		} else {
			exit.WithError("Failed to download kic base image", err)
		}

	}
	glog.Info("Successfully downloaded all kic artifacts")
}

// WaitCacheRequiredImages blocks until the required images are all cached.
func waitCacheRequiredImages(g *errgroup.Group) {
	if !viper.GetBool(cacheImages) {
		return
	}
	if err := g.Wait(); err != nil {
		glog.Errorln("Error caching images: ", err)
	}
}

// saveImagesToTarFromConfig saves images to tar in cache which specified in config file.
// currently only used by download-only option
func saveImagesToTarFromConfig() error {
	images, err := imagesInConfigFile()
	if err != nil {
		return err
	}
	if len(images) == 0 {
		return nil
	}
	return image.SaveToDir(images, constants.ImageCacheDir)
}

// CacheAndLoadImagesInConfig loads the images currently in the config file
// called by 'start' and 'cache reload' commands.
func CacheAndLoadImagesInConfig() error {
	images, err := imagesInConfigFile()
	if err != nil {
		return err
	}
	if len(images) == 0 {
		return nil
	}
	return machine.CacheAndLoadImages(images)
}

func imagesInConfigFile() ([]string, error) {
	configFile, err := config.ReadConfig(localpath.ConfigFile())
	if err != nil {
		return nil, err
	}
	if values, ok := configFile[cacheImageConfigKey]; ok {
		var images []string
		for key := range values.(map[string]interface{}) {
			images = append(images, key)
		}
		return images, nil
	}
	return []string{}, nil
}
<commit_msg>revert handling<commit_after>/*
Copyright 2020 The Kubernetes Authors All rights reserved.

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

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

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

package node

import (
	"os"
	"runtime"

	"github.com/golang/glog"
	"github.com/spf13/viper"
	"golang.org/x/sync/errgroup"
	cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
	"k8s.io/minikube/pkg/drivers/kic"
	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/download"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/image"
	"k8s.io/minikube/pkg/minikube/localpath"
	"k8s.io/minikube/pkg/minikube/machine"
	"k8s.io/minikube/pkg/minikube/out"
)

const (
	cacheImages         = "cache-images"
	cacheImageConfigKey = "cache"
)

// BeginCacheKubernetesImages caches images required for kubernetes version in the background
func beginCacheKubernetesImages(g *errgroup.Group, imageRepository string, k8sVersion string, cRuntime string) {
	if download.PreloadExists(k8sVersion, cRuntime) {
		glog.Info("Caching tarball of preloaded images")
		err := download.Preload(k8sVersion, cRuntime)
		if err == nil {
			glog.Infof("Finished downloading the preloaded tar for %s on %s", k8sVersion, cRuntime)
			return // don't cache individual images if preload is successful.
		}
		glog.Warningf("Error downloading preloaded artifacts will continue without preload: %v", err)
	}

	if !viper.GetBool(cacheImages) {
		return
	}

	g.Go(func() error {
		return machine.CacheImagesForBootstrapper(imageRepository, k8sVersion, viper.GetString(cmdcfg.Bootstrapper))
	})
}

// HandleDownloadOnly caches appropariate binaries and images
func handleDownloadOnly(cacheGroup, kicGroup *errgroup.Group, k8sVersion string) {
	// If --download-only, complete the remaining downloads and exit.
	if !viper.GetBool("download-only") {
		return
	}
	if err := doCacheBinaries(k8sVersion); err != nil {
		exit.WithError("Failed to cache binaries", err)
	}
	if _, err := CacheKubectlBinary(k8sVersion); err != nil {
		exit.WithError("Failed to cache kubectl", err)
	}
	waitCacheRequiredImages(cacheGroup)
	waitDownloadKicArtifacts(kicGroup)
	if err := saveImagesToTarFromConfig(); err != nil {
		exit.WithError("Failed to cache images to tar", err)
	}
	out.T(out.Check, "Download complete!")
	os.Exit(0)

}

// CacheKubectlBinary caches the kubectl binary
func CacheKubectlBinary(k8sVerison string) (string, error) {
	binary := "kubectl"
	if runtime.GOOS == "windows" {
		binary = "kubectl.exe"
	}

	return download.Binary(binary, k8sVerison, runtime.GOOS, runtime.GOARCH)
}

// doCacheBinaries caches Kubernetes binaries in the foreground
func doCacheBinaries(k8sVersion string) error {
	return machine.CacheBinariesForBootstrapper(k8sVersion, viper.GetString(cmdcfg.Bootstrapper))
}

// BeginDownloadKicArtifacts downloads the kic image + preload tarball, returns true if preload is available
func beginDownloadKicArtifacts(g *errgroup.Group) {
	out.T(out.Pulling, "Pulling base image ...")
	glog.Info("Beginning downloading kic artifacts")
	g.Go(func() error {
		glog.Infof("Downloading %s to local daemon", kic.BaseImage)
		return image.WriteImageToDaemon(kic.BaseImage)
	})
}

// WaitDownloadKicArtifacts blocks until the required artifacts for KIC are downloaded.
func waitDownloadKicArtifacts(g *errgroup.Group) {
	if err := g.Wait(); err != nil {
		glog.Errorln("Error downloading kic artifacts: ", err)
		return
	}
	glog.Info("Successfully downloaded all kic artifacts")
}

// WaitCacheRequiredImages blocks until the required images are all cached.
func waitCacheRequiredImages(g *errgroup.Group) {
	if !viper.GetBool(cacheImages) {
		return
	}
	if err := g.Wait(); err != nil {
		glog.Errorln("Error caching images: ", err)
	}
}

// saveImagesToTarFromConfig saves images to tar in cache which specified in config file.
// currently only used by download-only option
func saveImagesToTarFromConfig() error {
	images, err := imagesInConfigFile()
	if err != nil {
		return err
	}
	if len(images) == 0 {
		return nil
	}
	return image.SaveToDir(images, constants.ImageCacheDir)
}

// CacheAndLoadImagesInConfig loads the images currently in the config file
// called by 'start' and 'cache reload' commands.
func CacheAndLoadImagesInConfig() error {
	images, err := imagesInConfigFile()
	if err != nil {
		return err
	}
	if len(images) == 0 {
		return nil
	}
	return machine.CacheAndLoadImages(images)
}

func imagesInConfigFile() ([]string, error) {
	configFile, err := config.ReadConfig(localpath.ConfigFile())
	if err != nil {
		return nil, err
	}
	if values, ok := configFile[cacheImageConfigKey]; ok {
		var images []string
		for key := range values.(map[string]interface{}) {
			images = append(images, key)
		}
		return images, nil
	}
	return []string{}, nil
}
<|endoftext|>


<commit_before>//
// Last.Backend LLC CONFIDENTIAL
// __________________
//
// [2014] - [2018] Last.Backend LLC
// All Rights Reserved.
//
// NOTICE:  All information contained herein is, and remains
// the property of Last.Backend LLC and its suppliers,
// if any.  The intellectual and technical concepts contained
// herein are proprietary to Last.Backend LLC
// and its suppliers and may be covered by Russian Federation and Foreign Patents,
// patents in process, and are protected by trade secret or copyright law.
// Dissemination of this information or reproduction of this material
// is strictly forbidden unless prior written permission is obtained
// from Last.Backend LLC.
//

package views

import (
	"github.com/lastbackend/lastbackend/pkg/distribution/types"
	"time"
)

// Ingress - default node structure
// swagger:model views_ingress
type Ingress struct {
	Meta   IngressMeta   `json:"meta"`
	Status IngressStatus `json:"status"`
}

// IngressList - node map list
// swagger:model views_ingress_list
type IngressList map[string]*Ingress

// IngressMeta - node metadata structure
// swagger:model views_ingress_meta
type IngressMeta struct {
	Name        string    `json:"name"`
	Description string    `json:"description"`
	Created     time.Time `json:"created"`
	Updated     time.Time `json:"updated"`
}

// IngressStatus - node state struct
// swagger:model views_ingress_status
type IngressStatus struct {
	Ready bool `json:"ready"`
}

// swagger:model views_ingress_spec
type IngressSpec struct {
	Routes map[string]types.RouteSpec `json:"routes"`
}
<commit_msg>add ingress version to meta<commit_after>//
// Last.Backend LLC CONFIDENTIAL
// __________________
//
// [2014] - [2018] Last.Backend LLC
// All Rights Reserved.
//
// NOTICE:  All information contained herein is, and remains
// the property of Last.Backend LLC and its suppliers,
// if any.  The intellectual and technical concepts contained
// herein are proprietary to Last.Backend LLC
// and its suppliers and may be covered by Russian Federation and Foreign Patents,
// patents in process, and are protected by trade secret or copyright law.
// Dissemination of this information or reproduction of this material
// is strictly forbidden unless prior written permission is obtained
// from Last.Backend LLC.
//

package views

import (
	"github.com/lastbackend/lastbackend/pkg/distribution/types"
)

// Ingress - default node structure
// swagger:model views_ingress
type Ingress struct {
	Meta   IngressMeta   `json:"meta"`
	Status IngressStatus `json:"status"`
}

// IngressList - node map list
// swagger:model views_ingress_list
type IngressList map[string]*Ingress

// IngressMeta - node metadata structure
// swagger:model views_ingress_meta
type IngressMeta struct {
	Meta
	Version string `json:"version"`
}

// IngressStatus - node state struct
// swagger:model views_ingress_status
type IngressStatus struct {
	Ready bool `json:"ready"`
}

// swagger:model views_ingress_spec
type IngressSpec struct {
	Routes map[string]types.RouteSpec `json:"routes"`
}
<|endoftext|>


<commit_before>package build

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/werf/logboek"

	"github.com/werf/werf/pkg/build/stage"
	"github.com/werf/werf/pkg/container_runtime"
	"github.com/werf/werf/pkg/image"
	"github.com/werf/werf/pkg/storage"
	"github.com/werf/werf/pkg/tag_strategy"
	"github.com/werf/werf/pkg/util"
)

func NewPublishImagesPhase(c *Conveyor, imagesRepo storage.ImagesRepo, opts PublishImagesOptions) *PublishImagesPhase {
	tagsByScheme := map[tag_strategy.TagStrategy][]string{
		tag_strategy.Custom:    opts.CustomTags,
		tag_strategy.GitBranch: opts.TagsByGitBranch,
		tag_strategy.GitTag:    opts.TagsByGitTag,
		tag_strategy.GitCommit: opts.TagsByGitCommit,
	}
	return &PublishImagesPhase{
		BasePhase:            BasePhase{c},
		ImagesToPublish:      opts.ImagesToPublish,
		TagsByScheme:         tagsByScheme,
		TagByStagesSignature: opts.TagByStagesSignature,
		ImagesRepo:           imagesRepo,
		PublishReport:        &PublishReport{Images: make(map[string]PublishReportImageRecord)},
		PublishReportPath:    opts.PublishReportPath,
		PublishReportFormat:  opts.PublishReportFormat,
	}
}

type PublishImagesPhase struct {
	BasePhase
	ImagesToPublish      []string
	TagsByScheme         map[tag_strategy.TagStrategy][]string
	TagByStagesSignature bool
	ImagesRepo           storage.ImagesRepo

	PublishReport       *PublishReport
	PublishReportPath   string
	PublishReportFormat PublishReportFormat
}

type PublishReportFormat string

const (
	PublishReportJSON PublishReportFormat = "json"
)

type PublishReport struct {
	Images map[string]PublishReportImageRecord
}

type PublishReportImageRecord struct {
	WerfImageName string
	DockerRepo    string
	DockerTag     string
	DockerImageID string
}

func (phase *PublishImagesPhase) Name() string {
	return "publish"
}

func (phase *PublishImagesPhase) BeforeImages() error {
	return nil
}

func (phase *PublishImagesPhase) AfterImages() error {
	if data, err := json.Marshal(phase.PublishReport); err != nil {
		return fmt.Errorf("unable to prepare publish report: %s", err)
	} else {
		logboek.Debug.LogF("Publish report:\n%s\n", data)

		if phase.PublishReportPath != "" && phase.PublishReportFormat == PublishReportJSON {
			if err := ioutil.WriteFile(phase.PublishReportPath, append(data, []byte("\n")...), 0644); err != nil {
				return fmt.Errorf("unable to write publish report to %s: %s", phase.PublishReportPath, err)
			}
		}
	}

	return nil
}

func (phase *PublishImagesPhase) BeforeImageStages(img *Image) error {
	return nil
}

func (phase *PublishImagesPhase) OnImageStage(img *Image, stg stage.Interface) error {
	return nil
}

func (phase *PublishImagesPhase) AfterImageStages(img *Image) error {
	if img.isArtifact {
		return nil
	}

	if len(phase.ImagesToPublish) == 0 {
		return phase.publishImage(img)
	}

	for _, name := range phase.ImagesToPublish {
		if name == img.GetName() {
			return phase.publishImage(img)
		}
	}

	return nil
}

func (phase *PublishImagesPhase) ImageProcessingShouldBeStopped(img *Image) bool {
	return false
}

func (phase *PublishImagesPhase) publishImage(img *Image) error {
	var nonEmptySchemeInOrder []tag_strategy.TagStrategy
	for strategy, tags := range phase.TagsByScheme {
		if len(tags) == 0 {
			continue
		}

		nonEmptySchemeInOrder = append(nonEmptySchemeInOrder, strategy)
	}

	if phase.Conveyor.localGitRepo != nil {
		if err := logboek.Info.LogProcess(fmt.Sprintf("publishing image %s git metadata", img.GetName()), logboek.LevelLogProcessOptions{}, func() error {
			headCommit, err := phase.Conveyor.localGitRepo.HeadCommit()
			if err != nil {
				return err
			}

			// FIXME: Virtual merge commit?

			if metadata, err := phase.Conveyor.StagesManager.StagesStorage.GetImageMetadataByCommit(phase.Conveyor.projectName(), img.GetName(), headCommit); err != nil {
				return fmt.Errorf("unable to get image %s metadata by commit %s: %s", img.GetName(), headCommit, err)
			} else if metadata != nil {
				if metadata.ContentSignature != img.GetContentSignature() {
					// TODO: Check image existance and automatically allow republish if no images found by this commit. What if multiple images are published by multiple tagging strategies (including custom)?
					// TODO: allowInconsistentPublish: true option for werf.yaml
					return fmt.Errorf("inconsistent build: found already published image with stages-signature %s by commit %s, cannot publish a new image with stages-signature %s by the same commit", metadata.ContentSignature, headCommit, img.GetContentSignature())
				}
				return nil
			} else {
				return phase.Conveyor.StagesManager.StagesStorage.PutImageCommit(phase.Conveyor.projectName(), img.GetName(), headCommit, &storage.ImageMetadata{ContentSignature: img.GetContentSignature()})
			}
		}); err != nil {
			return err
		}
	}

	var existingTags []string
	if tags, err := phase.fetchExistingTags(img.GetName()); err != nil {
		return err
	} else {
		existingTags = tags
	}

	for _, strategy := range nonEmptySchemeInOrder {
		imageMetaTags := phase.TagsByScheme[strategy]

		if err := logboek.Info.LogProcess(
			fmt.Sprintf("%s tagging strategy", string(strategy)),
			logboek.LevelLogProcessOptions{Style: logboek.HighlightStyle()},
			func() error {
				for _, imageMetaTag := range imageMetaTags {
					if err := phase.publishImageByTag(img, imageMetaTag, strategy, publishImageByTagOptions{ExistingTagsList: existingTags, CheckAlreadyExistingTagByContentSignatureLabel: true}); err != nil {
						return fmt.Errorf("error publishing image %s by tag %s: %s", img.LogName(), imageMetaTag, err)
					}
				}

				return nil
			},
		); err != nil {
			return err
		}
	}

	if phase.TagByStagesSignature {
		if err := logboek.Info.LogProcess(
			fmt.Sprintf("%s tagging strategy", tag_strategy.StagesSignature),
			logboek.LevelLogProcessOptions{Style: logboek.HighlightStyle()},
			func() error {
				if err := phase.publishImageByTag(img, img.GetContentSignature(), tag_strategy.StagesSignature, publishImageByTagOptions{ExistingTagsList: existingTags}); err != nil {
					return fmt.Errorf("error publishing image %s by image signature %s: %s", img.GetName(), img.GetContentSignature(), err)
				}

				return nil
			},
		); err != nil {
			return err
		}
	}

	return nil
}

func (phase *PublishImagesPhase) fetchExistingTags(imageName string) (existingTags []string, err error) {
	logProcessMsg := fmt.Sprintf("Fetching existing repo tags")
	_ = logboek.Info.LogProcessInline(logProcessMsg, logboek.LevelLogProcessInlineOptions{}, func() error {
		existingTags, err = phase.ImagesRepo.GetAllImageRepoTags(imageName)
		return nil
	})
	logboek.Info.LogOptionalLn()

	if err != nil {
		return existingTags, fmt.Errorf("error fetching existing tags from image repository %s: %s", phase.ImagesRepo.String(), err)
	}
	return existingTags, nil
}

type publishImageByTagOptions struct {
	CheckAlreadyExistingTagByContentSignatureLabel bool
	ExistingTagsList                               []string
}

func (phase *PublishImagesPhase) publishImageByTag(img *Image, imageMetaTag string, tagStrategy tag_strategy.TagStrategy, opts publishImageByTagOptions) error {
	imageRepository := phase.ImagesRepo.ImageRepositoryName(img.GetName())
	imageName := phase.ImagesRepo.ImageRepositoryNameWithTag(img.GetName(), imageMetaTag)
	imageActualTag := phase.ImagesRepo.ImageRepositoryTag(img.GetName(), imageMetaTag)

	alreadyExists, alreadyExistingDockerImageID, err := phase.checkImageAlreadyExists(opts.ExistingTagsList, img.GetName(), imageMetaTag, img.GetContentSignature(), opts.CheckAlreadyExistingTagByContentSignatureLabel)
	if err != nil {
		return fmt.Errorf("error checking image %s already exists in the images repo: %s", img.LogName(), err)
	}

	if alreadyExists {
		logboek.Default.LogFHighlight("%s tag %s is up-to-date\n", strings.Title(string(tagStrategy)), imageActualTag)

		_ = logboek.WithIndent(func() error {
			logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
			logboek.Default.LogFDetails("      image: %s\n", imageName)
			return nil
		})

		logboek.LogOptionalLn()

		phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
			WerfImageName: img.GetName(),
			DockerRepo:    imageRepository,
			DockerTag:     imageActualTag,
			DockerImageID: alreadyExistingDockerImageID,
		}

		return nil
	}

	publishImage := container_runtime.NewWerfImage(phase.Conveyor.GetStageImage(img.GetLastNonEmptyStage().GetImage().Name()), imageName, phase.Conveyor.ContainerRuntime.(*container_runtime.LocalDockerServerRuntime))

	publishImage.Container().ServiceCommitChangeOptions().AddLabel(map[string]string{
		image.WerfDockerImageName:       imageName,
		image.WerfTagStrategyLabel:      string(tagStrategy),
		image.WerfImageLabel:            "true",
		image.WerfImageNameLabel:        img.GetName(),
		image.WerfImageTagLabel:         imageMetaTag,
		image.WerfContentSignatureLabel: img.GetContentSignature(),
		image.WerfImageVersionLabel:     image.WerfImageVersion,
	})

	successInfoSectionFunc := func() {
		_ = logboek.WithIndent(func() error {
			logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
			logboek.Default.LogFDetails("      image: %s\n", imageName)
			return nil
		})
	}

	publishingFunc := func() error {
		if err := phase.Conveyor.StagesManager.FetchStage(img.GetLastNonEmptyStage()); err != nil {
			return err
		}

		if err := logboek.Info.LogProcess("Building final image with meta information", logboek.LevelLogProcessOptions{}, func() error {
			if err := publishImage.Build(container_runtime.BuildOptions{}); err != nil {
				return fmt.Errorf("error building %s with tagging strategy '%s': %s", imageName, tagStrategy, err)
			}
			return nil
		}); err != nil {
			return err
		}

		if lock, err := phase.Conveyor.StorageLockManager.LockImage(phase.Conveyor.projectName(), imageName); err != nil {
			return fmt.Errorf("error locking image %s: %s", imageName, err)
		} else {
			defer phase.Conveyor.StorageLockManager.Unlock(lock)
		}

		existingTags, err := phase.fetchExistingTags(img.GetName())
		if err != nil {
			return err
		}

		alreadyExists, alreadyExistingImageID, err := phase.checkImageAlreadyExists(existingTags, img.GetName(), imageMetaTag, img.GetContentSignature(), opts.CheckAlreadyExistingTagByContentSignatureLabel)
		if err != nil {
			return fmt.Errorf("error checking image %s already exists in the images repo: %s", img.LogName(), err)
		}

		if alreadyExists {
			logboek.Default.LogFHighlight("%s tag %s is up-to-date\n", strings.Title(string(tagStrategy)), imageActualTag)
			_ = logboek.WithIndent(func() error {
				logboek.Info.LogFDetails("discarding newly built image %s\n", publishImage.MustGetBuiltId())
				logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
				logboek.Default.LogFDetails("      image: %s\n", imageName)

				return nil
			})

			logboek.LogOptionalLn()

			phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
				WerfImageName: img.GetName(),
				DockerRepo:    imageRepository,
				DockerTag:     imageActualTag,
				DockerImageID: alreadyExistingImageID,
			}

			return nil
		}

		if err := phase.ImagesRepo.PublishImage(publishImage); err != nil {
			return err
		}

		phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
			WerfImageName: img.GetName(),
			DockerRepo:    imageRepository,
			DockerTag:     imageActualTag,
			DockerImageID: publishImage.MustGetBuiltId(),
		}

		return nil
	}

	return logboek.Default.LogProcess(
		fmt.Sprintf("Publishing image %s by %s tag %s", img.LogName(), tagStrategy, imageMetaTag),
		logboek.LevelLogProcessOptions{
			SuccessInfoSectionFunc: successInfoSectionFunc,
			Style:                  logboek.HighlightStyle(),
		},
		publishingFunc)
}

func (phase *PublishImagesPhase) checkImageAlreadyExists(existingTags []string, werfImageName, imageMetaTag, imageContentSignature string, checkAlreadyExistingTagByContentSignatureFromLabels bool) (bool, string, error) {
	imageActualTag := phase.ImagesRepo.ImageRepositoryTag(werfImageName, imageMetaTag)

	if !util.IsStringsContainValue(existingTags, imageActualTag) {
		return false, "", nil
	} else if !checkAlreadyExistingTagByContentSignatureFromLabels {
		return true, "", nil
	}

	var repoImageContentSignature string
	var repoDockerImageID string
	var err error
	getImageContentSignature := func() error {
		repoImage, err := phase.ImagesRepo.GetRepoImage(werfImageName, imageMetaTag)
		if err != nil {
			return err
		}
		repoImageContentSignature = repoImage.Labels[image.WerfContentSignatureLabel]
		repoDockerImageID = repoImage.ID
		return nil
	}

	logProcessMsg := fmt.Sprintf("Getting existing tag %s manifest", imageActualTag)
	err = logboek.Info.LogProcessInline(logProcessMsg, logboek.LevelLogProcessInlineOptions{}, getImageContentSignature)
	if err != nil {
		return false, "", fmt.Errorf("unable to get image %s parent id: %s", werfImageName, err)
	}

	logboek.Debug.LogF("Current image content signature: %s\n", imageContentSignature)
	logboek.Debug.LogF("Already published image content signature: %s\n", repoImageContentSignature)
	logboek.Debug.LogF("Already published image docker ID: %s\n", repoDockerImageID)

	return imageContentSignature == repoImageContentSignature, repoDockerImageID, nil
}
<commit_msg>[publish-for-cleanup] Allow publish of different content-signatures by the same commit<commit_after>package build

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/werf/logboek"

	"github.com/werf/werf/pkg/build/stage"
	"github.com/werf/werf/pkg/container_runtime"
	"github.com/werf/werf/pkg/image"
	"github.com/werf/werf/pkg/storage"
	"github.com/werf/werf/pkg/tag_strategy"
	"github.com/werf/werf/pkg/util"
)

func NewPublishImagesPhase(c *Conveyor, imagesRepo storage.ImagesRepo, opts PublishImagesOptions) *PublishImagesPhase {
	tagsByScheme := map[tag_strategy.TagStrategy][]string{
		tag_strategy.Custom:    opts.CustomTags,
		tag_strategy.GitBranch: opts.TagsByGitBranch,
		tag_strategy.GitTag:    opts.TagsByGitTag,
		tag_strategy.GitCommit: opts.TagsByGitCommit,
	}
	return &PublishImagesPhase{
		BasePhase:            BasePhase{c},
		ImagesToPublish:      opts.ImagesToPublish,
		TagsByScheme:         tagsByScheme,
		TagByStagesSignature: opts.TagByStagesSignature,
		ImagesRepo:           imagesRepo,
		PublishReport:        &PublishReport{Images: make(map[string]PublishReportImageRecord)},
		PublishReportPath:    opts.PublishReportPath,
		PublishReportFormat:  opts.PublishReportFormat,
	}
}

type PublishImagesPhase struct {
	BasePhase
	ImagesToPublish      []string
	TagsByScheme         map[tag_strategy.TagStrategy][]string
	TagByStagesSignature bool
	ImagesRepo           storage.ImagesRepo

	PublishReport       *PublishReport
	PublishReportPath   string
	PublishReportFormat PublishReportFormat
}

type PublishReportFormat string

const (
	PublishReportJSON PublishReportFormat = "json"
)

type PublishReport struct {
	Images map[string]PublishReportImageRecord
}

type PublishReportImageRecord struct {
	WerfImageName string
	DockerRepo    string
	DockerTag     string
	DockerImageID string
}

func (phase *PublishImagesPhase) Name() string {
	return "publish"
}

func (phase *PublishImagesPhase) BeforeImages() error {
	return nil
}

func (phase *PublishImagesPhase) AfterImages() error {
	if data, err := json.Marshal(phase.PublishReport); err != nil {
		return fmt.Errorf("unable to prepare publish report: %s", err)
	} else {
		logboek.Debug.LogF("Publish report:\n%s\n", data)

		if phase.PublishReportPath != "" && phase.PublishReportFormat == PublishReportJSON {
			if err := ioutil.WriteFile(phase.PublishReportPath, append(data, []byte("\n")...), 0644); err != nil {
				return fmt.Errorf("unable to write publish report to %s: %s", phase.PublishReportPath, err)
			}
		}
	}

	return nil
}

func (phase *PublishImagesPhase) BeforeImageStages(img *Image) error {
	return nil
}

func (phase *PublishImagesPhase) OnImageStage(img *Image, stg stage.Interface) error {
	return nil
}

func (phase *PublishImagesPhase) AfterImageStages(img *Image) error {
	if img.isArtifact {
		return nil
	}

	if len(phase.ImagesToPublish) == 0 {
		return phase.publishImage(img)
	}

	for _, name := range phase.ImagesToPublish {
		if name == img.GetName() {
			return phase.publishImage(img)
		}
	}

	return nil
}

func (phase *PublishImagesPhase) ImageProcessingShouldBeStopped(img *Image) bool {
	return false
}

func (phase *PublishImagesPhase) publishImage(img *Image) error {
	var nonEmptySchemeInOrder []tag_strategy.TagStrategy
	for strategy, tags := range phase.TagsByScheme {
		if len(tags) == 0 {
			continue
		}

		nonEmptySchemeInOrder = append(nonEmptySchemeInOrder, strategy)
	}

	if phase.Conveyor.localGitRepo != nil {
		if err := logboek.Info.LogProcess(fmt.Sprintf("publishing image %s git metadata", img.GetName()), logboek.LevelLogProcessOptions{}, func() error {
			headCommit, err := phase.Conveyor.localGitRepo.HeadCommit()
			if err != nil {
				return err
			}

			// FIXME: Virtual merge commit?

			if metadata, err := phase.Conveyor.StagesManager.StagesStorage.GetImageMetadataByCommit(phase.Conveyor.projectName(), img.GetName(), headCommit); err != nil {
				return fmt.Errorf("unable to get image %s metadata by commit %s: %s", img.GetName(), headCommit, err)
			} else if metadata != nil {
				if metadata.ContentSignature != img.GetContentSignature() {
					// TODO: Check image existance and automatically allow republish if no images found by this commit. What if multiple images are published by multiple tagging strategies (including custom)?
					// TODO: allowInconsistentPublish: true option for werf.yaml
					// FIXME: return fmt.Errorf("inconsistent build: found already published image with stages-signature %s by commit %s, cannot publish a new image with stages-signature %s by the same commit", metadata.ContentSignature, headCommit, img.GetContentSignature())
					return phase.Conveyor.StagesManager.StagesStorage.PutImageCommit(phase.Conveyor.projectName(), img.GetName(), headCommit, &storage.ImageMetadata{ContentSignature: img.GetContentSignature()})
				}
				return nil
			} else {
				return phase.Conveyor.StagesManager.StagesStorage.PutImageCommit(phase.Conveyor.projectName(), img.GetName(), headCommit, &storage.ImageMetadata{ContentSignature: img.GetContentSignature()})
			}
		}); err != nil {
			return err
		}
	}

	var existingTags []string
	if tags, err := phase.fetchExistingTags(img.GetName()); err != nil {
		return err
	} else {
		existingTags = tags
	}

	for _, strategy := range nonEmptySchemeInOrder {
		imageMetaTags := phase.TagsByScheme[strategy]

		if err := logboek.Info.LogProcess(
			fmt.Sprintf("%s tagging strategy", string(strategy)),
			logboek.LevelLogProcessOptions{Style: logboek.HighlightStyle()},
			func() error {
				for _, imageMetaTag := range imageMetaTags {
					if err := phase.publishImageByTag(img, imageMetaTag, strategy, publishImageByTagOptions{ExistingTagsList: existingTags, CheckAlreadyExistingTagByContentSignatureLabel: true}); err != nil {
						return fmt.Errorf("error publishing image %s by tag %s: %s", img.LogName(), imageMetaTag, err)
					}
				}

				return nil
			},
		); err != nil {
			return err
		}
	}

	if phase.TagByStagesSignature {
		if err := logboek.Info.LogProcess(
			fmt.Sprintf("%s tagging strategy", tag_strategy.StagesSignature),
			logboek.LevelLogProcessOptions{Style: logboek.HighlightStyle()},
			func() error {
				if err := phase.publishImageByTag(img, img.GetContentSignature(), tag_strategy.StagesSignature, publishImageByTagOptions{ExistingTagsList: existingTags}); err != nil {
					return fmt.Errorf("error publishing image %s by image signature %s: %s", img.GetName(), img.GetContentSignature(), err)
				}

				return nil
			},
		); err != nil {
			return err
		}
	}

	return nil
}

func (phase *PublishImagesPhase) fetchExistingTags(imageName string) (existingTags []string, err error) {
	logProcessMsg := fmt.Sprintf("Fetching existing repo tags")
	_ = logboek.Info.LogProcessInline(logProcessMsg, logboek.LevelLogProcessInlineOptions{}, func() error {
		existingTags, err = phase.ImagesRepo.GetAllImageRepoTags(imageName)
		return nil
	})
	logboek.Info.LogOptionalLn()

	if err != nil {
		return existingTags, fmt.Errorf("error fetching existing tags from image repository %s: %s", phase.ImagesRepo.String(), err)
	}
	return existingTags, nil
}

type publishImageByTagOptions struct {
	CheckAlreadyExistingTagByContentSignatureLabel bool
	ExistingTagsList                               []string
}

func (phase *PublishImagesPhase) publishImageByTag(img *Image, imageMetaTag string, tagStrategy tag_strategy.TagStrategy, opts publishImageByTagOptions) error {
	imageRepository := phase.ImagesRepo.ImageRepositoryName(img.GetName())
	imageName := phase.ImagesRepo.ImageRepositoryNameWithTag(img.GetName(), imageMetaTag)
	imageActualTag := phase.ImagesRepo.ImageRepositoryTag(img.GetName(), imageMetaTag)

	alreadyExists, alreadyExistingDockerImageID, err := phase.checkImageAlreadyExists(opts.ExistingTagsList, img.GetName(), imageMetaTag, img.GetContentSignature(), opts.CheckAlreadyExistingTagByContentSignatureLabel)
	if err != nil {
		return fmt.Errorf("error checking image %s already exists in the images repo: %s", img.LogName(), err)
	}

	if alreadyExists {
		logboek.Default.LogFHighlight("%s tag %s is up-to-date\n", strings.Title(string(tagStrategy)), imageActualTag)

		_ = logboek.WithIndent(func() error {
			logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
			logboek.Default.LogFDetails("      image: %s\n", imageName)
			return nil
		})

		logboek.LogOptionalLn()

		phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
			WerfImageName: img.GetName(),
			DockerRepo:    imageRepository,
			DockerTag:     imageActualTag,
			DockerImageID: alreadyExistingDockerImageID,
		}

		return nil
	}

	publishImage := container_runtime.NewWerfImage(phase.Conveyor.GetStageImage(img.GetLastNonEmptyStage().GetImage().Name()), imageName, phase.Conveyor.ContainerRuntime.(*container_runtime.LocalDockerServerRuntime))

	publishImage.Container().ServiceCommitChangeOptions().AddLabel(map[string]string{
		image.WerfDockerImageName:       imageName,
		image.WerfTagStrategyLabel:      string(tagStrategy),
		image.WerfImageLabel:            "true",
		image.WerfImageNameLabel:        img.GetName(),
		image.WerfImageTagLabel:         imageMetaTag,
		image.WerfContentSignatureLabel: img.GetContentSignature(),
		image.WerfImageVersionLabel:     image.WerfImageVersion,
	})

	successInfoSectionFunc := func() {
		_ = logboek.WithIndent(func() error {
			logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
			logboek.Default.LogFDetails("      image: %s\n", imageName)
			return nil
		})
	}

	publishingFunc := func() error {
		if err := phase.Conveyor.StagesManager.FetchStage(img.GetLastNonEmptyStage()); err != nil {
			return err
		}

		if err := logboek.Info.LogProcess("Building final image with meta information", logboek.LevelLogProcessOptions{}, func() error {
			if err := publishImage.Build(container_runtime.BuildOptions{}); err != nil {
				return fmt.Errorf("error building %s with tagging strategy '%s': %s", imageName, tagStrategy, err)
			}
			return nil
		}); err != nil {
			return err
		}

		if lock, err := phase.Conveyor.StorageLockManager.LockImage(phase.Conveyor.projectName(), imageName); err != nil {
			return fmt.Errorf("error locking image %s: %s", imageName, err)
		} else {
			defer phase.Conveyor.StorageLockManager.Unlock(lock)
		}

		existingTags, err := phase.fetchExistingTags(img.GetName())
		if err != nil {
			return err
		}

		alreadyExists, alreadyExistingImageID, err := phase.checkImageAlreadyExists(existingTags, img.GetName(), imageMetaTag, img.GetContentSignature(), opts.CheckAlreadyExistingTagByContentSignatureLabel)
		if err != nil {
			return fmt.Errorf("error checking image %s already exists in the images repo: %s", img.LogName(), err)
		}

		if alreadyExists {
			logboek.Default.LogFHighlight("%s tag %s is up-to-date\n", strings.Title(string(tagStrategy)), imageActualTag)
			_ = logboek.WithIndent(func() error {
				logboek.Info.LogFDetails("discarding newly built image %s\n", publishImage.MustGetBuiltId())
				logboek.Default.LogFDetails("images-repo: %s\n", imageRepository)
				logboek.Default.LogFDetails("      image: %s\n", imageName)

				return nil
			})

			logboek.LogOptionalLn()

			phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
				WerfImageName: img.GetName(),
				DockerRepo:    imageRepository,
				DockerTag:     imageActualTag,
				DockerImageID: alreadyExistingImageID,
			}

			return nil
		}

		if err := phase.ImagesRepo.PublishImage(publishImage); err != nil {
			return err
		}

		phase.PublishReport.Images[img.GetName()] = PublishReportImageRecord{
			WerfImageName: img.GetName(),
			DockerRepo:    imageRepository,
			DockerTag:     imageActualTag,
			DockerImageID: publishImage.MustGetBuiltId(),
		}

		return nil
	}

	return logboek.Default.LogProcess(
		fmt.Sprintf("Publishing image %s by %s tag %s", img.LogName(), tagStrategy, imageMetaTag),
		logboek.LevelLogProcessOptions{
			SuccessInfoSectionFunc: successInfoSectionFunc,
			Style:                  logboek.HighlightStyle(),
		},
		publishingFunc)
}

func (phase *PublishImagesPhase) checkImageAlreadyExists(existingTags []string, werfImageName, imageMetaTag, imageContentSignature string, checkAlreadyExistingTagByContentSignatureFromLabels bool) (bool, string, error) {
	imageActualTag := phase.ImagesRepo.ImageRepositoryTag(werfImageName, imageMetaTag)

	if !util.IsStringsContainValue(existingTags, imageActualTag) {
		return false, "", nil
	} else if !checkAlreadyExistingTagByContentSignatureFromLabels {
		return true, "", nil
	}

	var repoImageContentSignature string
	var repoDockerImageID string
	var err error
	getImageContentSignature := func() error {
		repoImage, err := phase.ImagesRepo.GetRepoImage(werfImageName, imageMetaTag)
		if err != nil {
			return err
		}
		repoImageContentSignature = repoImage.Labels[image.WerfContentSignatureLabel]
		repoDockerImageID = repoImage.ID
		return nil
	}

	logProcessMsg := fmt.Sprintf("Getting existing tag %s manifest", imageActualTag)
	err = logboek.Info.LogProcessInline(logProcessMsg, logboek.LevelLogProcessInlineOptions{}, getImageContentSignature)
	if err != nil {
		return false, "", fmt.Errorf("unable to get image %s parent id: %s", werfImageName, err)
	}

	logboek.Debug.LogF("Current image content signature: %s\n", imageContentSignature)
	logboek.Debug.LogF("Already published image content signature: %s\n", repoImageContentSignature)
	logboek.Debug.LogF("Already published image docker ID: %s\n", repoDockerImageID)

	return imageContentSignature == repoImageContentSignature, repoDockerImageID, nil
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	kapi "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
	"k8s.io/kubernetes/pkg/kubelet/dockertools"
	pconfig "k8s.io/kubernetes/pkg/proxy/config"
	proxy "k8s.io/kubernetes/pkg/proxy/userspace"
	"k8s.io/kubernetes/pkg/util"
	utildbus "k8s.io/kubernetes/pkg/util/dbus"
	kexec "k8s.io/kubernetes/pkg/util/exec"
	"k8s.io/kubernetes/pkg/util/iptables"

	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	dockerutil "github.com/openshift/origin/pkg/cmd/util/docker"
)

type commandExecutor interface {
	LookPath(executable string) (string, error)
	Run(command string, args ...string) error
}

type defaultCommandExecutor struct{}

func (ce defaultCommandExecutor) LookPath(executable string) (string, error) {
	return exec.LookPath(executable)
}

func (ce defaultCommandExecutor) Run(command string, args ...string) error {
	c := exec.Command(command, args...)
	return c.Run()
}

const minimumDockerAPIVersionWithPullByID = "1.18"

// EnsureDocker attempts to connect to the Docker daemon defined by the helper,
// and if it is unable to it will print a warning.
func (c *NodeConfig) EnsureDocker(docker *dockerutil.Helper) {
	dockerClient, dockerAddr := docker.GetClientOrExit()
	if err := dockerClient.Ping(); err != nil {
		c.HandleDockerError(fmt.Sprintf("Docker could not be reached at %s.  Docker must be installed and running to start containers.\n%v", dockerAddr, err))
		return
	}

	glog.Infof("Connecting to Docker at %s", dockerAddr)

	env, err := dockerClient.Version()
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to check for Docker server version.\n%v", err))
		return
	}

	serverVersionString := env.Get("ApiVersion")
	serverVersion, err := dockerclient.NewAPIVersion(serverVersionString)
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to determine Docker server version from %q.\n%v", serverVersionString, err))
		return
	}

	minimumPullByIDVersion, err := dockerclient.NewAPIVersion(minimumDockerAPIVersionWithPullByID)
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to check for Docker server version.\n%v", err))
		return
	}

	if serverVersion.LessThan(minimumPullByIDVersion) {
		c.HandleDockerError(fmt.Sprintf("Docker 1.6 or later (server API version 1.18 or later) required."))
		return
	}

	c.DockerClient = dockerClient
}

// HandleDockerError handles an an error from the docker daemon
func (c *NodeConfig) HandleDockerError(message string) {
	if !c.AllowDisabledDocker {
		glog.Fatalf("ERROR: %s", message)
	}
	glog.Errorf("WARNING: %s", message)
	c.DockerClient = &dockertools.FakeDockerClient{VersionInfo: dockerclient.Env([]string{"ApiVersion=1.18"})}
}

// EnsureVolumeDir attempts to convert the provided volume directory argument to
// an absolute path and create the directory if it does not exist. Will exit if
// an error is encountered.
func (c *NodeConfig) EnsureVolumeDir() {
	if volumeDir, err := c.initializeVolumeDir(&defaultCommandExecutor{}, c.VolumeDir); err != nil {
		glog.Fatal(err)
	} else {
		c.VolumeDir = volumeDir
	}
}

func (c *NodeConfig) initializeVolumeDir(ce commandExecutor, path string) (string, error) {
	rootDirectory, err := filepath.Abs(path)
	if err != nil {
		return "", fmt.Errorf("Error converting volume directory to an absolute path: %v", err)
	}

	if _, err := os.Stat(rootDirectory); os.IsNotExist(err) {
		if err := os.MkdirAll(rootDirectory, 0750); err != nil {
			return "", fmt.Errorf("Couldn't create kubelet volume root directory '%s': %s", rootDirectory, err)
		}
	}
	// always try to chcon, in case the volume dir existed prior to the node starting
	if chconPath, err := ce.LookPath("chcon"); err != nil {
		glog.V(2).Infof("Couldn't locate 'chcon' to set the kubelet volume root directory SELinux context: %s", err)
	} else {
		if err := ce.Run(chconPath, "-t", "svirt_sandbox_file_t", rootDirectory); err != nil {
			glog.Warningf("Error running 'chcon' to set the kubelet volume root directory SELinux context: %s", err)
		}
	}
	return rootDirectory, nil
}

// RunKubelet starts the Kubelet.
func (c *NodeConfig) RunKubelet() {
	if c.KubeletConfig.ClusterDNS == nil {
		if service, err := c.Client.Services(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if includesServicePort(service.Spec.Ports, 53, "dns") {
				// Use master service if service includes "dns" port 53.
				c.KubeletConfig.ClusterDNS = net.ParseIP(service.Spec.ClusterIP)
			}
		}
	}
	if c.KubeletConfig.ClusterDNS == nil {
		if endpoint, err := c.Client.Endpoints(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if endpointIP, ok := firstEndpointIPWithNamedPort(endpoint, 53, "dns"); ok {
				// Use first endpoint if endpoint includes "dns" port 53.
				c.KubeletConfig.ClusterDNS = net.ParseIP(endpointIP)
			} else if endpointIP, ok := firstEndpointIP(endpoint, 53); ok {
				// Test and use first endpoint if endpoint includes any port 53.
				if err := cmdutil.WaitForSuccessfulDial(false, "tcp", fmt.Sprintf("%s:%d", endpointIP, 53), 50*time.Millisecond, 0, 2); err == nil {
					c.KubeletConfig.ClusterDNS = net.ParseIP(endpointIP)
				}
			}
		}
	}

	c.KubeletConfig.DockerClient = c.DockerClient
	// updated by NodeConfig.EnsureVolumeDir
	c.KubeletConfig.RootDirectory = c.VolumeDir

	// hook for overriding the cadvisor interface for integration tests
	c.KubeletConfig.CAdvisorInterface = defaultCadvisorInterface

	go func() {
		glog.Fatal(c.KubeletServer.Run(c.KubeletConfig))
	}()
}

// defaultCadvisorInterface holds the overridden default interface
// exists only to allow stubbing integration tests, should always be nil in production
var defaultCadvisorInterface cadvisor.Interface = nil

// SetFakeCadvisorInterfaceForIntegrationTest sets a fake cadvisor implementation to allow the node to run in integration tests
func SetFakeCadvisorInterfaceForIntegrationTest() {
	defaultCadvisorInterface = &cadvisor.Fake{}
}

type FilteringEndpointsConfigHandler interface {
	pconfig.EndpointsConfigHandler
	SetBaseEndpointsHandler(base pconfig.EndpointsConfigHandler)
}

// RunProxy starts the proxy
func (c *NodeConfig) RunProxy(endpointsFilterer FilteringEndpointsConfigHandler) {
	// initialize kube proxy
	serviceConfig := pconfig.NewServiceConfig()
	endpointsConfig := pconfig.NewEndpointsConfig()
	loadBalancer := proxy.NewLoadBalancerRR()
	if endpointsFilterer == nil {
		endpointsConfig.RegisterHandler(loadBalancer)
	} else {
		endpointsFilterer.SetBaseEndpointsHandler(loadBalancer)
		endpointsConfig.RegisterHandler(endpointsFilterer)
	}

	host, _, err := net.SplitHostPort(c.BindAddress)
	if err != nil {
		glog.Fatalf("The provided value to bind to must be an ip:port %q", c.BindAddress)
	}
	ip := net.ParseIP(host)
	if ip == nil {
		glog.Fatalf("The provided value to bind to must be an ip:port: %q", c.BindAddress)
	}

	protocol := iptables.ProtocolIpv4
	if ip.To4() == nil {
		protocol = iptables.ProtocolIpv6
	}

	syncPeriod, err := time.ParseDuration(c.IPTablesSyncPeriod)
	if err != nil {
		glog.Fatalf("Cannot parse the provided ip-tables sync period (%s) : %v", c.IPTablesSyncPeriod, err)
	}

	eventBroadcaster := record.NewBroadcaster()
	eventBroadcaster.StartRecordingToSink(c.Client.Events(""))
	recorder := eventBroadcaster.NewRecorder(kapi.EventSource{Component: "kube-proxy", Host: c.KubeletConfig.NodeName})
	nodeRef := &kapi.ObjectReference{
		Kind: "Node",
		Name: c.KubeletConfig.NodeName,
	}

	go util.Forever(func() {
		dbus := utildbus.New()
		iptables := iptables.New(kexec.New(), dbus, protocol)
		proxier, err := proxy.NewProxier(loadBalancer, ip, iptables, util.PortRange{}, syncPeriod)
		iptables.AddReloadFunc(proxier.Sync)

		if err != nil {
			switch {
			// conflicting use of iptables, retry
			case proxy.IsProxyLocked(err):
				glog.Errorf("Unable to start proxy, will retry: %v", err)
				return
			// on a system without iptables
			case strings.Contains(err.Error(), "executable file not found in path"):
				glog.V(4).Infof("kube-proxy initialization error: %v", err)
				glog.Warningf("WARNING: Could not find the iptables command. The service proxy requires iptables and will be disabled.")
			case err == proxy.ErrProxyOnLocalhost:
				glog.Warningf("WARNING: The service proxy cannot bind to localhost and will be disabled.")
			case strings.Contains(err.Error(), "you must be root"):
				glog.Warningf("WARNING: Could not modify iptables. You must run this process as root to use the service proxy.")
			default:
				glog.Warningf("WARNING: Could not modify iptables. You must run this process as root to use the service proxy: %v", err)
			}
			select {}
		}

		pconfig.NewSourceAPI(
			c.Client,
			10*time.Minute,
			serviceConfig.Channel("api"),
			endpointsConfig.Channel("api"))

		serviceConfig.RegisterHandler(proxier)
		recorder.Eventf(nodeRef, "Starting", "Starting kube-proxy.")
		glog.Infof("Started Kubernetes Proxy on %s", host)
		select {}
	}, 5*time.Second)
}

// TODO: more generic location
func includesServicePort(ports []kapi.ServicePort, port int, portName string) bool {
	for _, p := range ports {
		if p.Port == port && p.Name == portName {
			return true
		}
	}
	return false
}

// TODO: more generic location
func includesEndpointPort(ports []kapi.EndpointPort, port int) bool {
	for _, p := range ports {
		if p.Port == port {
			return true
		}
	}
	return false
}

// TODO: more generic location
func firstEndpointIP(endpoints *kapi.Endpoints, port int) (string, bool) {
	for _, s := range endpoints.Subsets {
		if !includesEndpointPort(s.Ports, port) {
			continue
		}
		for _, a := range s.Addresses {
			return a.IP, true
		}
	}
	return "", false
}

// TODO: more generic location
func firstEndpointIPWithNamedPort(endpoints *kapi.Endpoints, port int, portName string) (string, bool) {
	for _, s := range endpoints.Subsets {
		if !includesNamedEndpointPort(s.Ports, port, portName) {
			continue
		}
		for _, a := range s.Addresses {
			return a.IP, true
		}
	}
	return "", false
}

// TODO: more generic location
func includesNamedEndpointPort(ports []kapi.EndpointPort, port int, portName string) bool {
	for _, p := range ports {
		if p.Port == port && p.Name == portName {
			return true
		}
	}
	return false
}
<commit_msg>Use the iptables-based proxier instead of the userland one<commit_after>package kubernetes

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	kapi "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
	"k8s.io/kubernetes/pkg/kubelet/dockertools"
	pconfig "k8s.io/kubernetes/pkg/proxy/config"
	proxy "k8s.io/kubernetes/pkg/proxy/iptables"
	utildbus "k8s.io/kubernetes/pkg/util/dbus"
	kexec "k8s.io/kubernetes/pkg/util/exec"
	"k8s.io/kubernetes/pkg/util/iptables"

	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	dockerutil "github.com/openshift/origin/pkg/cmd/util/docker"
)

type commandExecutor interface {
	LookPath(executable string) (string, error)
	Run(command string, args ...string) error
}

type defaultCommandExecutor struct{}

func (ce defaultCommandExecutor) LookPath(executable string) (string, error) {
	return exec.LookPath(executable)
}

func (ce defaultCommandExecutor) Run(command string, args ...string) error {
	c := exec.Command(command, args...)
	return c.Run()
}

const minimumDockerAPIVersionWithPullByID = "1.18"

// EnsureDocker attempts to connect to the Docker daemon defined by the helper,
// and if it is unable to it will print a warning.
func (c *NodeConfig) EnsureDocker(docker *dockerutil.Helper) {
	dockerClient, dockerAddr := docker.GetClientOrExit()
	if err := dockerClient.Ping(); err != nil {
		c.HandleDockerError(fmt.Sprintf("Docker could not be reached at %s.  Docker must be installed and running to start containers.\n%v", dockerAddr, err))
		return
	}

	glog.Infof("Connecting to Docker at %s", dockerAddr)

	env, err := dockerClient.Version()
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to check for Docker server version.\n%v", err))
		return
	}

	serverVersionString := env.Get("ApiVersion")
	serverVersion, err := dockerclient.NewAPIVersion(serverVersionString)
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to determine Docker server version from %q.\n%v", serverVersionString, err))
		return
	}

	minimumPullByIDVersion, err := dockerclient.NewAPIVersion(minimumDockerAPIVersionWithPullByID)
	if err != nil {
		c.HandleDockerError(fmt.Sprintf("Unable to check for Docker server version.\n%v", err))
		return
	}

	if serverVersion.LessThan(minimumPullByIDVersion) {
		c.HandleDockerError(fmt.Sprintf("Docker 1.6 or later (server API version 1.18 or later) required."))
		return
	}

	c.DockerClient = dockerClient
}

// HandleDockerError handles an an error from the docker daemon
func (c *NodeConfig) HandleDockerError(message string) {
	if !c.AllowDisabledDocker {
		glog.Fatalf("ERROR: %s", message)
	}
	glog.Errorf("WARNING: %s", message)
	c.DockerClient = &dockertools.FakeDockerClient{VersionInfo: dockerclient.Env([]string{"ApiVersion=1.18"})}
}

// EnsureVolumeDir attempts to convert the provided volume directory argument to
// an absolute path and create the directory if it does not exist. Will exit if
// an error is encountered.
func (c *NodeConfig) EnsureVolumeDir() {
	if volumeDir, err := c.initializeVolumeDir(&defaultCommandExecutor{}, c.VolumeDir); err != nil {
		glog.Fatal(err)
	} else {
		c.VolumeDir = volumeDir
	}
}

func (c *NodeConfig) initializeVolumeDir(ce commandExecutor, path string) (string, error) {
	rootDirectory, err := filepath.Abs(path)
	if err != nil {
		return "", fmt.Errorf("Error converting volume directory to an absolute path: %v", err)
	}

	if _, err := os.Stat(rootDirectory); os.IsNotExist(err) {
		if err := os.MkdirAll(rootDirectory, 0750); err != nil {
			return "", fmt.Errorf("Couldn't create kubelet volume root directory '%s': %s", rootDirectory, err)
		}
	}
	// always try to chcon, in case the volume dir existed prior to the node starting
	if chconPath, err := ce.LookPath("chcon"); err != nil {
		glog.V(2).Infof("Couldn't locate 'chcon' to set the kubelet volume root directory SELinux context: %s", err)
	} else {
		if err := ce.Run(chconPath, "-t", "svirt_sandbox_file_t", rootDirectory); err != nil {
			glog.Warningf("Error running 'chcon' to set the kubelet volume root directory SELinux context: %s", err)
		}
	}
	return rootDirectory, nil
}

// RunKubelet starts the Kubelet.
func (c *NodeConfig) RunKubelet() {
	if c.KubeletConfig.ClusterDNS == nil {
		if service, err := c.Client.Services(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if includesServicePort(service.Spec.Ports, 53, "dns") {
				// Use master service if service includes "dns" port 53.
				c.KubeletConfig.ClusterDNS = net.ParseIP(service.Spec.ClusterIP)
			}
		}
	}
	if c.KubeletConfig.ClusterDNS == nil {
		if endpoint, err := c.Client.Endpoints(kapi.NamespaceDefault).Get("kubernetes"); err == nil {
			if endpointIP, ok := firstEndpointIPWithNamedPort(endpoint, 53, "dns"); ok {
				// Use first endpoint if endpoint includes "dns" port 53.
				c.KubeletConfig.ClusterDNS = net.ParseIP(endpointIP)
			} else if endpointIP, ok := firstEndpointIP(endpoint, 53); ok {
				// Test and use first endpoint if endpoint includes any port 53.
				if err := cmdutil.WaitForSuccessfulDial(false, "tcp", fmt.Sprintf("%s:%d", endpointIP, 53), 50*time.Millisecond, 0, 2); err == nil {
					c.KubeletConfig.ClusterDNS = net.ParseIP(endpointIP)
				}
			}
		}
	}

	c.KubeletConfig.DockerClient = c.DockerClient
	// updated by NodeConfig.EnsureVolumeDir
	c.KubeletConfig.RootDirectory = c.VolumeDir

	// hook for overriding the cadvisor interface for integration tests
	c.KubeletConfig.CAdvisorInterface = defaultCadvisorInterface

	go func() {
		glog.Fatal(c.KubeletServer.Run(c.KubeletConfig))
	}()
}

// defaultCadvisorInterface holds the overridden default interface
// exists only to allow stubbing integration tests, should always be nil in production
var defaultCadvisorInterface cadvisor.Interface = nil

// SetFakeCadvisorInterfaceForIntegrationTest sets a fake cadvisor implementation to allow the node to run in integration tests
func SetFakeCadvisorInterfaceForIntegrationTest() {
	defaultCadvisorInterface = &cadvisor.Fake{}
}

type FilteringEndpointsConfigHandler interface {
	pconfig.EndpointsConfigHandler
	SetBaseEndpointsHandler(base pconfig.EndpointsConfigHandler)
}

// RunProxy starts the proxy
func (c *NodeConfig) RunProxy(endpointsFilterer FilteringEndpointsConfigHandler) {
	// initialize kube proxy
	serviceConfig := pconfig.NewServiceConfig()
	endpointsConfig := pconfig.NewEndpointsConfig()

	host, _, err := net.SplitHostPort(c.BindAddress)
	if err != nil {
		glog.Fatalf("The provided value to bind to must be an ip:port %q", c.BindAddress)
	}
	ip := net.ParseIP(host)
	if ip == nil {
		glog.Fatalf("The provided value to bind to must be an ip:port: %q", c.BindAddress)
	}

	protocol := iptables.ProtocolIpv4
	if ip.To4() == nil {
		protocol = iptables.ProtocolIpv6
	}

	syncPeriod, err := time.ParseDuration(c.IPTablesSyncPeriod)
	if err != nil {
		glog.Fatalf("Cannot parse the provided ip-tables sync period (%s) : %v", c.IPTablesSyncPeriod, err)
	}

	eventBroadcaster := record.NewBroadcaster()
	eventBroadcaster.StartRecordingToSink(c.Client.Events(""))
	recorder := eventBroadcaster.NewRecorder(kapi.EventSource{Component: "kube-proxy", Host: c.KubeletConfig.NodeName})
	nodeRef := &kapi.ObjectReference{
		Kind: "Node",
		Name: c.KubeletConfig.NodeName,
	}

	exec := kexec.New()
	dbus := utildbus.New()
	iptables := iptables.New(exec, dbus, protocol)
	proxier, err := proxy.NewProxier(iptables, exec, syncPeriod, false)
	if err != nil {
		// This should be fatal, but that would break the integration tests
		glog.Warningf("WARNING: Could not initialize Kubernetes Proxy. You must run this process as root to use the service proxy: %v", err)
		return
	}
	iptables.AddReloadFunc(proxier.Sync)

	pconfig.NewSourceAPI(
		c.Client,
		10*time.Minute,
		serviceConfig.Channel("api"),
		endpointsConfig.Channel("api"))

	serviceConfig.RegisterHandler(proxier)
	if endpointsFilterer == nil {
		endpointsConfig.RegisterHandler(proxier)
	} else {
		endpointsFilterer.SetBaseEndpointsHandler(proxier)
		endpointsConfig.RegisterHandler(endpointsFilterer)
	}
	recorder.Eventf(nodeRef, "Starting", "Starting kube-proxy.")
	glog.Infof("Started Kubernetes Proxy on %s", host)
}

// TODO: more generic location
func includesServicePort(ports []kapi.ServicePort, port int, portName string) bool {
	for _, p := range ports {
		if p.Port == port && p.Name == portName {
			return true
		}
	}
	return false
}

// TODO: more generic location
func includesEndpointPort(ports []kapi.EndpointPort, port int) bool {
	for _, p := range ports {
		if p.Port == port {
			return true
		}
	}
	return false
}

// TODO: more generic location
func firstEndpointIP(endpoints *kapi.Endpoints, port int) (string, bool) {
	for _, s := range endpoints.Subsets {
		if !includesEndpointPort(s.Ports, port) {
			continue
		}
		for _, a := range s.Addresses {
			return a.IP, true
		}
	}
	return "", false
}

// TODO: more generic location
func firstEndpointIPWithNamedPort(endpoints *kapi.Endpoints, port int, portName string) (string, bool) {
	for _, s := range endpoints.Subsets {
		if !includesNamedEndpointPort(s.Ports, port, portName) {
			continue
		}
		for _, a := range s.Addresses {
			return a.IP, true
		}
	}
	return "", false
}

// TODO: more generic location
func includesNamedEndpointPort(ports []kapi.EndpointPort, port int, portName string) bool {
	for _, p := range ports {
		if p.Port == port && p.Name == portName {
			return true
		}
	}
	return false
}
<|endoftext|>