<commit_before>package routeservice_test

import (
	"Fmt"
	"errors"
	"net/http"
	"net/url"
	"time"

	"code.cloudfoundry.org/gorouter/common/secure"
	"code.cloudfoundry.org/gorouter/common/secure/fakes"
	"code.cloudfoundry.org/gorouter/routeservice"
	"code.cloudfoundry.org/gorouter/routeservice/header"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Route Service Config", func() {
	var (
		config         *routeservice.RouteServiceConfig
		crypto         secure.Crypto
		cryptoPrev     secure.Crypto
		cryptoKey      = "ABCDEFGHIJKLMNOP"
		logger         lager.Logger
		recommendHttps bool
	)

	BeforeEach(func() {
		var err error
		crypto, err = secure.NewAesGCM([]byte(cryptoKey))
		Expect(err).ToNot(HaveOccurred())
		logger = lagertest.NewTestLogger("test")
		config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
	})

	AfterEach(func() {
		crypto = nil
		cryptoPrev = nil
		config = nil
	})

	Describe("Request", func() {
		It("decodes an encoded URL", func() {
			encodedForwardedURL := url.QueryEscape("test.app.com?query=sample")
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).NotTo(HaveOccurred())

			signature, err := header.SignatureFromHeaders(args.Signature, args.Metadata, crypto)
			Expect(err).ToNot(HaveOccurred())

			Expect(signature.ForwardedUrl).ToNot(BeEmpty())
		})

		It("sets the requested time", func() {
			encodedForwardedURL := url.QueryEscape("test.app.com?query=sample")
			now := time.Now()
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).NotTo(HaveOccurred())

			signature, err := header.SignatureFromHeaders(args.Signature, args.Metadata, crypto)
			Expect(err).ToNot(HaveOccurred())

			Expect(signature.RequestedTime).To(BeTemporally(">=", now))
		})

		It("returns an error if given an invalid encoded URL", func() {
			encodedForwardedURL := "test.app.com?query=sample%"
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).To(HaveOccurred())

			Expect(args.Metadata).To(BeEmpty())
			Expect(args.Signature).To(BeEmpty())
		})

		Context("when encryption fails", func() {
			BeforeEach(func() {
				fakeCrypto := &fakes.FakeCrypto{}
				fakeCrypto.EncryptReturns([]byte{}, []byte{}, errors.New("test failed"))

				config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, fakeCrypto, cryptoPrev, recommendHttps)
			})

			It("returns an error", func() {
				encodedForwardedURL := "test.app.com"
				rsUrl := "https://example.com"

				args, err := config.Request(rsUrl, encodedForwardedURL)
				Expect(err).To(HaveOccurred())

				Expect(args.Metadata).To(BeEmpty())
				Expect(args.Signature).To(BeEmpty())
			})
		})

		It("returns route service request information", func() {
			rsUrl := "https://example.com"
			forwardedUrl := "https://forwarded.example.com"
			args, err := config.Request(rsUrl, forwardedUrl)
			Expect(err).NotTo(HaveOccurred())

			rsURL, err := url.Parse(rsUrl)
			Expect(err).ToNot(HaveOccurred())

			Expect(args.ParsedUrl).To(Equal(rsURL))
			Expect(args.URLString).To(Equal(rsUrl))
			Expect(args.ForwardedURL).To(Equal(fmt.Sprintf("%s", forwardedUrl)))
		})
	})

	Describe("ValidateSignature", func() {
		var (
			signatureHeader string
			metadataHeader  string
			requestUrl      string
			headers         *http.Header
			signature       *header.Signature
		)

		BeforeEach(func() {
			h := make(http.Header, 0)
			headers = &h
			var err error
			requestUrl = "some-forwarded-url"
			signature = &header.Signature{
				RequestedTime: time.Now(),
				ForwardedUrl:  requestUrl,
			}
			signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
			Expect(err).ToNot(HaveOccurred())

			headers.Set(routeservice.RouteServiceForwardedURL, "some-forwarded-url")
		})

		JustBeforeEach(func() {
			headers.Set(routeservice.RouteServiceSignature, signatureHeader)
			headers.Set(routeservice.RouteServiceMetadata, metadataHeader)
		})

		It("decrypts a valid signature", func() {
			err := config.ValidateSignature(headers, requestUrl)
			Expect(err).NotTo(HaveOccurred())
		})

		Context("when the timestamp is expired", func() {
			BeforeEach(func() {
				signature = &header.Signature{
					RequestedTime: time.Now().Add(-10 * time.Hour),
					ForwardedUrl:  "some-forwarded-url",
				}
				var err error
				signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
				Expect(err).ToNot(HaveOccurred())
			})

			It("returns an route service request expired error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
				Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceExpired))
				Expect(err.Error()).To(ContainSubstring("request expired"))
			})
		})

		Context("when the signature is invalid", func() {
			BeforeEach(func() {
				signatureHeader = "zKQt4bnxW30Kxky"
				metadataHeader = "eyJpdiI6IjlBVn"
			})
			It("returns an error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
			})
		})

		Context("when the request URL is different from the signature", func() {
			BeforeEach(func() {
				requestUrl = "not-forwarded-url"
			})

			It("returns a route service request bad forwarded url error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
				Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceForwardedURLMismatch))
			})
		})

		Context("when there is a url encoded character in the request", func() {
			encodedCharacters := make(map[string]string)
			encodedCharacters["%2C"] = ","
			encodedCharacters["%20"] = " "
			encodedCharacters["%41"] = "A"

			for encoded, decoded := range encodedCharacters {
				forwardedUrl := fmt.Sprintf("some-forwarded-url?fields=foo%sbar", decoded)
				url := fmt.Sprintf("?fields=foo%sbar", encoded)

				Context("with character "+decoded, func() {
					BeforeEach(func() {
						signature = &header.Signature{
							RequestedTime: time.Now(),
							ForwardedUrl:  forwardedUrl,
						}
						var err error
						signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
						Expect(err).ToNot(HaveOccurred())
						requestUrl = requestUrl + url
					})

					It("decrypts the valid signature with character "+encoded, func() {
						err := config.ValidateSignature(headers, requestUrl)
						Expect(err).NotTo(HaveOccurred())
					})
				})
			}
		})

		Context("when there is a percent without two hexadec following in the url", func() {
			BeforeEach(func() {
				signature = &header.Signature{
					RequestedTime: time.Now(),
					ForwardedUrl:  "random%",
				}
				var err error
				signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
				Expect(err).ToNot(HaveOccurred())
			})

			It("request url does not match forwarded url", func() {
				err := config.ValidateSignature(headers, "random%")
				Expect(err).To(HaveOccurred())
			})
		})

		Context("when the header does not match the current key", func() {
			BeforeEach(func() {
				var err error
				crypto, err = secure.NewAesGCM([]byte("QRSTUVWXYZ123456"))
				Expect(err).NotTo(HaveOccurred())
				config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
			})

			Context("when there is no previous key in the configuration", func() {
				It("rejects the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("authentication failed"))
				})
			})

			Context("when the header key matches the previous key in the configuration", func() {
				BeforeEach(func() {
					var err error
					cryptoPrev, err = secure.NewAesGCM([]byte(cryptoKey))
					Expect(err).ToNot(HaveOccurred())
					config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
				})

				It("validates the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).NotTo(HaveOccurred())
				})

				Context("when a request has an expired Route service signature header", func() {
					BeforeEach(func() {
						signature = &header.Signature{
							RequestedTime: time.Now().Add(-10 * time.Hour),
							ForwardedUrl:  "some-forwarded-url",
						}
						var err error
						signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
						Expect(err).ToNot(HaveOccurred())
					})

					It("returns an route service request expired error", func() {
						err := config.ValidateSignature(headers, requestUrl)
						Expect(err).To(HaveOccurred())
						Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceExpired))
					})
				})
			})

			Context("when the header key does not match the previous key in the configuration", func() {
				BeforeEach(func() {
					var err error
					cryptoPrev, err = secure.NewAesGCM([]byte("QRSTUVWXYZ123456"))
					Expect(err).ToNot(HaveOccurred())
					config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
				})

				It("rejects the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("authentication failed"))
				})
			})
		})
	})
})
<commit_msg>Fix package import issue<commit_after>package routeservice_test

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"code.cloudfoundry.org/gorouter/common/secure"
	"code.cloudfoundry.org/gorouter/common/secure/fakes"
	"code.cloudfoundry.org/gorouter/routeservice"
	"code.cloudfoundry.org/gorouter/routeservice/header"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Route Service Config", func() {
	var (
		config         *routeservice.RouteServiceConfig
		crypto         secure.Crypto
		cryptoPrev     secure.Crypto
		cryptoKey      = "ABCDEFGHIJKLMNOP"
		logger         lager.Logger
		recommendHttps bool
	)

	BeforeEach(func() {
		var err error
		crypto, err = secure.NewAesGCM([]byte(cryptoKey))
		Expect(err).ToNot(HaveOccurred())
		logger = lagertest.NewTestLogger("test")
		config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
	})

	AfterEach(func() {
		crypto = nil
		cryptoPrev = nil
		config = nil
	})

	Describe("Request", func() {
		It("decodes an encoded URL", func() {
			encodedForwardedURL := url.QueryEscape("test.app.com?query=sample")
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).NotTo(HaveOccurred())

			signature, err := header.SignatureFromHeaders(args.Signature, args.Metadata, crypto)
			Expect(err).ToNot(HaveOccurred())

			Expect(signature.ForwardedUrl).ToNot(BeEmpty())
		})

		It("sets the requested time", func() {
			encodedForwardedURL := url.QueryEscape("test.app.com?query=sample")
			now := time.Now()
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).NotTo(HaveOccurred())

			signature, err := header.SignatureFromHeaders(args.Signature, args.Metadata, crypto)
			Expect(err).ToNot(HaveOccurred())

			Expect(signature.RequestedTime).To(BeTemporally(">=", now))
		})

		It("returns an error if given an invalid encoded URL", func() {
			encodedForwardedURL := "test.app.com?query=sample%"
			rsUrl := "https://example.com"

			args, err := config.Request(rsUrl, encodedForwardedURL)
			Expect(err).To(HaveOccurred())

			Expect(args.Metadata).To(BeEmpty())
			Expect(args.Signature).To(BeEmpty())
		})

		Context("when encryption fails", func() {
			BeforeEach(func() {
				fakeCrypto := &fakes.FakeCrypto{}
				fakeCrypto.EncryptReturns([]byte{}, []byte{}, errors.New("test failed"))

				config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, fakeCrypto, cryptoPrev, recommendHttps)
			})

			It("returns an error", func() {
				encodedForwardedURL := "test.app.com"
				rsUrl := "https://example.com"

				args, err := config.Request(rsUrl, encodedForwardedURL)
				Expect(err).To(HaveOccurred())

				Expect(args.Metadata).To(BeEmpty())
				Expect(args.Signature).To(BeEmpty())
			})
		})

		It("returns route service request information", func() {
			rsUrl := "https://example.com"
			forwardedUrl := "https://forwarded.example.com"
			args, err := config.Request(rsUrl, forwardedUrl)
			Expect(err).NotTo(HaveOccurred())

			rsURL, err := url.Parse(rsUrl)
			Expect(err).ToNot(HaveOccurred())

			Expect(args.ParsedUrl).To(Equal(rsURL))
			Expect(args.URLString).To(Equal(rsUrl))
			Expect(args.ForwardedURL).To(Equal(fmt.Sprintf("%s", forwardedUrl)))
		})
	})

	Describe("ValidateSignature", func() {
		var (
			signatureHeader string
			metadataHeader  string
			requestUrl      string
			headers         *http.Header
			signature       *header.Signature
		)

		BeforeEach(func() {
			h := make(http.Header, 0)
			headers = &h
			var err error
			requestUrl = "some-forwarded-url"
			signature = &header.Signature{
				RequestedTime: time.Now(),
				ForwardedUrl:  requestUrl,
			}
			signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
			Expect(err).ToNot(HaveOccurred())

			headers.Set(routeservice.RouteServiceForwardedURL, "some-forwarded-url")
		})

		JustBeforeEach(func() {
			headers.Set(routeservice.RouteServiceSignature, signatureHeader)
			headers.Set(routeservice.RouteServiceMetadata, metadataHeader)
		})

		It("decrypts a valid signature", func() {
			err := config.ValidateSignature(headers, requestUrl)
			Expect(err).NotTo(HaveOccurred())
		})

		Context("when the timestamp is expired", func() {
			BeforeEach(func() {
				signature = &header.Signature{
					RequestedTime: time.Now().Add(-10 * time.Hour),
					ForwardedUrl:  "some-forwarded-url",
				}
				var err error
				signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
				Expect(err).ToNot(HaveOccurred())
			})

			It("returns an route service request expired error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
				Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceExpired))
				Expect(err.Error()).To(ContainSubstring("request expired"))
			})
		})

		Context("when the signature is invalid", func() {
			BeforeEach(func() {
				signatureHeader = "zKQt4bnxW30Kxky"
				metadataHeader = "eyJpdiI6IjlBVn"
			})
			It("returns an error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
			})
		})

		Context("when the request URL is different from the signature", func() {
			BeforeEach(func() {
				requestUrl = "not-forwarded-url"
			})

			It("returns a route service request bad forwarded url error", func() {
				err := config.ValidateSignature(headers, requestUrl)
				Expect(err).To(HaveOccurred())
				Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceForwardedURLMismatch))
			})
		})

		Context("when there is a url encoded character in the request", func() {
			encodedCharacters := make(map[string]string)
			encodedCharacters["%2C"] = ","
			encodedCharacters["%20"] = " "
			encodedCharacters["%41"] = "A"

			for encoded, decoded := range encodedCharacters {
				forwardedUrl := fmt.Sprintf("some-forwarded-url?fields=foo%sbar", decoded)
				url := fmt.Sprintf("?fields=foo%sbar", encoded)

				Context("with character "+decoded, func() {
					BeforeEach(func() {
						signature = &header.Signature{
							RequestedTime: time.Now(),
							ForwardedUrl:  forwardedUrl,
						}
						var err error
						signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
						Expect(err).ToNot(HaveOccurred())
						requestUrl = requestUrl + url
					})

					It("decrypts the valid signature with character "+encoded, func() {
						err := config.ValidateSignature(headers, requestUrl)
						Expect(err).NotTo(HaveOccurred())
					})
				})
			}
		})

		Context("when there is a percent without two hexadec following in the url", func() {
			BeforeEach(func() {
				signature = &header.Signature{
					RequestedTime: time.Now(),
					ForwardedUrl:  "random%",
				}
				var err error
				signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
				Expect(err).ToNot(HaveOccurred())
			})

			It("request url does not match forwarded url", func() {
				err := config.ValidateSignature(headers, "random%")
				Expect(err).To(HaveOccurred())
			})
		})

		Context("when the header does not match the current key", func() {
			BeforeEach(func() {
				var err error
				crypto, err = secure.NewAesGCM([]byte("QRSTUVWXYZ123456"))
				Expect(err).NotTo(HaveOccurred())
				config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
			})

			Context("when there is no previous key in the configuration", func() {
				It("rejects the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("authentication failed"))
				})
			})

			Context("when the header key matches the previous key in the configuration", func() {
				BeforeEach(func() {
					var err error
					cryptoPrev, err = secure.NewAesGCM([]byte(cryptoKey))
					Expect(err).ToNot(HaveOccurred())
					config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
				})

				It("validates the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).NotTo(HaveOccurred())
				})

				Context("when a request has an expired Route service signature header", func() {
					BeforeEach(func() {
						signature = &header.Signature{
							RequestedTime: time.Now().Add(-10 * time.Hour),
							ForwardedUrl:  "some-forwarded-url",
						}
						var err error
						signatureHeader, metadataHeader, err = header.BuildSignatureAndMetadata(crypto, signature)
						Expect(err).ToNot(HaveOccurred())
					})

					It("returns an route service request expired error", func() {
						err := config.ValidateSignature(headers, requestUrl)
						Expect(err).To(HaveOccurred())
						Expect(err).To(BeAssignableToTypeOf(routeservice.RouteServiceExpired))
					})
				})
			})

			Context("when the header key does not match the previous key in the configuration", func() {
				BeforeEach(func() {
					var err error
					cryptoPrev, err = secure.NewAesGCM([]byte("QRSTUVWXYZ123456"))
					Expect(err).ToNot(HaveOccurred())
					config = routeservice.NewRouteServiceConfig(logger, true, 1*time.Hour, crypto, cryptoPrev, recommendHttps)
				})

				It("rejects the signature", func() {
					err := config.ValidateSignature(headers, requestUrl)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("authentication failed"))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>package udp

import (
	"net"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/transport/internet/internal"
)

type UDPPayloadHandler func(*alloc.Buffer, *proxy.SessionInfo)

type UDPHub struct {
	sync.RWMutex
	conn      *net.UDPConn
	option    ListenOption
	accepting bool
}

type ListenOption struct {
	Callback            UDPPayloadHandler
	ReceiveOriginalDest bool
}

func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*UDPHub, error) {
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   address.IP(),
		Port: int(port),
	})
	if err != nil {
		return nil, err
	}
	if option.ReceiveOriginalDest {
		fd, err := internal.GetSysFd(udpConn)
		if err != nil {
			log.Warning("UDP|Listener: Failed to get fd: ", err)
			return nil, err
		}
		err = SetOriginalDestOptions(fd)
		if err != nil {
			log.Warning("UDP|Listener: Failed to set socket options: ", err)
			return nil, err
		}
	}
	hub := &UDPHub{
		conn:   udpConn,
		option: option,
	}
	go hub.start()
	return hub, nil
}

