<commit_before>package main

import "math/rand"
import "time"
import "fmt"
import "strings"
import "flag"

var players []*Player
var debug bool
var singleRound bool

func main() {
	rand.Seed(time.Now().Unix())

	flag.BoolVar(&debug, "v", false, "Provide more verbose output for debugging purposes")
	flag.BoolVar(&singleRound, "s", false, "Stop after running only a single round of the game")
	flag.Parse()

	players = make([]*Player, flag.NArg())
	var startPlayer = 0

	var deck = new(Deck)

	for i, _ := range players {
			players[i] = new(Player)
	}

	for won, _ := PlayerWon(); !won; won, _ = PlayerWon() {
		deck.Init()
		for i, _ := range players {
			players[i].Init(flag.Arg(i), i, len(players), startPlayer)
			cardDrawn := deck.Draw()
			players[i].Send("draw", cardDrawn)
			players[i].AddToHand(cardDrawn)
			Debug("*** Player", i, "drew", cardDrawn, "***")
			Debug("*** Player", i, "hand:", players[i].HandString(), "***")
		}

		_ = deck.Draw() //throw away a card to prevent perfect information

		var currentPlayer = startPlayer
		for !deck.IsEmpty() && (SurvivingPlayers() > 1) {
			var fullMove, action, cardStr, queryStr string
			var target, n  int
			var card, cardDrawn Card

			if players[currentPlayer].lost {
				goto endTurn
			}

			SendAll("player", currentPlayer)

			cardDrawn = deck.Draw()
			players[currentPlayer].Send("draw", cardDrawn)
			players[currentPlayer].AddToHand(cardDrawn)
			if players[currentPlayer].ministered && (players[currentPlayer].HandValue() >= 12) {
				Out(currentPlayer)
				goto endTurn
			}

			Debug("*** Player", currentPlayer, "drew", cardDrawn, "***")
			Debug("*** Player", currentPlayer, "hand:", players[currentPlayer].HandString(), "***")

			fullMove = players[currentPlayer].Recieve()
			Debug("*** Player", currentPlayer, "move:", fullMove, "***")

			n, _ = fmt.Sscan(fullMove, &action, &cardStr, &target, &queryStr)

			if !strings.EqualFold(action, "play") {
				//must be "forfeit" or some invalid action
				Debug("*** ERROR: Player", currentPlayer, "made an illegal play or forfeited ***")
				Out(currentPlayer)
				goto endTurn
			}

			if n < 2 {
				//malformed move
				Debug("*** ERROR: Player", currentPlayer, "passed too few arguments ***")
				Out(currentPlayer)
				goto endTurn
			}

			card = ParseCard(cardStr)
			if ok := players[currentPlayer].RemoveFromHand(card); !ok {
				//trying to play a card you don't have is illegal
				Debug("*** ERROR: Player", currentPlayer, "played a card they dont have:", card, "***")
				Out(currentPlayer)
				goto endTurn
			}
			Debug("*** Player", currentPlayer, "played", card, "***")
			Debug("*** Player", currentPlayer, "hand:", players[currentPlayer].HandString(), "***")

			//check the right number of arguments has been given
			switch card {
			case Princess, Minister, Priestess:
				if n != 2 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
			case General, Wizard, Knight, Clown:
				if n != 3 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
			case Soldier:
				if n != 4 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
			}

			SendAll("played", currentPlayer, card)
			switch card {
			case Princess:
				Out(currentPlayer)
			case Minister:
				players[currentPlayer].ministered = true
			case General:
			case Wizard:
			case Priestess:
			case Knight:
			case Clown:
			case Soldier:
			default:
			}

		endTurn:
			currentPlayer++
			if currentPlayer >= len(players) {
				currentPlayer = 0
			}
		}
		startPlayer++
		if startPlayer >= len(players) {
			startPlayer = 0
		}

		winningHandValue := 0
		for i, _ := range players {
			if players[i].HandValue() > winningHandValue {
				winningHandValue = players[i].HandValue()
			}
		}
		for i, _ := range players {
			if players[i].HandValue() == winningHandValue {
				players[i].roundsWon++
			}
			players[i].Forfeit()
		}
		fmt.Print("Round ended.\t")
		for i, p := range players {
			fmt.Print("Player ", i, " score: ", p.roundsWon, "\t")
		}
		fmt.Println()

		if singleRound {
			//only running one round so stop now
			return
		}
	}
	_, winner := PlayerWon()
	fmt.Println("Player won:", winner, players[winner].name)
}

func SendAll(args ...interface{}) {
	for _, player := range players {
		if !player.lost {
			player.Send(args...)
		}
	}
}

func SurvivingPlayers() int {
	result := 0
	for _, player := range players {
		if !player.lost {
			result++
		}
	}
	return result
}

func PlayerWon() (bool, int) {
	for i, p := range players {
		if p.roundsWon >= 4 {
			return true, i
		}
	}
	return false, 0
}

func Out(playerNumber int) {
	players[playerNumber].Forfeit()
	SendAll("out", playerNumber, players[playerNumber].HandString())
	Debug("*** Player", playerNumber, "out:", players[playerNumber].HandString(), "***")
}

func Debug(args ...interface{}) {
	if debug {
		fmt.Println(args...)
	}
}<commit_msg>Added check for validity of target and implemented General<commit_after>package main

import "math/rand"
import "time"
import "fmt"
import "strings"
import "flag"

var players []*Player
var debug bool
var singleRound bool

func main() {
	rand.Seed(time.Now().Unix())

	flag.BoolVar(&debug, "v", false, "Provide more verbose output for debugging purposes")
	flag.BoolVar(&singleRound, "s", false, "Stop after running only a single round of the game")
	flag.Parse()

	players = make([]*Player, flag.NArg())
	var startPlayer = 0

	var deck = new(Deck)

	for i, _ := range players {
			players[i] = new(Player)
	}

	for won, _ := PlayerWon(); !won; won, _ = PlayerWon() {
		deck.Init()
		for i, _ := range players {
			players[i].Init(flag.Arg(i), i, len(players), startPlayer)
			cardDrawn := deck.Draw()
			players[i].Send("draw", cardDrawn)
			players[i].AddToHand(cardDrawn)
			Debug("*** Player", i, "drew", cardDrawn, "***")
			Debug("*** Player", i, "hand:", players[i].HandString(), "***")
		}

		_ = deck.Draw() //throw away a card to prevent perfect information

		var currentPlayer = startPlayer
		for !deck.IsEmpty() && (SurvivingPlayers() > 1) {
			var fullMove, action, cardStr, queryStr string
			var target, n  int
			var card, cardDrawn Card

			if players[currentPlayer].lost {
				goto endTurn
			}

			SendAll("player", currentPlayer)

			cardDrawn = deck.Draw()
			players[currentPlayer].Send("draw", cardDrawn)
			players[currentPlayer].AddToHand(cardDrawn)
			if players[currentPlayer].ministered && (players[currentPlayer].HandValue() >= 12) {
				Out(currentPlayer)
				goto endTurn
			}

			Debug("*** Player", currentPlayer, "drew", cardDrawn, "***")
			Debug("*** Player", currentPlayer, "hand:", players[currentPlayer].HandString(), "***")

			fullMove = players[currentPlayer].Recieve()
			Debug("*** Player", currentPlayer, "move:", fullMove, "***")

			n, _ = fmt.Sscan(fullMove, &action, &cardStr, &target, &queryStr)

			if !strings.EqualFold(action, "play") {
				//must be "forfeit" or some invalid action
				Debug("*** ERROR: Player", currentPlayer, "made an illegal play or forfeited ***")
				Out(currentPlayer)
				goto endTurn
			}

			if n < 2 {
				//malformed move
				Debug("*** ERROR: Player", currentPlayer, "passed too few arguments ***")
				Out(currentPlayer)
				goto endTurn
			}

			card = ParseCard(cardStr)
			if ok := players[currentPlayer].RemoveFromHand(card); !ok {
				//trying to play a card you don't have is illegal
				Debug("*** ERROR: Player", currentPlayer, "played a card they dont have:", card, "***")
				Out(currentPlayer)
				goto endTurn
			}
			Debug("*** Player", currentPlayer, "played", card, "***")
			Debug("*** Player", currentPlayer, "hand:", players[currentPlayer].HandString(), "***")

			//check the right arguments have been given
			switch card {
			case Princess, Minister, Priestess:
				if n != 2 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
			case General, Wizard, Knight, Clown:
				if n != 3 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
				if (target >= len(players)) && (target < 0) {
					Debug("*** ERROR: Player", currentPlayer, "passed a bad target argument ***")
					Out(currentPlayer)
					goto endTurn
				}
			case Soldier:
				if n != 4 {
					Debug("*** ERROR: Player", currentPlayer, "passed the wrong number of arguments for the played card ***")
					Out(currentPlayer)
					goto endTurn
				}
				if (target >= len(players)) && (target < 0) {
					Debug("*** ERROR: Player", currentPlayer, "passed a bad target argument ***")
					Out(currentPlayer)
					goto endTurn
				}
			}

			SendAll("played", currentPlayer, card)
			switch card {
			case Princess:
				Out(currentPlayer)
			case Minister:
				players[currentPlayer].ministered = true
			case General:
				players[currentPlayer].Send("swap", players[target].hand[0])
				players[target].Send("swap", players[currentPlayer].hand[0])
				players[currentPlayer].hand[0], players[target].hand[0] = players[target].hand[0], players[currentPlayer].hand[0]
				Debug("*** Player", currentPlayer, "and Player", target, "swapped hands ***")
				Debug("*** Player", currentPlayer, "hand:", players[currentPlayer].HandString(), "***")
				Debug("*** Player", target, "hand:", players[target].HandString(), "***")
			case Wizard:
			case Priestess:
			case Knight:
			case Clown:
			case Soldier:
			default:
			}

		endTurn:
			currentPlayer++
			if currentPlayer >= len(players) {
				currentPlayer = 0
			}
		}
		startPlayer++
		if startPlayer >= len(players) {
			startPlayer = 0
		}

		winningHandValue := 0
		for i, _ := range players {
			if players[i].HandValue() > winningHandValue {
				winningHandValue = players[i].HandValue()
			}
		}
		for i, _ := range players {
			if players[i].HandValue() == winningHandValue {
				players[i].roundsWon++
			}
			players[i].Forfeit()
		}
		fmt.Print("Round ended.\t")
		for i, p := range players {
			fmt.Print("Player ", i, " score: ", p.roundsWon, "\t")
		}
		fmt.Println()

		if singleRound {
			//only running one round so stop now
			return
		}
	}
	_, winner := PlayerWon()
	fmt.Println("Player won:", winner, players[winner].name)
}

func SendAll(args ...interface{}) {
	for _, player := range players {
		if !player.lost {
			player.Send(args...)
		}
	}
}

func SurvivingPlayers() int {
	result := 0
	for _, player := range players {
		if !player.lost {
			result++
		}
	}
	return result
}

func PlayerWon() (bool, int) {
	for i, p := range players {
		if p.roundsWon >= 4 {
			return true, i
		}
	}
	return false, 0
}

func Out(playerNumber int) {
	players[playerNumber].Forfeit()
	SendAll("out", playerNumber, players[playerNumber].HandString())
	Debug("*** Player", playerNumber, "out:", players[playerNumber].HandString(), "***")
}

func Debug(args ...interface{}) {
	if debug {
		fmt.Println(args...)
	}
}<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
)

type CommitStatusParams struct {
	State       string `json:"state"`
	TargetUrl   string `json:"target_url"`
	Description string `json:"description"`
	Context     string `json:"context"`
}

func commitStatusURL(orgRepo string, sha string) string {
	return "https://api.github.com/repos/" + orgRepo + "/statuses/" + sha
}

