<commit_before>/*
 * Copyright 2015 Casey Marshall
 *
 * 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 quorum_test

import (
	"testing"

	gc "gopkg.in/check.v1"

	"github.com/cmars/quorum"
)

func Test(t *testing.T) { gc.TestingT(t) }

type StorageSuite struct {
	store quorum.Storage
}

var _ = gc.Suite(&StorageSuite{})

func (s *StorageSuite) SetUpTest(c *gc.C) {
	s.store = quorum.NewMemStorage()
}
func (s *StorageSuite) TestDifferentiateElections(c *gc.C) {
	election1 := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 1,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election1 message",
		},
		ID:       "election1-id",
		CaveatID: "election1-caveatid",
	}
	err := s.store.Add(election1, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election1-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election1-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)

	election2 := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"carol@e2", "dave@e2"},
			Message:            "election2 message",
		},
		ID:       "election2-id",
		CaveatID: "election2-caveatid",
	}
	err = s.store.Add(election2, []quorum.Ballot{{
		ID:        "carol-ballot",
		Election:  "election2-id",
		Recipient: "carol@e2",
	}, {
		ID:        "dave-ballot",
		Election:  "election2-id",
		Recipient: "dave@e2",
	}})
	c.Assert(err, gc.IsNil)

	election1Resp, err := s.store.Election("election1-id")
	c.Assert(err, gc.IsNil)
	c.Assert(election1Resp, gc.DeepEquals, election1)

	election2Resp, err := s.store.Election("election2-id")
	c.Assert(err, gc.IsNil)
	c.Assert(election2Resp, gc.DeepEquals, election2)
}

func (s *StorageSuite) TestInvalidElection(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 3,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := election.Validate()
	c.Assert(err, gc.ErrorMatches, "2 recipients will never satisfy 3 approver requirement")
}

func (s *StorageSuite) TestAccept(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Deny("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("bob-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionApproved)
}

func (s *StorageSuite) assertResult(c *gc.C, id string, result quorum.ElectionResult) {
	e, err := s.store.Election(id)
	c.Assert(err, gc.IsNil)
	c.Assert(e.Result(), gc.Equals, result)
}

func (s *StorageSuite) TestDeny(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Deny("alice-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Approve("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Deny("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	// Bob can approve, but it won't change the outcome.
	err = s.store.Approve("bob-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionDenied)
}

func (s *StorageSuite) TestNoApprovalsRequired(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 0,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionApproved)
}
<commit_msg>Add newline.<commit_after>/*
 * Copyright 2015 Casey Marshall
 *
 * 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 quorum_test

import (
	"testing"

	gc "gopkg.in/check.v1"

	"github.com/cmars/quorum"
)

func Test(t *testing.T) { gc.TestingT(t) }

type StorageSuite struct {
	store quorum.Storage
}

var _ = gc.Suite(&StorageSuite{})

func (s *StorageSuite) SetUpTest(c *gc.C) {
	s.store = quorum.NewMemStorage()
}

func (s *StorageSuite) TestDifferentiateElections(c *gc.C) {
	election1 := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 1,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election1 message",
		},
		ID:       "election1-id",
		CaveatID: "election1-caveatid",
	}
	err := s.store.Add(election1, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election1-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election1-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)

	election2 := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"carol@e2", "dave@e2"},
			Message:            "election2 message",
		},
		ID:       "election2-id",
		CaveatID: "election2-caveatid",
	}
	err = s.store.Add(election2, []quorum.Ballot{{
		ID:        "carol-ballot",
		Election:  "election2-id",
		Recipient: "carol@e2",
	}, {
		ID:        "dave-ballot",
		Election:  "election2-id",
		Recipient: "dave@e2",
	}})
	c.Assert(err, gc.IsNil)

	election1Resp, err := s.store.Election("election1-id")
	c.Assert(err, gc.IsNil)
	c.Assert(election1Resp, gc.DeepEquals, election1)

	election2Resp, err := s.store.Election("election2-id")
	c.Assert(err, gc.IsNil)
	c.Assert(election2Resp, gc.DeepEquals, election2)
}

func (s *StorageSuite) TestInvalidElection(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 3,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := election.Validate()
	c.Assert(err, gc.ErrorMatches, "2 recipients will never satisfy 3 approver requirement")
}

func (s *StorageSuite) TestAccept(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Deny("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Approve("bob-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionApproved)
}

func (s *StorageSuite) assertResult(c *gc.C, id string, result quorum.ElectionResult) {
	e, err := s.store.Election(id)
	c.Assert(err, gc.IsNil)
	c.Assert(e.Result(), gc.Equals, result)
}

func (s *StorageSuite) TestDeny(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 2,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionPending)

	err = s.store.Deny("alice-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Approve("alice-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Approve("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	err = s.store.Deny("mallory-ballot")
	c.Assert(err, gc.ErrorMatches, "not found")
	s.assertResult(c, "election-id", quorum.ElectionDenied)

	// Bob can approve, but it won't change the outcome.
	err = s.store.Approve("bob-ballot")
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionDenied)
}

func (s *StorageSuite) TestNoApprovalsRequired(c *gc.C) {
	election := quorum.Election{
		Policy: quorum.Policy{
			NApprovalsRequired: 0,
			Participants:       []string{"alice@e1", "bob@e1"},
			Message:            "election message",
		},
		ID:       "election-id",
		CaveatID: "election-caveatid",
	}
	err := s.store.Add(election, []quorum.Ballot{{
		ID:        "alice-ballot",
		Election:  "election-id",
		Recipient: "alice@e1",
	}, {
		ID:        "bob-ballot",
		Election:  "election-id",
		Recipient: "bob@e1",
	}})
	c.Assert(err, gc.IsNil)
	s.assertResult(c, "election-id", quorum.ElectionApproved)
}
<|endoftext|>


<commit_before>// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package mysql

import (
	"fmt"
	"io"
	"os"
	"strings"
)

var (
	fileRegister   map[string]bool
	readerRegister map[string]func() io.Reader
)

// RegisterLocalFile adds the given file to the file whitelist,
// so that it can be used by "LOAD DATA LOCAL INFILE <filepath>".
// Alternatively you can allow the use of all local files with
// the DSN parameter 'allowAllFiles=true'
//
//  filePath := "/home/gopher/data.csv"
//  mysql.RegisterLocalFile(filePath)
//  err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
//  if err != nil {
//  ...
//
func RegisterLocalFile(filePath string) {
	// lazy map init
	if fileRegister == nil {
		fileRegister = make(map[string]bool)
	}

	fileRegister[strings.Trim(filePath, `"`)] = true
}

// DeregisterLocalFile removes the given filepath from the whitelist.
func DeregisterLocalFile(filePath string) {
	delete(fileRegister, strings.Trim(filePath, `"`))
}

// RegisterReaderHandler registers a handler function which is used
// to receive a io.Reader.
// The Reader can be used by "LOAD DATA LOCAL INFILE Reader::<name>".
// If the handler returns a io.ReadCloser Close() is called when the
// request is finished.
//
//  mysql.RegisterReaderHandler("data", func() io.Reader {
//  	var csvReader io.Reader // Some Reader that returns CSV data
//  	... // Open Reader here
//  	return csvReader
//  })
//  err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
//  if err != nil {
//  ...
//
func RegisterReaderHandler(name string, handler func() io.Reader) {
	// lazy map init
	if readerRegister == nil {
		readerRegister = make(map[string]func() io.Reader)
	}

	readerRegister[name] = handler
}

// DeregisterReaderHandler removes the ReaderHandler function with
// the given name from the registry.
func DeregisterReaderHandler(name string) {
	delete(readerRegister, name)
}

func deferredClose(err *error, closer io.Closer) {
	closeErr := closer.Close()
	if *err == nil {
		*err = closeErr
	}
}

func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
	var rdr io.Reader
	var data []byte

	if strings.HasPrefix(name, "Reader::") { // io.Reader
		name = name[8:]
		if handler, inMap := readerRegister[name]; inMap {
			rdr = handler()
			if rdr != nil {
				data = make([]byte, 4+mc.maxWriteSize)

				if cl, ok := rdr.(io.Closer); ok {
					defer deferredClose(&err, cl)
				}
			} else {
				err = fmt.Errorf("Reader '%s' is <nil>", name)
			}
		} else {
			err = fmt.Errorf("Reader '%s' is not registered", name)
		}
	} else { // File
		name = strings.Trim(name, `"`)
		if mc.cfg.allowAllFiles || fileRegister[name] {
			var file *os.File
			var fi os.FileInfo

			if file, err = os.Open(name); err == nil {
				defer deferredClose(&err, file)

				// get file size
				if fi, err = file.Stat(); err == nil {
					rdr = file
					if fileSize := int(fi.Size()); fileSize <= mc.maxWriteSize {
						data = make([]byte, 4+fileSize)
					} else if fileSize <= mc.maxPacketAllowed {
						data = make([]byte, 4+mc.maxWriteSize)
					} else {
						err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed)
					}
				}
			}
		} else {
			err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name)
		}
	}

	// send content packets
	if err == nil {
		var n int
		for err == nil {
			n, err = rdr.Read(data[4:])
			if n > 0 {
				if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
					return ioErr
				}
			}
		}
		if err == io.EOF {
			err = nil
		}
	}

	// send empty packet (termination)
	if data == nil {
		data = make([]byte, 4)
	}
	if ioErr := mc.writePacket(data[:4]); ioErr != nil {
		return ioErr
	}

	// read OK packet
	if err == nil {
		return mc.readResultOK()
	} else {
		mc.readPacket()
	}
	return err
}
<commit_msg>infile: Support absolute paths<commit_after>// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package mysql

import (
	"fmt"
	"io"
	"os"
	"path"
	"strings"
)

var (
	fileRegister   map[string]bool
	readerRegister map[string]func() io.Reader
)

// RegisterLocalFile adds the given file to the file whitelist,
// so that it can be used by "LOAD DATA LOCAL INFILE <filepath>".
// Alternatively you can allow the use of all local files with
// the DSN parameter 'allowAllFiles=true'
//
//  filePath := "/home/gopher/data.csv"
//  mysql.RegisterLocalFile(filePath)
//  err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
//  if err != nil {
//  ...
//
func RegisterLocalFile(filePath string) {
	// lazy map init
	if fileRegister == nil {
		fileRegister = make(map[string]bool)
	}

	fileRegister[strings.Trim(filePath, `"`)] = true
}

// DeregisterLocalFile removes the given filepath from the whitelist.
func DeregisterLocalFile(filePath string) {
	delete(fileRegister, strings.Trim(filePath, `"`))
}

// RegisterReaderHandler registers a handler function which is used
// to receive a io.Reader.
// The Reader can be used by "LOAD DATA LOCAL INFILE Reader::<name>".
// If the handler returns a io.ReadCloser Close() is called when the
// request is finished.
//
//  mysql.RegisterReaderHandler("data", func() io.Reader {
//  	var csvReader io.Reader // Some Reader that returns CSV data
//  	... // Open Reader here
//  	return csvReader
//  })
//  err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
//  if err != nil {
//  ...
//
func RegisterReaderHandler(name string, handler func() io.Reader) {
	// lazy map init
	if readerRegister == nil {
		readerRegister = make(map[string]func() io.Reader)
	}

	readerRegister[name] = handler
}

// DeregisterReaderHandler removes the ReaderHandler function with
// the given name from the registry.
func DeregisterReaderHandler(name string) {
	delete(readerRegister, name)
}

func deferredClose(err *error, closer io.Closer) {
	closeErr := closer.Close()
	if *err == nil {
		*err = closeErr
	}
}

func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
	var rdr io.Reader
	var data []byte

	// The server might return an an absolute path. See issue #355.
	base := path.Base(name)

	if strings.HasPrefix(base, "Reader::") { // io.Reader
		name = base[8:]
		if handler, inMap := readerRegister[name]; inMap {
			rdr = handler()
			if rdr != nil {
				data = make([]byte, 4+mc.maxWriteSize)

				if cl, ok := rdr.(io.Closer); ok {
					defer deferredClose(&err, cl)
				}
			} else {
				err = fmt.Errorf("Reader '%s' is <nil>", name)
			}
		} else {
			err = fmt.Errorf("Reader '%s' is not registered", name)
		}
	} else { // File
		name = strings.Trim(name, `"`)
		if mc.cfg.allowAllFiles || fileRegister[name] {
			var file *os.File
			var fi os.FileInfo

			if file, err = os.Open(name); err == nil {
				defer deferredClose(&err, file)

				// get file size
				if fi, err = file.Stat(); err == nil {
					rdr = file
					if fileSize := int(fi.Size()); fileSize <= mc.maxWriteSize {
						data = make([]byte, 4+fileSize)
					} else if fileSize <= mc.maxPacketAllowed {
						data = make([]byte, 4+mc.maxWriteSize)
					} else {
						err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed)
					}
				}
			}
		} else {
			err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name)
		}
	}

	// send content packets
	if err == nil {
		var n int
		for err == nil {
			n, err = rdr.Read(data[4:])
			if n > 0 {
				if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
					return ioErr
				}
			}
		}
		if err == io.EOF {
			err = nil
		}
	}

	// send empty packet (termination)
	if data == nil {
		data = make([]byte, 4)
	}
	if ioErr := mc.writePacket(data[:4]); ioErr != nil {
		return ioErr
	}

	// read OK packet
	if err == nil {
		return mc.readResultOK()
	} else {
		mc.readPacket()
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
   "os"
   // "os/signal"
   // "syscall"
   "bufio"
   "log"
   "strings"
   "time"
   "./diskStat"
   "./ioStatTransform"
   "flag"
   // "fmt"

)
/**
Go version of iostat, pull stats from proc and optionally log or send to a zeroMQ
*/