func (this *UDPHub) Close() {
	this.Lock()
	defer this.Unlock()

	this.accepting = false
	this.conn.Close()
}

func (this *UDPHub) WriteTo(payload []byte, dest v2net.Destination) (int, error) {
	return this.conn.WriteToUDP(payload, &net.UDPAddr{
		IP:   dest.Address().IP(),
		Port: int(dest.Port()),
	})
}

func (this *UDPHub) start() {
	this.Lock()
	this.accepting = true
	this.Unlock()

	oobBytes := make([]byte, 256)
	for this.Running() {
		buffer := alloc.NewBuffer()
		nBytes, noob, _, addr, err := this.conn.ReadMsgUDP(buffer.Value, oobBytes)
		if err != nil {
			log.Info("UDP|Hub: Failed to read UDP msg: ", err)
			buffer.Release()
			continue
		}
		buffer.Slice(0, nBytes)

		session := new(proxy.SessionInfo)
		session.Source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port))
		if this.option.ReceiveOriginalDest && noob > 0 {
			session.Destination = RetrieveOriginalDest(oobBytes[:noob])
		}
		go this.option.Callback(buffer, session)
	}
}

func (this *UDPHub) Running() bool {
	this.RLock()
	defer this.RUnlock()

	return this.accepting
}

// Connection return the net.Conn underneath this hub.
// Private: Visible for testing only
func (this *UDPHub) Connection() net.Conn {
	return this.conn
}

func (this *UDPHub) Addr() net.Addr {
	return this.conn.LocalAddr()
}
<commit_msg>Apply new read function to UDP hub.<commit_after>package udp

import (
	"net"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/transport/internet/internal"
)

type UDPPayloadHandler func(*alloc.Buffer, *proxy.SessionInfo)

type UDPHub struct {
	sync.RWMutex
	conn      *net.UDPConn
	option    ListenOption
	accepting bool
}

type ListenOption struct {
	Callback            UDPPayloadHandler
	ReceiveOriginalDest bool
}

func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*UDPHub, error) {
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   address.IP(),
		Port: int(port),
	})
	if err != nil {
		return nil, err
	}
	if option.ReceiveOriginalDest {
		fd, err := internal.GetSysFd(udpConn)
		if err != nil {
			log.Warning("UDP|Listener: Failed to get fd: ", err)
			return nil, err
		}
		err = SetOriginalDestOptions(fd)
		if err != nil {
			log.Warning("UDP|Listener: Failed to set socket options: ", err)
			return nil, err
		}
	}
	hub := &UDPHub{
		conn:   udpConn,
		option: option,
	}
	go hub.start()
	return hub, nil
}

func (this *UDPHub) Close() {
	this.Lock()
	defer this.Unlock()

	this.accepting = false
	this.conn.Close()
}

func (this *UDPHub) WriteTo(payload []byte, dest v2net.Destination) (int, error) {
	return this.conn.WriteToUDP(payload, &net.UDPAddr{
		IP:   dest.Address().IP(),
		Port: int(dest.Port()),
	})
}

func (this *UDPHub) start() {
	this.Lock()
	this.accepting = true
	this.Unlock()

	oobBytes := make([]byte, 256)
	for this.Running() {
		buffer := alloc.NewBuffer()
		nBytes, noob, _, addr, err := ReadUDPMsg(this.conn, buffer.Value, oobBytes)
		if err != nil {
			log.Info("UDP|Hub: Failed to read UDP msg: ", err)
			buffer.Release()
			continue
		}
		buffer.Slice(0, nBytes)

		session := new(proxy.SessionInfo)
		session.Source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port))
		if this.option.ReceiveOriginalDest && noob > 0 {
			session.Destination = RetrieveOriginalDest(oobBytes[:noob])
		}
		go this.option.Callback(buffer, session)
	}
}

func (this *UDPHub) Running() bool {
	this.RLock()
	defer this.RUnlock()

	return this.accepting
}