func setGithubCommitStatus(url string, username string, password string, params *CommitStatusParams) {
	requestBody, err := json.Marshal(params)
	if err != nil {
		log.Fatalf("Error converting %q to json %s.", params, err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewReader(requestBody))
	req.SetBasicAuth(username, password)

	client := &http.Client{}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Error executing request to Github: %s", err)
	}

	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Error reading response body: %q %s", resp.Body, err)
	}

	if resp.StatusCode != http.StatusCreated {
		log.Fatalf("Error creating commit status on Github.\nPOST %s\nAuth: '%s:%s'\nParams: %s\nResponse Body: %s",
			url, username, password, requestBody, responseBody)
	}
}

func main() {
	orgRepo := flag.String("r", "", "Github repository in the form of organization/repository, e.g google/cadvisor")
	sha := flag.String("s", "", "Github commit status SHA")
	context := flag.String("c", "", "Github commit status context")
	description := flag.String("d", "", "Github commit status description")
	targetUrl := flag.String("t", "", "Github commit status target_url")
	username := flag.String("u", "", "Github username")
	password := flag.String("p", "", "Github password or token for basic auth")

	flag.Parse()

	if *username == "" || *password == "" {
		log.Fatalf("Error: no username or password provided")
	}

	var cmd string
	var args []string

	if flag.NArg() > 0 {
		cmd = flag.Args()[0]
		args = flag.Args()[1:]
	} else {
		log.Fatalf("Error: no command given")
	}

	url := commitStatusURL(*orgRepo, *sha)
	params := &CommitStatusParams{
		State:       "pending",
		TargetUrl:   *targetUrl,
		Description: *description,
		Context:     *context,
	}

	subprocess := exec.Command(cmd, args...)
	subprocess.Stdin, subprocess.Stdout, subprocess.Stderr = os.Stdin, os.Stdout, os.Stderr

	setGithubCommitStatus(url, *username, *password, params)

	err := subprocess.Run()

	if err == nil {
		params.State = "success"
		setGithubCommitStatus(url, *username, *password, params)
		os.Exit(0)
	}

	if err.Error() != "0" {
		params.State = "failure"
		setGithubCommitStatus(url, *username, *password, params)
		os.Exit(1)
	}

	if err != nil {
		params.State = "error"
		setGithubCommitStatus(url, *username, *password, params)
		log.Fatalf("Error: executing command %s with args %q: %s", cmd, args, err)
	}
}
<commit_msg>Refactor and validate flags<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
)

type CommitStatusParams struct {
	State       string `json:"state"`
	TargetUrl   string `json:"target_url"`
	Description string `json:"description"`
	Context     string `json:"context"`
}

type Flags struct {
	OrgRepo     *string
	SHA         *string
	Context     *string
	Description *string
	TargetUrl   *string
	Username    *string
	Password    *string
}

func commitStatusURL(orgRepo string, sha string) string {
	return "https://api.github.com/repos/" + orgRepo + "/statuses/" + sha
}

func validateRequiredFlags(flags Flags) {
	errors := false

	if *flags.Username == "" || *flags.Password == "" {
		fmt.Println("Error: No username and password provided")
		errors = true
	}

	if *flags.OrgRepo == "" {
		fmt.Println("Error: No Github organization/repository provided")
		errors = true
	}

	if *flags.Context == "" {
		fmt.Println("Error: No SHA provided")
		errors = true
	}

	if *flags.Context == "" {
		fmt.Println("Error: No Github commit status context provided")
		errors = true
	}

	if errors {
		flag.Usage()
		os.Exit(1)
	}
}

func setGithubCommitStatus(url string, flags Flags, state string) {
	params := &CommitStatusParams{
		State:       state,
		TargetUrl:   *flags.TargetUrl,
		Description: *flags.Description,
		Context:     *flags.Context,
	}

	requestBody, err := json.Marshal(params)
	if err != nil {
		log.Fatalf("Error converting %q to json %s.", params, err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewReader(requestBody))
	req.SetBasicAuth(*flags.Username, *flags.Password)

	client := &http.Client{}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Error executing request to Github: %s", err)
	}

	responseBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Error reading response body: %q %s", resp.Body, err)
	}

	if resp.StatusCode != http.StatusCreated {
		log.Fatalf("Error creating commit status on Github.\nPOST %s\nAuth: '%s:%s'\nParams: %s\nResponse Body: %s",
			url, *flags.Username, *flags.Password, requestBody, responseBody)
	}
}