var interval = flag.Int("interval", 5, "Interval that stats should be reported.")

const linuxDiskStats = "/proc/diskstats"

func main() {
  flag.Parse()
  for {
    my_channel := make(chan diskStat.DiskStat, 1000)
    go ioStatTransform.TransformStat(my_channel)

    // // Handle SIGINT and SIGTERM.
    // ch := make(chan os.Signal)
    // signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)

    file,err := os.Open(linuxDiskStats)
    if nil != err {
  		log.Fatal(err)
  	}

    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
    	line := strings.Fields(scanner.Text())
    	stat,err := diskStat.LineToStat(line)
    	if(nil != err) {
    		log.Fatal(err)
    	}
    	my_channel <- stat
    }
    if err := scanner.Err(); err != nil {
      log.Fatal(err)
  	}
    time.Sleep(time.Second * time.Duration(*interval))
  }

}
<commit_msg>cleanup file handles<commit_after>package main

import (
   "os"
   // "os/signal"
   // "syscall"
   "bufio"
   "log"
   "strings"
   "time"
   "./diskStat"
   "./ioStatTransform"
   "flag"
   // "fmt"

)
/**
Go version of iostat, pull stats from proc and optionally log or send to a zeroMQ
*/

var interval = flag.Int("interval", 5, "Interval that stats should be reported.")

const linuxDiskStats = "/proc/diskstats"

func main() {
  flag.Parse()
  for {
    my_channel := make(chan diskStat.DiskStat, 1)
    go ioStatTransform.TransformStat(my_channel)

    // // Handle SIGINT and SIGTERM.
    // ch := make(chan os.Signal)
    // signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)

    file,err := os.Open(linuxDiskStats)
    if nil != err {
  		log.Fatal(err)
  	}

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
    	line := strings.Fields(scanner.Text())
    	stat,err := diskStat.LineToStat(line)
    	if(nil != err) {
    		log.Fatal(err)
    	}
    	my_channel <- stat
    }
    file.Close()
    if err := scanner.Err(); err != nil {
      log.Fatal(err)
  	}
    time.Sleep(time.Second * time.Duration(*interval))
  }

}
<|endoftext|>


<commit_before>package landscaper

import (
	"fmt"
	"strings"

	"k8s.io/helm/pkg/helm"
	"k8s.io/helm/pkg/kube"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/restclient"
	"k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/labels"
)

// TODO refactor out this global var
var tillerTunnel *kube.Tunnel
var tillerNamespace = "kube-system"

// Environment contains all the information about the k8s cluster and local configuration
type Environment struct {
	DryRun             bool
	ChartLoader        ChartLoader
	HelmClient         *helm.Client
	HelmRepositoryName string
	LandscapeName      string
	LandscapeDir       string
	Namespace          string
}

// EnsureHelmClient makes sure the environment has a HelmClient initialized
func (e *Environment) EnsureHelmClient() error {
	if e.HelmClient == nil {
		tillerHost, err := setupConnection()
		if err != nil {
			return err
		}

		e.HelmClient = helm.NewClient(helm.Host(tillerHost))
	}

	return nil
}

// Teardown closes the tunnel etc
func (e *Environment) Teardown() {
	teardown()
}

// ReleaseName taks a component name, and uses info in the environment to return a release name
func (e *Environment) ReleaseName(componentName string) string {
	return fmt.Sprintf("%s-%s", strings.ToLower(string(e.LandscapeName[0])), strings.ToLower(componentName))
}

func setupConnection() (string, error) {
	tunnel, err := newTillerPortForwarder(tillerNamespace, "")
	if err != nil {
		return "", err
	}

	tillerTunnel = tunnel

	return fmt.Sprintf(":%d", tunnel.Local), nil
}

func teardown() {
	if tillerTunnel != nil {
		tillerTunnel.Close()
		tillerTunnel = nil
	}
}

// getKubeClient is a convenience method for creating kubernetes config and client
// for a given kubeconfig context
func getKubeClient(context string) (*restclient.Config, *unversioned.Client, error) {
	config, err := kube.GetConfig(context).ClientConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("could not get kubernetes config for context '%s': %s", context, err)
	}
	client, err := unversioned.New(config)
	if err != nil {
		return nil, nil, fmt.Errorf("could not get kubernetes client: %s", err)
	}
	return config, client, nil
}

func newTillerPortForwarder(namespace, context string) (*kube.Tunnel, error) {
	config, client, err := getKubeClient(context)
	if err != nil {
		return nil, err
	}

	podName, err := getTillerPodName(client, namespace)
	if err != nil {
		return nil, err
	}
	const tillerPort = 44134
	t := kube.NewTunnel(client.RESTClient, config, namespace, podName, tillerPort)
	return t, t.ForwardPort()
}

func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (string, error) {
	// TODO use a const for labels
	selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
	pod, err := getFirstRunningPod(client, namespace, selector)
	if err != nil {
		return "", err
	}
	return pod.ObjectMeta.GetName(), nil
}

func getFirstRunningPod(client unversioned.PodsNamespacer, namespace string, selector labels.Selector) (*api.Pod, error) {
	options := api.ListOptions{LabelSelector: selector}
	pods, err := client.Pods(namespace).List(options)
	if err != nil {
		return nil, err
	}
	if len(pods.Items) < 1 {
		return nil, fmt.Errorf("could not find tiller")
	}
	for _, p := range pods.Items {
		if api.IsPodReady(&p) {
			return &p, nil
		}
	}
	return nil, fmt.Errorf("could not find a ready tiller pod")
}
<commit_msg>Use helm.Interface instead of the client struct<commit_after>package landscaper

import (
	"fmt"
	"strings"

	"k8s.io/helm/pkg/helm"
	"k8s.io/helm/pkg/kube"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/restclient"
	"k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/labels"
)

// TODO refactor out this global var
var tillerTunnel *kube.Tunnel
var tillerNamespace = "kube-system"

// Environment contains all the information about the k8s cluster and local configuration
type Environment struct {
	DryRun             bool
	ChartLoader        ChartLoader
	HelmClient         helm.Interface
	HelmRepositoryName string
	LandscapeName      string
	LandscapeDir       string
	Namespace          string
}