// Connection return the net.Conn underneath this hub.
// Private: Visible for testing only
func (this *UDPHub) Connection() net.Conn {
	return this.conn
}

func (this *UDPHub) Addr() net.Addr {
	return this.conn.LocalAddr()
}
<|endoftext|>


<commit_before>package main

import (
	"../../lib/libocit"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
)

// The case now could be like this:
//  in this case type, we will send all the files to all the hostOS
//   casegroup
//          |____ casedir
//          |         |___ casename.json
//          |         |___ `source`        (must be `source`)
//          |                  |____ file1
//          |                  |____ ...
//          |                  |____ fileN
//          |                  |____ dir1
//          |                  |____ ...
//          |                  |____ dirN
//          |
//          |____  caselibdir
//                    |_____ libfile1
//                    |_____  ....
//                    |_____ libfile2
//
//
// The ideal case should be like this:
//
//   casedir
//        |___  `config.json` (must be `config.json`
//        |___  `source`      (must be `source` dir)
//                  |____ file1
//                  |____  ...
//                  |____ fileN
//                  |____ dir1 with files
//                  |____  ...
//                  |____ dirN with files
//

func FindCaseJson(base_dir string) (json_file string, json_dir string) {
	_, err := os.Stat(path.Join(base_dir, "config.json"))
	if err == nil {
		return path.Join(base_dir, "config.json"), base_dir
	}

	files_info, _ := ioutil.ReadDir(base_dir)
	for _, file := range files_info {
		if file.IsDir() {
			sub_json_file, sub_json_dir := FindCaseJson(path.Join(base_dir, file.Name()))
			if len(sub_json_dir) > 1 {
				return sub_json_file, sub_json_dir
			}
		} else {
			fileSuffix := path.Ext(file.Name())
			if fileSuffix == ".json" {
				_, err := os.Stat(path.Join(base_dir, "source"))
				if err != nil {
					continue
				} else {
					//  ./casename.json, ./source/
					json_file = path.Join(base_dir, file.Name())
					return json_file, base_dir
				}
			}
		}
	}
	return json_file, json_dir
}

type ValidatorMessage struct {
	//error; warning
	Type string
	Data string
}

func checkProp(tc libocit.TestCase) (messages []ValidatorMessage) {
	if len(tc.Name) < 1 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "'Name' not found."
		messages = append(messages, msg)
	}
	if len(tc.Version) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Version' not found."
		messages = append(messages, msg)
	}
	if len(tc.License) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'License' not found."
		messages = append(messages, msg)
	}
	if len(tc.Group) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Group' not found. Please read the 'Group' defination in OCT"
		messages = append(messages, msg)
	}
	if len(tc.Owner) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Owner' not found."
		messages = append(messages, msg)
	}
	if len(tc.Sources) > 0 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "Don't need to add `Source in this part."
		messages = append(messages, msg)
	}

	if len(tc.Requires) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Requires' found, we don't know what kind of resource your case need."
		messages = append(messages, msg)
	}

	if len(tc.Deploys) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Deploys' found, we don't know how to deploy the case."
		messages = append(messages, msg)
	} else {
		for d_index := 0; d_index < len(tc.Deploys); d_index++ {
			deploy := tc.Deploys[d_index]
			if (len(deploy.Cmd) == 0) && (len(deploy.Files) == 0) {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Cmd' and 'Files in 'Deploys/" + deploy.Object + "' found, maybe we can remove the object?"
				messages = append(messages, msg)
			}
		}
	}

	if len(tc.Run) == 0 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "No 'Run' found, if you put the running command to the 'Deploy' session, that is OK."
		messages = append(messages, msg)
	} else {
		for r_index := 0; r_index < len(tc.Run); r_index++ {
			run := tc.Run[r_index]
			if len(run.Files) > 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "It is OK to put files in 'Run' session in the " + run.Object + ". But we suggest to move it to 'Deploys' session."
				messages = append(messages, msg)
			}
			if len(run.Cmd) == 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Cmd' in 'Run/" + run.Object + "' session. maybe we can remove the object?"
				messages = append(messages, msg)
			}
		}
	}

	if len(tc.Collects) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Collects' found, we need the testing result to generate the report."
		messages = append(messages, msg)
	} else {
		haveCollectedFile := false
		for c_index := 0; c_index < len(tc.Collects); c_index++ {
			if len(tc.Collects[c_index].Files) == 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Files' in 'Collects/" + tc.Collects[c_index].Object + "' session, maybe we can remove the object?"
				messages = append(messages, msg)
			} else {
				haveCollectedFile = true
			}
		}
		if haveCollectedFile == false {
			var msg ValidatorMessage
			msg.Type = "error"
			msg.Data = "No 'Files' in 'Collects' found, we need the testing result to generate the report."
			messages = append(messages, msg)
		}
	}
	return messages
}

func checkFile(tc libocit.TestCase, casedir string) (messages []ValidatorMessage) {

	var file_store map[string]string
	file_store = make(map[string]string)

	files := libocit.GetDirFiles(casedir, "source")
	for index := 0; index < len(files); index++ {
		file_store[path.Join(casedir, files[index])] = files[index]
	}

	for index := 0; index < len(tc.Deploys); index++ {
		deploy := tc.Deploys[index]
		for f_index := 0; f_index < len(deploy.Files); f_index++ {
			file := path.Join(casedir, deploy.Files[f_index])
			if _, ok := file_store[file]; ok {
				file_store[file] = ""
			} else {
				var msg ValidatorMessage
				msg.Type = "error"
				msg.Data = "File " + file + " mentioned in 'Deploys/" + deploy.Object + "' part is not exist. Forget to submit the file?"
				messages = append(messages, msg)
			}
		}
	}

	for index := 0; index < len(tc.Run); index++ {
		run := tc.Run[index]
		for f_index := 0; f_index < len(run.Files); f_index++ {
			file := path.Join(casedir, run.Files[f_index])
			if _, ok := file_store[file]; ok {
				file_store[file] = ""
			} else {
				var msg ValidatorMessage
				msg.Type = "error"
				msg.Data = "File " + file + " mentioned in 'Run/" + run.Object + "' part is not exist. Forget to submit the file?"
				messages = append(messages, msg)
			}
		}
	}

	for _, val := range file_store {
		if len(val) > 0 {
			var msg ValidatorMessage
			msg.Type = "warning"
			msg.Data = "File " + val + " in the test case directory is not mentioned in the case file."
			messages = append(messages, msg)
		}
	}
	return messages
}

func validateByCaseID(caseID string) {
}

func validateByFile(caseFile string) {
}

func validateByDir(caseDir string) {
	var tc libocit.TestCase
	json_file, json_dir := FindCaseJson(caseDir)
	content := libocit.ReadFile(json_file)

	json.Unmarshal([]byte(content), &tc)

	fmt.Println(json_dir)

	prop_msgs := checkProp(tc)
	fmt.Println(prop_msgs)

	file_msgs := checkFile(tc, json_dir)
	fmt.Println(file_msgs)
}

func main() {
	var caseDir = flag.String("d", "", "input the case dir")
	var caseFile = flag.String("f", "", "input the file url, case.tar.gz")
	var caseID = flag.String("id", "", "input the 'case id' provided by 'Test Case server', please make sure the the tcserver is running.")
	flag.Parse()

	if len(*caseID) > 0 {
		validateByCaseID(*caseID)
	} else if len(*caseFile) > 0 {
		validateByFile(*caseFile)
	} else if len(*caseDir) > 0 {
		validateByDir(*caseDir)
	} else {
		fmt.Println("Please input the test case")
	}
}
<commit_msg>update casevalidator<commit_after>package main

import (
	"../../lib/libocit"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
)

// The case now could be like this:
//  in this case type, we will send all the files to all the hostOS
//   casegroup
//          |____ casedir
//          |         |___ casename.json
//          |         |___ `source`        (must be `source`)
//          |                  |____ file1
//          |                  |____ ...
//          |                  |____ fileN
//          |                  |____ dir1
//          |                  |____ ...
//          |                  |____ dirN
//          |
//          |____  caselibdir
//                    |_____ libfile1
//                    |_____  ....
//                    |_____ libfile2
//
//
// The ideal case should be like this:
//
//   casedir
//        |___  `config.json` (must be `config.json`
//        |___  `source`      (must be `source` dir)
//                  |____ file1
//                  |____  ...
//                  |____ fileN
//                  |____ dir1 with files
//                  |____  ...
//                  |____ dirN with files
//

func FindCaseJson(baseDir string, caseName string) (json_file string, json_dir string) {
	_, err := os.Stat(path.Join(baseDir, "config.json"))
	if err == nil {
		return path.Join(baseDir, "config.json"), baseDir
	}

	files_info, _ := ioutil.ReadDir(baseDir)
	for _, file := range files_info {
		if file.IsDir() {
			sub_json_file, sub_json_dir := FindCaseJson(path.Join(baseDir, file.Name()), caseName)
			if len(sub_json_dir) > 1 {
				return sub_json_file, sub_json_dir
			}
		} else {
			if len(caseName) > 0 {
				if caseName == file.Name() {
					json_file = path.Join(baseDir, file.Name())
					return json_file, baseDir
				}
			} else {
				fileSuffix := path.Ext(file.Name())
				if fileSuffix == ".json" {
					_, err := os.Stat(path.Join(baseDir, "source"))
					if err != nil {
						continue
					} else {
						//  ./casename.json, ./source/
						json_file = path.Join(baseDir, file.Name())
						return json_file, baseDir
					}
				}
			}
		}
	}
	return json_file, json_dir
}

type ValidatorMessage struct {
	//error; warning
	Type string
	Data string
}