func main() {
	flags := &Flags{
		OrgRepo:     flag.String("r", "", "Required: Github repository in the form of organization/repository, e.g google/cadvisor"),
		SHA:         flag.String("s", "", "Required: Github commit status SHA"),
		Context:     flag.String("c", "", "Required: Github commit status context"),
		Description: flag.String("d", "", "Optional: Github commit status description"),
		TargetUrl:   flag.String("t", "", "Optional: Github commit status target_url"),
		Username:    flag.String("u", "", "Required: Github username"),
		Password:    flag.String("p", "", "Required: Github password or token for basic auth"),
	}

	flag.Parse()

	validateRequiredFlags(*flags)

	var cmd string
	var args []string

	if flag.NArg() > 0 {
		cmd = flag.Args()[0]
		args = flag.Args()[1:]
	} else {
		log.Fatalf("Error: no command given")
	}

	url := commitStatusURL(*flags.OrgRepo, *flags.SHA)

	subprocess := exec.Command(cmd, args...)
	subprocess.Stdin, subprocess.Stdout, subprocess.Stderr = os.Stdin, os.Stdout, os.Stderr

	setGithubCommitStatus(url, *flags, "pending")

	err := subprocess.Run()

	if err == nil {
		setGithubCommitStatus(url, *flags, "success")
		os.Exit(0)
	}

	if err.Error() != "0" {
		setGithubCommitStatus(url, *flags, "failure")
		os.Exit(1)
	}

	if err != nil {
		setGithubCommitStatus(url, *flags, "error")
		log.Fatalf("Error: executing command %s with args %q: %s", cmd, args, err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"
)

func main() {
	cu := NewControlUnit(64, 16, 32)
	fmt.Println("You made a vector VM with " + strconv.Itoa(len(cu.PE)) + " processing elements.") //debug
	n := 3
	a := createMatrix(n)
	b := createMatrix(n)
	//	c := createMatrix()
	offset := int64(0)
	loadMatrix(cu, a, offset)
	offset += int64(len(a)) // row length
	loadMatrix(cu, b, offset)

	fmt.Println("main() Start State")
	cu.PrintMachine()
	fmt.Println("main() Multiplying...\n")
	matrixMultiply(cu, byte(n))
	fmt.Println("main() Final State")
	cu.PrintMachine()

	//	program := addInstruction(nil, isMov, []byte{4, 9, 15})
}

func createMatrix(n int) [][]int64 {
	matrix := make([][]int64, n, n)
	for i, _ := range matrix {
		matrix[i] = make([]int64, n, n)
		for j, _ := range matrix[i] {
			matrix[i][j] = int64(j + 2)
		}
	}
	return matrix
}

func printMatrix(matrix [][]int64) {

	for i, row := range matrix {
		if i == 0 {
			fmt.Printf("⎡")
		} else if i == len(matrix)-1 {
			fmt.Printf("⎣")
		} else {
			fmt.Printf("⎢")
		}

		for _, col := range row {
			fmt.Printf("%4d ", col)
		}

		if i == 0 {
			fmt.Printf("⎤")
		} else if i == len(matrix)-1 {
			fmt.Printf("⎦")
		} else {
			fmt.Printf("⎥")
		}
		fmt.Printf("\n")
	}
}

/// @todo account for matrices larger than the number of PEs
/// @param offset the memory offset to begin at,
func loadMatrix(cu *ControlUnit, matrix [][]int64, offset int64) {
	for i, _ := range matrix {
		if int64(i)+offset >= int64(len(cu.PE[0].Memory)) { // all PEs have the same amount of memory, so we just grab the first
			break
		}
		for j, _ := range matrix[i] {
			if j >= len(cu.PE) {
				break
			}
			cu.PE[j].Memory[int64(i)+offset] = matrix[i][j]
		}
	}
}

// multiplies matrices of the given dimension, assuming they're stored by-column,
// starting in memory location 0 and consecutive,
// and stores the result in the immediately following memory
//
/// @param n dimension of the matrices
func matrixMultiply(cu *ControlUnit, matrixDimension byte) {
	// indices into the CU Index Register
	lim := byte(1)
	i := byte(2)
	j := byte(3)

	// indices into memory
	a := byte(0)
	b := byte(a + matrixDimension)
	c := byte(b + matrixDimension)

	var pprogram PseudoProgram
	n := pprogram.DataOp(cu, matrixDimension)

	//	zero :=
	pprogram.DataOp(cu, 0)

	program := CreateProgram(pprogram)
	program.Push(isLdxi, []byte{j, 0, 0})

	program.PushMem(isLdx, lim, n)

	labelLoop := program.Size()
	program.Push(isLod, []byte{a, i, 0})
	program.Push(isMov, []byte{peArithmetic, peRouting, 0})
	program.Push(isBcast, []byte{j, 0, 0})
	program.Push(isLod, []byte{b, j, 0})
	program.Push(isRmul, []byte{0, 0, 0})
	program.Push(isAdd, []byte{c, i, 0})
	program.Push(isSto, []byte{c, i, 0})
	program.Push(isIncx, []byte{j, 1, 0})
	program.Push(isCmpx, []byte{j, lim, labelLoop})
	/*

	*/

	fmt.Print("matrixMultiply() Program: ")
	fmt.Println(program)
	fmt.Print("\n")
	cu.Run(program)
}
<commit_msg>added main.go instructions for multiplying every row of the matrix<commit_after>package main

import (
	"fmt"
	"strconv"
)

func main() {
	cu := NewControlUnit(64, 16, 32)
	fmt.Println("You made a vector VM with " + strconv.Itoa(len(cu.PE)) + " processing elements.") //debug
	n := 3
	a := createMatrix(n)
	b := createMatrix(n)
	//	c := createMatrix()
	offset := int64(0)
	loadMatrix(cu, a, offset)
	offset += int64(len(a)) // row length
	loadMatrix(cu, b, offset)

	fmt.Println("main() Start State")
	cu.PrintMachine()
	fmt.Println("main() Multiplying...\n")
	matrixMultiply(cu, byte(n))
	fmt.Println("main() Final State")
	cu.PrintMachine()

	//	program := addInstruction(nil, isMov, []byte{4, 9, 15})
}

func createMatrix(n int) [][]int64 {
	matrix := make([][]int64, n, n)
	for i, _ := range matrix {
		matrix[i] = make([]int64, n, n) // debug +1
//		matrix[i] = make([]int64, n+1, n+1) // debug +1
		for j, _ := range matrix[i] {
			matrix[i][j] = int64(j + 2)
		}
	}
	return matrix
}

func printMatrix(matrix [][]int64) {

	for i, row := range matrix {
		if i == 0 {
			fmt.Printf("⎡")
		} else if i == len(matrix)-1 {
			fmt.Printf("⎣")
		} else {
			fmt.Printf("⎢")
		}

		for _, col := range row {
			fmt.Printf("%4d ", col)
		}

		if i == 0 {
			fmt.Printf("⎤")
		} else if i == len(matrix)-1 {
			fmt.Printf("⎦")
		} else {
			fmt.Printf("⎥")
		}
		fmt.Printf("\n")
	}
}

/// @todo account for matrices larger than the number of PEs
/// @param offset the memory offset to begin at,
func loadMatrix(cu *ControlUnit, matrix [][]int64, offset int64) {
	for i, _ := range matrix {
		if int64(i)+offset >= int64(len(cu.PE[0].Memory)) { // all PEs have the same amount of memory, so we just grab the first
			break
		}
		for j, _ := range matrix[i] {
			if j >= len(cu.PE) {
				break
			}
			cu.PE[j].Memory[int64(i)+offset] = matrix[i][j]
		}
	}
}

// multiplies matrices of the given dimension, assuming they're stored by-column,
// starting in memory location 0 and consecutive,
// and stores the result in the immediately following memory
//
/// @param n dimension of the matrices
func matrixMultiply(cu *ControlUnit, matrixDimension byte) {
	// indices into the CU Index Register
	nextRegister := byte(0)
	lim := nextRegister
	nextRegister++

	i := nextRegister
	nextRegister++

	j := nextRegister
	nextRegister++

	// indices into memory
	a := byte(0)
	b := a + matrixDimension
	c := b + matrixDimension

	var pprogram PseudoProgram
	n := pprogram.DataOp(cu, matrixDimension)

	//	zero :=
	pprogram.DataOp(cu, 0)

	program := CreateProgram(pprogram)
	program.Push(isLdxi, []byte{i, 0, 0})
	program.Push(isLdxi, []byte{j, 0, 0})

	program.PushMem(isLdx, lim, n)

	labelLoop := program.Size()
	program.Push(isLod, []byte{a, i, 0})
	program.Push(isMov, []byte{peArithmetic, peRouting, 0})
	program.Push(isBcast, []byte{j, 0, 0})
	program.Push(isLod, []byte{b, j, 0})
	program.Push(isRmul, []byte{0, 0, 0})
	program.Push(isAdd, []byte{c, i, 0})
	program.Push(isSto, []byte{c, i, 0})
	program.Push(isIncx, []byte{j, 1, 0})
	program.Push(isCmpx, []byte{j, lim, labelLoop})

	program.Push(isLdxi, []byte{j, 0, 0})
	program.Push(isIncx, []byte{i, 1, 0})
	program.Push(isCmpx, []byte{i, lim, labelLoop})

	/*

	*/

	fmt.Print("matrixMultiply() Program: ")
	fmt.Println(program)
	fmt.Print("\n")
	cu.Run(program)
}
<|endoftext|>


<commit_before>package nsq

import (
	"fmt"
	"log"
	"sync"
	"sync/atomic"
	"time"
)

// Producer is a high-level type to publish to NSQ.
//
// A Producer instance is 1:1 with a destination `nsqd`
// and will lazily connect to that instance (and re-connect)
// when Publish commands are executed.
type Producer struct {
	id     int64
	addr   string
	conn   *Conn
	config *Config

	logger *log.Logger
	logLvl LogLevel

	responseChan  chan []byte
	errorChan     chan []byte
	ioErrorChan   chan error
	heartbeatChan chan int
	closeChan     chan int

	transactionChan chan *ProducerTransaction
	transactions    []*ProducerTransaction
	state           int32

	concurrentProducers int32
	stopFlag            int32
	exitChan            chan int
	wg                  sync.WaitGroup
}

// ProducerTransaction is returned by the async publish methods
// to retrieve metadata about the command after the
// response is received.
type ProducerTransaction struct {
	cmd      *Command
	doneChan chan *ProducerTransaction
	Error    error         // the error (or nil) of the publish command
	Args     []interface{} // the slice of variadic arguments passed to PublishAsync or MultiPublishAsync
}

func (t *ProducerTransaction) finish() {
	if t.doneChan != nil {
		t.doneChan <- t
	}
}

// NewProducer returns an instance of Producer for the specified address
func NewProducer(addr string, config *Config) *Producer {
	config.initialize()
	return &Producer{
		id: atomic.AddInt64(&instCount, 1),

		addr:   addr,
		config: config,

		transactionChan: make(chan *ProducerTransaction),
		exitChan:        make(chan int),
		responseChan:    make(chan []byte),
		errorChan:       make(chan []byte),
		ioErrorChan:     make(chan error),
		heartbeatChan:   make(chan int),
		closeChan:       make(chan int),
	}
}

// SetLogger assigns the logger to use as well as a level
func (w *Producer) SetLogger(logger *log.Logger, lvl LogLevel) {
	w.logger = logger
	w.logLvl = lvl
}

// String returns the address of the Producer
func (w *Producer) String() string {
	return w.addr
}

// Stop initiates a graceful stop of the Producer (permanent)
//
// NOTE: receive on StopChan to block until this process completes
func (w *Producer) Stop() {
	if !atomic.CompareAndSwapInt32(&w.stopFlag, 0, 1) {
		return
	}
	close(w.exitChan)
	w.close()
	w.wg.Wait()
}

// PublishAsync publishes a message body to the specified topic
// but does not wait for the response from `nsqd`.
//
// When the Producer eventually receives the response from `nsqd`,
// the supplied `doneChan` (if specified)
// will receive a `ProducerTransaction` instance with the supplied variadic arguments
// (and the response `FrameType`, `Data`, and `Error`)
func (w *Producer) PublishAsync(topic string, body []byte, doneChan chan *ProducerTransaction,
	args ...interface{}) error {
	return w.sendCommandAsync(Publish(topic, body), doneChan, args)
}

// MultiPublishAsync publishes a slice of message bodies to the specified topic
// but does not wait for the response from `nsqd`.
//
// When the Producer eventually receives the response from `nsqd`,
// the supplied `doneChan` (if specified)
// will receive a `ProducerTransaction` instance with the supplied variadic arguments
// (and the response `FrameType`, `Data`, and `Error`)
func (w *Producer) MultiPublishAsync(topic string, body [][]byte, doneChan chan *ProducerTransaction,
	args ...interface{}) error {
	cmd, err := MultiPublish(topic, body)
	if err != nil {
		return err
	}
	return w.sendCommandAsync(cmd, doneChan, args)
}

// Publish synchronously publishes a message body to the specified topic, returning
// the response frameType, data, and error
func (w *Producer) Publish(topic string, body []byte) error {
	return w.sendCommand(Publish(topic, body))
}

// MultiPublish synchronously publishes a slice of message bodies to the specified topic, returning
// the response frameType, data, and error
func (w *Producer) MultiPublish(topic string, body [][]byte) error {
	cmd, err := MultiPublish(topic, body)
	if err != nil {
		return err
	}
	return w.sendCommand(cmd)
}

func (w *Producer) sendCommand(cmd *Command) error {
	doneChan := make(chan *ProducerTransaction)
	err := w.sendCommandAsync(cmd, doneChan, nil)
	if err != nil {
		close(doneChan)
		return err
	}
	t := <-doneChan
	return t.Error
}

func (w *Producer) sendCommandAsync(cmd *Command, doneChan chan *ProducerTransaction,
	args []interface{}) error {
	// keep track of how many outstanding producers we're dealing with
	// in order to later ensure that we clean them all up...
	atomic.AddInt32(&w.concurrentProducers, 1)
	defer atomic.AddInt32(&w.concurrentProducers, -1)

	if atomic.LoadInt32(&w.state) != StateConnected {
		err := w.connect()
		if err != nil {
			return err
		}
	}

	t := &ProducerTransaction{
		cmd:      cmd,
		doneChan: doneChan,
		Args:     args,
	}

	select {
	case w.transactionChan <- t:
	case <-w.exitChan:
		return ErrStopped
	}

	return nil
}

func (w *Producer) connect() error {
	if atomic.LoadInt32(&w.stopFlag) == 1 {
		return ErrStopped
	}

	if !atomic.CompareAndSwapInt32(&w.state, StateInit, StateConnected) {
		return ErrNotConnected
	}

	w.log(LogLevelInfo, "(%s) connecting to nsqd", w.addr)

	conn := NewConn(w.addr, w.config)
	conn.SetLogger(w.logger, w.logLvl, fmt.Sprintf("%3d (%%s)", w.id))
	conn.Delegate = &producerConnDelegate{w}

	_, err := conn.Connect()
	if err != nil {
		conn.Close()
		w.log(LogLevelError, "(%s) error connecting to nsqd - %s", w.addr, err)
		atomic.StoreInt32(&w.state, StateInit)
		return err
	}
	w.conn = conn

	w.wg.Add(1)
	go w.router()

	return nil
}

func (w *Producer) close() {
	if !atomic.CompareAndSwapInt32(&w.state, StateConnected, StateDisconnected) {
		return
	}
	w.conn.Close()
	go func() {
		// we need to handle this in a goroutine so we don't
		// block the caller from making progress
		w.wg.Wait()
		atomic.StoreInt32(&w.state, StateInit)
	}()
}

func (w *Producer) router() {
	for {
		select {
		case t := <-w.transactionChan:
			w.transactions = append(w.transactions, t)
			err := w.conn.WriteCommand(t.cmd)
			if err != nil {
				w.log(LogLevelError, "(%s) sending command - %s", w.conn.String(), err)
				w.close()
			}
		case data := <-w.responseChan:
			w.popTransaction(FrameTypeResponse, data)
		case data := <-w.errorChan:
			w.popTransaction(FrameTypeError, data)
		case <-w.heartbeatChan:
		case <-w.ioErrorChan:
			w.close()
		case <-w.closeChan:
			goto exit
		case <-w.exitChan:
			goto exit
		}
	}

exit:
	w.transactionCleanup()
	w.wg.Done()
	w.log(LogLevelInfo, "exiting router")
}

func (w *Producer) popTransaction(frameType int32, data []byte) {
	t := w.transactions[0]
	w.transactions = w.transactions[1:]
	if frameType == FrameTypeError {
		t.Error = ErrProtocol{string(data)}
	}
	t.finish()
}

func (w *Producer) transactionCleanup() {
	// clean up transactions we can easily account for
	for _, t := range w.transactions {
		t.Error = ErrNotConnected
		t.finish()
	}
	w.transactions = w.transactions[:0]

	// spin and free up any writes that might have raced
	// with the cleanup process (blocked on writing
	// to transactionChan)
	for {
		select {
		case t := <-w.transactionChan:
			t.Error = ErrNotConnected
			t.finish()
		default:
			// keep spinning until there are 0 concurrent producers
			if atomic.LoadInt32(&w.concurrentProducers) == 0 {
				return
			}
			// give the runtime a chance to schedule other racing goroutines
			time.Sleep(5 * time.Millisecond)
			continue
		}
	}
}

func (w *Producer) log(lvl LogLevel, line string, args ...interface{}) {
	var prefix string

	if w.logger == nil {
		return
	}

	if w.logLvl > lvl {
		return
	}

	switch lvl {
	case LogLevelDebug:
		prefix = "DBG"
	case LogLevelInfo:
		prefix = "INF"
	case LogLevelWarning:
		prefix = "WRN"
	case LogLevelError:
		prefix = "ERR"
	}

	w.logger.Printf("%-4s %3d %s", prefix, w.id, fmt.Sprintf(line, args...))
}

func (w *Producer) onConnResponse(c *Conn, data []byte) { w.responseChan <- data }
func (w *Producer) onConnError(c *Conn, data []byte)    { w.errorChan <- data }
func (w *Producer) onConnHeartbeat(c *Conn)             { w.heartbeatChan <- 1 }
func (w *Producer) onConnIOError(c *Conn, err error)    { w.ioErrorChan <- err }
func (w *Producer) onConnClose(c *Conn)                 { w.closeChan <- 1 }
<commit_msg>producer: prevent connect/close race<commit_after>package nsq

import (
	"fmt"
	"log"
	"sync"
	"sync/atomic"
	"time"
)

// Producer is a high-level type to publish to NSQ.
//
// A Producer instance is 1:1 with a destination `nsqd`
// and will lazily connect to that instance (and re-connect)
// when Publish commands are executed.
type Producer struct {
	id     int64
	addr   string
	conn   *Conn
	config *Config

	logger *log.Logger
	logLvl LogLevel

	responseChan  chan []byte
	errorChan     chan []byte
	ioErrorChan   chan error
	heartbeatChan chan int
	closeChan     chan int

	transactionChan chan *ProducerTransaction
	transactions    []*ProducerTransaction
	state           int32

	concurrentProducers int32
	stopFlag            int32
	exitChan            chan int
	wg                  sync.WaitGroup
	guard               sync.Mutex
}

// ProducerTransaction is returned by the async publish methods
// to retrieve metadata about the command after the
// response is received.
type ProducerTransaction struct {
	cmd      *Command
	doneChan chan *ProducerTransaction
	Error    error         // the error (or nil) of the publish command
	Args     []interface{} // the slice of variadic arguments passed to PublishAsync or MultiPublishAsync
}

func (t *ProducerTransaction) finish() {
	if t.doneChan != nil {
		t.doneChan <- t
	}
}

// NewProducer returns an instance of Producer for the specified address
func NewProducer(addr string, config *Config) *Producer {
	config.initialize()
	return &Producer{
		id: atomic.AddInt64(&instCount, 1),

		addr:   addr,
		config: config,

		transactionChan: make(chan *ProducerTransaction),
		exitChan:        make(chan int),
		responseChan:    make(chan []byte),
		errorChan:       make(chan []byte),
		ioErrorChan:     make(chan error),
		heartbeatChan:   make(chan int),
		closeChan:       make(chan int),
	}
}

// SetLogger assigns the logger to use as well as a level
func (w *Producer) SetLogger(logger *log.Logger, lvl LogLevel) {
	w.logger = logger
	w.logLvl = lvl
}

// String returns the address of the Producer
func (w *Producer) String() string {
	return w.addr
}

// Stop initiates a graceful stop of the Producer (permanent)
//
// NOTE: this blocks until completion
func (w *Producer) Stop() {
	w.guard.Lock()
	if !atomic.CompareAndSwapInt32(&w.stopFlag, 0, 1) {
		w.guard.Unlock()
		return
	}
	w.log(LogLevelInfo, "stopping")
	close(w.exitChan)
	w.close()
	w.guard.Unlock()
	w.wg.Wait()
}

// PublishAsync publishes a message body to the specified topic
// but does not wait for the response from `nsqd`.
//
// When the Producer eventually receives the response from `nsqd`,
// the supplied `doneChan` (if specified)
// will receive a `ProducerTransaction` instance with the supplied variadic arguments
// (and the response `FrameType`, `Data`, and `Error`)
func (w *Producer) PublishAsync(topic string, body []byte, doneChan chan *ProducerTransaction,
	args ...interface{}) error {
	return w.sendCommandAsync(Publish(topic, body), doneChan, args)
}

// MultiPublishAsync publishes a slice of message bodies to the specified topic
// but does not wait for the response from `nsqd`.
//
// When the Producer eventually receives the response from `nsqd`,
// the supplied `doneChan` (if specified)
// will receive a `ProducerTransaction` instance with the supplied variadic arguments
// (and the response `FrameType`, `Data`, and `Error`)
func (w *Producer) MultiPublishAsync(topic string, body [][]byte, doneChan chan *ProducerTransaction,
	args ...interface{}) error {
	cmd, err := MultiPublish(topic, body)
	if err != nil {
		return err
	}
	return w.sendCommandAsync(cmd, doneChan, args)
}

// Publish synchronously publishes a message body to the specified topic, returning
// the response frameType, data, and error
func (w *Producer) Publish(topic string, body []byte) error {
	return w.sendCommand(Publish(topic, body))
}

// MultiPublish synchronously publishes a slice of message bodies to the specified topic, returning
// the response frameType, data, and error
func (w *Producer) MultiPublish(topic string, body [][]byte) error {
	cmd, err := MultiPublish(topic, body)
	if err != nil {
		return err
	}
	return w.sendCommand(cmd)
}

func (w *Producer) sendCommand(cmd *Command) error {
	doneChan := make(chan *ProducerTransaction)
	err := w.sendCommandAsync(cmd, doneChan, nil)
	if err != nil {
		close(doneChan)
		return err
	}
	t := <-doneChan
	return t.Error
}

func (w *Producer) sendCommandAsync(cmd *Command, doneChan chan *ProducerTransaction,
	args []interface{}) error {
	// keep track of how many outstanding producers we're dealing with
	// in order to later ensure that we clean them all up...
	atomic.AddInt32(&w.concurrentProducers, 1)
	defer atomic.AddInt32(&w.concurrentProducers, -1)

	if atomic.LoadInt32(&w.state) != StateConnected {
		err := w.connect()
		if err != nil {
			return err
		}
	}

	t := &ProducerTransaction{
		cmd:      cmd,
		doneChan: doneChan,
		Args:     args,
	}

	select {
	case w.transactionChan <- t:
	case <-w.exitChan:
		return ErrStopped
	}

	return nil
}

func (w *Producer) connect() error {
	w.guard.Lock()
	defer w.guard.Unlock()

	if atomic.LoadInt32(&w.stopFlag) == 1 {
		return ErrStopped
	}

	if !atomic.CompareAndSwapInt32(&w.state, StateInit, StateConnected) {
		return ErrNotConnected
	}

	w.log(LogLevelInfo, "(%s) connecting to nsqd", w.addr)

	conn := NewConn(w.addr, w.config)
	conn.SetLogger(w.logger, w.logLvl, fmt.Sprintf("%3d (%%s)", w.id))
	conn.Delegate = &producerConnDelegate{w}

	_, err := conn.Connect()
	if err != nil {
		conn.Close()
		w.log(LogLevelError, "(%s) error connecting to nsqd - %s", w.addr, err)
		atomic.StoreInt32(&w.state, StateInit)
		return err
	}
	w.conn = conn

	w.wg.Add(1)
	go w.router()

	return nil
}

func (w *Producer) close() {
	if !atomic.CompareAndSwapInt32(&w.state, StateConnected, StateDisconnected) {
		return
	}
	w.conn.Close()
	go func() {
		// we need to handle this in a goroutine so we don't
		// block the caller from making progress
		w.wg.Wait()
		atomic.StoreInt32(&w.state, StateInit)
	}()
}

func (w *Producer) router() {
	for {
		select {
		case t := <-w.transactionChan:
			w.transactions = append(w.transactions, t)
			err := w.conn.WriteCommand(t.cmd)
			if err != nil {
				w.log(LogLevelError, "(%s) sending command - %s", w.conn.String(), err)
				w.close()
			}
		case data := <-w.responseChan:
			w.popTransaction(FrameTypeResponse, data)
		case data := <-w.errorChan:
			w.popTransaction(FrameTypeError, data)
		case <-w.heartbeatChan:
		case <-w.ioErrorChan:
			w.close()
		case <-w.closeChan:
			goto exit
		case <-w.exitChan:
			goto exit
		}
	}

exit:
	w.transactionCleanup()
	w.wg.Done()
	w.log(LogLevelInfo, "exiting router")
}

func (w *Producer) popTransaction(frameType int32, data []byte) {
	t := w.transactions[0]
	w.transactions = w.transactions[1:]
	if frameType == FrameTypeError {
		t.Error = ErrProtocol{string(data)}
	}
	t.finish()
}

func (w *Producer) transactionCleanup() {
	// clean up transactions we can easily account for
	for _, t := range w.transactions {
		t.Error = ErrNotConnected
		t.finish()
	}
	w.transactions = w.transactions[:0]

	// spin and free up any writes that might have raced
	// with the cleanup process (blocked on writing
	// to transactionChan)
	for {
		select {
		case t := <-w.transactionChan:
			t.Error = ErrNotConnected
			t.finish()
		default:
			// keep spinning until there are 0 concurrent producers
			if atomic.LoadInt32(&w.concurrentProducers) == 0 {
				return
			}
			// give the runtime a chance to schedule other racing goroutines
			time.Sleep(5 * time.Millisecond)
			continue
		}
	}
}

func (w *Producer) log(lvl LogLevel, line string, args ...interface{}) {
	var prefix string

	if w.logger == nil {
		return
	}

	if w.logLvl > lvl {
		return
	}

	switch lvl {
	case LogLevelDebug:
		prefix = "DBG"
	case LogLevelInfo:
		prefix = "INF"
	case LogLevelWarning:
		prefix = "WRN"
	case LogLevelError:
		prefix = "ERR"
	}

	w.logger.Printf("%-4s %3d %s", prefix, w.id, fmt.Sprintf(line, args...))
}

func (w *Producer) onConnResponse(c *Conn, data []byte) { w.responseChan <- data }
func (w *Producer) onConnError(c *Conn, data []byte)    { w.errorChan <- data }
func (w *Producer) onConnHeartbeat(c *Conn)             { w.heartbeatChan <- 1 }
func (w *Producer) onConnIOError(c *Conn, err error)    { w.ioErrorChan <- err }
func (w *Producer) onConnClose(c *Conn)                 { w.closeChan <- 1 }
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"io"
	"log"
	"os"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var host *string = flag.String("host", "irc.ps0ke.de:2342", "IRC server")
var channel *string = flag.String("channel", "#metttest", "IRC channel")
var nick *string = flag.String("nick", "rohmett", "IRC nick")
var longnick *string = flag.String("longnick", "Le MettBot", "IRC fullname")
var timeformat *string = flag.String("timeformat", "2006-01-02T15:04", "Time format string (standard date: 2006-01-02T15:04:05")
var quotes *string = flag.String("quotes", "mett_quotes.txt", "Quote database file")

func init() {
	flag.Parse()
}

type Mettbot struct {
	*irc.Conn
	Quitted    chan bool
	Prnt       chan string
	Input      chan string
	ReallyQuit bool
}

func NewMettbot(nick string, args ...string) *Mettbot {
	bot := &Mettbot{
		irc.SimpleClient(nick, args...),
		make(chan bool),
		make(chan string),
		make(chan string, 4),
		false,
	}
	bot.EnableStateTracking()
	return bot
}

func (bot *Mettbot) hConnected()    { bot.Join(*channel) }
func (bot *Mettbot) hDisconnected() { bot.Quitted <- true }

func (bot *Mettbot) hPrivmsg(line *irc.Line) {
	actChannel := line.Args[0]
	msg := line.Args[1]

	if msg[0] == '!' {
		cmd := msg
		args := ""
		idx := strings.Index(msg, " ")
		if idx != -1 {
			cmd = msg[:idx]
			args = msg[idx+1:]
		}

		switch {
		case cmd == "!help":
			bot.Help(actChannel)
		case args == "":
			bot.Syntax(actChannel)
		case cmd == "!quote":
			bot.cQuote(actChannel, args, line.Time)
		case cmd == "!print":
			bot.cPrint(actChannel, args)
		default:
			bot.Syntax(actChannel)
		}
	}
}

func (bot *Mettbot) Syntax(channel string) {
	bot.Notice(channel, "Wrong Syntax. Try !help")
}

func (bot *Mettbot) Help(channel string) {
	bot.Notice(channel, "Mett")
}

func (bot *Mettbot) cQuote(channel string, msg string, t time.Time) {
	s := fmt.Sprintln(t.Format(*timeformat), msg)
	fmt.Print(s)
	bot.Prnt <- s
	bot.Notice(channel, "Added Quote to Database")
}

func (bot *Mettbot) cPrint(channel string, msg string) {
	num, err := strconv.Atoi(msg)
	if err != nil {
		bot.Syntax(channel)
		return
	}

	fi, err := os.Open(*quotes)
	if err != nil {
		log.Println(err)
		bot.Notice(channel, "Failed to open quote database")
		return
	}
	defer fi.Close()

	reader := bufio.NewReader(fi)
	quote := ""
	for ; num >= 0; num-- {
		quote, err = reader.ReadString('\n')
		if err == io.EOF {
			bot.Notice(channel, "Quote not found")
			return
		}
		if err != nil {
			log.Println(err)
			bot.Notice(channel, "Failed to read from quote database")
			return
		}
	}
	bot.Notice(channel, quote)
}

func (bot *Mettbot) readStdin() {
	con := bufio.NewReader(os.Stdin)
	for {
		s, err := con.ReadString('\n')
		if err != nil {
			// wha?, maybe ctrl-D...
			close(bot.Input)
			break
		}
		// no point in sending empty lines down the channel
		if len(s) > 2 {
			bot.Input <- s[0 : len(s)-1]
		}
	}
}

func (bot *Mettbot) parseStdin() {
	for cmd := range bot.Input {
		if cmd[0] == ':' {
			switch idx := strings.Index(cmd, " "); {
			case cmd[1] == 'd':
				fmt.Printf(bot.String())
			case cmd[1] == 'f':
				if len(cmd) > 2 && cmd[2] == 'e' {
					// enable flooding
					bot.Flood = true
				} else if len(cmd) > 2 && cmd[2] == 'd' {
					// disable flooding
					bot.Flood = false
				}
				for i := 0; i < 20; i++ {
					bot.Privmsg(*channel, "salami!1!")
				}
			case idx == -1:
				continue
			case cmd[1] == 'q':
				bot.ReallyQuit = true
				bot.Quit(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'j':
				bot.Join(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'p':
				bot.Part(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'm':
				bot.Privmsg(*channel, cmd[idx+1:len(cmd)])
			case cmd[1] == 'a':
				bot.Action(*channel, cmd[idx+1:len(cmd)])
			}
		} else {
			bot.Raw(cmd)
		}
	}
}

func (bot *Mettbot) writeQuote() {
	for messages := range bot.Prnt {
		fo, err := os.OpenFile(*quotes, syscall.O_WRONLY+syscall.O_CREAT+syscall.O_APPEND, 0644)
		if err != nil {
			log.Println(err)
			bot.Notice(*channel, "Couldn't open quote database")
			continue
		}
		defer fo.Close()

		_, err = fo.WriteString(messages)
		if err != nil {
			log.Println(err)
			bot.Notice(*channel, "Couldn't write to quote database")
		}
		fo.Close()
	}
}

func main() {
	// create new IRC connection
	mett := NewMettbot(*nick, *nick, *longnick)

	// Set up handlers
	mett.AddHandler("connected", func(conn *irc.Conn, line *irc.Line) { mett.hConnected() })
	mett.AddHandler("disconnected", func(conn *irc.Conn, line *irc.Line) { mett.hDisconnected() })
	mett.AddHandler("privmsg", func(conn *irc.Conn, line *irc.Line) { mett.hPrivmsg(line) })

	// set up a goroutine to read commands from stdin
	go mett.readStdin()

	// set up a goroutine to do parsey things with the stuff from stdin
	go mett.parseStdin()

	// Set up a go routine to write quotes to file
	go mett.writeQuote()

	for !mett.ReallyQuit {
		// connect to server
		if err := mett.Connect(*host); err != nil {
			fmt.Printf("Connection error: %s\n", err)
			return
		}

		// wait on quit channel
		<-mett.Quitted
	}
}
<commit_msg>implemented topic tracking<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	irc "github.com/fluffle/goirc/client"
	"io"
	"log"
	"os"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var host *string = flag.String("host", "irc.ps0ke.de:2342", "IRC server")
var channel *string = flag.String("channel", "#metttest", "IRC channel")
var nick *string = flag.String("nick", "rohmett", "IRC nick")
var longnick *string = flag.String("longnick", "Le MettBot", "IRC fullname")
var timeformat *string = flag.String("timeformat", "2006-01-02T15:04", "Time format string (standard date: 2006-01-02T15:04:05")
var quotes *string = flag.String("quotes", "mett_quotes.txt", "Quote database file")

func init() {
	flag.Parse()
}

type Mettbot struct {
	*irc.Conn
	Quitted    chan bool
	Prnt       chan string
	Input      chan string
	ReallyQuit bool
	Topics     map[string]string
}

func NewMettbot(nick string, args ...string) *Mettbot {
	bot := &Mettbot{
		irc.SimpleClient(nick, args...), // *irc.Conn
		make(chan bool),                 // Quitted
		make(chan string),               // Prnt
		make(chan string, 4),            // Input
		false,                           // ReallyQuit
		make(map[string]string), // Topics
	}
	bot.EnableStateTracking()
	return bot
}

func (bot *Mettbot) hConnected()    { bot.Join(*channel) }
func (bot *Mettbot) hDisconnected() { bot.Quitted <- true }

func (bot *Mettbot) hJoin(line *irc.Line) {
	time.Sleep(1000 * time.Millisecond)
	actChannel := line.Args[0]
	bot.Topics[actChannel] = bot.ST.GetChannel(actChannel).Topic
}

func (bot *Mettbot) hTopic(line *irc.Line) {
	actChannel := line.Args[0]
	newTopic := line.Args[1]
	oldTopic := bot.Topics[actChannel]
	bot.Topics[actChannel] = newTopic
	bot.Notice(actChannel, "Old topic: " + oldTopic)
	//bot.Notice(actChannel, "New topic: "+newTopic)
}

func (bot *Mettbot) hPrivmsg(line *irc.Line) {
	actChannel := line.Args[0]
	msg := line.Args[1]

	if msg[0] == '!' {
		cmd := msg
		args := ""
		idx := strings.Index(msg, " ")
		if idx != -1 {
			cmd = msg[:idx]
			args = msg[idx+1:]
		}

		switch {
		case cmd == "!help":
			bot.Help(actChannel)
		case args == "":
			bot.Syntax(actChannel)
		case cmd == "!quote":
			bot.cQuote(actChannel, args, line.Time)
		case cmd == "!print":
			bot.cPrint(actChannel, args)
		default:
			bot.Syntax(actChannel)
		}
	}
}

func (bot *Mettbot) Syntax(channel string) {
	bot.Notice(channel, "Wrong Syntax. Try !help")
}

func (bot *Mettbot) Help(channel string) {
	bot.Notice(channel, "Mett")
}

func (bot *Mettbot) cQuote(channel string, msg string, t time.Time) {
	s := fmt.Sprintln(t.Format(*timeformat), msg)
	fmt.Print(s)
	bot.Prnt <- s
	bot.Notice(channel, "Added Quote to Database")
}

func (bot *Mettbot) cPrint(channel string, msg string) {
	num, err := strconv.Atoi(msg)
	if err != nil {
		bot.Syntax(channel)
		return
	}

	fi, err := os.Open(*quotes)
	if err != nil {
		log.Println(err)
		bot.Notice(channel, "Failed to open quote database")
		return
	}
	defer fi.Close()

	reader := bufio.NewReader(fi)
	quote := ""
	for ; num >= 0; num-- {
		quote, err = reader.ReadString('\n')
		if err == io.EOF {
			bot.Notice(channel, "Quote not found")
			return
		}
		if err != nil {
			log.Println(err)
			bot.Notice(channel, "Failed to read from quote database")
			return
		}
	}
	bot.Notice(channel, quote)
}

func (bot *Mettbot) readStdin() {
	con := bufio.NewReader(os.Stdin)
	for {
		s, err := con.ReadString('\n')
		if err != nil {
			// wha?, maybe ctrl-D...
			close(bot.Input)
			break
		}
		// no point in sending empty lines down the channel
		if len(s) > 2 {
			bot.Input <- s[0 : len(s)-1]
		}
	}
}

func (bot *Mettbot) parseStdin() {
	for cmd := range bot.Input {
		if cmd[0] == ':' {
			switch idx := strings.Index(cmd, " "); {
			case cmd[1] == 'd':
				fmt.Printf(bot.String())
			case cmd[1] == 'f':
				if len(cmd) > 2 && cmd[2] == 'e' {
					// enable flooding
					bot.Flood = true
				} else if len(cmd) > 2 && cmd[2] == 'd' {
					// disable flooding
					bot.Flood = false
				}
				for i := 0; i < 20; i++ {
					bot.Privmsg(*channel, "salami!1!")
				}
			case idx == -1:
				continue
			case cmd[1] == 'q':
				bot.ReallyQuit = true
				bot.Quit(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'j':
				bot.Join(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'p':
				bot.Part(cmd[idx+1 : len(cmd)])
			case cmd[1] == 'm':
				bot.Privmsg(*channel, cmd[idx+1:len(cmd)])
			case cmd[1] == 'a':
				bot.Action(*channel, cmd[idx+1:len(cmd)])
			}
		} else {
			bot.Raw(cmd)
		}
	}
}

func (bot *Mettbot) writeQuote() {
	for messages := range bot.Prnt {
		fo, err := os.OpenFile(*quotes, syscall.O_WRONLY+syscall.O_CREAT+syscall.O_APPEND, 0644)
		if err != nil {
			log.Println(err)
			bot.Notice(*channel, "Couldn't open quote database")
			continue
		}
		defer fo.Close()

		_, err = fo.WriteString(messages)
		if err != nil {
			log.Println(err)
			bot.Notice(*channel, "Couldn't write to quote database")
		}
		fo.Close()
	}
}

func main() {
	// create new IRC connection
	mett := NewMettbot(*nick, *nick, *longnick)

	// Set up handlers
	mett.AddHandler("connected", func(conn *irc.Conn, line *irc.Line) { mett.hConnected() })
	mett.AddHandler("disconnected", func(conn *irc.Conn, line *irc.Line) { mett.hDisconnected() })
	mett.AddHandler("join", func(conn *irc.Conn, line *irc.Line) { mett.hJoin(line) })
	mett.AddHandler("privmsg", func(conn *irc.Conn, line *irc.Line) { mett.hPrivmsg(line) })
	mett.AddHandler("topic", func(conn *irc.Conn, line *irc.Line) { mett.hTopic(line) })

	// set up a goroutine to read commands from stdin
	go mett.readStdin()

	// set up a goroutine to do parsey things with the stuff from stdin
	go mett.parseStdin()

	// Set up a go routine to write quotes to file
	go mett.writeQuote()

	for !mett.ReallyQuit {
		// connect to server
		if err := mett.Connect(*host); err != nil {
			fmt.Printf("Connection error: %s\n", err)
			return
		}

		// wait on quit channel
		<-mett.Quitted
	}
}
<|endoftext|>


<commit_before>package main

import . "syscall"
import "fmt"
import "unsafe"

type NetlinkAuditRequest struct {
    Header NlMsghdr
    Data   RtGenmsg
}

func (rr *NetlinkAuditRequest) toWireFormat() []byte {
    b := make([]byte, rr.Header.Len)
    *(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
    *(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
    *(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
    *(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
    *(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
    b[16] = byte(rr.Data.Family)
    return b
}

func newNetlinkAuditRequest(proto, seq, family int) []byte {
    rr := &NetlinkAuditRequest{}
    rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
    rr.Header.Type = uint16(proto)
    rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
    rr.Header.Seq = uint32(seq)
    rr.Data.Family = uint8(family)
    return rr.toWireFormat()
}

func main() {

    s, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_AUDIT)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer Close(s)

    lsa := &SockaddrNetlink{Family: AF_NETLINK}
    if err := Bind(s, lsa); err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("**** Starting Netlink")

    // this should be 10 or not??
    //the purpose of sequence number is to give index number to the request , so for each request there will be different
    //sequence number , this sequence number should be matched with the corresponding reply we get from kernel space
    wb := newNetlinkAuditRequest(AF_NETLINK, 10, NETLINK_AUDIT)
    if err := Sendto(s, wb, 0, lsa); err != nil {
        fmt.Println(err)
        return
    }
    var tab []byte
    for {
        //In the below statement, make variable initialization we used Getpagesize(), this function returns us the PAGE_SIZE of the system,
        // PAGE_SIZE of the system depends upon archietecture of the system, the use of page size is to store some memory during one
        // run cycle of the cpu, greater the PAGE_SIZE, greater can be the memory stored during one run time of the CPU cycle
        rb := make([]byte, Getpagesize())
        nr, _, err := Recvfrom(s, rb, 0)
        if err != nil {
            fmt.Println(err)
            return
        }
        if nr < NLMSG_HDRLEN {
            fmt.Println(EINVAL)
            fmt.Println("**** Starting Netlink")
            return
        }
        rb = rb[:nr]
        //fmt.Println(rb);
        tab = append(tab, rb...)
        msgs, err := ParseNetlinkMessage(rb)
        //fmt.Println(msgs);
        if err != nil {
            fmt.Println(err)
        }
        for _, m := range msgs {
            lsa, err := Getsockname(s)
            if err != nil {
                fmt.Println(err)
            }
            switch v := lsa.(type) {
            case *SockaddrNetlink:
                if m.Header.Seq != 1 || m.Header.Pid != v.Pid {
                    fmt.Println(EINVAL)
                }
            default:
                fmt.Println(EINVAL)
            }
            if m.Header.Type == NLMSG_DONE {
                fmt.Println("*****Done******")
            }
            if m.Header.Type == NLMSG_ERROR {
                fmt.Println(EINVAL)
            }
        }

    }

    ////////////////////

    fmt.Println(tab)

    ///////////////////
}

<commit_msg>Added message parsing<commit_after>package main

import . "syscall"
import . "encoding/binary"
import "fmt"
import . "unsafe"

type NetlinkAuditRequest struct {
    Header NlMsghdr
    Data   RtGenmsg
}

func (msg *IfInfomsg) ToWireFormat() []byte {
    native := nativeEndian()
    length := SizeofIfInfomsg
    b := make([]byte, length)
    b[0] = msg.Family
    b[1] = 0
    native.PutUint16(b[2:4], msg.Type)
    native.PutUint32(b[4:8], uint32(msg.Index))
    native.PutUint32(b[8:12], msg.Flags)
    native.PutUint32(b[12:16], msg.Change)
    return b
}

func nativeEndian() ByteOrder {
    var x uint32 = 0x01020304
    if *(*byte)(Pointer(&x)) == 0x01 {
        return BigEndian
    }
    return LittleEndian
}

/*
func newNetlinkAuditRequest(proto, seq, family int) []byte {
    rr := &NetlinkAuditRequest{}
    rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
    rr.Header.Type = uint16(proto)
    rr.Header.Flags = NLM_F_ACK | NLM_F_REQUEST
    rr.Header.Seq = uint32(seq)
    rr.Data.Family = uint8(family)
    return rr.toWireFormat()
}
*/

type IfInfomsg struct {
    IfInfomsg
}

type NetlinkRequest struct {
    NlMsghdr
    Data []NetlinkRequestData
}

func (msg *IfInfomsg) Len() int {
    return SizeofIfInfomsg
}

func (s *NetlinkSocket) Close() {
    Close(s.fd)
}

type NetlinkRequestData interface {
    Len() int
    ToWireFormat() []byte
}

type NetlinkSocket struct {
    fd int
    lsa SockaddrNetlink
}

func getNetlinkSocket() (*NetlinkSocket, error) {
    fd, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_AUDIT)
    if err != nil {
        return nil, err
    }
    s := &NetlinkSocket{
        fd: fd,
    }
    s.lsa.Family = AF_NETLINK
    if err := Bind(fd, &s.lsa); err != nil {
        Close(fd)
        return nil, err
    }
    return s, nil
}

func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
    if err := Sendto(s.fd, request.ToWireFormat(), 0, &s.lsa); err != nil {
        return err
    }
    return nil
}

func (s *NetlinkSocket) Receive() ([]NetlinkMessage, error) {
    rb := make([]byte, Getpagesize())
    nr, _, err := Recvfrom(s.fd, rb, 0)
    if err != nil {
        return nil, err
    }
    if nr < NLMSG_HDRLEN {
        return nil, ErrShortResponse
    }
    rb = rb[:nr]
    return ParseNetlinkMessage(rb)
}

func (s *NetlinkSocket) GetPid() (uint32, error) {
    lsa, err := Getsockname(s.fd)
    if err != nil {
        return 0, err
    }
    switch v := lsa.(type) {
    case *SockaddrNetlink:
        return v.Pid, nil
    }
    return 0, ErrWrongSockType
}

func (s *NetlinkSocket) HandleAck(seq uint32) error {
    native := nativeEndian()
    pid, err := s.GetPid()
    if err != nil {
        return err
    }
    done:
        for {
            msgs, err := s.Receive()
            if err != nil {
                return err
            }
            for _, m := range msgs {
                if m.Header.Seq != seq {
                    return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, seq)
                }
                if m.Header.Pid != pid {
                    return fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
                }
                if m.Header.Type == NLMSG_DONE {
                    break done
                }
                if m.Header.Type == NLMSG_ERROR {
                    error := int32(native.Uint32(m.Data[0:4]))
                    if error == 0 {
                        break done
                    }
                    return Errno(-error)
                }
            }
        }
    return nil
}

func main() {

}<|endoftext|>


<commit_before>/*
Quick and simple monitoring system

Usage:
 jsonmon path.to/config.yml
 jsonmon -v # Prints version to stdout and exits

Environment:
 HOST
  - defaults to localhost
  - the JSON API network interface
 PORT
  - defaults to 3000
  - the JSON API port
 GOMAXPROCS
  - defaults to CPU number + 1
  - number of threads to start
*/
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"runtime"
	"strconv"
	"sync"
	"time"
)

// Application version.
const Version = "1.0"

// This one is for internal use.
type ver struct {
	App  string `json:"jsonmon"`
	Go   string `json:"runtime"`
	Os   string `json:"os"`
	Arch string `json:"arch"`
}

var version ver

// Check details.
type Check struct {
	Name   string      `json:"name,omitempty" yaml:"name"`
	Web    string      `json:"web,omitempty" yaml:"web"`
	Shell  string      `json:"shell,omitempty" yaml:"shell"`
	Match  string      `json:"-" yaml:"match"`
	Return int         `json:"-" yaml:"return"`
	Notify interface{} `json:"-" yaml:"notify"`
	Tries  int         `json:"-" yaml:"tries"`
	Repeat int         `json:"-" yaml:"repeat"`
	Failed bool        `json:"failed" yaml:"-"`
	Since  string      `json:"since,omitempty" yaml:"-"`
}

// Global checks list. Need to share it with workers and Web UI.
var checks []Check

// The main loop.
func main() {
	// Parse CLI args.
	usage := "Usage: " + path.Base(os.Args[0]) + " path.to/config.yml\nDocs:  https://github.com/chillum/jsonmon/wiki"
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, usage)
		os.Exit(1)
	}
	// -v for version.
	version.App = Version
	version.Go = runtime.Version()
	version.Os = runtime.GOOS
	version.Arch = runtime.GOARCH
	switch os.Args[1] {
	case "-h":
		fallthrough
	case "-help":
		fallthrough
	case "--help":
		fmt.Fprintln(os.Stderr, usage)
		os.Exit(0)
	case "-v":
		fallthrough
	case "-version":
		fallthrough
	case "--version":
		json, _ := json.MarshalIndent(&version, "", "  ")
		fmt.Println(string(json))
		os.Exit(0)
	}
	// Tune concurrency.
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU() + 1)
	}
	// Read config file or exit with error.
	config, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", err)
		os.Exit(3)
	}
	err = yaml.Unmarshal(config, &checks)
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", config[0], err)
		os.Exit(3)
	}
	// Run checks.
	var wg sync.WaitGroup
	wg.Add(1)
	for i := range checks {
		go worker(&checks[i])
	}
	// Launch the JSON API.
	host := os.Getenv("HOST")
	port := os.Getenv("PORT")
	if host == "" {
		host = "localhost"
	}
	if port == "" {
		port = "3000"
	}
	http.HandleFunc("/version", getVersion)
	http.HandleFunc("/", getChecks)
	err = http.ListenAndServe(host+":"+port, nil)
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", err)
	}
	// Wait forever.
	wg.Wait()
}