// EnsureHelmClient makes sure the environment has a HelmClient initialized
func (e *Environment) EnsureHelmClient() error {
	if e.HelmClient == nil {
		tillerHost, err := setupConnection()
		if err != nil {
			return err
		}

		e.HelmClient = helm.NewClient(helm.Host(tillerHost))
	}

	return nil
}

// Teardown closes the tunnel etc
func (e *Environment) Teardown() {
	teardown()
}

// ReleaseName taks a component name, and uses info in the environment to return a release name
func (e *Environment) ReleaseName(componentName string) string {
	return fmt.Sprintf("%s-%s", strings.ToLower(string(e.LandscapeName[0])), strings.ToLower(componentName))
}

func setupConnection() (string, error) {
	tunnel, err := newTillerPortForwarder(tillerNamespace, "")
	if err != nil {
		return "", err
	}

	tillerTunnel = tunnel

	return fmt.Sprintf(":%d", tunnel.Local), nil
}

func teardown() {
	if tillerTunnel != nil {
		tillerTunnel.Close()
		tillerTunnel = nil
	}
}

// getKubeClient is a convenience method for creating kubernetes config and client
// for a given kubeconfig context
func getKubeClient(context string) (*restclient.Config, *unversioned.Client, error) {
	config, err := kube.GetConfig(context).ClientConfig()
	if err != nil {
		return nil, nil, fmt.Errorf("could not get kubernetes config for context '%s': %s", context, err)
	}
	client, err := unversioned.New(config)
	if err != nil {
		return nil, nil, fmt.Errorf("could not get kubernetes client: %s", err)
	}
	return config, client, nil
}

func newTillerPortForwarder(namespace, context string) (*kube.Tunnel, error) {
	config, client, err := getKubeClient(context)
	if err != nil {
		return nil, err
	}

	podName, err := getTillerPodName(client, namespace)
	if err != nil {
		return nil, err
	}
	const tillerPort = 44134
	t := kube.NewTunnel(client.RESTClient, config, namespace, podName, tillerPort)
	return t, t.ForwardPort()
}

func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (string, error) {
	// TODO use a const for labels
	selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
	pod, err := getFirstRunningPod(client, namespace, selector)
	if err != nil {
		return "", err
	}
	return pod.ObjectMeta.GetName(), nil
}

func getFirstRunningPod(client unversioned.PodsNamespacer, namespace string, selector labels.Selector) (*api.Pod, error) {
	options := api.ListOptions{LabelSelector: selector}
	pods, err := client.Pods(namespace).List(options)
	if err != nil {
		return nil, err
	}
	if len(pods.Items) < 1 {
		return nil, fmt.Errorf("could not find tiller")
	}
	for _, p := range pods.Items {
		if api.IsPodReady(&p) {
			return &p, nil
		}
	}
	return nil, fmt.Errorf("could not find a ready tiller pod")
}
<|endoftext|>


<commit_before>package middleware

import (
	"fmt"
	"net"
	"net/http"
	"os"
	"strconv"

	base "github.com/hellofresh/janus/pkg/opentracing"
	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	log "github.com/sirupsen/logrus"
)

var healthChecks = [...]string{
	"/",
	"/status",
	"/metrics",
	"/health",
	"/healthz",
	"/health_check",
	"/healthcheck",
}

type statusCodeTracker struct {
	http.ResponseWriter
	status int
}

func (w *statusCodeTracker) WriteHeader(status int) {
	w.status = status
	w.ResponseWriter.WriteHeader(status)
}

// OpenTracing is a middleware that traces the request latency
type OpenTracing struct {
	https bool
}

// NewOpenTracing creates a new instance of OpenTracing
func NewOpenTracing(https bool) *OpenTracing {
	return &OpenTracing{https}
}

// Handler is the middleware function for OpenTracing
func (h *OpenTracing) Handler(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if isHealthCheck(r.URL.Path) {
			handler.ServeHTTP(w, r)
			return
		}

		var span opentracing.Span
		var err error

		// Attempt to join a trace by getting trace context from the headers.
		wireContext, err := opentracing.GlobalTracer().Extract(
			opentracing.HTTPHeaders,
			opentracing.HTTPHeadersCarrier(r.Header))
		if err != nil {
			// If for whatever reason we can't join, go ahead an start a new root span.
			span = opentracing.StartSpan(r.URL.Path)
		} else {
			span = opentracing.StartSpan(r.URL.Path, opentracing.ChildOf(wireContext))
		}
		defer span.Finish()

		host, err := os.Hostname()
		if host == "" || err != nil {
			log.WithError(err).Debug("Failed to get host name")
			host = "unknown"
		}

		ext.HTTPMethod.Set(span, r.Method)
		ext.HTTPUrl.Set(
			span,
			fmt.Sprintf("%s://%s%s", map[bool]string{true: "https", false: "http"}[h.https], r.Host, r.URL.Path),
		)
		ext.Component.Set(span, "janus")
		ext.SpanKind.Set(span, "server")

		span.SetTag("user.agent", r.UserAgent())
		span.SetTag("peer.address", r.RemoteAddr)
		span.SetTag("host.name", host)
		span.SetTag("referer", r.Referer())
		span.SetTag("request.id", RequestIDFromContext(r.Context()))

		// Add information on the peer service we're about to contact.
		if host, portString, err := net.SplitHostPort(r.URL.Host); err == nil {
			ext.PeerHostname.Set(span, host)
			if port, err := strconv.Atoi(portString); err != nil {
				ext.PeerPort.Set(span, uint16(port))
			}
		} else {
			ext.PeerHostname.Set(span, r.URL.Host)
		}

		err = span.Tracer().Inject(
			span.Context(),
			opentracing.HTTPHeaders,
			opentracing.HTTPHeadersCarrier(r.Header))
		if err != nil {
			log.WithError(err).Error("Could not inject span context into header")
		}

		w = &statusCodeTracker{w, http.StatusOK}
		handler.ServeHTTP(w, base.ToContext(r, span))
		code := uint16(w.(*statusCodeTracker).status)
		if code > http.StatusInternalServerError {
			ext.HTTPStatusCode.Set(span, code)
		}
	})
}

func isHealthCheck(path string) bool {
	for _, hc := range healthChecks {
		if hc == path {
			return true
		}
	}
	return false
}
<commit_msg>set error tag in the trace<commit_after>package middleware

import (
	"fmt"
	"net"
	"net/http"
	"os"
	"strconv"

	base "github.com/hellofresh/janus/pkg/opentracing"
	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	log "github.com/sirupsen/logrus"
)

var healthChecks = [...]string{
	"/",
	"/status",
	"/metrics",
	"/health",
	"/healthz",
	"/health_check",
	"/healthcheck",
}

type statusCodeTracker struct {
	http.ResponseWriter
	status int
}

func (w *statusCodeTracker) WriteHeader(status int) {
	w.status = status
	w.ResponseWriter.WriteHeader(status)
}

// OpenTracing is a middleware that traces the request latency
type OpenTracing struct {
	https bool
}

// NewOpenTracing creates a new instance of OpenTracing
func NewOpenTracing(https bool) *OpenTracing {
	return &OpenTracing{https}
}

// Handler is the middleware function for OpenTracing
func (h *OpenTracing) Handler(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if isHealthCheck(r.URL.Path) {
			handler.ServeHTTP(w, r)
			return
		}

		var span opentracing.Span
		var err error

		// Attempt to join a trace by getting trace context from the headers.
		wireContext, err := opentracing.GlobalTracer().Extract(
			opentracing.HTTPHeaders,
			opentracing.HTTPHeadersCarrier(r.Header))
		if err != nil {
			// If for whatever reason we can't join, go ahead an start a new root span.
			span = opentracing.StartSpan(r.URL.Path)
		} else {
			span = opentracing.StartSpan(r.URL.Path, opentracing.ChildOf(wireContext))
		}
		defer span.Finish()

		host, err := os.Hostname()
		if host == "" || err != nil {
			log.WithError(err).Debug("Failed to get host name")
			host = "unknown"
		}

		ext.HTTPMethod.Set(span, r.Method)
		ext.HTTPUrl.Set(
			span,
			fmt.Sprintf("%s://%s%s", map[bool]string{true: "https", false: "http"}[h.https], r.Host, r.URL.Path),
		)
		ext.Component.Set(span, "janus")
		ext.SpanKind.Set(span, "server")

		span.SetTag("user.agent", r.UserAgent())
		span.SetTag("peer.address", r.RemoteAddr)
		span.SetTag("host.name", host)
		span.SetTag("referer", r.Referer())
		span.SetTag("request.id", RequestIDFromContext(r.Context()))

		// Add information on the peer service we're about to contact.
		if host, portString, err := net.SplitHostPort(r.URL.Host); err == nil {
			ext.PeerHostname.Set(span, host)
			if port, err := strconv.Atoi(portString); err != nil {
				ext.PeerPort.Set(span, uint16(port))
			}
		} else {
			ext.PeerHostname.Set(span, r.URL.Host)
		}

		err = span.Tracer().Inject(
			span.Context(),
			opentracing.HTTPHeaders,
			opentracing.HTTPHeadersCarrier(r.Header))
		if err != nil {
			log.WithError(err).Error("Could not inject span context into header")
		}

		w = &statusCodeTracker{w, http.StatusOK}
		handler.ServeHTTP(w, base.ToContext(r, span))
		code := uint16(w.(*statusCodeTracker).status)
		ext.HTTPStatusCode.Set(span, code)
		if code >= http.StatusInternalServerError {
			ext.Error.Set(span, true)
		}
	})
}