func checkProp(tc libocit.TestCase) (messages []ValidatorMessage) {
	if len(tc.Name) < 1 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "'Name' not found."
		messages = append(messages, msg)
	}
	if len(tc.Version) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Version' not found."
		messages = append(messages, msg)
	}
	if len(tc.License) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'License' not found."
		messages = append(messages, msg)
	}
	if len(tc.Group) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Group' not found. Please read the 'Group' defination in OCT"
		messages = append(messages, msg)
	}
	if len(tc.Owner) < 1 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "'Owner' not found."
		messages = append(messages, msg)
	}
	if len(tc.Sources) > 0 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "Don't need to add `Source in this part."
		messages = append(messages, msg)
	}

	if len(tc.Requires) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Requires' found, we don't know what kind of resource your case need."
		messages = append(messages, msg)
	}

	if len(tc.Deploys) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Deploys' found, we don't know how to deploy the case."
		messages = append(messages, msg)
	} else {
		for d_index := 0; d_index < len(tc.Deploys); d_index++ {
			deploy := tc.Deploys[d_index]
			if (len(deploy.Cmd) == 0) && (len(deploy.Files) == 0) {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Cmd' and 'Files in 'Deploys/" + deploy.Object + "' found, maybe we can remove the object?"
				messages = append(messages, msg)
			}
		}
	}

	if len(tc.Run) == 0 {
		var msg ValidatorMessage
		msg.Type = "warning"
		msg.Data = "No 'Run' found, if you put the running command to the 'Deploy' session, that is OK."
		messages = append(messages, msg)
	} else {
		for r_index := 0; r_index < len(tc.Run); r_index++ {
			run := tc.Run[r_index]
			if len(run.Files) > 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "It is OK to put files in 'Run' session in the " + run.Object + ". But we suggest to move it to 'Deploys' session."
				messages = append(messages, msg)
			}
			if len(run.Cmd) == 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Cmd' in 'Run/" + run.Object + "' session. maybe we can remove the object?"
				messages = append(messages, msg)
			}
		}
	}

	if len(tc.Collects) == 0 {
		var msg ValidatorMessage
		msg.Type = "error"
		msg.Data = "No 'Collects' found, we need the testing result to generate the report."
		messages = append(messages, msg)
	} else {
		haveCollectedFile := false
		for c_index := 0; c_index < len(tc.Collects); c_index++ {
			if len(tc.Collects[c_index].Files) == 0 {
				var msg ValidatorMessage
				msg.Type = "warning"
				msg.Data = "No 'Files' in 'Collects/" + tc.Collects[c_index].Object + "' session, maybe we can remove the object?"
				messages = append(messages, msg)
			} else {
				haveCollectedFile = true
			}
		}
		if haveCollectedFile == false {
			var msg ValidatorMessage
			msg.Type = "error"
			msg.Data = "No 'Files' in 'Collects' found, we need the testing result to generate the report."
			messages = append(messages, msg)
		}
	}
	return messages
}

func checkFile(tc libocit.TestCase, casedir string) (messages []ValidatorMessage) {

	var file_store map[string]string
	file_store = make(map[string]string)

	files := libocit.GetDirFiles(casedir, "source")
	for index := 0; index < len(files); index++ {
		file_store[path.Join(casedir, files[index])] = files[index]
	}

	for index := 0; index < len(tc.Deploys); index++ {
		deploy := tc.Deploys[index]
		for f_index := 0; f_index < len(deploy.Files); f_index++ {
			file := path.Join(casedir, deploy.Files[f_index])
			if _, ok := file_store[file]; ok {
				file_store[file] = ""
			} else {
				var msg ValidatorMessage
				msg.Type = "error"
				msg.Data = "File " + file + " mentioned in 'Deploys/" + deploy.Object + "' part is not exist. Forget to submit the file?"
				messages = append(messages, msg)
			}
		}
	}

	for index := 0; index < len(tc.Run); index++ {
		run := tc.Run[index]
		for f_index := 0; f_index < len(run.Files); f_index++ {
			file := path.Join(casedir, run.Files[f_index])
			if _, ok := file_store[file]; ok {
				file_store[file] = ""
			} else {
				var msg ValidatorMessage
				msg.Type = "error"
				msg.Data = "File " + file + " mentioned in 'Run/" + run.Object + "' part is not exist. Forget to submit the file?"
				messages = append(messages, msg)
			}
		}
	}

	for _, val := range file_store {
		if len(val) > 0 {
			var msg ValidatorMessage
			msg.Type = "warning"
			msg.Data = "File " + val + " in the test case directory is not mentioned in the case file."
			messages = append(messages, msg)
		}
	}
	return messages
}

func validateByCaseID(caseID string) {
}

func validateByFile(caseFile string) {
}

func validateByDir(caseDir string, caseName string) (warning_msg []ValidatorMessage, err_msg []ValidatorMessage) {
	var tc libocit.TestCase
	json_file, json_dir := FindCaseJson(caseDir, caseName)
	fmt.Println("The case file found is ", json_file)
	content := libocit.ReadFile(json_file)

	json.Unmarshal([]byte(content), &tc)

	fmt.Println(json_dir)

	prop_msgs := checkProp(tc)
	for index := 0; index < len(prop_msgs); index++ {
		if prop_msgs[index].Type == "warning" {
			warning_msg = append(warning_msg, prop_msgs[index])
		} else if prop_msgs[index].Type == "error" {
			err_msg = append(err_msg, prop_msgs[index])
		}
	}
	file_msgs := checkFile(tc, json_dir)
	for index := 0; index < len(file_msgs); index++ {
		if file_msgs[index].Type == "warning" {
			warning_msg = append(warning_msg, file_msgs[index])
		} else if file_msgs[index].Type == "error" {
			err_msg = append(err_msg, file_msgs[index])
		}
	}
	return warning_msg, err_msg
}

func main() {
	var caseDir = flag.String("d", "", "input the case dir")
	var caseFile = flag.String("f", "", "input the file url, case.tar.gz")
	var caseName = flag.String("n", "", "input the 'case name' in the case dir, if there were multiply cases in the case dir. You can use this with -d and -f.")
	var caseID = flag.String("id", "", "input the 'case id' provided by 'Test Case server', please make sure the the tcserver is running.")
	flag.Parse()

	var warning_msg []ValidatorMessage
	var err_msg []ValidatorMessage
	if len(*caseID) > 0 {
		validateByCaseID(*caseID)
	} else if len(*caseFile) > 0 {
		validateByFile(*caseFile)
	} else if len(*caseDir) > 0 {
		warning_msg, err_msg = validateByDir(*caseDir, *caseName)
	} else {
		fmt.Println("Please input the test case")
		return
	}
	if len(err_msg) > 0 {
		fmt.Printf("The case is invalid, there are %d error(errors) and %d warning(warnings)", len(err_msg), len(warning_msg))
		fmt.Println("Please see the details:")
		fmt.Println(err_msg)
		fmt.Println(warning_msg)
	} else if len(warning_msg) > 0 {
		fmt.Printf("The case is OK, but there are %d warning(warnings)", len(warning_msg))
		fmt.Println("Please see the details:")
		fmt.Println(warning_msg)
	} else {
		fmt.Println("Good case.")
	}
}
<|endoftext|>


<commit_before>package eratosthenes_sieve

// http://stackoverflow.com/a/568618

type Sieve struct {
	// The last returned prime.
	i int

	// Maps each composite to a list of primes that divide it.
	sieve map[int][]int
}

func NewSieve() *Sieve {
	return &Sieve{
		1,
		map[int][]int{},
	}
}

func (s *Sieve) Next() int {
	for {
		s.i++

		if _, ok := s.sieve[s.i]; !ok {
			// i is a prime.
			// All multiples i*j with j < i have already been marked when j has been processed, so
			// the first multiple that needs to be marked is i*i.
			s.sieve[s.i*s.i] = []int{s.i}
			return s.i
		}

		// i is a composite.
		for _, p := range s.sieve[s.i] {
			// i is a multiple of p: i = n*p.
			// Now, the next multiple of p needs to be marked: m = (n+1)*p = i+p.
			m := s.i + p
			s.sieve[m] = append(s.sieve[m], p)
		}
		// i won't be needed in the sieve anymore.
		delete(s.sieve, s.i)
	}
}
<commit_msg>[eratosthenes_sieve/go] Cleanup<commit_after>package eratosthenes_sieve

type Sieve struct {
	// The last tested number.
	i int

	// Maps each composite to a list of primes that divide it.
	sieve map[int][]int
}

func NewSieve() *Sieve {
	return &Sieve{
		1,
		map[int][]int{},
	}
}