// Background worker.
func worker(check *Check) {
	for {
		if check.Repeat == 0 { // Set default timeout.
			check.Repeat = 60
		}
		if check.Tries == 0 { // Default to 1 attempt.
			check.Tries = 1
		}
		if check.Web != "" {
			web(check)
		}
		if check.Shell != "" {
			shell(check)
		}
		time.Sleep(time.Second * time.Duration(check.Repeat))
	}
}

// Shell worker.
func shell(check *Check) {
	// Set check's display name.
	var name string
	if check.Name != "" {
		name = check.Name
	} else {
		name = check.Shell
	}
	// Execute with shell in N attemps.
	var out []byte
	var err error
	for i := 0; i < check.Tries; i++ {
		out, err = exec.Command("/bin/sh", "-c", check.Shell).CombinedOutput()
		if err == nil {
			if check.Match != "" { // Match regexp.
				var regex *regexp.Regexp
				regex, err = regexp.Compile(check.Match)
				if err == nil && !regex.Match(out) {
					err = errors.New("ERROR: output did not match " + check.Match)
				}
			}
			break
		}
	}
	// Process results.
	if err == nil {
		if check.Failed {
			check.Failed = false
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "Fixed: "+name, "")
		}
	} else {
		if !check.Failed {
			check.Failed = true
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "Failed: "+name, string(out)+err.Error())
		}
	}
}