func isHealthCheck(path string) bool {
	for _, hc := range healthChecks {
		if hc == path {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package secrets

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"

	kerrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	kapi "k8s.io/kubernetes/pkg/api"
	kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/resource"
)

// SecretOptions Structure holding state for processing secret linking and
// unlinking.
type SecretOptions struct {
	TargetName  string
	SecretNames []string
	typeFlags   []string

	Namespace string

	BuilderFunc    func(bool) *resource.Builder
	KubeCoreClient kcoreclient.CoreInterface

	Out io.Writer
}

// Complete Parses the command line arguments and populates SecretOptions
func (o *SecretOptions) Complete(f kcmdutil.Factory, args []string) error {
	if len(args) < 2 {
		return errors.New("must have service account name and at least one secret name")
	}
	o.TargetName = args[0]
	o.SecretNames = args[1:]

	o.BuilderFunc = f.NewBuilder

	var err error
	kubeClientSet, err := f.ClientSet()
	if err != nil {
		return err
	}
	o.KubeCoreClient = kubeClientSet.Core()

	o.Namespace, _, err = f.DefaultNamespace()
	if err != nil {
		return err
	}

	return nil
}

// Validate Ensures that all arguments have appropriate values
func (o SecretOptions) Validate() error {
	if len(o.TargetName) == 0 {
		return errors.New("service account name must be present")
	}
	if len(o.SecretNames) == 0 {
		return errors.New("secret name must be present")
	}
	if o.KubeCoreClient == nil {
		return errors.New("KubeCoreClient must be present")
	}

	return nil
}

// GetServiceAccount Retrieve the service account object specified by the command
func (o SecretOptions) GetServiceAccount() (*kapi.ServiceAccount, error) {
	r := o.BuilderFunc(true).
		NamespaceParam(o.Namespace).
		ResourceNames("serviceaccounts", o.TargetName).
		SingleResourceType().
		Do()
	if r.Err() != nil {
		return nil, r.Err()
	}
	obj, err := r.Object()
	if err != nil {
		return nil, err
	}

	switch t := obj.(type) {
	case *kapi.ServiceAccount:
		return t, nil
	default:
		return nil, fmt.Errorf("unhandled object: %#v", t)
	}
}

// GetSecretNames Get a list of the names of the secrets in a set of them
func (o SecretOptions) GetSecretNames(secrets []*kapi.Secret) sets.String {
	names := sets.String{}
	for _, secret := range secrets {
		names.Insert(parseSecretName(secret.Name))
	}
	return names
}

// parseSecretName receives a resource name as either
// <resource type> / <name> or <name> and returns only the resource <name>.
func parseSecretName(name string) string {
	segs := strings.Split(name, "/")
	if len(segs) < 2 {
		return name
	}

	if segs[0] == "secret" || segs[0] == "secrets" {
		return segs[1]
	}

	return name
}

// GetMountSecretNames Get a list of the names of the mount secrets associated
// with a service account
func (o SecretOptions) GetMountSecretNames(serviceaccount *kapi.ServiceAccount) sets.String {
	names := sets.String{}
	for _, secret := range serviceaccount.Secrets {
		names.Insert(secret.Name)
	}
	return names
}

// GetPullSecretNames Get a list of the names of the pull secrets associated
// with a service account.
func (o SecretOptions) GetPullSecretNames(serviceaccount *kapi.ServiceAccount) sets.String {
	names := sets.String{}
	for _, secret := range serviceaccount.ImagePullSecrets {
		names.Insert(secret.Name)
	}
	return names
}

// GetOut Retrieve the output writer
func (o SecretOptions) GetOut() io.Writer {
	if o.Out == nil {
		return ioutil.Discard
	}

	return o.Out
}

// GetSecrets Return a list of secret objects in the default namespace
// If allowNonExisting is set to true, we will return the non-existing secrets as well.
func (o SecretOptions) GetSecrets(allowNonExisting bool) ([]*kapi.Secret, bool, error) {
	secrets := []*kapi.Secret{}
	hasNotFound := false

	for _, secretName := range o.SecretNames {
		r := o.BuilderFunc(true).
			NamespaceParam(o.Namespace).
			ResourceNames("secrets", secretName).
			SingleResourceType().
			Do()
		if r.Err() != nil {
			return nil, false, r.Err()
		}
		obj, err := r.Object()
		if err != nil {
			// If the secret is not found it means it was deleted but we want still to allow to
			// unlink a removed secret from the service account
			if kerrors.IsNotFound(err) {
				fmt.Fprintf(os.Stderr, "secret %q not found\n", secretName)
				hasNotFound = true
				if allowNonExisting {
					obj = &kapi.Secret{
						ObjectMeta: metav1.ObjectMeta{
							Name: secretName,
						},
					}
				} else {
					continue
				}
			} else if err != nil {
				return nil, false, err
			}
		}
		switch t := obj.(type) {
		case *kapi.Secret:
			secrets = append(secrets, t)
		default:
			return nil, false, fmt.Errorf("unhandled object: %#v", t)
		}
	}

	if len(secrets) == 0 {
		return nil, false, errors.New("No valid secrets found")
	}

	return secrets, hasNotFound, nil
}
<commit_msg>validate user-specified resource, if given<commit_after>package secrets

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"

	kerrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	kapi "k8s.io/kubernetes/pkg/api"
	kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/resource"
)

// SecretOptions Structure holding state for processing secret linking and
// unlinking.
type SecretOptions struct {
	TargetName  string
	SecretNames []string
	typeFlags   []string

	Namespace string

	BuilderFunc    func(bool) *resource.Builder
	KubeCoreClient kcoreclient.CoreInterface

	Out io.Writer
}

// Complete Parses the command line arguments and populates SecretOptions
func (o *SecretOptions) Complete(f kcmdutil.Factory, args []string) error {
	if len(args) < 2 {
		return errors.New("must have service account name and at least one secret name")
	}
	o.TargetName = args[0]
	o.SecretNames = args[1:]

	o.BuilderFunc = f.NewBuilder

	var err error
	kubeClientSet, err := f.ClientSet()
	if err != nil {
		return err
	}
	o.KubeCoreClient = kubeClientSet.Core()

	o.Namespace, _, err = f.DefaultNamespace()
	if err != nil {
		return err
	}

	return nil
}

// Validate Ensures that all arguments have appropriate values
func (o SecretOptions) Validate() error {
	if len(o.TargetName) == 0 {
		return errors.New("service account name must be present")
	}
	if len(o.SecretNames) == 0 {
		return errors.New("secret name must be present")
	}
	if o.KubeCoreClient == nil {
		return errors.New("KubeCoreClient must be present")
	}

	// if any secret names are of the form <resource>/<name>,
	// ensure <resource> is a secret.
	for _, secretName := range o.SecretNames {
		if segs := strings.Split(secretName, "/"); len(segs) > 1 {
			if segs[0] != "secret" && segs[0] != "secrets" {
				return errors.New(fmt.Sprintf("expected resource of type secret, got %q", secretName))
			}
		}
	}

	return nil
}

// GetServiceAccount Retrieve the service account object specified by the command
func (o SecretOptions) GetServiceAccount() (*kapi.ServiceAccount, error) {
	r := o.BuilderFunc(true).
		NamespaceParam(o.Namespace).
		ResourceNames("serviceaccounts", o.TargetName).
		SingleResourceType().
		Do()
	if r.Err() != nil {
		return nil, r.Err()
	}
	obj, err := r.Object()
	if err != nil {
		return nil, err
	}

	switch t := obj.(type) {
	case *kapi.ServiceAccount:
		return t, nil
	default:
		return nil, fmt.Errorf("unhandled object: %#v", t)
	}
}

// GetSecretNames Get a list of the names of the secrets in a set of them
func (o SecretOptions) GetSecretNames(secrets []*kapi.Secret) sets.String {
	names := sets.String{}
	for _, secret := range secrets {
		names.Insert(parseSecretName(secret.Name))
	}
	return names
}

// parseSecretName receives a resource name as either
// <resource type> / <name> or <name> and returns only the resource <name>.
func parseSecretName(name string) string {
	segs := strings.Split(name, "/")
	if len(segs) < 2 {
		return name
	}

	return segs[1]
}

// GetMountSecretNames Get a list of the names of the mount secrets associated
// with a service account
func (o SecretOptions) GetMountSecretNames(serviceaccount *kapi.ServiceAccount) sets.String {
	names := sets.String{}
	for _, secret := range serviceaccount.Secrets {
		names.Insert(secret.Name)
	}
	return names
}

// GetPullSecretNames Get a list of the names of the pull secrets associated
// with a service account.
func (o SecretOptions) GetPullSecretNames(serviceaccount *kapi.ServiceAccount) sets.String {
	names := sets.String{}
	for _, secret := range serviceaccount.ImagePullSecrets {
		names.Insert(secret.Name)
	}
	return names
}

// GetOut Retrieve the output writer
func (o SecretOptions) GetOut() io.Writer {
	if o.Out == nil {
		return ioutil.Discard
	}

	return o.Out
}

// GetSecrets Return a list of secret objects in the default namespace
// If allowNonExisting is set to true, we will return the non-existing secrets as well.
func (o SecretOptions) GetSecrets(allowNonExisting bool) ([]*kapi.Secret, bool, error) {
	secrets := []*kapi.Secret{}
	hasNotFound := false

	for _, secretName := range o.SecretNames {
		r := o.BuilderFunc(true).
			NamespaceParam(o.Namespace).
			ResourceNames("secrets", secretName).
			SingleResourceType().
			Do()
		if r.Err() != nil {
			return nil, false, r.Err()
		}
		obj, err := r.Object()
		if err != nil {
			// If the secret is not found it means it was deleted but we want still to allow to
			// unlink a removed secret from the service account
			if kerrors.IsNotFound(err) {
				fmt.Fprintf(os.Stderr, "secret %q not found\n", secretName)
				hasNotFound = true
				if allowNonExisting {
					obj = &kapi.Secret{
						ObjectMeta: metav1.ObjectMeta{
							Name: secretName,
						},
					}
				} else {
					continue
				}
			} else if err != nil {
				return nil, false, err
			}
		}
		switch t := obj.(type) {
		case *kapi.Secret:
			secrets = append(secrets, t)
		default:
			return nil, false, fmt.Errorf("unhandled object: %#v", t)
		}
	}

	if len(secrets) == 0 {
		return nil, false, errors.New("No valid secrets found")
	}

	return secrets, hasNotFound, nil
}
<|endoftext|>


<commit_before>package plugins

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
)