func (s *Sieve) Next() int {
	for {
		s.i++
		primes, ok := s.sieve[s.i]

		if !ok {
			// i is a prime.
			// All multiples i*j with j < i have already been marked when j has been processed, so
			// the first multiple that needs to be marked is i*i.
			s.sieve[s.i*s.i] = []int{s.i}
			return s.i
		}

		// i is a composite.
		for _, p := range primes {
			// i is a multiple of p: i = n*p.
			// Now, the next multiple of p needs to be marked: m = (n+1)*p = i+p.
			m := s.i + p
			s.sieve[m] = append(s.sieve[m], p)
		}
		// i won't be needed in the sieve anymore.
		delete(s.sieve, s.i)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 CloudAwan LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     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 webhook

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"errors"
	"github.com/cloudawan/cloudone/authorization"
	"github.com/cloudawan/cloudone/image"
	"github.com/coreos/etcd/client"
)

func getGitHashSignature(secret string, message string) string {
	key := []byte(secret)
	hash := hmac.New(sha1.New, key)
	hash.Write([]byte(message))

	return "sha1=" + hex.EncodeToString(hash.Sum(nil))
}

func Notify(username string, imageInformationName string, signature string, payload string) error {
	if len(username) == 0 {
		log.Error("User couldn't be empty. Signature %s", signature)
		log.Debug(payload)
		return errors.New("User couldn't be empty")
	}

	user, err := authorization.GetStorage().LoadUser(username)
	etcdError, _ := err.(client.Error)
	if etcdError.Code == client.ErrorCodeKeyNotFound {
		return errors.New("The user " + username + " doesn't exist")
	}
	if err != nil {
		log.Error("Get user error %s. User name %s, signature %s", err, username, signature)
		log.Debug(payload)
		return err
	}

	if len(signature) > 0 {
		// If secret is used
		githubWebhookSecret := user.MetaDataMap["githubWebhookSecret"]
		generatedSignature := getGitHashSignature(githubWebhookSecret, payload)
		if generatedSignature != signature {
			log.Error("The signature is invalid. User name %s, signature %s, generated signature %s", username, signature, generatedSignature)
			log.Debug(payload)
			return errors.New("The signature is invalid")
		}
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal([]byte(payload), &jsonMap)
	if err != nil {
		log.Error("Unmarshal payload error %s. User name %s, signature %s", err, username, signature)
		log.Debug(payload)
		return err
	}

	pusherJsonMap, _ := jsonMap["pusher"].(map[string]interface{})
	pusherName, _ := pusherJsonMap["name"].(string)

	repositoryJsonMap, _ := jsonMap["repository"].(map[string]interface{})
	cloneUrl, _ := repositoryJsonMap["clone_url"].(string)

	if len(cloneUrl) == 0 {
		log.Error("Can't find clone_url in github payload. User name %s, signature %s", username, signature)
		log.Debug(payload)
		return errors.New("Can't find clone_url in github payload")
	}

	imageInformation, err := image.GetStorage().LoadImageInformation(imageInformationName)
	etcdError, _ = err.(client.Error)
	if etcdError.Code == client.ErrorCodeKeyNotFound {
		return errors.New("The repository " + imageInformationName + " doesn't exist")
	}
	if err != nil {
		log.Error(err)
		return err
	}

	sourceCodeURL := imageInformation.BuildParameter["sourceCodeURL"]
	if sourceCodeURL != cloneUrl {
		// Not the target, ignore.
		return errors.New("Source code url " + sourceCodeURL + " is different from the github clone_url " + cloneUrl)
	}

	if len(imageInformationName) == 0 {
		log.Error("Can't find image information using the github url %s. User name %s, signature %s", cloneUrl, username, signature)
		log.Debug(payload)
		return errors.New("Can't find image information using the github url")
	}

	// Asyncronized build
	go func() {
		outputMessage, err := image.BuildUpgrade(imageInformationName, "Github webhook. Pusher: "+pusherName)
		if err != nil {
			log.Error(err)
			log.Debug(outputMessage)
		}
	}()

	return nil
}
<commit_msg>Ignore unrelated image build Require secret<commit_after>// Copyright 2015 CloudAwan LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     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 webhook

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"errors"
	"github.com/cloudawan/cloudone/authorization"
	"github.com/cloudawan/cloudone/image"
	"github.com/coreos/etcd/client"
)

func getGitHashSignature(secret string, message string) string {
	key := []byte(secret)
	hash := hmac.New(sha1.New, key)
	hash.Write([]byte(message))

	return "sha1=" + hex.EncodeToString(hash.Sum(nil))
}

func Notify(username string, imageInformationName string, signature string, payload string) error {
	if len(username) == 0 {
		log.Error("User couldn't be empty. Signature %s", signature)
		log.Debug(payload)
		return errors.New("User couldn't be empty")
	}

	if len(signature) == 0 {
		return errors.New("The secret is required")
	}

	user, err := authorization.GetStorage().LoadUser(username)
	etcdError, _ := err.(client.Error)
	if etcdError.Code == client.ErrorCodeKeyNotFound {
		return errors.New("The user " + username + " doesn't exist")
	}
	if err != nil {
		log.Error("Get user error %s. User name %s, signature %s", err, username, signature)
		log.Debug(payload)
		return err
	}

	// If secret is used
	githubWebhookSecret := user.MetaDataMap["githubWebhookSecret"]
	generatedSignature := getGitHashSignature(githubWebhookSecret, payload)
	if generatedSignature != signature {
		log.Error("The signature is invalid. User name %s, signature %s, generated signature %s", username, signature, generatedSignature)
		log.Debug(payload)
		return errors.New("The signature is invalid")
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal([]byte(payload), &jsonMap)
	if err != nil {
		log.Error("Unmarshal payload error %s. User name %s, signature %s", err, username, signature)
		log.Debug(payload)
		return err
	}

	pusherJsonMap, _ := jsonMap["pusher"].(map[string]interface{})
	pusherName, _ := pusherJsonMap["name"].(string)

	repositoryJsonMap, _ := jsonMap["repository"].(map[string]interface{})
	cloneUrl, _ := repositoryJsonMap["clone_url"].(string)

	if len(cloneUrl) == 0 {
		log.Error("Can't find clone_url in github payload. User name %s, signature %s", username, signature)
		log.Debug(payload)
		return errors.New("Can't find clone_url in github payload")
	}

	imageInformation, err := image.GetStorage().LoadImageInformation(imageInformationName)
	etcdError, _ = err.(client.Error)
	if etcdError.Code == client.ErrorCodeKeyNotFound {
		return errors.New("The repository " + imageInformationName + " doesn't exist")
	}
	if err != nil {
		log.Error(err)
		return err
	}

	sourceCodeURL := imageInformation.BuildParameter["sourceCodeURL"]
	if sourceCodeURL != cloneUrl {
		// Not the target, ignore.
		return nil
	}

	if len(imageInformationName) == 0 {
		log.Error("Can't find image information using the github url %s. User name %s, signature %s", cloneUrl, username, signature)
		log.Debug(payload)
		return errors.New("Can't find image information using the github url")
	}

	// Asyncronized build
	go func() {
		outputMessage, err := image.BuildUpgrade(imageInformationName, "Github webhook. Pusher: "+pusherName)
		if err != nil {
			log.Error(err)
			log.Debug(outputMessage)
		}
	}()

	return nil
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/gandalf/api"
	"github.com/globocom/gandalf/db"
	"log"
	"net/http"
)

const version = "0.2.2"

func main() {
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	configFile := flag.String("config", "/etc/gandalf.conf", "Gandalf configuration file")
	gVersion := flag.Bool("version", false, "Print version and exit")
	flag.Parse()

	if *gVersion {
		fmt.Printf("gandalf-webserver version %s\n", version)
		return
	}

	err := config.ReadAndWatchConfigFile(*configFile)
	if err != nil {
		msg := `Could not find gandalf config file. Searched on %s.
For an example conf check gandalf/etc/gandalf.conf file.\n %s`
		log.Panicf(msg, *configFile, err)
	}
	db.Connect()
	router := pat.New()
	router.Post("/user/:name/key", http.HandlerFunc(api.AddKey))
	router.Del("/user/:name/key/:keyname", http.HandlerFunc(api.RemoveKey))
	router.Get("/user/:name/keys", http.HandlerFunc(api.ListKeys))
	router.Post("/user", http.HandlerFunc(api.NewUser))
	router.Del("/user/:name", http.HandlerFunc(api.RemoveUser))
	router.Post("/repository", http.HandlerFunc(api.NewRepository))
	router.Post("/repository/grant", http.HandlerFunc(api.GrantAccess))
	router.Del("/repository/revoke", http.HandlerFunc(api.RevokeAccess))
	router.Del("/repository/:name", http.HandlerFunc(api.RemoveRepository))
	router.Get("/repository/:name", http.HandlerFunc(api.GetRepository))
	router.Put("/repository/:name", http.HandlerFunc(api.RenameRepository))
	router.Get("/healthcheck/", http.HandlerFunc(api.HealthCheck))
	router.Post("/hook/:name", http.HandlerFunc(api.AddHook))

	bind, err := config.GetString("bind")
	if err != nil {
		var perr error
		bind, perr = config.GetString("webserver:port")
		if perr != nil {
			panic(err)
		}
	}
	if !*dry {
		log.Fatal(http.ListenAndServe(bind, router))
	}
}
<commit_msg>webserver: bump to 0.3.0<commit_after>// Copyright 2014 gandalf authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/gandalf/api"
	"github.com/globocom/gandalf/db"
	"log"
	"net/http"
)

const version = "0.3.0"

func main() {
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	configFile := flag.String("config", "/etc/gandalf.conf", "Gandalf configuration file")
	gVersion := flag.Bool("version", false, "Print version and exit")
	flag.Parse()

	if *gVersion {
		fmt.Printf("gandalf-webserver version %s\n", version)
		return
	}

	err := config.ReadAndWatchConfigFile(*configFile)
	if err != nil {
		msg := `Could not find gandalf config file. Searched on %s.
For an example conf check gandalf/etc/gandalf.conf file.\n %s`
		log.Panicf(msg, *configFile, err)
	}
	db.Connect()
	router := pat.New()
	router.Post("/user/:name/key", http.HandlerFunc(api.AddKey))
	router.Del("/user/:name/key/:keyname", http.HandlerFunc(api.RemoveKey))
	router.Get("/user/:name/keys", http.HandlerFunc(api.ListKeys))
	router.Post("/user", http.HandlerFunc(api.NewUser))
	router.Del("/user/:name", http.HandlerFunc(api.RemoveUser))
	router.Post("/repository", http.HandlerFunc(api.NewRepository))
	router.Post("/repository/grant", http.HandlerFunc(api.GrantAccess))
	router.Del("/repository/revoke", http.HandlerFunc(api.RevokeAccess))
	router.Del("/repository/:name", http.HandlerFunc(api.RemoveRepository))
	router.Get("/repository/:name", http.HandlerFunc(api.GetRepository))
	router.Put("/repository/:name", http.HandlerFunc(api.RenameRepository))
	router.Get("/healthcheck/", http.HandlerFunc(api.HealthCheck))
	router.Post("/hook/:name", http.HandlerFunc(api.AddHook))

	bind, err := config.GetString("bind")
	if err != nil {
		var perr error
		bind, perr = config.GetString("webserver:port")
		if perr != nil {
			panic(err)
		}
	}
	if !*dry {
		log.Fatal(http.ListenAndServe(bind, router))
	}
}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"strings"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/executors"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	client "k8s.io/kubernetes/pkg/client/unversioned"
)

var (
	kubeClient *client.Client
)

type kubernetesOptions struct {
	Image    string   `json:"image"`
	Services []string `json:"services"`
}

type executor struct {
	executors.AbstractExecutor

	prepod       *api.Pod
	pod          *api.Pod
	options      *kubernetesOptions
	extraOptions Options

	buildLimits   api.ResourceList
	serviceLimits api.ResourceList
}

func (s *executor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) error {
	err := s.AbstractExecutor.Prepare(globalConfig, config, build)
	if err != nil {
		return err
	}

	if kubeClient == nil {
		kubeClient, err = getKubeClient(config.Kubernetes)
		if err != nil {
			return err
		}
	}

	if s.BuildScript.PassFile {
		return fmt.Errorf("Kubernetes doesn't support shells that require script file")
	}

	err = build.Options.Decode(&s.options)
	if err != nil {
		return err
	}

	s.extraOptions = DefaultOptions{s.Build.GetAllVariables()}

	if !s.Config.Kubernetes.AllowPrivileged && s.extraOptions.Privileged() {
		return fmt.Errorf("Runner does not allow privileged containers")
	}

	parse := func(s string) (resource.Quantity, error) {
		q := new(resource.Quantity)
		if len(s) == 0 {
			return *q, nil
		}
		if q, err = resource.ParseQuantity(s); err != nil {
			return *q, fmt.Errorf("error parsing resource limit: %s", err.Error())
		}
		return *q, nil
	}

	if s.serviceLimits[api.ResourceCPU], err = parse(s.Config.Kubernetes.ServiceCPUs); err != nil {
		return err
	}

	if s.serviceLimits[api.ResourceMemory], err = parse(s.Config.Kubernetes.ServiceMemory); err != nil {
		return err
	}

	if s.buildLimits[api.ResourceCPU], err = parse(s.Config.Kubernetes.CPUs); err != nil {
		return err
	}

	if s.buildLimits[api.ResourceMemory], err = parse(s.Config.Kubernetes.Memory); err != nil {
		return err
	}

	s.Println("Using Kubernetes executor with image", s.options.Image, "...")

	return nil
}

func (s *executor) Cleanup() {
	if s.pod != nil {
		err := kubeClient.Pods(s.pod.Namespace).Delete(s.pod.Name, nil)

		if err != nil {
			s.Errorln("Error cleaning up pod: %s", err.Error())
		}
	}
	s.AbstractExecutor.Cleanup()
}

func buildVariables(bv common.BuildVariables) []api.EnvVar {
	e := make([]api.EnvVar, len(bv))
	for i, b := range bv {
		e[i] = api.EnvVar{
			Name:  b.Key,
			Value: b.Value,
		}
	}
	return e
}