// Web worker.
func web(check *Check) {
	// Set check's display name.
	var name string
	if check.Name != "" {
		name = check.Name
	} else {
		name = check.Web
	}
	if check.Return == 0 { // Successful HTTP return code is 200.
		check.Return = 200
	}
	// Get the URL in N attempts.
	var err error
	for i := 0; i < check.Tries; i++ {
		err = fetch(check.Web, check.Match, check.Return)
		if err == nil {
			break
		}
	}
	// Process results.
	if err == nil {
		if check.Failed {
			check.Failed = false
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "FIXED: "+name, "")
		}
	} else {
		if !check.Failed {
			check.Failed = true
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "FAILED: "+name, err.Error())
		}
	}
}

// The actual HTTP GET.
func fetch(url string, match string, code int) error {
	var err error
	var resp *http.Response
	resp, err = http.Get(url)
	if err == nil && resp.StatusCode != code {
		err = errors.New(url + " returned " + strconv.Itoa(resp.StatusCode))
	} else { // Match regexp.
		if resp != nil && match != "" {
			var regex *regexp.Regexp
			regex, err = regexp.Compile(match)
			if err == nil {
				var body []byte
				body, _ = ioutil.ReadAll(resp.Body)
				if !regex.Match(body) {
					err = errors.New(url + " output did not match " + match)
				}
			}
		}
	}
	if resp != nil {
		resp.Body.Close()
	}
	return err
}