type GrafanaNetPlugin struct {
	Slug    string `json:"slug"`
	Version string `json:"version"`
}

type GithubLatest struct {
	Stable  string `json:"stable"`
	Testing string `json:"testing"`
}

func StartPluginUpdateChecker() {
	if !setting.CheckForUpdates {
		return
	}

	// do one check directly
	go checkForUpdates()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			checkForUpdates()
		}
	}
}

func getAllExternalPluginSlugs() string {
	str := ""

	for _, plug := range Plugins {
		if plug.IsCorePlugin {
			continue
		}

		str += plug.Id + ","
	}

	return str
}

func checkForUpdates() {
	log.Trace("Checking for updates")

	client := http.Client{Timeout: time.Duration(5 * time.Second)}

	pluginSlugs := getAllExternalPluginSlugs()
	resp, err := client.Get("https://grafana.net/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)

	if err != nil {
		log.Trace("Failed to get plugins repo from grafana.net, %v", err.Error())
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from grafana.net, %v", err.Error())
		return
	}

	gNetPlugins := []GrafanaNetPlugin{}
	err = json.Unmarshal(body, &gNetPlugins)
	if err != nil {
		log.Trace("Failed to unmarshal plugin repo, reading response from grafana.net, %v", err.Error())
		return
	}

	for _, plug := range Plugins {
		for _, gplug := range gNetPlugins {
			if gplug.Slug == plug.Id {
				plug.GrafanaNetVersion = gplug.Version
				plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion
			}
		}
	}

	resp2, err := client.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json")
	if err != nil {
		log.Trace("Failed to get latest.json repo from github: %v", err.Error())
		return
	}

	defer resp2.Body.Close()
	body, err = ioutil.ReadAll(resp2.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from github.com, %v", err.Error())
		return
	}

	var githubLatest GithubLatest
	err = json.Unmarshal(body, &githubLatest)
	if err != nil {
		log.Trace("Failed to unmarshal github latest, reading response from github: %v", err.Error())
		return
	}

	if strings.Contains(setting.BuildVersion, "-") {
		GrafanaLatestVersion = githubLatest.Testing
		GrafanaHasUpdate = !strings.HasPrefix(setting.BuildVersion, githubLatest.Testing)
	} else {
		GrafanaLatestVersion = githubLatest.Stable
		GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion
	}
}
<commit_msg>fix(gnet): remove trailing ,<commit_after>package plugins

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
)

type GrafanaNetPlugin struct {
	Slug    string `json:"slug"`
	Version string `json:"version"`
}

type GithubLatest struct {
	Stable  string `json:"stable"`
	Testing string `json:"testing"`
}

func StartPluginUpdateChecker() {
	if !setting.CheckForUpdates {
		return
	}

	// do one check directly
	go checkForUpdates()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			checkForUpdates()
		}
	}
}

func getAllExternalPluginSlugs() string {
	var result []string
	for _, plug := range Plugins {
		if plug.IsCorePlugin {
			continue
		}

		result = append(result, plug.Id)
	}

	return strings.Join(result, ",")
}

func checkForUpdates() {
	log.Trace("Checking for updates")

	client := http.Client{Timeout: time.Duration(5 * time.Second)}

	pluginSlugs := getAllExternalPluginSlugs()
	resp, err := client.Get("https://grafana.net/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)

	if err != nil {
		log.Trace("Failed to get plugins repo from grafana.net, %v", err.Error())
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from grafana.net, %v", err.Error())
		return
	}

	gNetPlugins := []GrafanaNetPlugin{}
	err = json.Unmarshal(body, &gNetPlugins)
	if err != nil {
		log.Trace("Failed to unmarshal plugin repo, reading response from grafana.net, %v", err.Error())
		return
	}

	for _, plug := range Plugins {
		for _, gplug := range gNetPlugins {
			if gplug.Slug == plug.Id {
				plug.GrafanaNetVersion = gplug.Version
				plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion
			}
		}
	}

	resp2, err := client.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json")
	if err != nil {
		log.Trace("Failed to get latest.json repo from github: %v", err.Error())
		return
	}

	defer resp2.Body.Close()
	body, err = ioutil.ReadAll(resp2.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from github.com, %v", err.Error())
		return
	}

	var githubLatest GithubLatest
	err = json.Unmarshal(body, &githubLatest)
	if err != nil {
		log.Trace("Failed to unmarshal github latest, reading response from github: %v", err.Error())
		return
	}

	if strings.Contains(setting.BuildVersion, "-") {
		GrafanaLatestVersion = githubLatest.Testing
		GrafanaHasUpdate = !strings.HasPrefix(setting.BuildVersion, githubLatest.Testing)
	} else {
		GrafanaLatestVersion = githubLatest.Stable
		GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

import (
	"crypto/tls"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"net"
	"path"
	"strconv"

	"github.com/golang/glog"
	"github.com/pborman/uuid"
	"github.com/spf13/pflag"

	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apiserver/pkg/server"
	utilflag "k8s.io/apiserver/pkg/util/flag"
	certutil "k8s.io/client-go/util/cert"
)

type SecureServingOptions struct {
	BindAddress net.IP
	BindPort    int

	// ServerCert is the TLS cert info for serving secure traffic
	ServerCert GeneratableKeyCert
	// SNICertKeys are named CertKeys for serving secure traffic with SNI support.
	SNICertKeys []utilflag.NamedCertKey
}

type CertKey struct {
	// CertFile is a file containing a PEM-encoded certificate, and possibly the complete certificate chain
	CertFile string
	// KeyFile is a file containing a PEM-encoded private key for the certificate specified by CertFile
	KeyFile string
}

type GeneratableKeyCert struct {
	CertKey CertKey

	// CACertFile is an optional file containing the certificate chain for CertKey.CertFile
	CACertFile string
	// CertDirectory is a directory that will contain the certificates.  If the cert and key aren't specifically set
	// this will be used to derive a match with the "pair-name"
	CertDirectory string
	// PairName is the name which will be used with CertDirectory to make a cert and key names
	// It becomes CertDirector/PairName.crt and CertDirector/PairName.key
	PairName string
}

func NewSecureServingOptions() *SecureServingOptions {
	return &SecureServingOptions{
		BindAddress: net.ParseIP("0.0.0.0"),
		BindPort:    443,
		ServerCert: GeneratableKeyCert{
			PairName:      "apiserver",
			CertDirectory: "apiserver.local.config/certificates",
		},
	}
}

func (s *SecureServingOptions) DefaultExternalAddress() (net.IP, error) {
	return utilnet.ChooseBindAddress(s.BindAddress)
}

func (s *SecureServingOptions) Validate() []error {
	if s == nil {
		return nil
	}

	errors := []error{}

	if s.BindPort < 0 || s.BindPort > 65535 {
		errors = append(errors, fmt.Errorf("--secure-port %v must be between 0 and 65535, inclusive. 0 for turning off secure port.", s.BindPort))
	}

	return errors
}

func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
	if s == nil {
		return
	}

	fs.IPVar(&s.BindAddress, "bind-address", s.BindAddress, ""+
		"The IP address on which to listen for the --secure-port port. The "+
		"associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+
		"clients. If blank, all interfaces will be used (0.0.0.0).")

	fs.IntVar(&s.BindPort, "secure-port", s.BindPort, ""+
		"The port on which to serve HTTPS with authentication and authorization. If 0, "+
		"don't serve HTTPS at all.")

	fs.StringVar(&s.ServerCert.CertDirectory, "cert-dir", s.ServerCert.CertDirectory, ""+
		"The directory where the TLS certs are located. "+
		"If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored.")

	fs.StringVar(&s.ServerCert.CertKey.CertFile, "tls-cert-file", s.ServerCert.CertKey.CertFile, ""+
		"File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated "+
		"after server cert). If HTTPS serving is enabled, and --tls-cert-file and "+
		"--tls-private-key-file are not provided, a self-signed certificate and key "+
		"are generated for the public address and saved to /var/run/kubernetes.")

	fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile,
		"File containing the default x509 private key matching --tls-cert-file.")

	fs.StringVar(&s.ServerCert.CACertFile, "tls-ca-file", s.ServerCert.CACertFile, "If set, this "+
		"certificate authority will used for secure access from Admission "+
		"Controllers. This must be a valid PEM-encoded CA bundle. Altneratively, the certificate authority "+
		"can be appended to the certificate provided by --tls-cert-file.")

	fs.Var(utilflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+
		"A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+
		"domain patterns which are fully qualified domain names, possibly with prefixed wildcard "+
		"segments. If no domain patterns are provided, the names of the certificate are "+
		"extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns "+
		"trump over extracted names. For multiple key/certificate pairs, use the "+
		"--tls-sni-cert-key multiple times. "+
		"Examples: \"example.crt,example.key\" or \"foo.crt,foo.key:*.foo.com,foo.com\".")
}

func (s *SecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) {
	fs.IPVar(&s.BindAddress, "public-address-override", s.BindAddress,
		"DEPRECATED: see --bind-address instead.")
	fs.MarkDeprecated("public-address-override", "see --bind-address instead.")
}

// ApplyTo fills up serving information in the server configuration.
func (s *SecureServingOptions) ApplyTo(c *server.Config) error {
	if s == nil {
		return nil
	}

	if s.BindPort <= 0 {
		return nil
	}
	if err := s.applyServingInfoTo(c); err != nil {
		return err
	}

	// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
	// let the server return it when the loopback client connects.
	certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
	if err != nil {
		return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
	}
	tlsCert, err := tls.X509KeyPair(certPem, keyPem)
	if err != nil {
		return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
	}

	secureLoopbackClientConfig, err := c.SecureServingInfo.NewLoopbackClientConfig(uuid.NewRandom().String(), certPem)
	switch {
	// if we failed and there's no fallback loopback client config, we need to fail
	case err != nil && c.LoopbackClientConfig == nil:
		return err

	// if we failed, but we already have a fallback loopback client config (usually insecure), allow it
	case err != nil && c.LoopbackClientConfig != nil:

	default:
		c.LoopbackClientConfig = secureLoopbackClientConfig
		c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
	}

	return nil
}

func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error {
	if s.BindPort <= 0 {
		return nil
	}

	secureServingInfo := &server.SecureServingInfo{
		BindAddress: net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort)),
	}

	serverCertFile, serverKeyFile := s.ServerCert.CertKey.CertFile, s.ServerCert.CertKey.KeyFile

	// load main cert
	if len(serverCertFile) != 0 || len(serverKeyFile) != 0 {
		tlsCert, err := tls.LoadX509KeyPair(serverCertFile, serverKeyFile)
		if err != nil {
			return fmt.Errorf("unable to load server certificate: %v", err)
		}
		secureServingInfo.Cert = &tlsCert
	}

	// optionally load CA cert
	if len(s.ServerCert.CACertFile) != 0 {
		pemData, err := ioutil.ReadFile(s.ServerCert.CACertFile)
		if err != nil {
			return fmt.Errorf("failed to read certificate authority from %q: %v", s.ServerCert.CACertFile, err)
		}
		block, pemData := pem.Decode(pemData)
		if block == nil {
			return fmt.Errorf("no certificate found in certificate authority file %q", s.ServerCert.CACertFile)
		}
		if block.Type != "CERTIFICATE" {
			return fmt.Errorf("expected CERTIFICATE block in certiticate authority file %q, found: %s", s.ServerCert.CACertFile, block.Type)
		}
		secureServingInfo.CACert = &tls.Certificate{
			Certificate: [][]byte{block.Bytes},
		}
	}

	// load SNI certs
	namedTLSCerts := make([]server.NamedTLSCert, 0, len(s.SNICertKeys))
	for _, nck := range s.SNICertKeys {
		tlsCert, err := tls.LoadX509KeyPair(nck.CertFile, nck.KeyFile)
		namedTLSCerts = append(namedTLSCerts, server.NamedTLSCert{
			TLSCert: tlsCert,
			Names:   nck.Names,
		})
		if err != nil {
			return fmt.Errorf("failed to load SNI cert and key: %v", err)
		}
	}
	var err error
	secureServingInfo.SNICerts, err = server.GetNamedCertificateMap(namedTLSCerts)
	if err != nil {
		return err
	}

	c.SecureServingInfo = secureServingInfo
	c.ReadWritePort = s.BindPort

	return nil
}