func (s *executor) buildContainer(name, image string, limits api.ResourceList, command ...string) api.Container {
	path := strings.Split(s.Shell.Build.BuildDir, "/")
	path = path[:len(path)-1]

	privileged := s.extraOptions.Privileged()

	return api.Container{
		Name:    name,
		Image:   image,
		Command: command,
		Env:     buildVariables(s.Build.GetAllVariables().PublicOrInternal()),
		Resources: api.ResourceRequirements{
			Limits: limits,
		},
		VolumeMounts: []api.VolumeMount{
			api.VolumeMount{
				Name:      "repo",
				MountPath: strings.Join(path, "/"),
			},
		},
		SecurityContext: &api.SecurityContext{
			Privileged: &privileged,
		},
		Stdin: true,
	}
}

func (s *executor) runInContainer(name, command string) <-chan error {
	errc := make(chan error, 1)
	go func() {
		defer close(errc)

		status, err := waitForPodRunning(kubeClient, s.pod, s.BuildLog)

		if err != nil {
			errc <- err
			return
		}

		if status != api.PodRunning {
			errc <- fmt.Errorf("pod failed to enter running state: %s", status)
			return
		}

		config, err := getKubeClientConfig(s.Config.Kubernetes)

		if err != nil {
			errc <- err
			return
		}

		exec := ExecOptions{
			PodName:       s.pod.Name,
			Namespace:     s.pod.Namespace,
			ContainerName: name,
			Command:       s.BuildScript.DockerCommand,
			In:            strings.NewReader(command),
			Out:           s.BuildLog,
			Err:           s.BuildLog,
			Stdin:         true,
			Config:        config,
			Client:        kubeClient,
			Executor:      &DefaultRemoteExecutor{},
		}

		errc <- exec.Run()
	}()

	return errc
}

func (s *executor) Run(cmd common.ExecutorCommand) error {
	var err error
	s.Debugln("Starting Kubernetes command...")

	if s.pod == nil {
		services := make([]api.Container, len(s.options.Services))
		for i, image := range s.options.Services {
			services[i] = s.buildContainer(fmt.Sprintf("svc-%d", i), image, s.serviceLimits)
		}

		s.pod, err = kubeClient.Pods(s.Config.Kubernetes.Namespace).Create(&api.Pod{
			ObjectMeta: api.ObjectMeta{
				GenerateName: s.Build.ProjectUniqueName(),
				Namespace:    s.Config.Kubernetes.Namespace,
			},
			Spec: api.PodSpec{
				Volumes: []api.Volume{
					api.Volume{
						Name: "repo",
						VolumeSource: api.VolumeSource{
							EmptyDir: &api.EmptyDirVolumeSource{},
						},
					},
				},
				RestartPolicy: api.RestartPolicyNever,
				Containers: append([]api.Container{
					s.buildContainer("build", s.options.Image, s.buildLimits, s.BuildScript.DockerCommand...),
					s.buildContainer("pre", "munnerz/gitlab-runner-helper", s.serviceLimits, s.BuildScript.DockerCommand...),
				}, services...),
			},
		})

		if err != nil {
			return err
		}
	}

	var containerName string
	switch {
	case cmd.Predefined:
		containerName = "pre"
	default:
		containerName = "build"
	}

	select {
	case err := <-s.runInContainer(containerName, cmd.Script):
		return err
	case _ = <-cmd.Abort:
		return fmt.Errorf("build aborted")
	}
}

func init() {
	options := executors.ExecutorOptions{
		SharedBuildsDir: false,
		Shell: common.ShellScriptInfo{
			Shell:         "bash",
			Type:          common.NormalShell,
			RunnerCommand: "/gitlab-runner-helper",
		},
		ShowHostname:     true,
		SupportedOptions: []string{"image", "services", "artifacts", "cache"},
	}

	creator := func() common.Executor {
		return &executor{
			AbstractExecutor: executors.AbstractExecutor{
				ExecutorOptions: options,
			},
		}
	}

	featuresUpdater := func(features *common.FeaturesInfo) {
		features.Variables = true
		features.Image = true
		features.Services = true
		features.Artifacts = true
		features.Cache = true
	}

	common.RegisterExecutor("kubernetes", executors.DefaultExecutorProvider{
		Creator:         creator,
		FeaturesUpdater: featuresUpdater,
	})
}
<commit_msg>Update runner command path for official build docker image<commit_after>package kubernetes

import (
	"fmt"
	"strings"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/executors"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	client "k8s.io/kubernetes/pkg/client/unversioned"
)

var (
	kubeClient *client.Client
)

type kubernetesOptions struct {
	Image    string   `json:"image"`
	Services []string `json:"services"`
}

type executor struct {
	executors.AbstractExecutor

	prepod       *api.Pod
	pod          *api.Pod
	options      *kubernetesOptions
	extraOptions Options

	buildLimits   api.ResourceList
	serviceLimits api.ResourceList
}

func (s *executor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) error {
	err := s.AbstractExecutor.Prepare(globalConfig, config, build)
	if err != nil {
		return err
	}

	if kubeClient == nil {
		kubeClient, err = getKubeClient(config.Kubernetes)
		if err != nil {
			return err
		}
	}

	if s.BuildScript.PassFile {
		return fmt.Errorf("Kubernetes doesn't support shells that require script file")
	}

	err = build.Options.Decode(&s.options)
	if err != nil {
		return err
	}

	s.extraOptions = DefaultOptions{s.Build.GetAllVariables()}

	if !s.Config.Kubernetes.AllowPrivileged && s.extraOptions.Privileged() {
		return fmt.Errorf("Runner does not allow privileged containers")
	}

	parse := func(s string) (resource.Quantity, error) {
		q := new(resource.Quantity)
		if len(s) == 0 {
			return *q, nil
		}
		if q, err = resource.ParseQuantity(s); err != nil {
			return *q, fmt.Errorf("error parsing resource limit: %s", err.Error())
		}
		return *q, nil
	}

	if s.serviceLimits[api.ResourceCPU], err = parse(s.Config.Kubernetes.ServiceCPUs); err != nil {
		return err
	}

	if s.serviceLimits[api.ResourceMemory], err = parse(s.Config.Kubernetes.ServiceMemory); err != nil {
		return err
	}

	if s.buildLimits[api.ResourceCPU], err = parse(s.Config.Kubernetes.CPUs); err != nil {
		return err
	}

	if s.buildLimits[api.ResourceMemory], err = parse(s.Config.Kubernetes.Memory); err != nil {
		return err
	}

	s.Println("Using Kubernetes executor with image", s.options.Image, "...")

	return nil
}

func (s *executor) Cleanup() {
	if s.pod != nil {
		err := kubeClient.Pods(s.pod.Namespace).Delete(s.pod.Name, nil)

		if err != nil {
			s.Errorln("Error cleaning up pod: %s", err.Error())
		}
	}
	s.AbstractExecutor.Cleanup()
}

func buildVariables(bv common.BuildVariables) []api.EnvVar {
	e := make([]api.EnvVar, len(bv))
	for i, b := range bv {
		e[i] = api.EnvVar{
			Name:  b.Key,
			Value: b.Value,
		}
	}
	return e
}

func (s *executor) buildContainer(name, image string, limits api.ResourceList, command ...string) api.Container {
	path := strings.Split(s.Shell.Build.BuildDir, "/")
	path = path[:len(path)-1]

	privileged := s.extraOptions.Privileged()

	return api.Container{
		Name:    name,
		Image:   image,
		Command: command,
		Env:     buildVariables(s.Build.GetAllVariables().PublicOrInternal()),
		Resources: api.ResourceRequirements{
			Limits: limits,
		},
		VolumeMounts: []api.VolumeMount{
			api.VolumeMount{
				Name:      "repo",
				MountPath: strings.Join(path, "/"),
			},
		},
		SecurityContext: &api.SecurityContext{
			Privileged: &privileged,
		},
		Stdin: true,
	}
}

func (s *executor) runInContainer(name, command string) <-chan error {
	errc := make(chan error, 1)
	go func() {
		defer close(errc)

		status, err := waitForPodRunning(kubeClient, s.pod, s.BuildLog)

		if err != nil {
			errc <- err
			return
		}

		if status != api.PodRunning {
			errc <- fmt.Errorf("pod failed to enter running state: %s", status)
			return
		}

		config, err := getKubeClientConfig(s.Config.Kubernetes)

		if err != nil {
			errc <- err
			return
		}

		exec := ExecOptions{
			PodName:       s.pod.Name,
			Namespace:     s.pod.Namespace,
			ContainerName: name,
			Command:       s.BuildScript.DockerCommand,
			In:            strings.NewReader(command),
			Out:           s.BuildLog,
			Err:           s.BuildLog,
			Stdin:         true,
			Config:        config,
			Client:        kubeClient,
			Executor:      &DefaultRemoteExecutor{},
		}

		errc <- exec.Run()
	}()

	return errc
}

func (s *executor) Run(cmd common.ExecutorCommand) error {
	var err error
	s.Debugln("Starting Kubernetes command...")

	if s.pod == nil {
		services := make([]api.Container, len(s.options.Services))
		for i, image := range s.options.Services {
			services[i] = s.buildContainer(fmt.Sprintf("svc-%d", i), image, s.serviceLimits)
		}

		s.pod, err = kubeClient.Pods(s.Config.Kubernetes.Namespace).Create(&api.Pod{
			ObjectMeta: api.ObjectMeta{
				GenerateName: s.Build.ProjectUniqueName(),
				Namespace:    s.Config.Kubernetes.Namespace,
			},
			Spec: api.PodSpec{
				Volumes: []api.Volume{
					api.Volume{
						Name: "repo",
						VolumeSource: api.VolumeSource{
							EmptyDir: &api.EmptyDirVolumeSource{},
						},
					},
				},
				RestartPolicy: api.RestartPolicyNever,
				Containers: append([]api.Container{
					s.buildContainer("build", s.options.Image, s.buildLimits, s.BuildScript.DockerCommand...),
					s.buildContainer("pre", "munnerz/gitlab-runner-helper", s.serviceLimits, s.BuildScript.DockerCommand...),
				}, services...),
			},
		})

		if err != nil {
			return err
		}
	}

	var containerName string
	switch {
	case cmd.Predefined:
		containerName = "pre"
	default:
		containerName = "build"
	}

	select {
	case err := <-s.runInContainer(containerName, cmd.Script):
		return err
	case _ = <-cmd.Abort:
		return fmt.Errorf("build aborted")
	}
}