// Logs and mail alerting.
func alert(mail interface{}, subject string, message string) {
	// Log the alerts.
	if message == "" {
		fmt.Println(subject)
	} else {
		fmt.Println(subject + "\n" + message)
	}
	// Mail the alerts.
	if mail != nil {
		// Make the message.
		var rcpt string
		var ok bool
		if rcpt, ok = mail.(string); !ok {
			for i, v := range mail.([]interface{}) {
				if i != 0 {
					rcpt += ", "
				}
				rcpt += v.(string)
			}
		}
		msg := "To: " + rcpt + "\nSubject: " + subject + "\n\n"
		if message != "" {
			msg += message
		}
		msg += "\n.\n"
		// And send it.
		sendmail := exec.Command("/usr/sbin/sendmail", "-t")
		stdin, err := sendmail.StdinPipe()
		err = sendmail.Start()
		if err != nil {
			fmt.Fprintln(os.Stderr, "ERROR:", err)
		}
		io.WriteString(stdin, msg)
		sendmail.Wait()
	}
}

// Display checks' details.
func getChecks(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" { // Serve for root page only, 404 otherwise.
		w.Header().Set("Server", "jsonmon")
		http.NotFound(w, r)
		return
	}
	displayJSON(w, &checks)
}

// Display application version.
func getVersion(w http.ResponseWriter, r *http.Request) {
	displayJSON(w, &version)
}