func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress string, alternateDNS []string, alternateIPs []net.IP) error {
	if s == nil {
		return nil
	}
	keyCert := &s.ServerCert.CertKey
	if s.BindPort == 0 || len(keyCert.CertFile) != 0 || len(keyCert.KeyFile) != 0 {
		return nil
	}

	keyCert.CertFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".crt")
	keyCert.KeyFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".key")

	canReadCertAndKey, err := certutil.CanReadCertAndKey(keyCert.CertFile, keyCert.KeyFile)
	if err != nil {
		return err
	}
	if !canReadCertAndKey {
		// add either the bind address or localhost to the valid alternates
		bindIP := s.BindAddress.String()
		if bindIP == "0.0.0.0" {
			alternateDNS = append(alternateDNS, "localhost")
		} else {
			alternateIPs = append(alternateIPs, s.BindAddress)
		}

		if cert, key, err := certutil.GenerateSelfSignedCertKey(publicAddress, alternateIPs, alternateDNS); err != nil {
			return fmt.Errorf("unable to generate self signed cert: %v", err)
		} else {
			if err := certutil.WriteCert(keyCert.CertFile, cert); err != nil {
				return err
			}

			if err := certutil.WriteKey(keyCert.KeyFile, key); err != nil {
				return err
			}
			glog.Infof("Generated self-signed cert (%s, %s)", keyCert.CertFile, keyCert.KeyFile)
		}
	}

	return nil
}
<commit_msg>Fix apiserver help message<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package options

import (
	"crypto/tls"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"net"
	"path"
	"strconv"

	"github.com/golang/glog"
	"github.com/pborman/uuid"
	"github.com/spf13/pflag"

	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apiserver/pkg/server"
	utilflag "k8s.io/apiserver/pkg/util/flag"
	certutil "k8s.io/client-go/util/cert"
)

type SecureServingOptions struct {
	BindAddress net.IP
	BindPort    int

	// ServerCert is the TLS cert info for serving secure traffic
	ServerCert GeneratableKeyCert
	// SNICertKeys are named CertKeys for serving secure traffic with SNI support.
	SNICertKeys []utilflag.NamedCertKey
}

type CertKey struct {
	// CertFile is a file containing a PEM-encoded certificate, and possibly the complete certificate chain
	CertFile string
	// KeyFile is a file containing a PEM-encoded private key for the certificate specified by CertFile
	KeyFile string
}

type GeneratableKeyCert struct {
	CertKey CertKey

	// CACertFile is an optional file containing the certificate chain for CertKey.CertFile
	CACertFile string
	// CertDirectory is a directory that will contain the certificates.  If the cert and key aren't specifically set
	// this will be used to derive a match with the "pair-name"
	CertDirectory string
	// PairName is the name which will be used with CertDirectory to make a cert and key names
	// It becomes CertDirector/PairName.crt and CertDirector/PairName.key
	PairName string
}

func NewSecureServingOptions() *SecureServingOptions {
	return &SecureServingOptions{
		BindAddress: net.ParseIP("0.0.0.0"),
		BindPort:    443,
		ServerCert: GeneratableKeyCert{
			PairName:      "apiserver",
			CertDirectory: "apiserver.local.config/certificates",
		},
	}
}

func (s *SecureServingOptions) DefaultExternalAddress() (net.IP, error) {
	return utilnet.ChooseBindAddress(s.BindAddress)
}

func (s *SecureServingOptions) Validate() []error {
	if s == nil {
		return nil
	}

	errors := []error{}

	if s.BindPort < 0 || s.BindPort > 65535 {
		errors = append(errors, fmt.Errorf("--secure-port %v must be between 0 and 65535, inclusive. 0 for turning off secure port.", s.BindPort))
	}

	return errors
}

func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
	if s == nil {
		return
	}

	fs.IPVar(&s.BindAddress, "bind-address", s.BindAddress, ""+
		"The IP address on which to listen for the --secure-port port. The "+
		"associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+
		"clients. If blank, all interfaces will be used (0.0.0.0).")

	fs.IntVar(&s.BindPort, "secure-port", s.BindPort, ""+
		"The port on which to serve HTTPS with authentication and authorization. If 0, "+
		"don't serve HTTPS at all.")

	fs.StringVar(&s.ServerCert.CertDirectory, "cert-dir", s.ServerCert.CertDirectory, ""+
		"The directory where the TLS certs are located. "+
		"If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored.")

	fs.StringVar(&s.ServerCert.CertKey.CertFile, "tls-cert-file", s.ServerCert.CertKey.CertFile, ""+
		"File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated "+
		"after server cert). If HTTPS serving is enabled, and --tls-cert-file and "+
		"--tls-private-key-file are not provided, a self-signed certificate and key "+
		"are generated for the public address and saved to the directory specified by --cert-dir.")

	fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile,
		"File containing the default x509 private key matching --tls-cert-file.")

	fs.StringVar(&s.ServerCert.CACertFile, "tls-ca-file", s.ServerCert.CACertFile, "If set, this "+
		"certificate authority will used for secure access from Admission "+
		"Controllers. This must be a valid PEM-encoded CA bundle. Altneratively, the certificate authority "+
		"can be appended to the certificate provided by --tls-cert-file.")

	fs.Var(utilflag.NewNamedCertKeyArray(&s.SNICertKeys), "tls-sni-cert-key", ""+
		"A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+
		"domain patterns which are fully qualified domain names, possibly with prefixed wildcard "+
		"segments. If no domain patterns are provided, the names of the certificate are "+
		"extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns "+
		"trump over extracted names. For multiple key/certificate pairs, use the "+
		"--tls-sni-cert-key multiple times. "+
		"Examples: \"example.crt,example.key\" or \"foo.crt,foo.key:*.foo.com,foo.com\".")
}

func (s *SecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) {
	fs.IPVar(&s.BindAddress, "public-address-override", s.BindAddress,
		"DEPRECATED: see --bind-address instead.")
	fs.MarkDeprecated("public-address-override", "see --bind-address instead.")
}

// ApplyTo fills up serving information in the server configuration.
func (s *SecureServingOptions) ApplyTo(c *server.Config) error {
	if s == nil {
		return nil
	}

	if s.BindPort <= 0 {
		return nil
	}
	if err := s.applyServingInfoTo(c); err != nil {
		return err
	}

	// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
	// let the server return it when the loopback client connects.
	certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
	if err != nil {
		return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
	}
	tlsCert, err := tls.X509KeyPair(certPem, keyPem)
	if err != nil {
		return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
	}

	secureLoopbackClientConfig, err := c.SecureServingInfo.NewLoopbackClientConfig(uuid.NewRandom().String(), certPem)
	switch {
	// if we failed and there's no fallback loopback client config, we need to fail
	case err != nil && c.LoopbackClientConfig == nil:
		return err

	// if we failed, but we already have a fallback loopback client config (usually insecure), allow it
	case err != nil && c.LoopbackClientConfig != nil:

	default:
		c.LoopbackClientConfig = secureLoopbackClientConfig
		c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert
	}

	return nil
}