func init() {
	options := executors.ExecutorOptions{
		SharedBuildsDir: false,
		Shell: common.ShellScriptInfo{
			Shell:         "bash",
			Type:          common.NormalShell,
			RunnerCommand: "/usr/bin/gitlab-runner-helper",
		},
		ShowHostname:     true,
		SupportedOptions: []string{"image", "services", "artifacts", "cache"},
	}

	creator := func() common.Executor {
		return &executor{
			AbstractExecutor: executors.AbstractExecutor{
				ExecutorOptions: options,
			},
		}
	}

	featuresUpdater := func(features *common.FeaturesInfo) {
		features.Variables = true
		features.Image = true
		features.Services = true
		features.Artifacts = true
		features.Cache = true
	}

	common.RegisterExecutor("kubernetes", executors.DefaultExecutorProvider{
		Creator:         creator,
		FeaturesUpdater: featuresUpdater,
	})
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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 driver

// #cgo LDFLAGS: -lwinmm
//
// #include <windows.h>
// #include <mmsystem.h>
//
// #define sizeOfWavehdr (sizeof(WAVEHDR))
//
// MMRESULT waveOutOpen2(HWAVEOUT* waveOut, WAVEFORMATEX* format);
import "C"

import (
	"errors"
	"fmt"
	"io"
	"unsafe"
)

type header struct {
	buffer     unsafe.Pointer
	bufferSize int
	waveHdr    C.WAVEHDR
}

func newHeader(waveOut C.HWAVEOUT, bufferSize int) (*header, error) {
	// NOTE: This is never freed so far.
	buf := C.malloc(C.size_t(bufferSize))
	h := &header{
		buffer:     buf,
		bufferSize: bufferSize,
		waveHdr: C.WAVEHDR{
			lpData:         C.LPSTR(buf),
			dwBufferLength: C.DWORD(bufferSize),
		},
	}
	// TODO: Need to unprepare to avoid memory leak?
	if err := C.waveOutPrepareHeader(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR {
		return nil, fmt.Errorf("audio: waveOutPrepareHeader error: %d", err)
	}
	return h, nil
}

func (h *header) Write(waveOut C.HWAVEOUT, data []byte) error {
	if len(data) != h.bufferSize {
		return errors.New("audio: len(data) must equal to h.bufferSize")
	}
	C.memcpy(h.buffer, unsafe.Pointer(&data[0]), C.size_t(h.bufferSize))
	if err := C.waveOutWrite(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR {
		return fmt.Errorf("audio: waveOutWriter error: %d", err)
	}
	return nil
}

const numHeader = 8

var sem = make(chan struct{}, numHeader)

//export releaseSemaphore
func releaseSemaphore() {
	<-sem
}

type Player struct {
	src     io.Reader
	out     C.HWAVEOUT
	buffer  []byte
	headers []*header
}

const bufferSize = 1024

func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	const numBlockAlign = channelNum * bytesPerSample
	f := C.WAVEFORMATEX{
		wFormatTag:      C.WAVE_FORMAT_PCM,
		nChannels:       channelNum,
		nSamplesPerSec:  C.DWORD(sampleRate),
		nAvgBytesPerSec: C.DWORD(sampleRate) * numBlockAlign,
		wBitsPerSample:  bytesPerSample * 8,
		nBlockAlign:     numBlockAlign,
	}
	var w C.HWAVEOUT
	if err := C.waveOutOpen2(&w, &f); err != C.MMSYSERR_NOERROR {
		return nil, fmt.Errorf("audio: waveOutOpen error: %d", err)
	}
	p := &Player{
		src:     src,
		out:     w,
		buffer:  []byte{},
		headers: make([]*header, numHeader),
	}
	for i := 0; i < numHeader; i++ {
		var err error
		p.headers[i], err = newHeader(w, bufferSize)
		if err != nil {
			return nil, err
		}
	}
	return p, nil
}

func (p *Player) Proceed() error {
	if len(p.buffer) < bufferSize {
		b := make([]byte, bufferSize)
		n, err := p.src.Read(b)
		if 0 < n {
			p.buffer = append(p.buffer, b[:n]...)
		}
		if err != nil {
			return err
		}
	}
	if bufferSize <= len(p.buffer) {
		sem <- struct{}{}
		headerToWrite := (*header)(nil)
		for _, h := range p.headers {
			// TODO: Need to check WHDR_DONE?
			if h.waveHdr.dwFlags&C.WHDR_INQUEUE == 0 {
				headerToWrite = h
				break
			}
		}
		if headerToWrite == nil {
			return errors.New("audio: no available buffers")
		}
		if err := headerToWrite.Write(p.out, p.buffer[:bufferSize]); err != nil {
			return err
		}
		p.buffer = p.buffer[bufferSize:]
	}
	return nil
}

func (p *Player) Close() {
	// TODO: Implement this
}
<commit_msg>audio: Bug fix: compilation error on Windows<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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 driver

// #cgo LDFLAGS: -lwinmm
//
// #include <windows.h>
// #include <mmsystem.h>
//
// #define sizeOfWavehdr (sizeof(WAVEHDR))
//
// MMRESULT waveOutOpen2(HWAVEOUT* waveOut, WAVEFORMATEX* format);
import "C"

import (
	"errors"
	"fmt"
	"io"
	"unsafe"
)

type header struct {
	buffer     unsafe.Pointer
	bufferSize int
	waveHdr    C.WAVEHDR
}

func newHeader(waveOut C.HWAVEOUT, bufferSize int) (*header, error) {
	// NOTE: This is never freed so far.
	buf := C.malloc(C.size_t(bufferSize))
	h := &header{
		buffer:     buf,
		bufferSize: bufferSize,
		waveHdr: C.WAVEHDR{
			lpData:         C.LPSTR(buf),
			dwBufferLength: C.DWORD(bufferSize),
		},
	}
	// TODO: Need to unprepare to avoid memory leak?
	if err := C.waveOutPrepareHeader(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR {
		return nil, fmt.Errorf("audio: waveOutPrepareHeader error: %d", err)
	}
	return h, nil
}

func (h *header) Write(waveOut C.HWAVEOUT, data []byte) error {
	if len(data) != h.bufferSize {
		return errors.New("audio: len(data) must equal to h.bufferSize")
	}
	C.memcpy(h.buffer, unsafe.Pointer(&data[0]), C.size_t(h.bufferSize))
	if err := C.waveOutWrite(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR {
		return fmt.Errorf("audio: waveOutWriter error: %d", err)
	}
	return nil
}

const numHeader = 8

var sem = make(chan struct{}, numHeader)

//export releaseSemaphore
func releaseSemaphore() {
	<-sem
}

type Player struct {
	src     io.Reader
	out     C.HWAVEOUT
	buffer  []byte
	headers []*header
}

const bufferSize = 1024

func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	numBlockAlign := channelNum * bytesPerSample
	f := C.WAVEFORMATEX{
		wFormatTag:      C.WAVE_FORMAT_PCM,
		nChannels:       C.WORD(channelNum),
		nSamplesPerSec:  C.DWORD(sampleRate),
		nAvgBytesPerSec: C.DWORD(sampleRate * numBlockAlign),
		wBitsPerSample:  C.WORD(bytesPerSample * 8),
		nBlockAlign:     C.WORD(numBlockAlign),
	}
	var w C.HWAVEOUT
	if err := C.waveOutOpen2(&w, &f); err != C.MMSYSERR_NOERROR {
		return nil, fmt.Errorf("audio: waveOutOpen error: %d", err)
	}
	p := &Player{
		src:     src,
		out:     w,
		buffer:  []byte{},
		headers: make([]*header, numHeader),
	}
	for i := 0; i < numHeader; i++ {
		var err error
		p.headers[i], err = newHeader(w, bufferSize)
		if err != nil {
			return nil, err
		}
	}
	return p, nil
}

func (p *Player) Proceed() error {
	if len(p.buffer) < bufferSize {
		b := make([]byte, bufferSize)
		n, err := p.src.Read(b)
		if 0 < n {
			p.buffer = append(p.buffer, b[:n]...)
		}
		if err != nil {
			return err
		}
	}
	if bufferSize <= len(p.buffer) {
		sem <- struct{}{}
		headerToWrite := (*header)(nil)
		for _, h := range p.headers {
			// TODO: Need to check WHDR_DONE?
			if h.waveHdr.dwFlags&C.WHDR_INQUEUE == 0 {
				headerToWrite = h
				break
			}
		}
		if headerToWrite == nil {
			return errors.New("audio: no available buffers")
		}
		if err := headerToWrite.Write(p.out, p.buffer[:bufferSize]); err != nil {
			return err
		}
		p.buffer = p.buffer[bufferSize:]
	}
	return nil
}

func (p *Player) Close() {
	// TODO: Implement this
}
<|endoftext|>


<commit_before>package syslog

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagerctx"
	"github.com/concourse/concourse/atc/db"
	"github.com/concourse/concourse/atc/event"
)

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

//counterfeiter:generate . Drainer
type Drainer interface {
	Run(context.Context) error
}

type drainer struct {
	hostname     string
	transport    string
	address      string
	caCerts      []string
	buildFactory db.BuildFactory
}

func NewDrainer(transport string, address string, hostname string, caCerts []string, buildFactory db.BuildFactory) Drainer {
	return &drainer{
		hostname:     hostname,
		transport:    transport,
		address:      address,
		buildFactory: buildFactory,
		caCerts:      caCerts,
	}
}

func (d *drainer) Run(ctx context.Context) error {
	logger := lagerctx.FromContext(ctx).Session("syslog")

	builds, err := d.buildFactory.GetDrainableBuilds()
	if err != nil {
		logger.Error("failed-to-get-drainable-builds", err)
		return err
	}

	if len(builds) > 0 {
		syslog, err := Dial(d.transport, d.address, d.caCerts)
		if err != nil {
			logger.Error("failed-to-connect", err)
			return err
		}

		// ignore any errors coming from syslog.Close()
		defer db.Close(syslog)

		for _, build := range builds {
			err := d.drainBuild(logger, build, syslog)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (d *drainer) drainBuild(logger lager.Logger, build db.Build, syslog *Syslog) error {
	logger = logger.Session("drain-build", build.LagerData())

	events, err := build.Events(0)
	if err != nil {
		return err
	}

	// ignore any errors coming from events.Close()
	defer db.Close(events)

	for {
		ev, err := events.Next()
		if err != nil {
			if err == db.ErrEndOfBuildEventStream {
				break
			}
			logger.Error("failed-to-get-next-event", err)
			return err
		}

		err = d.sendEvent(logger, build, syslog, ev)
		if err != nil {
			logger.Error("failed-to-send-event", err)
			return err
		}
	}

	err = build.SetDrained(true)
	if err != nil {
		logger.Error("failed-to-update-status", err)
		return err
	}

	return nil
}

func (d *drainer) sendEvent(logger lager.Logger, build db.Build, syslog *Syslog, ev event.Envelope) error {
	var (
		hostname string = d.hostname
		ts       time.Time
		tag      string
		message  string
	)

	switch ev.Event {
	case event.EventTypeInitialize:
		var initEvent event.Initialize
		err := json.Unmarshal(*ev.Data, &initEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initEvent.Time, 0)
		tag = build.SyslogTag(initEvent.Origin.ID)
		message = fmt.Sprintf("initializing")
	case event.EventTypeInitializeGet:
		var initGetEvent event.InitializeGet
		err := json.Unmarshal(*ev.Data, &initGetEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initGetEvent.Time, 0)
		tag = build.SyslogTag(initGetEvent.Origin.ID)
		message = fmt.Sprintf("get initializing")
	case event.EventTypeInitializePut:
		var initPutEvent event.InitializePut
		err := json.Unmarshal(*ev.Data, &initPutEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initPutEvent.Time, 0)
		tag = build.SyslogTag(initPutEvent.Origin.ID)
		message = fmt.Sprintf("put initializing")
	case event.EventTypeInitializeCheck:
		var initCheckEvent event.InitializeCheck
		err := json.Unmarshal(*ev.Data, &initCheckEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initCheckEvent.Time, 0)
		tag = build.SyslogTag(initCheckEvent.Origin.ID)
		message = fmt.Sprintf("check initializing %s", initCheckEvent.Name)
	case event.EventTypeInitializeTask:
		var initTaskEvent event.InitializeTask
		err := json.Unmarshal(*ev.Data, &initTaskEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initTaskEvent.Time, 0)
		tag = build.SyslogTag(initTaskEvent.Origin.ID)
		message = fmt.Sprintf("task initializing")
	case event.EventTypeSelectedWorker:
		var selectedWorkerEvent event.SelectedWorker
		err := json.Unmarshal(*ev.Data, &selectedWorkerEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(selectedWorkerEvent.Time, 0)
		tag = build.SyslogTag(selectedWorkerEvent.Origin.ID)
		message = fmt.Sprintf("selected worker: %s", selectedWorkerEvent.WorkerName)
	case event.EventTypeStartTask:
		var startTaskEvent event.StartTask
		err := json.Unmarshal(*ev.Data, &startTaskEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(startTaskEvent.Time, 0)
		tag = build.SyslogTag(startTaskEvent.Origin.ID)

		buildConfig := startTaskEvent.TaskConfig
		argv := strings.Join(append([]string{buildConfig.Run.Path}, buildConfig.Run.Args...), " ")
		message = fmt.Sprintf("running %s", argv)
	case event.EventTypeLog:
		var logEvent event.Log
		err := json.Unmarshal(*ev.Data, &logEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(logEvent.Time, 0)
		tag = build.SyslogTag(logEvent.Origin.ID)
		message = logEvent.Payload
	case event.EventTypeFinishGet:
		var finishGetEvent event.FinishGet
		err := json.Unmarshal(*ev.Data, &finishGetEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(finishGetEvent.Time, 0)
		tag = build.SyslogTag(finishGetEvent.Origin.ID)

		version, _ := json.Marshal(finishGetEvent.FetchedVersion)
		metadata, _ := json.Marshal(finishGetEvent.FetchedMetadata)
		message = fmt.Sprintf("get {\"version\": %s, \"metadata\": %s", string(version), string(metadata))
	case event.EventTypeFinishPut:
		var finishPutEvent event.FinishPut
		err := json.Unmarshal(*ev.Data, &finishPutEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(finishPutEvent.Time, 0)
		tag = build.SyslogTag(finishPutEvent.Origin.ID)

		version, _ := json.Marshal(finishPutEvent.CreatedVersion)
		metadata, _ := json.Marshal(finishPutEvent.CreatedMetadata)
		message = fmt.Sprintf("put {\"version\": %s, \"metadata\": %s", string(version), string(metadata))
	case event.EventTypeError:
		var errorEvent event.Error
		err := json.Unmarshal(*ev.Data, &errorEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(errorEvent.Time, 0)
		tag = build.SyslogTag(errorEvent.Origin.ID)
		message = errorEvent.Message
	case event.EventTypeStatus:
		var statusEvent event.Status
		err := json.Unmarshal(*ev.Data, &statusEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(statusEvent.Time, 0)
		tag = build.SyslogTag(event.OriginID(""))
		message = statusEvent.Status.String()
	}

	if message != "" {
		err := syslog.Write(hostname, tag, ts, message, ev.EventID)
		if err != nil {
			logger.Error("failed-to-write-to-server", err)
			return err
		}
	}

	return nil
}
<commit_msg>unnecessary use of fmt.Sprintf()<commit_after>package syslog

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagerctx"
	"github.com/concourse/concourse/atc/db"
	"github.com/concourse/concourse/atc/event"
)

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

//counterfeiter:generate . Drainer
type Drainer interface {
	Run(context.Context) error
}

type drainer struct {
	hostname     string
	transport    string
	address      string
	caCerts      []string
	buildFactory db.BuildFactory
}

func NewDrainer(transport string, address string, hostname string, caCerts []string, buildFactory db.BuildFactory) Drainer {
	return &drainer{
		hostname:     hostname,
		transport:    transport,
		address:      address,
		buildFactory: buildFactory,
		caCerts:      caCerts,
	}
}

func (d *drainer) Run(ctx context.Context) error {
	logger := lagerctx.FromContext(ctx).Session("syslog")

	builds, err := d.buildFactory.GetDrainableBuilds()
	if err != nil {
		logger.Error("failed-to-get-drainable-builds", err)
		return err
	}

	if len(builds) > 0 {
		syslog, err := Dial(d.transport, d.address, d.caCerts)
		if err != nil {
			logger.Error("failed-to-connect", err)
			return err
		}

		// ignore any errors coming from syslog.Close()
		defer db.Close(syslog)

		for _, build := range builds {
			err := d.drainBuild(logger, build, syslog)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (d *drainer) drainBuild(logger lager.Logger, build db.Build, syslog *Syslog) error {
	logger = logger.Session("drain-build", build.LagerData())

	events, err := build.Events(0)
	if err != nil {
		return err
	}

	// ignore any errors coming from events.Close()
	defer db.Close(events)

	for {
		ev, err := events.Next()
		if err != nil {
			if err == db.ErrEndOfBuildEventStream {
				break
			}
			logger.Error("failed-to-get-next-event", err)
			return err
		}

		err = d.sendEvent(logger, build, syslog, ev)
		if err != nil {
			logger.Error("failed-to-send-event", err)
			return err
		}
	}

	err = build.SetDrained(true)
	if err != nil {
		logger.Error("failed-to-update-status", err)
		return err
	}

	return nil
}

func (d *drainer) sendEvent(logger lager.Logger, build db.Build, syslog *Syslog, ev event.Envelope) error {
	var (
		hostname string = d.hostname
		ts       time.Time
		tag      string
		message  string
	)

	switch ev.Event {
	case event.EventTypeInitialize:
		var initEvent event.Initialize
		err := json.Unmarshal(*ev.Data, &initEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initEvent.Time, 0)
		tag = build.SyslogTag(initEvent.Origin.ID)
		message = "initializing"
	case event.EventTypeInitializeGet:
		var initGetEvent event.InitializeGet
		err := json.Unmarshal(*ev.Data, &initGetEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initGetEvent.Time, 0)
		tag = build.SyslogTag(initGetEvent.Origin.ID)
		message = "get initializing"
	case event.EventTypeInitializePut:
		var initPutEvent event.InitializePut
		err := json.Unmarshal(*ev.Data, &initPutEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initPutEvent.Time, 0)
		tag = build.SyslogTag(initPutEvent.Origin.ID)
		message = "put initializing"
	case event.EventTypeInitializeCheck:
		var initCheckEvent event.InitializeCheck
		err := json.Unmarshal(*ev.Data, &initCheckEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initCheckEvent.Time, 0)
		tag = build.SyslogTag(initCheckEvent.Origin.ID)
		message = fmt.Sprintf("check initializing %s", initCheckEvent.Name)
	case event.EventTypeInitializeTask:
		var initTaskEvent event.InitializeTask
		err := json.Unmarshal(*ev.Data, &initTaskEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(initTaskEvent.Time, 0)
		tag = build.SyslogTag(initTaskEvent.Origin.ID)
		message = "task initializing"
	case event.EventTypeSelectedWorker:
		var selectedWorkerEvent event.SelectedWorker
		err := json.Unmarshal(*ev.Data, &selectedWorkerEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(selectedWorkerEvent.Time, 0)
		tag = build.SyslogTag(selectedWorkerEvent.Origin.ID)
		message = fmt.Sprintf("selected worker: %s", selectedWorkerEvent.WorkerName)
	case event.EventTypeStartTask:
		var startTaskEvent event.StartTask
		err := json.Unmarshal(*ev.Data, &startTaskEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(startTaskEvent.Time, 0)
		tag = build.SyslogTag(startTaskEvent.Origin.ID)

		buildConfig := startTaskEvent.TaskConfig
		argv := strings.Join(append([]string{buildConfig.Run.Path}, buildConfig.Run.Args...), " ")
		message = fmt.Sprintf("running %s", argv)
	case event.EventTypeLog:
		var logEvent event.Log
		err := json.Unmarshal(*ev.Data, &logEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(logEvent.Time, 0)
		tag = build.SyslogTag(logEvent.Origin.ID)
		message = logEvent.Payload
	case event.EventTypeFinishGet:
		var finishGetEvent event.FinishGet
		err := json.Unmarshal(*ev.Data, &finishGetEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(finishGetEvent.Time, 0)
		tag = build.SyslogTag(finishGetEvent.Origin.ID)

		version, _ := json.Marshal(finishGetEvent.FetchedVersion)
		metadata, _ := json.Marshal(finishGetEvent.FetchedMetadata)
		message = fmt.Sprintf("get {\"version\": %s, \"metadata\": %s", string(version), string(metadata))
	case event.EventTypeFinishPut:
		var finishPutEvent event.FinishPut
		err := json.Unmarshal(*ev.Data, &finishPutEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(finishPutEvent.Time, 0)
		tag = build.SyslogTag(finishPutEvent.Origin.ID)

		version, _ := json.Marshal(finishPutEvent.CreatedVersion)
		metadata, _ := json.Marshal(finishPutEvent.CreatedMetadata)
		message = fmt.Sprintf("put {\"version\": %s, \"metadata\": %s", string(version), string(metadata))
	case event.EventTypeError:
		var errorEvent event.Error
		err := json.Unmarshal(*ev.Data, &errorEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(errorEvent.Time, 0)
		tag = build.SyslogTag(errorEvent.Origin.ID)
		message = errorEvent.Message
	case event.EventTypeStatus:
		var statusEvent event.Status
		err := json.Unmarshal(*ev.Data, &statusEvent)
		if err != nil {
			logger.Error("failed-to-unmarshal", err)
			return err
		}
		ts = time.Unix(statusEvent.Time, 0)
		tag = build.SyslogTag(event.OriginID(""))
		message = statusEvent.Status.String()
	}

	if message != "" {
		err := syslog.Write(hostname, tag, ts, message, ev.EventID)
		if err != nil {
			logger.Error("failed-to-write-to-server", err)
			return err
		}
	}

	return nil
}
<|endoftext|>