// Output JSON.
func displayJSON(w http.ResponseWriter, data interface{}) {
	json, _ := json.MarshalIndent(&data, "", "  ")
	w.Header().Set("Server", "jsonmon")
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Write(json)
	fmt.Fprintln(w, "") // Trailing newline.
}
<commit_msg>more helpful usage message (real config path)<commit_after>/*
Quick and simple monitoring system

Usage:
 jsonmon /etc/jsonmon/config.yml
 jsonmon -v # Prints version to stdout and exits

Environment:
 HOST
  - defaults to localhost
  - the JSON API network interface
 PORT
  - defaults to 3000
  - the JSON API port
 GOMAXPROCS
  - defaults to CPU number + 1
  - number of threads to start
*/
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"runtime"
	"strconv"
	"sync"
	"time"
)

// Application version.
const Version = "1.0"

// This one is for internal use.
type ver struct {
	App  string `json:"jsonmon"`
	Go   string `json:"runtime"`
	Os   string `json:"os"`
	Arch string `json:"arch"`
}

var version ver

// Check details.
type Check struct {
	Name   string      `json:"name,omitempty" yaml:"name"`
	Web    string      `json:"web,omitempty" yaml:"web"`
	Shell  string      `json:"shell,omitempty" yaml:"shell"`
	Match  string      `json:"-" yaml:"match"`
	Return int         `json:"-" yaml:"return"`
	Notify interface{} `json:"-" yaml:"notify"`
	Tries  int         `json:"-" yaml:"tries"`
	Repeat int         `json:"-" yaml:"repeat"`
	Failed bool        `json:"failed" yaml:"-"`
	Since  string      `json:"since,omitempty" yaml:"-"`
}

// Global checks list. Need to share it with workers and Web UI.
var checks []Check

// The main loop.
func main() {
	// Parse CLI args.
	usage := "Usage: " + path.Base(os.Args[0]) + " /etc/jsonmon/config.yml\n" +
		"Docs:  https://github.com/chillum/jsonmon/wiki"
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, usage)
		os.Exit(1)
	}
	// -v for version.
	version.App = Version
	version.Go = runtime.Version()
	version.Os = runtime.GOOS
	version.Arch = runtime.GOARCH
	switch os.Args[1] {
	case "-h":
		fallthrough
	case "-help":
		fallthrough
	case "--help":
		fmt.Fprintln(os.Stderr, usage)
		os.Exit(0)
	case "-v":
		fallthrough
	case "-version":
		fallthrough
	case "--version":
		json, _ := json.MarshalIndent(&version, "", "  ")
		fmt.Println(string(json))
		os.Exit(0)
	}
	// Tune concurrency.
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(runtime.NumCPU() + 1)
	}
	// Read config file or exit with error.
	config, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", err)
		os.Exit(3)
	}
	err = yaml.Unmarshal(config, &checks)
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", config[0], err)
		os.Exit(3)
	}
	// Run checks.
	var wg sync.WaitGroup
	wg.Add(1)
	for i := range checks {
		go worker(&checks[i])
	}
	// Launch the JSON API.
	host := os.Getenv("HOST")
	port := os.Getenv("PORT")
	if host == "" {
		host = "localhost"
	}
	if port == "" {
		port = "3000"
	}
	http.HandleFunc("/version", getVersion)
	http.HandleFunc("/", getChecks)
	err = http.ListenAndServe(host+":"+port, nil)
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR:", err)
	}
	// Wait forever.
	wg.Wait()
}

// Background worker.
func worker(check *Check) {
	for {
		if check.Repeat == 0 { // Set default timeout.
			check.Repeat = 60
		}
		if check.Tries == 0 { // Default to 1 attempt.
			check.Tries = 1
		}
		if check.Web != "" {
			web(check)
		}
		if check.Shell != "" {
			shell(check)
		}
		time.Sleep(time.Second * time.Duration(check.Repeat))
	}
}

// Shell worker.
func shell(check *Check) {
	// Set check's display name.
	var name string
	if check.Name != "" {
		name = check.Name
	} else {
		name = check.Shell
	}
	// Execute with shell in N attemps.
	var out []byte
	var err error
	for i := 0; i < check.Tries; i++ {
		out, err = exec.Command("/bin/sh", "-c", check.Shell).CombinedOutput()
		if err == nil {
			if check.Match != "" { // Match regexp.
				var regex *regexp.Regexp
				regex, err = regexp.Compile(check.Match)
				if err == nil && !regex.Match(out) {
					err = errors.New("ERROR: output did not match " + check.Match)
				}
			}
			break
		}
	}
	// Process results.
	if err == nil {
		if check.Failed {
			check.Failed = false
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "Fixed: "+name, "")
		}
	} else {
		if !check.Failed {
			check.Failed = true
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "Failed: "+name, string(out)+err.Error())
		}
	}
}

// Web worker.
func web(check *Check) {
	// Set check's display name.
	var name string
	if check.Name != "" {
		name = check.Name
	} else {
		name = check.Web
	}
	if check.Return == 0 { // Successful HTTP return code is 200.
		check.Return = 200
	}
	// Get the URL in N attempts.
	var err error
	for i := 0; i < check.Tries; i++ {
		err = fetch(check.Web, check.Match, check.Return)
		if err == nil {
			break
		}
	}
	// Process results.
	if err == nil {
		if check.Failed {
			check.Failed = false
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "FIXED: "+name, "")
		}
	} else {
		if !check.Failed {
			check.Failed = true
			check.Since = time.Now().Format(time.RFC3339)
			alert(check.Notify, "FAILED: "+name, err.Error())
		}
	}
}

// The actual HTTP GET.
func fetch(url string, match string, code int) error {
	var err error
	var resp *http.Response
	resp, err = http.Get(url)
	if err == nil && resp.StatusCode != code {
		err = errors.New(url + " returned " + strconv.Itoa(resp.StatusCode))
	} else { // Match regexp.
		if resp != nil && match != "" {
			var regex *regexp.Regexp
			regex, err = regexp.Compile(match)
			if err == nil {
				var body []byte
				body, _ = ioutil.ReadAll(resp.Body)
				if !regex.Match(body) {
					err = errors.New(url + " output did not match " + match)
				}
			}
		}
	}
	if resp != nil {
		resp.Body.Close()
	}
	return err
}

// Logs and mail alerting.
func alert(mail interface{}, subject string, message string) {
	// Log the alerts.
	if message == "" {
		fmt.Println(subject)
	} else {
		fmt.Println(subject + "\n" + message)
	}
	// Mail the alerts.
	if mail != nil {
		// Make the message.
		var rcpt string
		var ok bool
		if rcpt, ok = mail.(string); !ok {
			for i, v := range mail.([]interface{}) {
				if i != 0 {
					rcpt += ", "
				}
				rcpt += v.(string)
			}
		}
		msg := "To: " + rcpt + "\nSubject: " + subject + "\n\n"
		if message != "" {
			msg += message
		}
		msg += "\n.\n"
		// And send it.
		sendmail := exec.Command("/usr/sbin/sendmail", "-t")
		stdin, err := sendmail.StdinPipe()
		err = sendmail.Start()
		if err != nil {
			fmt.Fprintln(os.Stderr, "ERROR:", err)
		}
		io.WriteString(stdin, msg)
		sendmail.Wait()
	}
}

// Display checks' details.
func getChecks(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" { // Serve for root page only, 404 otherwise.
		w.Header().Set("Server", "jsonmon")
		http.NotFound(w, r)
		return
	}
	displayJSON(w, &checks)
}

// Display application version.
func getVersion(w http.ResponseWriter, r *http.Request) {
	displayJSON(w, &version)
}

// Output JSON.
func displayJSON(w http.ResponseWriter, data interface{}) {
	json, _ := json.MarshalIndent(&data, "", "  ")
	w.Header().Set("Server", "jsonmon")
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Write(json)
	fmt.Fprintln(w, "") // Trailing newline.
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gorilla/mux"
	"github.com/paked/gerrycode/communicator"
	"github.com/paked/models"
	"gopkg.in/mgo.v2/bson"
)

type Image struct {
	ID  bson.ObjectId `bson:"_id" json:"id"`
	URL string        `bson:"url" json:"url"`
}

func (i Image) BID() bson.ObjectId {
	return i.ID
}

func (i Image) C() string {
	return "images"
}

type Number struct {
	ID     bson.ObjectId `bson:"_id" json:"id"`
	For    bson.ObjectId `bson:"for" json:"for"`
	Number float64       `bson:"number" json:"number"`
}

func (n Number) BID() bson.ObjectId {
	return n.ID
}

func (n Number) C() string {
	return "numbers"
}

func main() {
	models.Init("localhost", "imagenumberdescriptions")
	r := mux.NewRouter()
	api := r.PathPrefix("/api").Subrouter()

	r.HandleFunc("/", homeHandler).Methods("GET")
	api.HandleFunc("/image/new", createImageHandler).Methods("POST")
	api.HandleFunc("/image/{image_id}/number/new", addNumberHandler).Methods("POST")

	http.Handle("/", r)

	fmt.Println("Listening on port 8080")
	fmt.Println(http.ListenAndServe("localhost:8080", nil))
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

func createImageHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	location := r.FormValue("url")

	u, err := url.Parse(location)
	if err != nil {
		c.Error("Not a good URL!")
		return
	}

	location = u.String()

	var i Image
	if err := models.Restore(&i, bson.M{"url": location}); err == nil {
		c.Fail("An image with that URL already exists")
		return
	}

	i = Image{
		ID:  bson.NewObjectId(),
		URL: location,
	}

	if err := models.Persist(i); err != nil {
		c.Fail("An error with the database has occured")
		return
	}

	c.OKWithData("Here is your image", i)
}

func addNumberHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	imageId := mux.Vars(r)["image_id"]
	numberString := r.FormValue("number")

	number, err := strconv.ParseFloat(numberString, 64)
	if err != nil {
		c.Error("That is not a valid float!")
		return
	}

	if !bson.IsObjectIdHex(imageId) {
		c.Error("Not valid image id!")
		return
	}

	n := Number{
		ID:     bson.NewObjectId(),
		For:    bson.ObjectIdHex(imageId),
		Number: number,
	}

	if err := models.Persist(n); err != nil {
		c.Error("Something bad happened in the database...")
		return
	}

	c.OKWithData("Here is your number", n)
}
<commit_msg>main: fix usage of Communicator.Fail and Communicator.Error<commit_after>package main

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

	"github.com/gorilla/mux"
	"github.com/paked/gerrycode/communicator"
	"github.com/paked/models"
	"gopkg.in/mgo.v2/bson"
)

type Image struct {
	ID  bson.ObjectId `bson:"_id" json:"id"`
	URL string        `bson:"url" json:"url"`
}

func (i Image) BID() bson.ObjectId {
	return i.ID
}

func (i Image) C() string {
	return "images"
}

type Number struct {
	ID     bson.ObjectId `bson:"_id" json:"id"`
	For    bson.ObjectId `bson:"for" json:"for"`
	Number float64       `bson:"number" json:"number"`
}