func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error {
	if s.BindPort <= 0 {
		return nil
	}

	secureServingInfo := &server.SecureServingInfo{
		BindAddress: net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort)),
	}

	serverCertFile, serverKeyFile := s.ServerCert.CertKey.CertFile, s.ServerCert.CertKey.KeyFile

	// load main cert
	if len(serverCertFile) != 0 || len(serverKeyFile) != 0 {
		tlsCert, err := tls.LoadX509KeyPair(serverCertFile, serverKeyFile)
		if err != nil {
			return fmt.Errorf("unable to load server certificate: %v", err)
		}
		secureServingInfo.Cert = &tlsCert
	}

	// optionally load CA cert
	if len(s.ServerCert.CACertFile) != 0 {
		pemData, err := ioutil.ReadFile(s.ServerCert.CACertFile)
		if err != nil {
			return fmt.Errorf("failed to read certificate authority from %q: %v", s.ServerCert.CACertFile, err)
		}
		block, pemData := pem.Decode(pemData)
		if block == nil {
			return fmt.Errorf("no certificate found in certificate authority file %q", s.ServerCert.CACertFile)
		}
		if block.Type != "CERTIFICATE" {
			return fmt.Errorf("expected CERTIFICATE block in certiticate authority file %q, found: %s", s.ServerCert.CACertFile, block.Type)
		}
		secureServingInfo.CACert = &tls.Certificate{
			Certificate: [][]byte{block.Bytes},
		}
	}

	// load SNI certs
	namedTLSCerts := make([]server.NamedTLSCert, 0, len(s.SNICertKeys))
	for _, nck := range s.SNICertKeys {
		tlsCert, err := tls.LoadX509KeyPair(nck.CertFile, nck.KeyFile)
		namedTLSCerts = append(namedTLSCerts, server.NamedTLSCert{
			TLSCert: tlsCert,
			Names:   nck.Names,
		})
		if err != nil {
			return fmt.Errorf("failed to load SNI cert and key: %v", err)
		}
	}
	var err error
	secureServingInfo.SNICerts, err = server.GetNamedCertificateMap(namedTLSCerts)
	if err != nil {
		return err
	}

	c.SecureServingInfo = secureServingInfo
	c.ReadWritePort = s.BindPort

	return nil
}

func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress string, alternateDNS []string, alternateIPs []net.IP) error {
	if s == nil {
		return nil
	}
	keyCert := &s.ServerCert.CertKey
	if s.BindPort == 0 || len(keyCert.CertFile) != 0 || len(keyCert.KeyFile) != 0 {
		return nil
	}

	keyCert.CertFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".crt")
	keyCert.KeyFile = path.Join(s.ServerCert.CertDirectory, s.ServerCert.PairName+".key")

	canReadCertAndKey, err := certutil.CanReadCertAndKey(keyCert.CertFile, keyCert.KeyFile)
	if err != nil {
		return err
	}
	if !canReadCertAndKey {
		// add either the bind address or localhost to the valid alternates
		bindIP := s.BindAddress.String()
		if bindIP == "0.0.0.0" {
			alternateDNS = append(alternateDNS, "localhost")
		} else {
			alternateIPs = append(alternateIPs, s.BindAddress)
		}

		if cert, key, err := certutil.GenerateSelfSignedCertKey(publicAddress, alternateIPs, alternateDNS); err != nil {
			return fmt.Errorf("unable to generate self signed cert: %v", err)
		} else {
			if err := certutil.WriteCert(keyCert.CertFile, cert); err != nil {
				return err
			}

			if err := certutil.WriteKey(keyCert.KeyFile, key); err != nil {
				return err
			}
			glog.Infof("Generated self-signed cert (%s, %s)", keyCert.CertFile, keyCert.KeyFile)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package keymutex

import (
	"fmt"
	"github.com/golang/glog"
	"sync"
)

// KeyMutex is a thread-safe interface for acquiring locks on arbitrary strings.
type KeyMutex interface {
	// Acquires a lock associated with the specified ID, creates the lock if one doesn't already exist.
	LockKey(id string)

	// Releases the lock associated with the specified ID.
	// Returns an error if the specified ID doesn't exist.
	UnlockKey(id string) error
}

// Returns a new instance of a key mutex.
func NewKeyMutex() KeyMutex {
	return &keyMutex{
		mutexMap: make(map[string]*sync.Mutex),
	}
}

type keyMutex struct {
	sync.RWMutex
	mutexMap map[string]*sync.Mutex
}

// Acquires a lock associated with the specified ID (creates the lock if one doesn't already exist).
func (km *keyMutex) LockKey(id string) {
	glog.V(5).Infof("LockKey(...) called for id %q\r\n", id)
	mutex := km.getOrCreateLock(id)
	mutex.Lock()
	glog.V(5).Infof("LockKey(...) for id %q completed.\r\n", id)
}

// Releases the lock associated with the specified ID.
// Returns an error if the specified ID doesn't exist.
func (km *keyMutex) UnlockKey(id string) error {
	glog.V(5).Infof("UnlockKey(...) called for id %q\r\n", id)
	km.RLock()
	defer km.RUnlock()
	mutex, exists := km.mutexMap[id]
	if !exists {
		return fmt.Errorf("id %q not found", id)
	}
	glog.V(5).Infof("UnlockKey(...) for id. Mutex found, trying to unlock it. %q\r\n", id)

	mutex.Unlock()
	glog.V(5).Infof("UnlockKey(...) for id %q completed.\r\n", id)
	return nil
}

// Returns lock associated with the specified ID, or creates the lock if one doesn't already exist.
func (km *keyMutex) getOrCreateLock(id string) *sync.Mutex {
	km.Lock()
	defer km.Unlock()

	if _, exists := km.mutexMap[id]; !exists {
		km.mutexMap[id] = &sync.Mutex{}
	}

	return km.mutexMap[id]
}
<commit_msg>Run goimports<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package keymutex

import (
	"fmt"
	"sync"

	"github.com/golang/glog"
)

// KeyMutex is a thread-safe interface for acquiring locks on arbitrary strings.
type KeyMutex interface {
	// Acquires a lock associated with the specified ID, creates the lock if one doesn't already exist.
	LockKey(id string)

	// Releases the lock associated with the specified ID.
	// Returns an error if the specified ID doesn't exist.
	UnlockKey(id string) error
}

// Returns a new instance of a key mutex.
func NewKeyMutex() KeyMutex {
	return &keyMutex{
		mutexMap: make(map[string]*sync.Mutex),
	}
}

type keyMutex struct {
	sync.RWMutex
	mutexMap map[string]*sync.Mutex
}

// Acquires a lock associated with the specified ID (creates the lock if one doesn't already exist).
func (km *keyMutex) LockKey(id string) {
	glog.V(5).Infof("LockKey(...) called for id %q\r\n", id)
	mutex := km.getOrCreateLock(id)
	mutex.Lock()
	glog.V(5).Infof("LockKey(...) for id %q completed.\r\n", id)
}

// Releases the lock associated with the specified ID.
// Returns an error if the specified ID doesn't exist.
func (km *keyMutex) UnlockKey(id string) error {
	glog.V(5).Infof("UnlockKey(...) called for id %q\r\n", id)
	km.RLock()
	defer km.RUnlock()
	mutex, exists := km.mutexMap[id]
	if !exists {
		return fmt.Errorf("id %q not found", id)
	}
	glog.V(5).Infof("UnlockKey(...) for id. Mutex found, trying to unlock it. %q\r\n", id)

	mutex.Unlock()
	glog.V(5).Infof("UnlockKey(...) for id %q completed.\r\n", id)
	return nil
}

// Returns lock associated with the specified ID, or creates the lock if one doesn't already exist.
func (km *keyMutex) getOrCreateLock(id string) *sync.Mutex {
	km.Lock()
	defer km.Unlock()

	if _, exists := km.mutexMap[id]; !exists {
		km.mutexMap[id] = &sync.Mutex{}
	}

	return km.mutexMap[id]
}
<|endoftext|>


<commit_before>package pki

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rsa"
	"fmt"
	"strings"
	"testing"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
)

func buildCertificateWithKeyParams(keyAlgo v1alpha1.KeyAlgorithm, keySize int) *v1alpha1.Certificate {
	return &v1alpha1.Certificate{
		Spec: v1alpha1.CertificateSpec{
			CommonName:   "test",
			DNSNames:     []string{"test.test"},
			KeyAlgorithm: keyAlgo,
			KeySize:      keySize,
		},
	}
}

func ecCurveForKeySize(keySize int) (elliptic.Curve, error) {
	switch keySize {
	case 0, ECCurve256:
		return elliptic.P256(), nil
	case ECCurve384:
		return elliptic.P384(), nil
	case ECCurve521:
		return elliptic.P521(), nil
	default:
		return nil, fmt.Errorf("unknown ecdsa key size specified: %d", keySize)
	}
}

func TestGeneratePrivateKeyForCertificate(t *testing.T) {
	type testT struct {
		name         string
		keyAlgo      v1alpha1.KeyAlgorithm
		keySize      int
		expectErr    bool
		expectErrStr string
	}

	tests := []testT{
		{
			name:         "rsa key with weak keysize (< 2048)",
			keyAlgo:      v1alpha1.RSAKeyAlgorithm,
			keySize:      1024,
			expectErr:    true,
			expectErrStr: "weak rsa key size specified",
		},
		{
			name:         "rsa key with too big keysize (> 8192)",
			keyAlgo:      v1alpha1.RSAKeyAlgorithm,
			keySize:      8196,
			expectErr:    true,
			expectErrStr: "rsa key size specified too big",
		},
		{
			name:         "ecdsa key with unsupported keysize",
			keyAlgo:      v1alpha1.ECDSAKeyAlgorithm,
			keySize:      100,
			expectErr:    true,
			expectErrStr: "unsupported ecdsa key size specified",
		},
		{
			name:         "unsupported key algo specified",
			keyAlgo:      v1alpha1.KeyAlgorithm("blahblah"),
			keySize:      256,
			expectErr:    true,
			expectErrStr: "unsupported private key algorithm specified",
		},
		{
			name:      "rsa key with keysize 2048",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			keySize:   2048,
			expectErr: false,
		},
		{
			name:      "rsa key with keysize 4096",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			keySize:   4096,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 256",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   256,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 384",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   384,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 521",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   521,
			expectErr: false,
		},
		{
			name:      "valid key size with key algorithm not specified",
			keyAlgo:   v1alpha1.KeyAlgorithm(""),
			keySize:   2048,
			expectErr: false,
		},
		{
			name:      "rsa with keysize not specified",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			expectErr: false,
		},
		{
			name:      "ecdsa with keysize not specified",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			expectErr: false,
		},
	}

	testFn := func(test testT) func(*testing.T) {
		return func(t *testing.T) {
			privateKey, err := GeneratePrivateKeyForCertificate(buildCertificateWithKeyParams(test.keyAlgo, test.keySize))
			if test.expectErr {
				if err == nil {
					t.Error("expected err, but got no error")
					return
				}

				if !strings.Contains(err.Error(), test.expectErrStr) {
					t.Errorf("expected err string to match: '%s', got: '%s'", test.expectErrStr, err.Error())
					return
				}
			}

			if !test.expectErr {
				if err != nil {
					t.Errorf("expected no err, but got '%q'", err)
					return
				}

				if test.keyAlgo == "rsa" {
					// For rsa algorithm, if keysize is not provided, the default of 2048 will be used
					expectedRsaKeySize := 2048
					if test.keySize != 0 {
						expectedRsaKeySize = test.keySize
					}

					key, ok := privateKey.(*rsa.PrivateKey)
					if !ok {
						t.Errorf("expected rsa private key, but got %T", privateKey)
						return
					}

					actualKeySize := key.N.BitLen()
					if expectedRsaKeySize != actualKeySize {
						t.Errorf("expected %d, but got %d", expectedRsaKeySize, actualKeySize)
						return
					}
				}

				if test.keyAlgo == "ecdsa" {
					// For ecdsa algorithm, if keysize is not provided, the default of 256 will be used
					expectedEcdsaKeySize := ECCurve256
					if test.keySize != 0 {
						expectedEcdsaKeySize = test.keySize
					}

					key, ok := privateKey.(*ecdsa.PrivateKey)
					if !ok {
						t.Errorf("expected ecdsa private key, but got %T", privateKey)
						return
					}

					actualKeySize := key.Curve.Params().BitSize
					if expectedEcdsaKeySize != actualKeySize {
						t.Errorf("expected %d but got %d", expectedEcdsaKeySize, actualKeySize)
						return
					}

					curve, err := ecCurveForKeySize(test.keySize)
					if err != nil {
						t.Errorf(err.Error())
						return
					}

					if !curve.IsOnCurve(key.PublicKey.X, key.PublicKey.Y) {
						t.Error("expected key to be on specified curve")
						return
					}
				}
			}
		}
	}

	for _, test := range tests {
		t.Run(test.name, testFn(test))
	}
}
<commit_msg>Add unit test for PublicKeyMatchesCertificate<commit_after>package pki

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"fmt"
	"strings"
	"testing"
	"time"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
)