func (n Number) BID() bson.ObjectId {
	return n.ID
}

func (n Number) C() string {
	return "numbers"
}

func main() {
	models.Init("localhost", "imagenumberdescriptions")
	r := mux.NewRouter()
	api := r.PathPrefix("/api").Subrouter()

	r.HandleFunc("/", homeHandler).Methods("GET")
	api.HandleFunc("/image/new", createImageHandler).Methods("POST")
	api.HandleFunc("/image/{image_id}/number/new", addNumberHandler).Methods("POST")

	http.Handle("/", r)

	fmt.Println("Listening on port 8080")
	fmt.Println(http.ListenAndServe("localhost:8080", nil))
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

func createImageHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	location := r.FormValue("url")

	u, err := url.Parse(location)
	if err != nil {
		c.Fail("Not a good URL!")
		return
	}

	location = u.String()

	var i Image
	if err := models.Restore(&i, bson.M{"url": location}); err == nil {
		c.Fail("An image with that URL already exists")
		return
	}

	i = Image{
		ID:  bson.NewObjectId(),
		URL: location,
	}

	if err := models.Persist(i); err != nil {
		c.Error("An error with the database has occured")
		return
	}

	c.OKWithData("Here is your image", i)
}

func addNumberHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	imageId := mux.Vars(r)["image_id"]
	numberString := r.FormValue("number")

	number, err := strconv.ParseFloat(numberString, 64)
	if err != nil {
		c.Fail("That is not a valid float!")
		return
	}

	if !bson.IsObjectIdHex(imageId) {
		c.Fail("Not valid image id!")
		return
	}

	n := Number{
		ID:     bson.NewObjectId(),
		For:    bson.ObjectIdHex(imageId),
		Number: number,
	}

	if err := models.Persist(n); err != nil {
		c.Error("Something bad happened in the database...")
		return
	}

	c.OKWithData("Here is your number", n)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"

	"github.com/drone/drone-go/drone"
	"github.com/drone/drone-go/plugin"
	"github.com/drone/drone-go/template"
)

func main() {

	// plugin settings
	var sys = drone.System{}
	var repo = drone.Repo{}
	var build = drone.Build{}
	var vargs = Webhook{}

	// set plugin parameters
	plugin.Param("system", &sys)
	plugin.Param("repo", &repo)
	plugin.Param("build", &build)
	plugin.Param("vargs", &vargs)

	// parse the parameters
	if err := plugin.Parse(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// set default values
	if len(vargs.Method) == 0 {
		vargs.Method = "POST"
	}
	if len(vargs.ContentType) == 0 {
		vargs.ContentType = "application/json"
	}

	// data structure
	data := struct {
		Repo  drone.Repo  `json:"repo"`
		Build drone.Build `json:"build"`
	}{repo, build}

	// creates the payload. by default the payload
	// is the build details in json format, but a custom
	// template may also be used.
	var buf bytes.Buffer
	if len(vargs.Template) == 0 {
		if err := json.NewEncoder(&buf).Encode(&data); err != nil {
			fmt.Printf("Error encoding json payload. %s\n", err)
			os.Exit(1)
		}
	} else {
		err := template.Write(&buf, vargs.Template, &drone.Payload{
			Build:  &build,
			Repo:   &repo,
			System: &sys,
		})
		if err != nil {
			fmt.Printf("Error executing content template. %s\n", err)
			os.Exit(1)
		}
	}

	// build and execute a request for each url.
	// all auth, headers, method, template (payload),
	// and content_type values will be applied to
	// every webhook request.
	for i, rawurl := range vargs.Urls {

		uri, err := url.Parse(rawurl)
		if err != nil {
			fmt.Printf("Error parsing hook url. %s\n", err)
			os.Exit(1)
		}

		// vargs.Method defaults to POST, no need to check
		b := buf.Bytes()
		r := bytes.NewReader(b)
		req, err := http.NewRequest(vargs.Method, uri.String(), r)
		if err != nil {
			fmt.Printf("Error creating http request. %s\n", err)
			os.Exit(1)
		}

		// vargs.ContentType defaults to application/json, no need to check
		req.Header.Set("Content-Type", vargs.ContentType)
		for key, value := range vargs.Headers {
			req.Header.Set(key, value)
		}

		// set basic auth if a user or user and pass is provided
		if len(vargs.Auth.Username) > 0 {
			if len(vargs.Auth.Password) > 0 {
				req.SetBasicAuth(vargs.Auth.Username, vargs.Auth.Password)
			} else {
				req.SetBasicAuth(vargs.Auth.Username, "")
			}
		}

		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			fmt.Printf("Error executing http request. %s\n", err)
			os.Exit(1)
		}
		defer resp.Body.Close()

		// if debug is on or response status code is bad
		if vargs.Debug || resp.StatusCode >= http.StatusBadRequest {

			// read the response body
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				// I do not think we need to os.Exit(1) if we are
				// unable to read a http response body.
				fmt.Printf("Error reading http response body. %s\n", err)
			}

			// debug/info print
			if vargs.Debug {
				fmt.Printf("[debug] Webhook %d\n  URL: %s\n  METHOD: %s\n  HEADERS: %s\n  REQUEST BODY: %s\n  RESPONSE STATUS: %s\n  RESPONSE BODY: %s\n", i+1, req.URL, req.Method, req.Header, string(b), resp.Status, string(body))
			} else {
				fmt.Printf("[info] Webhook %d\n  URL: %s\n  RESPONSE STATUS: %s\n  RESPONSE BODY: %s\n", i+1, req.URL, resp.Status, string(body))
			}
		}
	}
}
<commit_msg>add system to webhook payload so that we know the drone url<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"

	"github.com/drone/drone-go/drone"
	"github.com/drone/drone-go/plugin"
	"github.com/drone/drone-go/template"
)

func main() {

	// plugin settings
	var sys = drone.System{}
	var repo = drone.Repo{}
	var build = drone.Build{}
	var vargs = Webhook{}

	// set plugin parameters
	plugin.Param("system", &sys)
	plugin.Param("repo", &repo)
	plugin.Param("build", &build)
	plugin.Param("vargs", &vargs)

	// parse the parameters
	if err := plugin.Parse(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// set default values
	if len(vargs.Method) == 0 {
		vargs.Method = "POST"
	}
	if len(vargs.ContentType) == 0 {
		vargs.ContentType = "application/json"
	}

	// data structure
	data := struct {
		System drone.System `json:"system"`
		Repo   drone.Repo   `json:"repo"`
		Build  drone.Build  `json:"build"`
	}{sys, repo, build}

	// creates the payload. by default the payload
	// is the build details in json format, but a custom
	// template may also be used.
	var buf bytes.Buffer
	if len(vargs.Template) == 0 {
		if err := json.NewEncoder(&buf).Encode(&data); err != nil {
			fmt.Printf("Error encoding json payload. %s\n", err)
			os.Exit(1)
		}
	} else {
		err := template.Write(&buf, vargs.Template, &drone.Payload{
			Build:  &build,
			Repo:   &repo,
			System: &sys,
		})
		if err != nil {
			fmt.Printf("Error executing content template. %s\n", err)
			os.Exit(1)
		}
	}

	// build and execute a request for each url.
	// all auth, headers, method, template (payload),
	// and content_type values will be applied to
	// every webhook request.
	for i, rawurl := range vargs.Urls {

		uri, err := url.Parse(rawurl)
		if err != nil {
			fmt.Printf("Error parsing hook url. %s\n", err)
			os.Exit(1)
		}

		// vargs.Method defaults to POST, no need to check
		b := buf.Bytes()
		r := bytes.NewReader(b)
		req, err := http.NewRequest(vargs.Method, uri.String(), r)
		if err != nil {
			fmt.Printf("Error creating http request. %s\n", err)
			os.Exit(1)
		}

		// vargs.ContentType defaults to application/json, no need to check
		req.Header.Set("Content-Type", vargs.ContentType)
		for key, value := range vargs.Headers {
			req.Header.Set(key, value)
		}

		// set basic auth if a user or user and pass is provided
		if len(vargs.Auth.Username) > 0 {
			if len(vargs.Auth.Password) > 0 {
				req.SetBasicAuth(vargs.Auth.Username, vargs.Auth.Password)
			} else {
				req.SetBasicAuth(vargs.Auth.Username, "")
			}
		}

		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			fmt.Printf("Error executing http request. %s\n", err)
			os.Exit(1)
		}
		defer resp.Body.Close()

		// if debug is on or response status code is bad
		if vargs.Debug || resp.StatusCode >= http.StatusBadRequest {

			// read the response body
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				// I do not think we need to os.Exit(1) if we are
				// unable to read a http response body.
				fmt.Printf("Error reading http response body. %s\n", err)
			}

			// debug/info print
			if vargs.Debug {
				fmt.Printf("[debug] Webhook %d\n  URL: %s\n  METHOD: %s\n  HEADERS: %s\n  REQUEST BODY: %s\n  RESPONSE STATUS: %s\n  RESPONSE BODY: %s\n", i+1, req.URL, req.Method, req.Header, string(b), resp.Status, string(body))
			} else {
				fmt.Printf("[info] Webhook %d\n  URL: %s\n  RESPONSE STATUS: %s\n  RESPONSE BODY: %s\n", i+1, req.URL, resp.Status, string(body))
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"io/ioutil"

	"github.com/fatih/color"
	"github.com/oshalygin/k8s-config/services"
)

func main() {
	var err error

	configurationType := flag.String("type", "deployment", "Kubernetes configuration type, eg: deployment, rc, secret")
	image := flag.String("image", "", "Docker image name")
	imageTag := flag.String("tag", "", "Docker image tag")
	filePath := flag.String("file-path", "", "Configuration file location")

	flag.Parse()
	err = checkRequiredFlags(*configurationType, *image, *imageTag, *filePath)

	if err != nil {
		color.Red("Error: %v", err)
		color.Black("--------------------")
		flag.PrintDefaults()
		os.Exit(1)
	}

	file, err := ioutil.ReadFile(*filePath)
	if err != nil {
		color.Red("Error: %v", err)
		os.Exit(1)
	}

	services.UpdateDeploymentConfiguration(file, *image, *imageTag)

	fmt.Printf("type: %s\n", *configurationType)
	fmt.Printf("image: %s\n", *image)
	fmt.Printf("tag: %s\n", *imageTag)
	fmt.Printf("file-path: %s\n", *filePath)

}
<commit_msg>Refactor dashed lines<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"io/ioutil"

	"strings"

	"github.com/fatih/color"
	"github.com/oshalygin/k8s-config/services"
)

func main() {
	var err error

	configurationType := flag.String("type", "deployment", "Kubernetes configuration type, eg: deployment, rc, secret")
	image := flag.String("image", "", "Docker image name")
	imageTag := flag.String("tag", "", "Docker image tag")
	filePath := flag.String("file-path", "", "Configuration file location")

	flag.Parse()
	err = checkRequiredFlags(*configurationType, *image, *imageTag, *filePath)

	if err != nil {
		errorOutput := fmt.Sprintf("Error: %v", err)
		color.Red(errorOutput)
		fmt.Println(strings.Repeat("-", len(errorOutput)))

		flag.PrintDefaults()
		os.Exit(1)
	}

	file, err := ioutil.ReadFile(*filePath)
	if err != nil {
		color.Red("Error: %v", err)
		os.Exit(1)
	}

	services.UpdateDeploymentConfiguration(file, *image, *imageTag)

	fmt.Printf("type: %s\n", *configurationType)
	fmt.Printf("image: %s\n", *image)
	fmt.Printf("tag: %s\n", *imageTag)
	fmt.Printf("file-path: %s\n", *filePath)

}
<|endoftext|>