func buildCertificateWithKeyParams(keyAlgo v1alpha1.KeyAlgorithm, keySize int) *v1alpha1.Certificate {
	return &v1alpha1.Certificate{
		Spec: v1alpha1.CertificateSpec{
			CommonName:   "test",
			DNSNames:     []string{"test.test"},
			KeyAlgorithm: keyAlgo,
			KeySize:      keySize,
		},
	}
}

func ecCurveForKeySize(keySize int) (elliptic.Curve, error) {
	switch keySize {
	case 0, ECCurve256:
		return elliptic.P256(), nil
	case ECCurve384:
		return elliptic.P384(), nil
	case ECCurve521:
		return elliptic.P521(), nil
	default:
		return nil, fmt.Errorf("unknown ecdsa key size specified: %d", keySize)
	}
}

func TestGeneratePrivateKeyForCertificate(t *testing.T) {
	type testT struct {
		name         string
		keyAlgo      v1alpha1.KeyAlgorithm
		keySize      int
		expectErr    bool
		expectErrStr string
	}

	tests := []testT{
		{
			name:         "rsa key with weak keysize (< 2048)",
			keyAlgo:      v1alpha1.RSAKeyAlgorithm,
			keySize:      1024,
			expectErr:    true,
			expectErrStr: "weak rsa key size specified",
		},
		{
			name:         "rsa key with too big keysize (> 8192)",
			keyAlgo:      v1alpha1.RSAKeyAlgorithm,
			keySize:      8196,
			expectErr:    true,
			expectErrStr: "rsa key size specified too big",
		},
		{
			name:         "ecdsa key with unsupported keysize",
			keyAlgo:      v1alpha1.ECDSAKeyAlgorithm,
			keySize:      100,
			expectErr:    true,
			expectErrStr: "unsupported ecdsa key size specified",
		},
		{
			name:         "unsupported key algo specified",
			keyAlgo:      v1alpha1.KeyAlgorithm("blahblah"),
			keySize:      256,
			expectErr:    true,
			expectErrStr: "unsupported private key algorithm specified",
		},
		{
			name:      "rsa key with keysize 2048",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			keySize:   2048,
			expectErr: false,
		},
		{
			name:      "rsa key with keysize 4096",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			keySize:   4096,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 256",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   256,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 384",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   384,
			expectErr: false,
		},
		{
			name:      "ecdsa key with keysize 521",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			keySize:   521,
			expectErr: false,
		},
		{
			name:      "valid key size with key algorithm not specified",
			keyAlgo:   v1alpha1.KeyAlgorithm(""),
			keySize:   2048,
			expectErr: false,
		},
		{
			name:      "rsa with keysize not specified",
			keyAlgo:   v1alpha1.RSAKeyAlgorithm,
			expectErr: false,
		},
		{
			name:      "ecdsa with keysize not specified",
			keyAlgo:   v1alpha1.ECDSAKeyAlgorithm,
			expectErr: false,
		},
	}

	testFn := func(test testT) func(*testing.T) {
		return func(t *testing.T) {
			privateKey, err := GeneratePrivateKeyForCertificate(buildCertificateWithKeyParams(test.keyAlgo, test.keySize))
			if test.expectErr {
				if err == nil {
					t.Error("expected err, but got no error")
					return
				}

				if !strings.Contains(err.Error(), test.expectErrStr) {
					t.Errorf("expected err string to match: '%s', got: '%s'", test.expectErrStr, err.Error())
					return
				}
			}

			if !test.expectErr {
				if err != nil {
					t.Errorf("expected no err, but got '%q'", err)
					return
				}

				if test.keyAlgo == "rsa" {
					// For rsa algorithm, if keysize is not provided, the default of 2048 will be used
					expectedRsaKeySize := 2048
					if test.keySize != 0 {
						expectedRsaKeySize = test.keySize
					}

					key, ok := privateKey.(*rsa.PrivateKey)
					if !ok {
						t.Errorf("expected rsa private key, but got %T", privateKey)
						return
					}

					actualKeySize := key.N.BitLen()
					if expectedRsaKeySize != actualKeySize {
						t.Errorf("expected %d, but got %d", expectedRsaKeySize, actualKeySize)
						return
					}
				}

				if test.keyAlgo == "ecdsa" {
					// For ecdsa algorithm, if keysize is not provided, the default of 256 will be used
					expectedEcdsaKeySize := ECCurve256
					if test.keySize != 0 {
						expectedEcdsaKeySize = test.keySize
					}

					key, ok := privateKey.(*ecdsa.PrivateKey)
					if !ok {
						t.Errorf("expected ecdsa private key, but got %T", privateKey)
						return
					}

					actualKeySize := key.Curve.Params().BitSize
					if expectedEcdsaKeySize != actualKeySize {
						t.Errorf("expected %d but got %d", expectedEcdsaKeySize, actualKeySize)
						return
					}

					curve, err := ecCurveForKeySize(test.keySize)
					if err != nil {
						t.Errorf(err.Error())
						return
					}

					if !curve.IsOnCurve(key.PublicKey.X, key.PublicKey.Y) {
						t.Error("expected key to be on specified curve")
						return
					}
				}
			}
		}
	}

	for _, test := range tests {
		t.Run(test.name, testFn(test))
	}
}

func signTestCert(key crypto.Signer) *x509.Certificate {
	commonName := "testingcert"

	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		panic(fmt.Errorf("failed to generate serial number: %s", err.Error()))
	}

	template := &x509.Certificate{
		Version:               3,
		BasicConstraintsValid: true,
		SerialNumber:          serialNumber,
		SignatureAlgorithm:    x509.SHA256WithRSA,
		Subject: pkix.Name{
			Organization: []string{defaultOrganization},
			CommonName:   commonName,
		},
		NotBefore: time.Now(),
		NotAfter:  time.Now().Add(defaultNotAfter),
		// see http://golang.org/pkg/crypto/x509/#KeyUsage
		KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
	}

	_, crt, err := SignCertificate(template, template, key.Public(), key)
	if err != nil {
		panic(fmt.Errorf("error signing test cert: %v", err))
	}

	return crt
}

func TestPublicKeyMatchesCertificate(t *testing.T) {
	privKey1, err := GenerateRSAPrivateKey(2048)
	if err != nil {
		t.Errorf("error generating private key: %v", err)
	}
	privKey2, err := GenerateRSAPrivateKey(2048)
	if err != nil {
		t.Errorf("error generating private key: %v", err)
	}

	testCert1 := signTestCert(privKey1)
	testCert2 := signTestCert(privKey2)

	matches, err := PublicKeyMatchesCertificate(privKey1.Public(), testCert1)
	if err != nil {
		t.Errorf("expected no error, but got: %v", err)
	}
	if !matches {
		t.Errorf("expected private key to match certificate, but it did not")
	}

	matches, err = PublicKeyMatchesCertificate(privKey1.Public(), testCert2)
	if err != nil {
		t.Errorf("expected no error, but got: %v", err)
	}
	if matches {
		t.Errorf("expected private key to not match certificate, but it did")
	}
}
<|endoftext|>