<commit_before>package main

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

type Template struct {
	FuncName   string
	Parameters string
	Imports    map[string]bool
	Escape     string
	Body       bytes.Buffer
}

func (t *Template) Parse(templateBytes []byte) (err error) {
	regions := bytes.SplitN(templateBytes, []byte("\n---\n"), 2)

	if len(regions) != 2 {
		return errors.New("Did not find divider between header and body.")
	}

	err = t.parseHeader(regions[0])
	if err != nil {
		return err
	}

	err = t.parseBody(regions[1])
	if err != nil {
		return err
	}

	return nil
}

func (t *Template) parseHeader(header []byte) (err error) {
	lines := bytes.Split(header, []byte("\n"))
	options := make(map[string]string, len(lines))
	for i, l := range lines {
		pair := bytes.SplitN(l, []byte(":"), 2)
		if len(pair) != 2 {
			return fmt.Errorf("Bad header line: %d", i)
		}
		options[string(pair[0])] = string(bytes.Trim(pair[1], " "))
	}

	t.FuncName = options["func"]
	if t.FuncName == "" {
		return errors.New(`Missing "func"`)
	}

	t.Escape = options["escape"]

	t.Parameters = "writer io.Writer"
	var extraParameters string
	extraParameters = options["parameters"]
	if len(extraParameters) > 0 {
		t.Parameters = t.Parameters + ", " + extraParameters
	}

	t.Imports = map[string]bool{"io": true}

	var extraImports string
	extraImports = options["imports"]
	if len(extraImports) > 0 {
		for _, pkg := range strings.Split(extraImports, " ") {
			t.Imports[strings.Trim(pkg, " ")] = true
		}
	}

	return nil
}

func (t *Template) parseBody(body []byte) (err error) {
	unparsed := body

	for len(unparsed) > 0 {
		next := bytes.Index(unparsed, []byte("<%"))
		switch {
		case next > 0:
			segment := unparsed[:next]
			t.writeStringSegment(segment)
			unparsed = unparsed[next:]
		case next == 0:
			unparsed = unparsed[2:]
			endGo := bytes.Index(unparsed, []byte("%>"))

			if endGo > -1 {
				segment := unparsed[:endGo]

				if segment[0] == '=' {
					t.writeInterpolationSegment(segment[1:])
				} else {
					t.writeGoSegment(segment)
				}

				unparsed = unparsed[endGo+2:]
			} else {
				return errors.New("Unable to parse")
			}
		default:
			segment := unparsed
			t.writeStringSegment(segment)
			unparsed = nil
			break
		}
	}

	return nil
}

func (t *Template) writeStringSegment(segment []byte) (err error) {
	_, err = writeWrapped(&t.Body, "io.WriteString(writer, `", segment, "`)\n")
	return err
}

func (t *Template) writeInterpolationSegment(segment []byte) (err error) {
	switch {
	case segment[0] == 'i':
		t.Imports["strconv"] = true
		segment = segment[1:]
		t.writeIntegerInterpolationSegment(segment)
	default:
		t.writeStringInterpolationSegment(segment)
	}

	return nil
}

func (t *Template) writeIntegerInterpolationSegment(segment []byte) (err error) {
	_, err = writeWrapped(&t.Body, "io.WriteString(writer, strconv.FormatInt(int64(", segment, "), 10))\n")
	return err
}

func (t *Template) writeStringInterpolationSegment(segment []byte) (err error) {
	switch t.Escape {
	case "":
		return t.writeRawStringInterpolationSegment(segment)
	case "html":
		t.Imports["html"] = true
		return t.writeHTMLEscapedStringInterpolationSegment(segment)
	default:
		return errors.New("Unknown escape type")
	}
}

func (t *Template) writeRawStringInterpolationSegment(segment []byte) (err error) {
	_, err = writeWrapped(&t.Body, "io.WriteString(writer, ", segment, ")\n")
	return err
}

func (t *Template) writeHTMLEscapedStringInterpolationSegment(segment []byte) (err error) {
	_, err = writeWrapped(&t.Body, "io.WriteString(writer, html.EscapeString(", segment, "))\n")
	return err
}

func (t *Template) writeGoSegment(segment []byte) (err error) {
	_, err = writeMultiple(&t.Body, segment, []byte("\n"))
	return err
}

func writeWrapped(w io.Writer, prefix string, data []byte, suffix string) (count int64, err error) {
	return writeMultiple(w, []byte(prefix), data, []byte(suffix))
}

func writeMultiple(w io.Writer, segments ...[]byte) (count int64, err error) {
	for _, s := range segments {
		var n int
		n, err = w.Write(s)
		count += int64(n)
		if err != nil {
			return
		}
	}

	return count, err
}

func main() {

	templates := make([]*Template, 0, len(os.Args[1:]))

	for _, path := range os.Args[1:] {
		fileBytes, err := ioutil.ReadFile(path)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		var t Template
		err = t.Parse(fileBytes)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Invalid template format: %v", err)
			os.Exit(1)
		}
		templates = append(templates, &t)
	}

	imports := make(map[string]bool)
	for _, t := range templates {
		for pkg, _ := range t.Imports {
			imports[pkg] = true
		}
	}

	fmt.Printf("package main\n")
	fmt.Printf("import (\n")
	for pkg, _ := range imports {
		fmt.Printf("\"%s\"\n", pkg)
	}
	fmt.Printf(")\n")

	for _, t := range templates {

		fmt.Printf("func %s(%s) (err error) {\n%s\nreturn\n}\n", t.FuncName, t.Parameters, t.Body.String())
	}
}
<commit_msg>Refactor to segments<commit_after>package main

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

type Template struct {
	FuncName   string
	Parameters string
	Imports    map[string]bool
	Escape     string
	Segments   []io.WriterTo
}

type StringSegment []byte

func (s StringSegment) WriteTo(w io.Writer) (n int64, err error) {
	return writeWrapped(w, "io.WriteString(writer, `", s, "`)\n")
}

type GoSegment []byte

func (s GoSegment) WriteTo(w io.Writer) (n int64, err error) {
	return writeMultiple(w, s, []byte("\n"))
}

type IntegerInterpolationSegment []byte

func (s IntegerInterpolationSegment) WriteTo(w io.Writer) (n int64, err error) {
	return writeWrapped(w, "io.WriteString(writer, strconv.FormatInt(int64(", s, "), 10))\n")
}

type RawStringInterpolationSegment []byte

func (s RawStringInterpolationSegment) WriteTo(w io.Writer) (n int64, err error) {
	return writeWrapped(w, "io.WriteString(writer, ", s, ")\n")
}

type HTMLEscapedStringInterpolationSegment []byte

func (s HTMLEscapedStringInterpolationSegment) WriteTo(w io.Writer) (n int64, err error) {
	return writeWrapped(w, "io.WriteString(writer, html.EscapeString(", s, "))\n")
}

func (t *Template) Parse(templateBytes []byte) (err error) {
	regions := bytes.SplitN(templateBytes, []byte("\n---\n"), 2)

	if len(regions) != 2 {
		return errors.New("Did not find divider between header and body.")
	}

	err = t.parseHeader(regions[0])
	if err != nil {
		return err
	}

	err = t.parseBody(regions[1])
	if err != nil {
		return err
	}

	return nil
}

func (t *Template) parseHeader(header []byte) (err error) {
	lines := bytes.Split(header, []byte("\n"))
	options := make(map[string]string, len(lines))
	for i, l := range lines {
		pair := bytes.SplitN(l, []byte(":"), 2)
		if len(pair) != 2 {
			return fmt.Errorf("Bad header line: %d", i)
		}
		options[string(pair[0])] = string(bytes.Trim(pair[1], " "))
	}

	t.FuncName = options["func"]
	if t.FuncName == "" {
		return errors.New(`Missing "func"`)
	}

	t.Escape = options["escape"]

	t.Parameters = "writer io.Writer"
	var extraParameters string
	extraParameters = options["parameters"]
	if len(extraParameters) > 0 {
		t.Parameters = t.Parameters + ", " + extraParameters
	}

	t.Imports = map[string]bool{"io": true}

	var extraImports string
	extraImports = options["imports"]
	if len(extraImports) > 0 {
		for _, pkg := range strings.Split(extraImports, " ") {
			t.Imports[strings.Trim(pkg, " ")] = true
		}
	}

	return nil
}

func (t *Template) parseBody(body []byte) (err error) {
	unparsed := body

	for len(unparsed) > 0 {
		next := bytes.Index(unparsed, []byte("<%"))
		switch {
		case next > 0:
			segment := unparsed[:next]
			t.Segments = append(t.Segments, StringSegment(segment))
			unparsed = unparsed[next:]
		case next == 0:
			unparsed = unparsed[2:]
			endGo := bytes.Index(unparsed, []byte("%>"))

			if endGo > -1 {
				segment := unparsed[:endGo]

				if segment[0] == '=' {
					if segment[1] == 'i' {
						t.Imports["strconv"] = true
						t.Segments = append(t.Segments, IntegerInterpolationSegment(segment[2:]))
					} else {
						switch t.Escape {
						case "":
							t.Segments = append(t.Segments, RawStringInterpolationSegment(segment[1:]))
						case "html":
							t.Imports["html"] = true
							t.Segments = append(t.Segments, HTMLEscapedStringInterpolationSegment(segment[1:]))
						default:
							return errors.New("Unknown escape type")
						}
					}
				} else {
					t.Segments = append(t.Segments, GoSegment(segment))
				}

				unparsed = unparsed[endGo+2:]
			} else {
				return errors.New("Unable to parse")
			}
		default:
			t.Segments = append(t.Segments, StringSegment(unparsed))
			unparsed = nil
			break
		}
	}

	return nil
}

func writeWrapped(w io.Writer, prefix string, data []byte, suffix string) (count int64, err error) {
	return writeMultiple(w, []byte(prefix), data, []byte(suffix))
}

func writeMultiple(w io.Writer, segments ...[]byte) (count int64, err error) {
	for _, s := range segments {
		var n int
		n, err = w.Write(s)
		count += int64(n)
		if err != nil {
			return
		}
	}

	return count, err
}

func main() {

	templates := make([]*Template, 0, len(os.Args[1:]))

	for _, path := range os.Args[1:] {
		fileBytes, err := ioutil.ReadFile(path)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		var t Template
		err = t.Parse(fileBytes)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Invalid template format: %v", err)
			os.Exit(1)
		}
		templates = append(templates, &t)
	}

	imports := make(map[string]bool)
	for _, t := range templates {
		for pkg, _ := range t.Imports {
			imports[pkg] = true
		}
	}

	fmt.Printf("package main\n")
	fmt.Printf("import (\n")
	for pkg, _ := range imports {
		fmt.Printf("\"%s\"\n", pkg)
	}
	fmt.Printf(")\n")

	for _, t := range templates {
		fmt.Printf("func %s(%s) (err error) {\n", t.FuncName, t.Parameters)
		for _, s := range t.Segments {
			s.WriteTo(os.Stdout)
		}
		fmt.Printf("\nreturn\n}\n")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/gob"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

var (
	modshell32         = syscall.NewLazyDLL("shell32.dll")
	procShellExecuteEx = modshell32.NewProc("ShellExecuteExW")
)

const (
	SEE_MASK_NOCLOSEPROCESS = 0x00000040
)

const (
	ERROR_BAD_FORMAT = 11
)

const (
	SE_ERR_FNF             = 2
	SE_ERR_PNF             = 3
	SE_ERR_ACCESSDENIED    = 5
	SE_ERR_OOM             = 8
	SE_ERR_DLLNOTFOUND     = 32
	SE_ERR_SHARE           = 26
	SE_ERR_ASSOCINCOMPLETE = 27
	SE_ERR_DDETIMEOUT      = 28
	SE_ERR_DDEFAIL         = 29
	SE_ERR_DDEBUSY         = 30
	SE_ERR_NOASSOC         = 31
)

type (
	DWORD     uint32
	HANDLE    uintptr
	HINSTANCE HANDLE
	HKEY      HANDLE
	HWND      HANDLE
	ULONG     uint32
	LPCTSTR   uintptr
	LPVOID    uintptr
)

type SHELLEXECUTEINFO struct {
	cbSize         DWORD
	fMask          ULONG
	hwnd           HWND
	lpVerb         LPCTSTR
	lpFile         LPCTSTR
	lpParameters   LPCTSTR
	lpDirectory    LPCTSTR
	nShow          int
	hInstApp       HINSTANCE
	lpIDList       LPVOID
	lpClass        LPCTSTR
	hkeyClass      HKEY
	dwHotKey       DWORD
	hIconOrMonitor HANDLE
	hProcess       HANDLE
}

func ShellExecuteAndWait(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
	var lpctstrVerb, lpctstrParameters, lpctstrDirectory LPCTSTR
	if len(lpOperation) != 0 {
		lpctstrVerb = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
	}
	if len(lpParameters) != 0 {
		lpctstrParameters = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
	}
	if len(lpDirectory) != 0 {
		lpctstrDirectory = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
	}
	i := &SHELLEXECUTEINFO{
		fMask:        SEE_MASK_NOCLOSEPROCESS,
		hwnd:         hwnd,
		lpVerb:       lpctstrVerb,
		lpFile:       LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
		lpParameters: lpctstrParameters,
		lpDirectory:  lpctstrDirectory,
		nShow:        nShowCmd,
	}
	i.cbSize = DWORD(unsafe.Sizeof(*i))
	return ShellExecuteEx(i)
}

func ShellExecuteEx(pExecInfo *SHELLEXECUTEINFO) error {
	ret, _, _ := procShellExecuteEx.Call(uintptr(unsafe.Pointer(pExecInfo)))
	if ret == 1 && pExecInfo.fMask&SEE_MASK_NOCLOSEPROCESS != 0 {
		s, e := syscall.WaitForSingleObject(syscall.Handle(pExecInfo.hProcess), syscall.INFINITE)
		switch s {
		case syscall.WAIT_OBJECT_0:
			break
		case syscall.WAIT_FAILED:
			return os.NewSyscallError("WaitForSingleObject", e)
		default:
			return errors.New("Unexpected result from WaitForSingleObject")
		}
	}
	errorMsg := ""
	if pExecInfo.hInstApp != 0 && pExecInfo.hInstApp <= 32 {
		switch int(pExecInfo.hInstApp) {
		case SE_ERR_FNF:
			errorMsg = "The specified file was not found"
		case SE_ERR_PNF:
			errorMsg = "The specified path was not found"
		case ERROR_BAD_FORMAT:
			errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)"
		case SE_ERR_ACCESSDENIED:
			errorMsg = "The operating system denied access to the specified file"
		case SE_ERR_ASSOCINCOMPLETE:
			errorMsg = "The file name association is incomplete or invalid"
		case SE_ERR_DDEBUSY:
			errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed"
		case SE_ERR_DDEFAIL:
			errorMsg = "The DDE transaction failed"
		case SE_ERR_DDETIMEOUT:
			errorMsg = "The DDE transaction could not be completed because the request timed out"
		case SE_ERR_DLLNOTFOUND:
			errorMsg = "The specified DLL was not found"
		case SE_ERR_NOASSOC:
			errorMsg = "There is no application associated with the given file name extension"
		case SE_ERR_OOM:
			errorMsg = "There was not enough memory to complete the operation"
		case SE_ERR_SHARE:
			errorMsg = "A sharing violation occurred"
		default:
			errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", pExecInfo.hInstApp)
		}
	} else {
		return nil
	}
	return errors.New(errorMsg)
}

type Message struct {
	Type string
	Exit int
	Data []byte
}

func msgWrite(enc *gob.Encoder, typ string) io.WriteCloser {
	r, w := io.Pipe()
	go func() {
		defer r.Close()
		var b [256]byte
		for {
			n, err := r.Read(b[:])
			if err != nil {
				break
			}
			enc.Encode(&Message{Type: typ, Exit: 0, Data: b[:n]})
		}
	}()
	return w
}

func client(addr string) int {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)
	dec := gob.NewDecoder(conn)

	outw := msgWrite(enc, "stdout")
	defer outw.Close()
	errw := msgWrite(enc, "stderr")
	defer errw.Close()

	cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
	inw, err := cmd.StdinPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer inw.Close()
	cmd.Stdout = outw
	cmd.Stderr = errw

	go func() {
		defer inw.Close()
	in_loop:
		for {
			var msg Message
			err = dec.Decode(&msg)
			if err != nil {
				return
			}
			switch msg.Type {
			case "close":
				break in_loop
			case "stdin":
				inw.Write(msg.Data)
			}
		}
	}()

	err = cmd.Run()

	code := 1
	if err != nil {
		if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
			code = status.ExitStatus()
		}
	} else {
		code = 0
	}
	enc.Encode(&Message{Type: "exit", Exit: code})
	return 0
}

func makeCmdLine(args []string) string {
	var s string
	for _, v := range args {
		if s != "" {
			s += " "
		}
		s += syscall.EscapeArg(v)
	}
	return s
}

func server() int {
	lis, err := net.Listen("tcp", "127.0.0.1:8880")
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer lis.Close()

	os.Setenv("GO-SUDO", lis.Addr().String())

	exe, err := os.Executable()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	args := []string{"-mode", lis.Addr().String()}
	args = append(args, flag.Args()...)

	var conn net.Conn

	go func() {
		err = ShellExecuteAndWait(0, "runas", exe, makeCmdLine(args), "", syscall.SW_HIDE)
		if err != nil && conn != nil {
			conn.Close()
		}
		lis.Close()
	}()

	conn, err = lis.Accept()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot execute command: %v", exe)
		return 1
	}
	defer conn.Close()

	go func() {
		return
		var b [256]byte
		enc := gob.NewEncoder(conn)
		for {
			n, err := os.Stdin.Read(b[:])
			if err != nil {
				enc.Encode(&Message{Type: "close"})
				break
			}
			enc.Encode(&Message{Type: "stdin", Data: b[:n]})
		}
	}()

	dec := gob.NewDecoder(conn)
	for {
		var msg Message
		err = dec.Decode(&msg)
		if err != nil {
			fmt.Fprintln(os.Stderr, "cannot communicate child process: %v", err)
			return 1
		}
		switch msg.Type {
		case "stdout":
			os.Stdout.Write(msg.Data)
		case "stderr":
			os.Stderr.Write(msg.Data)
		case "exit":
			return msg.Exit
		}
	}
	return 0
}

func main() {
	var mode string
	flag.StringVar(&mode, "mode", "", "mode")
	flag.Parse()
	if mode != "" {
		os.Exit(client(mode))
	}
	os.Exit(server())
}
<commit_msg>use random port number<commit_after>package main

import (
	"encoding/gob"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

var (
	modshell32         = syscall.NewLazyDLL("shell32.dll")
	procShellExecuteEx = modshell32.NewProc("ShellExecuteExW")
)

const (
	SEE_MASK_NOCLOSEPROCESS = 0x00000040
)

const (
	ERROR_BAD_FORMAT = 11
)

const (
	SE_ERR_FNF             = 2
	SE_ERR_PNF             = 3
	SE_ERR_ACCESSDENIED    = 5
	SE_ERR_OOM             = 8
	SE_ERR_DLLNOTFOUND     = 32
	SE_ERR_SHARE           = 26
	SE_ERR_ASSOCINCOMPLETE = 27
	SE_ERR_DDETIMEOUT      = 28
	SE_ERR_DDEFAIL         = 29
	SE_ERR_DDEBUSY         = 30
	SE_ERR_NOASSOC         = 31
)

type (
	DWORD     uint32
	HANDLE    uintptr
	HINSTANCE HANDLE
	HKEY      HANDLE
	HWND      HANDLE
	ULONG     uint32
	LPCTSTR   uintptr
	LPVOID    uintptr
)

type SHELLEXECUTEINFO struct {
	cbSize         DWORD
	fMask          ULONG
	hwnd           HWND
	lpVerb         LPCTSTR
	lpFile         LPCTSTR
	lpParameters   LPCTSTR
	lpDirectory    LPCTSTR
	nShow          int
	hInstApp       HINSTANCE
	lpIDList       LPVOID
	lpClass        LPCTSTR
	hkeyClass      HKEY
	dwHotKey       DWORD
	hIconOrMonitor HANDLE
	hProcess       HANDLE
}

func ShellExecuteAndWait(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
	var lpctstrVerb, lpctstrParameters, lpctstrDirectory LPCTSTR
	if len(lpOperation) != 0 {
		lpctstrVerb = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
	}
	if len(lpParameters) != 0 {
		lpctstrParameters = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
	}
	if len(lpDirectory) != 0 {
		lpctstrDirectory = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
	}
	i := &SHELLEXECUTEINFO{
		fMask:        SEE_MASK_NOCLOSEPROCESS,
		hwnd:         hwnd,
		lpVerb:       lpctstrVerb,
		lpFile:       LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
		lpParameters: lpctstrParameters,
		lpDirectory:  lpctstrDirectory,
		nShow:        nShowCmd,
	}
	i.cbSize = DWORD(unsafe.Sizeof(*i))
	return ShellExecuteEx(i)
}

func ShellExecuteEx(pExecInfo *SHELLEXECUTEINFO) error {
	ret, _, _ := procShellExecuteEx.Call(uintptr(unsafe.Pointer(pExecInfo)))
	if ret == 1 && pExecInfo.fMask&SEE_MASK_NOCLOSEPROCESS != 0 {
		s, e := syscall.WaitForSingleObject(syscall.Handle(pExecInfo.hProcess), syscall.INFINITE)
		switch s {
		case syscall.WAIT_OBJECT_0:
			break
		case syscall.WAIT_FAILED:
			return os.NewSyscallError("WaitForSingleObject", e)
		default:
			return errors.New("Unexpected result from WaitForSingleObject")
		}
	}
	errorMsg := ""
	if pExecInfo.hInstApp != 0 && pExecInfo.hInstApp <= 32 {
		switch int(pExecInfo.hInstApp) {
		case SE_ERR_FNF:
			errorMsg = "The specified file was not found"
		case SE_ERR_PNF:
			errorMsg = "The specified path was not found"
		case ERROR_BAD_FORMAT:
			errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)"
		case SE_ERR_ACCESSDENIED:
			errorMsg = "The operating system denied access to the specified file"
		case SE_ERR_ASSOCINCOMPLETE:
			errorMsg = "The file name association is incomplete or invalid"
		case SE_ERR_DDEBUSY:
			errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed"
		case SE_ERR_DDEFAIL:
			errorMsg = "The DDE transaction failed"
		case SE_ERR_DDETIMEOUT:
			errorMsg = "The DDE transaction could not be completed because the request timed out"
		case SE_ERR_DLLNOTFOUND:
			errorMsg = "The specified DLL was not found"
		case SE_ERR_NOASSOC:
			errorMsg = "There is no application associated with the given file name extension"
		case SE_ERR_OOM:
			errorMsg = "There was not enough memory to complete the operation"
		case SE_ERR_SHARE:
			errorMsg = "A sharing violation occurred"
		default:
			errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", pExecInfo.hInstApp)
		}
	} else {
		return nil
	}
	return errors.New(errorMsg)
}

type Message struct {
	Type string
	Exit int
	Data []byte
}

func msgWrite(enc *gob.Encoder, typ string) io.WriteCloser {
	r, w := io.Pipe()
	go func() {
		defer r.Close()
		var b [256]byte
		for {
			n, err := r.Read(b[:])
			if err != nil {
				break
			}
			enc.Encode(&Message{Type: typ, Exit: 0, Data: b[:n]})
		}
	}()
	return w
}

func client(addr string) int {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)
	dec := gob.NewDecoder(conn)

	outw := msgWrite(enc, "stdout")
	defer outw.Close()
	errw := msgWrite(enc, "stderr")
	defer errw.Close()

	cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
	inw, err := cmd.StdinPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer inw.Close()
	cmd.Stdout = outw
	cmd.Stderr = errw

	go func() {
		defer inw.Close()
	in_loop:
		for {
			var msg Message
			err = dec.Decode(&msg)
			if err != nil {
				return
			}
			switch msg.Type {
			case "close":
				break in_loop
			case "stdin":
				inw.Write(msg.Data)
			}
		}
	}()

	err = cmd.Run()

	code := 1
	if err != nil {
		if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
			code = status.ExitStatus()
		}
	} else {
		code = 0
	}
	enc.Encode(&Message{Type: "exit", Exit: code})
	return 0
}

func makeCmdLine(args []string) string {
	var s string
	for _, v := range args {
		if s != "" {
			s += " "
		}
		s += syscall.EscapeArg(v)
	}
	return s
}

func server() int {
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	defer lis.Close()

	os.Setenv("GO-SUDO", lis.Addr().String())

	exe, err := os.Executable()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot find executable: %v", os.Args[0])
		return 1
	}
	args := []string{"-mode", lis.Addr().String()}
	args = append(args, flag.Args()...)

	var conn net.Conn

	go func() {
		err = ShellExecuteAndWait(0, "runas", exe, makeCmdLine(args), "", syscall.SW_HIDE)
		if err != nil && conn != nil {
			conn.Close()
		}
		lis.Close()
	}()

	conn, err = lis.Accept()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot execute command: %v", exe)
		return 1
	}
	defer conn.Close()

	go func() {
		return
		var b [256]byte
		enc := gob.NewEncoder(conn)
		for {
			n, err := os.Stdin.Read(b[:])
			if err != nil {
				enc.Encode(&Message{Type: "close"})
				break
			}
			enc.Encode(&Message{Type: "stdin", Data: b[:n]})
		}
	}()

	dec := gob.NewDecoder(conn)
	for {
		var msg Message
		err = dec.Decode(&msg)
		if err != nil {
			fmt.Fprintln(os.Stderr, "cannot communicate child process: %v", err)
			return 1
		}
		switch msg.Type {
		case "stdout":
			os.Stdout.Write(msg.Data)
		case "stderr":
			os.Stderr.Write(msg.Data)
		case "exit":
			return msg.Exit
		}
	}
	return 0
}

func main() {
	var mode string
	flag.StringVar(&mode, "mode", "", "mode")
	flag.Parse()
	if mode != "" {
		os.Exit(client(mode))
	}
	os.Exit(server())
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

var (
	client      *http.Client
	registryURL string
)

type repos struct {
	Query      string `json:"query"`
	NumResults int    `json:"num_results"`
	Results    []repo `json:"results"`
}

type repo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

type tag string

type image string

type tags map[tag]image

type imageNode struct {
	id       image
	tags     []tag
	children []*imageNode
}

func init() {
	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client = &http.Client{Transport: transport}
}

func doGet(path string) []byte {
	res, err := client.Get(registryURL + "/v1/" + path)
	if err != nil {
		panic(err.Error())
	}
	if res.StatusCode != 200 {
		return []byte{}
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err.Error())
	}
	res.Body.Close()
	return body
}

func getRepos() repos {
	log.Print("Fetching repos...")
	var repos repos
	json.Unmarshal(doGet("search"), &repos)
	log.Printf("%v repo(s) fetched", repos.NumResults)
	return repos
}

func getTags(name string) map[tag]image {
	log.Printf("Fetching tags for %s ...", name)
	var (
		rawTags tags
		fqTags  tags
	)
	json.Unmarshal(doGet("repositories/"+name+"/tags"), &rawTags)
	log.Printf("%v tags fetched for repo %s", len(rawTags), name)
	fqTags = make(map[tag]image)
	for tag, id := range rawTags {
		fqTags[fqTag(name, tag)] = id
	}
	return fqTags
}

func getAncestry(id image) []image {
	log.Printf("Fetching ancestry for %s ...", id)
	var ancestry []image
	json.Unmarshal(doGet("images/"+string(id)+"/ancestry"), &ancestry)
	log.Printf("%v ancestors fetched for repo %s", len(ancestry), id)
	return ancestry
}

func fqTag(name string, t tag) tag {
	canonicalName := strings.TrimPrefix(name, "library/")
	return tag(canonicalName + ":" + string(t))
}

func printTree(root *imageNode, level int) {
	if len(root.tags) > 0 || len(root.children) > 1 {
		fmt.Printf("%s %s%v\n", root.id, strings.Repeat("  ", level), root.tags)
		level = level + 1
	}
	for _, child := range root.children {
		printTree(child, level)
	}
}

func main() {
	var (
		remaining   int                          // how many more responses are we waiting from the goroutine?
		tagsCh      = make(chan tags)            // tags fetcher/consumer channel
		tagsByImage = make(map[image][]tag)      // image ids grouped by tags
		ancestryCh  = make(chan []image)         // ancestries fetcher/consumer channel
		images      = make(map[image]*imageNode) // already processed nodes as we are building up the trees
		roots       []*imageNode                 // roots as we are building up the threes
	)
	if len(registryURL) == 0 {
		registryURL = os.Getenv("REGISTRY_URL")
	}
	if len(registryURL) == 0 {
		log.Fatal("No registry URL provided, use the environment variable REGISTRY_URL to set it")
	}
	if len(os.Getenv("REGISTREE_DEBUG")) > 0 {
		log.SetOutput(os.Stderr)
	} else {
		log.SetOutput(ioutil.Discard)
	}
	// get tags in parallel
	for _, repo := range getRepos().Results {
		remaining = remaining + 1
		go func(name string) { tagsCh <- getTags(name) }(repo.Name)
	}
	// group them as they are fetched
	for remaining != 0 {
		for tag, id := range <-tagsCh {
			tags, _ := tagsByImage[id]
			tagsByImage[id] = append(tags, tag)
		}
		remaining = remaining - 1
	}
	// get ancestries in parallel
	for imageId := range tagsByImage {
		go func(id image) { ancestryCh <- getAncestry(id) }(imageId)
	}
	// process them as they arrive until all tagged images have been used
	for len(tagsByImage) != 0 {
		var (
			ancestry     = <-ancestryCh
			previousNode *imageNode
		)
		for _, id := range ancestry {
			if node, ok := images[id]; ok {
				// we already went up the hierarchy from there, just append a new child
				if previousNode != nil {
					node.children = append(node.children, previousNode)
				}
				previousNode = nil
				break
			}
			node := &imageNode{id: id}
			if tags, ok := tagsByImage[id]; ok {
				node.tags = tags
				// don't wait for that image's ancestry, we already are going up that one
				delete(tagsByImage, id)
			}
			if previousNode != nil {
				// this is not a leaf in the tree, so attach its child
				node.children = []*imageNode{previousNode}
			}
			images[id] = node
			previousNode = node
		}
		if previousNode != nil {
			// the previous loop didn't break out, so the last node considered is a root
			roots = append(roots, previousNode)
		}
	}
	// dump all the trees
	for _, root := range roots {
		printTree(root, 0)
	}

}
<commit_msg>use docker-reg-client for v1 access instead of custom code<commit_after>package main

import (
	"fmt"
	"github.com/CenturyLinkLabs/docker-reg-client/registry"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"strings"
)

var (
	client      *registry.Client
	registryURL string
)

type imageNode struct {
	id       string
	tags     []string
	children []*imageNode
}

func init() {
	client = registry.NewClient()
}

func getRepos() *registry.SearchResults {
	log.Print("Fetching repos...")
	results, _ := client.Search.Query("", 0, 0)
	log.Printf("%v repo(s) fetched", results.NumResults)
	return results
}

func getTags(name string) registry.TagMap {
	log.Printf("Fetching tags for %s ...", name)
	tags, _ := client.Repository.ListTags(name, registry.NilAuth{})
	log.Printf("%v tags fetched for repo %s", len(tags), name)
	fqTags := make(registry.TagMap)
	for tag, id := range tags {
		fqTags[fqTag(name, tag)] = id
	}
	return fqTags
}

func getAncestry(id string) []string {
	log.Printf("Fetching ancestry for %s ...", id)
	ancestry, _ := client.Image.GetAncestry(id, registry.NilAuth{})
	log.Printf("%v ancestors fetched for repo %s", len(ancestry), id)
	return ancestry
}

func fqTag(name string, t string) string {
	canonicalName := strings.TrimPrefix(name, "library/")
	return canonicalName + ":" + t
}

func printTree(root *imageNode, level int) {
	if len(root.tags) > 0 || len(root.children) > 1 {
		fmt.Printf("%s %s%v\n", root.id, strings.Repeat("  ", level), root.tags)
		level = level + 1
	}
	for _, child := range root.children {
		printTree(child, level)
	}
}

func main() {
	var (
		remaining   int                           // how many more responses are we waiting from the goroutine?
		tagsCh      = make(chan registry.TagMap)  // tags fetcher/consumer channel
		tagsByImage = make(map[string][]string)   // image ids grouped by tags
		ancestryCh  = make(chan []string)         // ancestries fetcher/consumer channel
		images      = make(map[string]*imageNode) // already processed nodes as we are building up the trees
		roots       []*imageNode                  // roots as we are building up the threes
	)
	if len(registryURL) == 0 {
		registryURL = os.Getenv("REGISTRY_URL")
	}
	if len(registryURL) == 0 {
		log.Fatal("No registry URL provided, use the environment variable REGISTRY_URL to set it")
	}
	if len(os.Getenv("REGISTREE_DEBUG")) > 0 {
		log.SetOutput(os.Stderr)
	} else {
		log.SetOutput(ioutil.Discard)
	}
	client.BaseURL, _ = url.Parse(registryURL + "/v1/")
	// get tags in parallel
	for _, repo := range getRepos().Results {
		remaining = remaining + 1
		go func(name string) { tagsCh <- getTags(name) }(repo.Name)
	}
	// group them as they are fetched
	for remaining != 0 {
		for tag, id := range <-tagsCh {
			tags, _ := tagsByImage[id]
			tagsByImage[id] = append(tags, tag)
		}
		remaining = remaining - 1
	}
	// get ancestries in parallel
	for imageId := range tagsByImage {
		go func(id string) { ancestryCh <- getAncestry(id) }(imageId)
	}
	// process them as they arrive until all tagged images have been used
	for len(tagsByImage) != 0 {
		var (
			ancestry     = <-ancestryCh
			previousNode *imageNode
		)
		for _, id := range ancestry {
			if node, ok := images[id]; ok {
				// we already went up the hierarchy from there, just append a new child
				if previousNode != nil {
					node.children = append(node.children, previousNode)
				}
				previousNode = nil
				break
			}
			node := &imageNode{id: id}
			if tags, ok := tagsByImage[id]; ok {
				node.tags = tags
				// don't wait for that image's ancestry, we already are going up that one
				delete(tagsByImage, id)
			}
			if previousNode != nil {
				// this is not a leaf in the tree, so attach its child
				node.children = []*imageNode{previousNode}
			}
			images[id] = node
			previousNode = node
		}
		if previousNode != nil {
			// the previous loop didn't break out, so the last node considered is a root
			roots = append(roots, previousNode)
		}
	}
	// dump all the trees
	for _, root := range roots {
		printTree(root, 0)
	}

}
<|endoftext|>


<commit_before>package main

//go:generate make generate

import (
	"math/rand"
	"time"

	"github.com/kolide/kolide-ose/cli"
	_ "github.com/kolide/kolide-ose/config"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	cli.Launch()
}
<commit_msg>rm go generate<commit_after>package main

import (
	"math/rand"
	"time"

	"github.com/kolide/kolide-ose/cli"
	_ "github.com/kolide/kolide-ose/config"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	cli.Launch()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"syscall"
	"time"

	"strconv"

	"github.com/go-resty/resty"
	"github.com/yosssi/gmq/mqtt"
	"github.com/yosssi/gmq/mqtt/client"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/yaml.v2"
)

//HomeAssistant data
type HomeAssistantData struct {
	EventType string    `json:"event_type"`
	EventData EventData `json:"event_data"`
}

type EventData struct {
	EntityID string     `json:"entity_id"`
	OldState EventState `json:"old_state"`
	NewState EventState `json:"new_state"`
}

type EventState struct {
	EntityID    string                 `json:"entity_id"`
	State       string                 `json:"state"`
	Attributes  map[string]interface{} `json:"attributes"`
	LastChanged *time.Time             `json:"last_changed"`
	LastUpdated *time.Time             `json:"last_updated"`
}

//DomoticzsData data from Domoticz
type DomoticzsData struct {
	ID      string `json:"id"`
	Svalue1 string `json:"svalue1"`
	Name    string `json:"name"`
}

// sample = {'name' : row[1], 'value' : float(row[0]), 'type' : 'TEMPERATURE', 'timestamp' : row[2] * 1000}
type VaderData struct {
	Name       string  `json:"name"`
	Value      float64 `json:"value"`
	SensorType string  `json:"type"`
	Timestamp  string  `json:"timestamp"`
}

type Configuration struct {
	DataFormat string
	RemoteHost string
	RemoteApp  string
	MQTTHost   string
	Group      string
	Sensor     []ConfigurationSensor
}

type ConfigurationSensor struct {
	Domoticz string
	Vader    string
	SType    string
}

var blowup bool
var premult bool
var temperature string
var tempKitchen string
var configFile = "config.yaml"
var config Configuration
var logger *zap.Logger

func init() {
	flag.StringVar(&configFile, "configfile", "config.yaml", "The config file to use, default config.yaml")
}

func main() {
	flag.Parse()
	logger, level, err := createLogger()

	if err != nil {
		fmt.Printf("Could not initialize zap logger: %v\n", err)
		os.Exit(1)
	}

	level.SetLevel(zapcore.DebugLevel)

	logger.Info("Starting up...\n")
	config = Configuration{}

	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		logger.Fatal("Could not read config file", zap.String("config file", configFile))
	}

	err = yaml.Unmarshal(data, &config)
	if err != nil {
		logger.Fatal("error", zap.Error(err))
	}

	logger.Debug("Lengt of sensors list", zap.Int("len", len(config.Sensor)))

	sigs := make(chan os.Signal, 1)
	done := make(chan bool, 1)

	go func() {
		_ = <-sigs
		done <- true
	}()

	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	cli := client.New(&client.Options{
		ErrorHandler: func(err error) {
			fmt.Println(err)
		},
	})

	// Terminate the Client.
	defer cli.Terminate()

	// Connect to the MQTT Server.
	err = cli.Connect(&client.ConnectOptions{
		Network:  "tcp",
		Address:  fmt.Sprintf("%s:1883", config.MQTTHost),
		ClientID: []byte("vader"),
	})
	if err != nil {
		panic(err)
	}

	logger.Debug("Connected to server")

	if config.DataFormat == "hass" {
		logger.Debug("Dataformat Home Assistant")
		// Subscribe to topics.
		err = cli.Subscribe(&client.SubscribeOptions{
			SubReqs: []*client.SubReq{
				&client.SubReq{
					TopicFilter: []byte("Tvistevägen"),
					QoS:         mqtt.QoS0,
					// Define the processing of the message handler.
					Handler: func(topicName, message []byte) {
						logger.Debug("full message", zap.ByteString("msg", message))
						had := &HomeAssistantData{}
						err := json.Unmarshal(message, had)
						if err != nil {
							logger.Error("Failed to unmarshall data", zap.Error(err))
						}
						name, stype := findVaderTypes(had.EventData.EntityID)
						if name != "" {
							valueFloat := had.EventData.NewState.Attributes["Temperature"].(float64)
							if err != nil {
								logger.Error("Could not parse float", zap.Any("value", had.EventData.NewState.Attributes["Temperature"]))
								return
							}
							if name != "" {
								vd := VaderData{
									Name:       name,
									Value:      valueFloat,
									SensorType: stype,
									Timestamp:  fmt.Sprintf("%d", time.Now().Unix()*1000),
								}
								sendData(vd)
							} else {
								logger.Debug("Found NO name")
							}
						}
					},
				},
			},
		})
	}
	if config.DataFormat == "domoticz" {
		logger.Debug("Dataformat Domoticz")
		// Subscribe to topics.
		err = cli.Subscribe(&client.SubscribeOptions{
			SubReqs: []*client.SubReq{
				&client.SubReq{
					TopicFilter: []byte("domoticz/out"),
					QoS:         mqtt.QoS0,
					// Define the processing of the message handler.
					Handler: func(topicName, message []byte) {
						logger.Debug("full message", zap.ByteString("msg", message))
						dd := &DomoticzsData{}
						err := json.Unmarshal(message, dd)
						if err != nil {
							logger.Error("Failed to unmarshall data", zap.Error(err))
						}
						name, stype := findVaderTypes(dd.Name)
						valueFloat, err := strconv.ParseFloat(dd.Svalue1, 64)
						if err != nil {
							logger.Error("Could not parse float", zap.String("value", dd.Svalue1))
							return
						}
						if name != "" {
							vd := VaderData{
								Name:       name,
								Value:      valueFloat,
								SensorType: stype,
								Timestamp:  fmt.Sprintf("%d", time.Now().Unix()*1000),
							}
							sendData(vd)
						}
					},
				},
			},
		})
	}

	if err != nil {
		panic(err)
	}

	logger.Debug("Awaiting signal")
	<-done
	logger.Info("Exiting")

	// Disconnect the Network Connection.
	if err := cli.Disconnect(); err != nil {
		panic(err)
	}
}

func newEncoderConfig() zapcore.EncoderConfig {
	return zapcore.EncoderConfig{
		// Keys can be anything except the empty string.
		TimeKey:        "T",
		LevelKey:       "L",
		NameKey:        "N",
		CallerKey:      "C",
		MessageKey:     "M",
		StacktraceKey:  "S",
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
}

func newDevelopmentConfig() zap.Config {
	dyn := zap.NewAtomicLevel()
	dyn.SetLevel(zap.DebugLevel)

	return zap.Config{
		Level:            dyn,
		Development:      true,
		Encoding:         "console",
		EncoderConfig:    newEncoderConfig(),
		OutputPaths:      []string{"stderr"},
		ErrorOutputPaths: []string{"stderr"},
	}
}

func createLogger() (*zap.Logger, zap.AtomicLevel, error) {
	cfg := newDevelopmentConfig()
	logger, err := cfg.Build()
	if err != nil {
		return nil, zap.AtomicLevel{}, err
	}
	return logger, cfg.Level, nil
}

func findVaderTypes(domoticz string) (string, string) {
	for _, s := range config.Sensor {
		fmt.Printf("%s, %s\n", s.Domoticz, domoticz)
		if s.Domoticz == domoticz {
			return s.Vader, s.SType
		}
	}
	return "", ""
}

func sendData(vd VaderData) {
	list := make([]VaderData, 0)
	list = append(list, vd)
	resp, err := resty.R().
		SetBody(list).
		Post("http://" + config.RemoteHost + "/" + config.RemoteApp + "/rest/save")
	if err != nil {
		logger.Error("Failed to post data", zap.Error(err))
		return
	}
	if resp == nil {
		logger.Debug("Respsonse is nil")
	} else {
		fmt.Printf("status code is %d", resp.StatusCode())
		resp.Error()
	}
}
<commit_msg>Remove more debug<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"syscall"
	"time"

	"strconv"

	"github.com/go-resty/resty"
	"github.com/yosssi/gmq/mqtt"
	"github.com/yosssi/gmq/mqtt/client"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/yaml.v2"
)

//HomeAssistant data
type HomeAssistantData struct {
	EventType string    `json:"event_type"`
	EventData EventData `json:"event_data"`
}

type EventData struct {
	EntityID string     `json:"entity_id"`
	OldState EventState `json:"old_state"`
	NewState EventState `json:"new_state"`
}

type EventState struct {
	EntityID    string                 `json:"entity_id"`
	State       string                 `json:"state"`
	Attributes  map[string]interface{} `json:"attributes"`
	LastChanged *time.Time             `json:"last_changed"`
	LastUpdated *time.Time             `json:"last_updated"`
}

//DomoticzsData data from Domoticz
type DomoticzsData struct {
	ID      string `json:"id"`
	Svalue1 string `json:"svalue1"`
	Name    string `json:"name"`
}

// sample = {'name' : row[1], 'value' : float(row[0]), 'type' : 'TEMPERATURE', 'timestamp' : row[2] * 1000}
type VaderData struct {
	Name       string  `json:"name"`
	Value      float64 `json:"value"`
	SensorType string  `json:"type"`
	Timestamp  string  `json:"timestamp"`
}

type Configuration struct {
	DataFormat string
	RemoteHost string
	RemoteApp  string
	MQTTHost   string
	Group      string
	Sensor     []ConfigurationSensor
}

type ConfigurationSensor struct {
	Domoticz string
	Vader    string
	SType    string
}

var blowup bool
var premult bool
var temperature string
var tempKitchen string
var configFile = "config.yaml"
var config Configuration
var logger *zap.Logger

func init() {
	flag.StringVar(&configFile, "configfile", "config.yaml", "The config file to use, default config.yaml")
}

func main() {
	flag.Parse()
	logger, level, err := createLogger()

	if err != nil {
		fmt.Printf("Could not initialize zap logger: %v\n", err)
		os.Exit(1)
	}

	level.SetLevel(zapcore.DebugLevel)

	logger.Info("Starting up...\n")
	config = Configuration{}

	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		logger.Fatal("Could not read config file", zap.String("config file", configFile))
	}

	err = yaml.Unmarshal(data, &config)
	if err != nil {
		logger.Fatal("error", zap.Error(err))
	}

	logger.Debug("Lengt of sensors list", zap.Int("len", len(config.Sensor)))

	sigs := make(chan os.Signal, 1)
	done := make(chan bool, 1)

	go func() {
		_ = <-sigs
		done <- true
	}()

	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	cli := client.New(&client.Options{
		ErrorHandler: func(err error) {
			fmt.Println(err)
		},
	})

	// Terminate the Client.
	defer cli.Terminate()

	// Connect to the MQTT Server.
	err = cli.Connect(&client.ConnectOptions{
		Network:  "tcp",
		Address:  fmt.Sprintf("%s:1883", config.MQTTHost),
		ClientID: []byte("vader"),
	})
	if err != nil {
		panic(err)
	}

	logger.Debug("Connected to server")

	if config.DataFormat == "hass" {
		logger.Debug("Dataformat Home Assistant")
		// Subscribe to topics.
		err = cli.Subscribe(&client.SubscribeOptions{
			SubReqs: []*client.SubReq{
				&client.SubReq{
					TopicFilter: []byte("Tvistevägen"),
					QoS:         mqtt.QoS0,
					// Define the processing of the message handler.
					Handler: func(topicName, message []byte) {
						logger.Debug("full message", zap.ByteString("msg", message))
						had := &HomeAssistantData{}
						err := json.Unmarshal(message, had)
						if err != nil {
							logger.Error("Failed to unmarshall data", zap.Error(err))
						}
						name, stype := findVaderTypes(had.EventData.EntityID)
						if name != "" {
							valueFloat := had.EventData.NewState.Attributes["Temperature"].(float64)
							if err != nil {
								logger.Error("Could not parse float", zap.Any("value", had.EventData.NewState.Attributes["Temperature"]))
								return
							}
							if name != "" {
								vd := VaderData{
									Name:       name,
									Value:      valueFloat,
									SensorType: stype,
									Timestamp:  fmt.Sprintf("%d", time.Now().Unix()*1000),
								}
								sendData(vd)
							} else {
								logger.Debug("Found NO name")
							}
						}
					},
				},
			},
		})
	}
	if config.DataFormat == "domoticz" {
		logger.Debug("Dataformat Domoticz")
		// Subscribe to topics.
		err = cli.Subscribe(&client.SubscribeOptions{
			SubReqs: []*client.SubReq{
				&client.SubReq{
					TopicFilter: []byte("domoticz/out"),
					QoS:         mqtt.QoS0,
					// Define the processing of the message handler.
					Handler: func(topicName, message []byte) {
						dd := &DomoticzsData{}
						err := json.Unmarshal(message, dd)
						if err != nil {
							logger.Error("Failed to unmarshall data", zap.Error(err))
						}
						name, stype := findVaderTypes(dd.Name)
						valueFloat, err := strconv.ParseFloat(dd.Svalue1, 64)
						if err != nil {
							logger.Error("Could not parse float", zap.String("value", dd.Svalue1))
							return
						}
						if name != "" {
							vd := VaderData{
								Name:       name,
								Value:      valueFloat,
								SensorType: stype,
								Timestamp:  fmt.Sprintf("%d", time.Now().Unix()*1000),
							}
							sendData(vd)
						}
					},
				},
			},
		})
	}

	if err != nil {
		panic(err)
	}

	logger.Debug("Awaiting signal")
	<-done
	logger.Info("Exiting")

	// Disconnect the Network Connection.
	if err := cli.Disconnect(); err != nil {
		panic(err)
	}
}

func newEncoderConfig() zapcore.EncoderConfig {
	return zapcore.EncoderConfig{
		// Keys can be anything except the empty string.
		TimeKey:        "T",
		LevelKey:       "L",
		NameKey:        "N",
		CallerKey:      "C",
		MessageKey:     "M",
		StacktraceKey:  "S",
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
}

func newDevelopmentConfig() zap.Config {
	dyn := zap.NewAtomicLevel()
	dyn.SetLevel(zap.DebugLevel)

	return zap.Config{
		Level:            dyn,
		Development:      true,
		Encoding:         "console",
		EncoderConfig:    newEncoderConfig(),
		OutputPaths:      []string{"stderr"},
		ErrorOutputPaths: []string{"stderr"},
	}
}

func createLogger() (*zap.Logger, zap.AtomicLevel, error) {
	cfg := newDevelopmentConfig()
	logger, err := cfg.Build()
	if err != nil {
		return nil, zap.AtomicLevel{}, err
	}
	return logger, cfg.Level, nil
}

func findVaderTypes(domoticz string) (string, string) {
	for _, s := range config.Sensor {
		if s.Domoticz == domoticz {
			return s.Vader, s.SType
		}
	}
	return "", ""
}

func sendData(vd VaderData) {
	list := make([]VaderData, 0)
	list = append(list, vd)
	_, err := resty.R().
		SetBody(list).
		Post("http://" + config.RemoteHost + "/" + config.RemoteApp + "/rest/save")
	if err != nil {
		logger.Error("Failed to post data", zap.Error(err))
		return
	}
}
<|endoftext|>


<commit_before>package operators

import (
	"encoding/json"
	"fmt"
	"path/filepath"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
	e2e "k8s.io/kubernetes/test/e2e/framework"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
)

var _ = g.Describe("[sig-operator] OLM should", func() {
	defer g.GinkgoRecover()

	var oc = exutil.NewCLIWithoutNamespace("default")

	operators := "operators.coreos.com"
	providedAPIs := []struct {
		fromAPIService bool
		group          string
		version        string
		plural         string
	}{
		{
			fromAPIService: true,
			group:          "packages." + operators,
			version:        "v1",
			plural:         "packagemanifests",
		},
		{
			group:   operators,
			version: "v1",
			plural:  "operatorgroups",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "clusterserviceversions",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "catalogsources",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "installplans",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "subscriptions",
		},
	}

	for i := range providedAPIs {
		api := providedAPIs[i]
		g.It(fmt.Sprintf("be installed with %s at version %s", api.plural, api.version), func() {
			if api.fromAPIService {
				// Ensure spec.version matches expected
				raw, err := oc.AsAdmin().Run("get").Args("apiservices", fmt.Sprintf("%s.%s", api.version, api.group), "-o=jsonpath={.spec.version}").Output()
				o.Expect(err).NotTo(o.HaveOccurred())
				o.Expect(raw).To(o.Equal(api.version))
			} else {
				// Ensure expected version exists in spec.versions and is both served and stored
				raw, err := oc.AsAdmin().Run("get").Args("crds", fmt.Sprintf("%s.%s", api.plural, api.group), fmt.Sprintf("-o=jsonpath={.spec.versions[?(@.name==\"%s\")]}", api.version)).Output()
				o.Expect(err).NotTo(o.HaveOccurred())
				o.Expect(raw).To(o.MatchRegexp(`served.?:true`))
				o.Expect(raw).To(o.MatchRegexp(`storage.?:true`))
			}
		})
	}

	// OCP-24061 - [bz 1685230] OLM operator should use imagePullPolicy: IfNotPresent
	// author: bandrade@redhat.com
	g.It("have imagePullPolicy:IfNotPresent on thier deployments", func() {
		deploymentResource := []string{"catalog-operator", "olm-operator", "packageserver"}
		for _, v := range deploymentResource {
			msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("-n", "openshift-operator-lifecycle-manager", "deployment", v, "-o=jsonpath={.spec.template.spec.containers[*].imagePullPolicy}").Output()
			e2e.Logf("%s.imagePullPolicy:%s", v, msg)
			if err != nil {
				e2e.Failf("Unable to get %s, error:%v", msg, err)
			}
			o.Expect(err).NotTo(o.HaveOccurred())

			// ensure that all containers in the current deployment contain the IfNotPresent
			// image pull policy
			policies := strings.Split(msg, " ")
			for _, policy := range policies {
				o.Expect(policy).To(o.Equal("IfNotPresent"))
			}
		}
	})

	// OCP-21082 - Implement packages API server and list packagemanifest info with namespace not NULL
	// author: bandrade@redhat.com
	g.It("Implement packages API server and list packagemanifest info with namespace not NULL", func() {
		msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("packagemanifest", "--all-namespaces", "--no-headers").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		packageserverLines := strings.Split(msg, "\n")
		if len(packageserverLines) > 0 {
			packageserverLine := strings.Fields(packageserverLines[0])
			if strings.Index(packageserverLines[0], packageserverLine[0]) != 0 {
				e2e.Failf("It should display a namespace for CSV: %s [ref:bz1670311]", packageserverLines[0])
			}
		} else {
			e2e.Failf("No packages for evaluating if package namespace is not NULL")
		}
	})
})

var _ = g.Describe("[sig-arch] ocp payload should be based on existing source", func() {
	defer g.GinkgoRecover()

	var oc = exutil.NewCLIWithoutNamespace("default")

	// TODO: This test should be more generic and across components
	// OCP-20981, [BZ 1626434]The olm/catalog binary should output the exact version info
	// author: jiazha@redhat.com
	g.It("OLM version should contain the source commit id", func() {
		sameCommit := ""
		subPods := []string{"catalog-operator", "olm-operator", "packageserver"}

		for _, v := range subPods {
			podName, err := oc.AsAdmin().Run("get").Args("-n", "openshift-operator-lifecycle-manager", "pods", "-l", fmt.Sprintf("app=%s", v), "-o=jsonpath={.items[0].metadata.name}").Output()
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By(fmt.Sprintf("get olm version from pod %s", podName))
			oc.SetNamespace("openshift-operator-lifecycle-manager")
			olmVersion, err := oc.AsAdmin().Run("exec").Args("-n", "openshift-operator-lifecycle-manager", podName, "--", "olm", "--version").Output()
			o.Expect(err).NotTo(o.HaveOccurred())
			idSlice := strings.Split(olmVersion, ":")
			gitCommitID := strings.TrimSpace(idSlice[len(idSlice)-1])
			e2e.Logf("olm source git commit ID:%s", gitCommitID)
			if len(gitCommitID) != 40 {
				e2e.Failf(fmt.Sprintf("the length of the git commit id is %d, != 40", len(gitCommitID)))
			}

			if sameCommit == "" {
				sameCommit = gitCommitID

			} else if gitCommitID != sameCommit {
				e2e.Failf("commitIDs of components within OLM do not match, possible build anomalies")
			}
		}
	})
})

func hasRedHatOperatorsSource(oc *exutil.CLI) (bool, error) {
	spec, err := oc.AsAdmin().Run("get").Args("operatorhub/cluster", "-o=jsonpath={.spec}").Output()
	if err != nil {
		return true, fmt.Errorf("Error reading operatorhub spec: %s", spec)
	}
	type Source struct {
		Name     string `json:"name"`
		Disabled bool   `json:"disabled"`
	}
	type Spec struct {
		DisableAllDefaultSources bool     `json:"disableAllDefaultSources"`
		Sources                  []Source `json:"sources"`
	}
	parsed := Spec{}
	err = json.Unmarshal([]byte(spec), &parsed)
	if err != nil {
		return true, fmt.Errorf("Error unmarshalling operatorhub spec: %s", spec)
	}
	// Check if default hub sources are used
	if len(parsed.Sources) == 0 && !parsed.DisableAllDefaultSources {
		return true, nil
	}

	// Check if redhat-operators is listed and not disabled
	for _, source := range parsed.Sources {
		if source.Name == "redhat-operators" && source.Disabled == false {
			return true, nil
		}
	}
	return false, nil
}

// This context will cover test case: OCP-23440, author: jiazha@redhat.com
// Uses nfd operator
var _ = g.Describe("[sig-operator] an end user can use OLM", func() {
	defer g.GinkgoRecover()

	var (
		oc = exutil.NewCLI("olm-23440")

		buildPruningBaseDir = exutil.FixturePath("testdata", "olm")
		operatorGroup       = filepath.Join(buildPruningBaseDir, "operatorgroup.yaml")
		sub                 = filepath.Join(buildPruningBaseDir, "subscription.yaml")
	)

	files := []string{sub}
	g.It("can subscribe to the operator", func() {
		g.By("Cluster-admin user subscribe the operator resource")

		// skip test if redhat-operators is not present or disabled
		ok, err := hasRedHatOperatorsSource(oc)
		o.Expect(err).NotTo(o.HaveOccurred())
		if !ok {
			g.Skip("redhat-operators source not found in enabled sources")
		}

		// TODO: Come up with an arch agnostic operator to deploy during this test.
		// For now this does not work for arm64
		if e2e.NodeOSArchIs("arm64") {
			e2eskipper.Skipf("Not supported for node OS distro %v (is arm64)", e2e.TestContext.NodeOSDistro)
		}
		// configure OperatorGroup before tests
		configFile, err := oc.AsAdmin().Run("process").Args("--ignore-unknown-parameters=true", "-f", operatorGroup, "-p", "NAME=test-operator", fmt.Sprintf("NAMESPACE=%s", oc.Namespace())).OutputToFile("config.json")
		o.Expect(err).NotTo(o.HaveOccurred())
		err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", configFile).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Eventually(func() []string {
			// Using json output instead of jsonpath - oc/jsonpath bug seems to improperly decode `[""]` as `[]`
			output, err := oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "operatorgroup", "test-operator", "-o=json").Output()
			if err != nil {
				e2e.Logf("Failed to get valid operatorgroup, error:%v", err)
				return []string{""}
			}
			type ogStatus struct {
				Namespaces []string `json:"namespaces"`
			}
			type og struct {
				Status ogStatus `json:"status"`
			}
			parsed := og{
				Status: ogStatus{
					Namespaces: []string{},
				},
			}
			if err := json.Unmarshal([]byte(output), &parsed); err != nil {
				e2e.Logf("Failed to parse operatorgroup, error:%v", err)
				return []string{""}
			}
			return parsed.Status.Namespaces
		}, 5*time.Minute, time.Second).Should(o.Equal([]string{""}))

		for _, v := range files {
			configFile, err := oc.AsAdmin().Run("process").Args("--ignore-unknown-parameters=true", "-f", v, "-p", "NAME=test-operator", fmt.Sprintf("NAMESPACE=%s", oc.Namespace()), "SOURCENAME=redhat-operators", "SOURCENAMESPACE=openshift-marketplace", "PACKAGE=cluster-logging", "CHANNEL=stable").OutputToFile("config.json")
			o.Expect(err).NotTo(o.HaveOccurred())
			err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", configFile).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}

		var current string
		o.Eventually(func() string {
			var err error
			current, err = oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "subscription", "test-operator", "-o=jsonpath={.status.installedCSV}").Output()
			if err != nil {
				e2e.Logf("Failed to check test-operator, error: %v, try next round", err)
			}
			return current
		}, 5*time.Minute, time.Second).ShouldNot(o.Equal(""))

		defer func() {
			// clean up so that it doesn't emit an alert when namespace is deleted
			_, err = oc.AsAdmin().Run("delete").Args("-n", oc.Namespace(), "csv", current).Output()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()

		o.Eventually(func() string {
			output, err := oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "csv", current, "-o=jsonpath={.status.phase}").Output()
			if err != nil {
				e2e.Logf("Failed to check %s, error: %v, try next round", current, err)
			}
			return output

		}, 5*time.Minute, time.Second).ShouldNot(o.BeEmpty())
	})

	// OCP-24829 - Report `Upgradeable` in OLM ClusterOperators status
	// author: bandrade@redhat.com
	g.It("Report Upgradeable in OLM ClusterOperators status", func() {
		olmCOs := []string{"operator-lifecycle-manager", "operator-lifecycle-manager-catalog", "operator-lifecycle-manager-packageserver"}
		for _, co := range olmCOs {
			msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("co", co, "-o=jsonpath={range .status.conditions[*]}{.type}{' '}{.status}").Output()
			if err != nil {
				e2e.Failf("Unable to get co %s status, error:%v", msg, err)
			}
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(msg).To(o.ContainSubstring("Upgradeable True"))
		}

	})
})
<commit_msg>operators: properly skip OLM test on arm64<commit_after>package operators

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

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	e2e "k8s.io/kubernetes/test/e2e/framework"
)

var _ = g.Describe("[sig-operator] OLM should", func() {
	defer g.GinkgoRecover()

	var oc = exutil.NewCLIWithoutNamespace("default")

	operators := "operators.coreos.com"
	providedAPIs := []struct {
		fromAPIService bool
		group          string
		version        string
		plural         string
	}{
		{
			fromAPIService: true,
			group:          "packages." + operators,
			version:        "v1",
			plural:         "packagemanifests",
		},
		{
			group:   operators,
			version: "v1",
			plural:  "operatorgroups",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "clusterserviceversions",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "catalogsources",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "installplans",
		},
		{
			group:   operators,
			version: "v1alpha1",
			plural:  "subscriptions",
		},
	}

	for i := range providedAPIs {
		api := providedAPIs[i]
		g.It(fmt.Sprintf("be installed with %s at version %s", api.plural, api.version), func() {
			if api.fromAPIService {
				// Ensure spec.version matches expected
				raw, err := oc.AsAdmin().Run("get").Args("apiservices", fmt.Sprintf("%s.%s", api.version, api.group), "-o=jsonpath={.spec.version}").Output()
				o.Expect(err).NotTo(o.HaveOccurred())
				o.Expect(raw).To(o.Equal(api.version))
			} else {
				// Ensure expected version exists in spec.versions and is both served and stored
				raw, err := oc.AsAdmin().Run("get").Args("crds", fmt.Sprintf("%s.%s", api.plural, api.group), fmt.Sprintf("-o=jsonpath={.spec.versions[?(@.name==\"%s\")]}", api.version)).Output()
				o.Expect(err).NotTo(o.HaveOccurred())
				o.Expect(raw).To(o.MatchRegexp(`served.?:true`))
				o.Expect(raw).To(o.MatchRegexp(`storage.?:true`))
			}
		})
	}

	// OCP-24061 - [bz 1685230] OLM operator should use imagePullPolicy: IfNotPresent
	// author: bandrade@redhat.com
	g.It("have imagePullPolicy:IfNotPresent on thier deployments", func() {
		deploymentResource := []string{"catalog-operator", "olm-operator", "packageserver"}
		for _, v := range deploymentResource {
			msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("-n", "openshift-operator-lifecycle-manager", "deployment", v, "-o=jsonpath={.spec.template.spec.containers[*].imagePullPolicy}").Output()
			e2e.Logf("%s.imagePullPolicy:%s", v, msg)
			if err != nil {
				e2e.Failf("Unable to get %s, error:%v", msg, err)
			}
			o.Expect(err).NotTo(o.HaveOccurred())

			// ensure that all containers in the current deployment contain the IfNotPresent
			// image pull policy
			policies := strings.Split(msg, " ")
			for _, policy := range policies {
				o.Expect(policy).To(o.Equal("IfNotPresent"))
			}
		}
	})

	// OCP-21082 - Implement packages API server and list packagemanifest info with namespace not NULL
	// author: bandrade@redhat.com
	g.It("Implement packages API server and list packagemanifest info with namespace not NULL", func() {
		msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("packagemanifest", "--all-namespaces", "--no-headers").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		packageserverLines := strings.Split(msg, "\n")
		if len(packageserverLines) > 0 {
			packageserverLine := strings.Fields(packageserverLines[0])
			if strings.Index(packageserverLines[0], packageserverLine[0]) != 0 {
				e2e.Failf("It should display a namespace for CSV: %s [ref:bz1670311]", packageserverLines[0])
			}
		} else {
			e2e.Failf("No packages for evaluating if package namespace is not NULL")
		}
	})
})

var _ = g.Describe("[sig-arch] ocp payload should be based on existing source", func() {
	defer g.GinkgoRecover()

	var oc = exutil.NewCLIWithoutNamespace("default")

	// TODO: This test should be more generic and across components
	// OCP-20981, [BZ 1626434]The olm/catalog binary should output the exact version info
	// author: jiazha@redhat.com
	g.It("OLM version should contain the source commit id", func() {
		sameCommit := ""
		subPods := []string{"catalog-operator", "olm-operator", "packageserver"}

		for _, v := range subPods {
			podName, err := oc.AsAdmin().Run("get").Args("-n", "openshift-operator-lifecycle-manager", "pods", "-l", fmt.Sprintf("app=%s", v), "-o=jsonpath={.items[0].metadata.name}").Output()
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By(fmt.Sprintf("get olm version from pod %s", podName))
			oc.SetNamespace("openshift-operator-lifecycle-manager")
			olmVersion, err := oc.AsAdmin().Run("exec").Args("-n", "openshift-operator-lifecycle-manager", podName, "--", "olm", "--version").Output()
			o.Expect(err).NotTo(o.HaveOccurred())
			idSlice := strings.Split(olmVersion, ":")
			gitCommitID := strings.TrimSpace(idSlice[len(idSlice)-1])
			e2e.Logf("olm source git commit ID:%s", gitCommitID)
			if len(gitCommitID) != 40 {
				e2e.Failf(fmt.Sprintf("the length of the git commit id is %d, != 40", len(gitCommitID)))
			}

			if sameCommit == "" {
				sameCommit = gitCommitID

			} else if gitCommitID != sameCommit {
				e2e.Failf("commitIDs of components within OLM do not match, possible build anomalies")
			}
		}
	})
})

func archHasDefaultIndex(oc *exutil.CLI) bool {
	workerNodes, err := oc.AsAdmin().KubeClient().CoreV1().Nodes().List(context.Background(), metav1.ListOptions{LabelSelector: "node-role.kubernetes.io/worker"})
	if err != nil {
		e2e.Logf("problem getting nodes for arch check: %s", err)
	}
	for _, node := range workerNodes.Items {
		switch node.Status.NodeInfo.Architecture {
		case "amd64":
			return true
		case "ppc64le":
			return true
		case "s390x":
			return true
		default:
		}
	}
	return false
}

func hasRedHatOperatorsSource(oc *exutil.CLI) (bool, error) {
	spec, err := oc.AsAdmin().Run("get").Args("operatorhub/cluster", "-o=jsonpath={.spec}").Output()
	if err != nil {
		return true, fmt.Errorf("Error reading operatorhub spec: %s", spec)
	}
	type Source struct {
		Name     string `json:"name"`
		Disabled bool   `json:"disabled"`
	}
	type Spec struct {
		DisableAllDefaultSources bool     `json:"disableAllDefaultSources"`
		Sources                  []Source `json:"sources"`
	}
	parsed := Spec{}
	err = json.Unmarshal([]byte(spec), &parsed)
	if err != nil {
		return true, fmt.Errorf("Error unmarshalling operatorhub spec: %s", spec)
	}
	// Check if default hub sources are used
	if len(parsed.Sources) == 0 && !parsed.DisableAllDefaultSources && archHasDefaultIndex(oc) {
		return true, nil
	}

	// Check if redhat-operators is listed and not disabled
	for _, source := range parsed.Sources {
		if source.Name == "redhat-operators" && source.Disabled == false {
			return true, nil
		}
	}
	return false, nil
}

// This context will cover test case: OCP-23440, author: jiazha@redhat.com
// Uses nfd operator
var _ = g.Describe("[sig-operator] an end user can use OLM", func() {
	defer g.GinkgoRecover()

	var (
		oc = exutil.NewCLI("olm-23440")

		buildPruningBaseDir = exutil.FixturePath("testdata", "olm")
		operatorGroup       = filepath.Join(buildPruningBaseDir, "operatorgroup.yaml")
		sub                 = filepath.Join(buildPruningBaseDir, "subscription.yaml")
	)

	files := []string{sub}
	g.It("can subscribe to the operator", func() {
		g.By("Cluster-admin user subscribe the operator resource")

		// skip test if redhat-operators is not present or disabled
		ok, err := hasRedHatOperatorsSource(oc)
		o.Expect(err).NotTo(o.HaveOccurred())
		if !ok {
			g.Skip("redhat-operators source not found in enabled sources")
		}

		// configure OperatorGroup before tests
		configFile, err := oc.AsAdmin().Run("process").Args("--ignore-unknown-parameters=true", "-f", operatorGroup, "-p", "NAME=test-operator", fmt.Sprintf("NAMESPACE=%s", oc.Namespace())).OutputToFile("config.json")
		o.Expect(err).NotTo(o.HaveOccurred())
		err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", configFile).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Eventually(func() []string {
			// Using json output instead of jsonpath - oc/jsonpath bug seems to improperly decode `[""]` as `[]`
			output, err := oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "operatorgroup", "test-operator", "-o=json").Output()
			if err != nil {
				e2e.Logf("Failed to get valid operatorgroup, error:%v", err)
				return []string{""}
			}
			type ogStatus struct {
				Namespaces []string `json:"namespaces"`
			}
			type og struct {
				Status ogStatus `json:"status"`
			}
			parsed := og{
				Status: ogStatus{
					Namespaces: []string{},
				},
			}
			if err := json.Unmarshal([]byte(output), &parsed); err != nil {
				e2e.Logf("Failed to parse operatorgroup, error:%v", err)
				return []string{""}
			}
			return parsed.Status.Namespaces
		}, 5*time.Minute, time.Second).Should(o.Equal([]string{""}))

		for _, v := range files {
			configFile, err := oc.AsAdmin().Run("process").Args("--ignore-unknown-parameters=true", "-f", v, "-p", "NAME=test-operator", fmt.Sprintf("NAMESPACE=%s", oc.Namespace()), "SOURCENAME=redhat-operators", "SOURCENAMESPACE=openshift-marketplace", "PACKAGE=cluster-logging", "CHANNEL=stable").OutputToFile("config.json")
			o.Expect(err).NotTo(o.HaveOccurred())
			err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", configFile).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}

		var current string
		o.Eventually(func() string {
			var err error
			current, err = oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "subscription", "test-operator", "-o=jsonpath={.status.installedCSV}").Output()
			if err != nil {
				e2e.Logf("Failed to check test-operator, error: %v, try next round", err)
			}
			return current
		}, 5*time.Minute, time.Second).ShouldNot(o.Equal(""))

		defer func() {
			// clean up so that it doesn't emit an alert when namespace is deleted
			_, err = oc.AsAdmin().Run("delete").Args("-n", oc.Namespace(), "csv", current).Output()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()

		o.Eventually(func() string {
			output, err := oc.AsAdmin().Run("get").Args("-n", oc.Namespace(), "csv", current, "-o=jsonpath={.status.phase}").Output()
			if err != nil {
				e2e.Logf("Failed to check %s, error: %v, try next round", current, err)
			}
			return output

		}, 5*time.Minute, time.Second).ShouldNot(o.BeEmpty())
	})

	// OCP-24829 - Report `Upgradeable` in OLM ClusterOperators status
	// author: bandrade@redhat.com
	g.It("Report Upgradeable in OLM ClusterOperators status", func() {
		olmCOs := []string{"operator-lifecycle-manager", "operator-lifecycle-manager-catalog", "operator-lifecycle-manager-packageserver"}
		for _, co := range olmCOs {
			msg, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("co", co, "-o=jsonpath={range .status.conditions[*]}{.type}{' '}{.status}").Output()
			if err != nil {
				e2e.Failf("Unable to get co %s status, error:%v", msg, err)
			}
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(msg).To(o.ContainSubstring("Upgradeable True"))
		}

	})
})
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"runtime"
	"time"

	"github.com/antihax/goesi"

	"github.com/EVE-Tools/element43/go/lib/transport"
	"github.com/EVE-Tools/static-data/lib/locations"

	"github.com/boltdb/bolt"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/contrib/ginrus"
	"github.com/gin-gonic/gin"
	"github.com/kelseyhightower/envconfig"
	"github.com/sirupsen/logrus"
)

// Config holds the application's configuration info from the environment.
type Config struct {
	DBPath            string `default:"static-data.db" envconfig:"db_path"`
	LogLevel          string `default:"info" envconfig:"log_level"`
	Port              string `default:"8000" envconfig:"port"`
	ESIHost           string `default:"esi.tech.ccp.is" envconfig:"esi_host"`
	StructureHuntHost string `default:"stop.hammerti.me.uk" envconfig:"structure_hunt_host"`
	DisableTLS        bool   `default:"false" envconfig:"disable_tls"`
}

func main() {
	config := loadConfig()
	startEndpoint(config)

	// Terminate this goroutine, crash if all other goroutines exited
	runtime.Goexit()
}

// Load configuration from environment
func loadConfig() Config {
	config := Config{}
	envconfig.MustProcess("STATIC_DATA", &config)

	logLevel, err := logrus.ParseLevel(config.LogLevel)
	if err != nil {
		panic(err)
	}

	logrus.SetLevel(logLevel)
	logrus.Debugf("Config: %q", config)
	return config
}

// getClients generates API clients and base URLs
func getClients(config Config) (*goesi.APIClient, *http.Client, string) {
	const userAgent string = "Element43/static-data (element-43.com)"
	const timeout time.Duration = time.Duration(time.Second * 10)
	var structureHuntURL string

	// Initialize clients
	genericClient := &http.Client{
		Timeout:   time.Minute,
		Transport: transport.NewTransport(userAgent),
	}

	httpClientESI := &http.Client{
		Timeout:   timeout,
		Transport: transport.NewESITransport(userAgent, timeout),
	}

	esiClient := goesi.NewAPIClient(httpClientESI, userAgent)

	if config.DisableTLS {
		esiClient.ChangeBasePath(fmt.Sprintf("http://%s:443", config.ESIHost))
		structureHuntURL = fmt.Sprintf("http://%s:443/api/structure/all", config.StructureHuntHost)
	} else {
		esiClient.ChangeBasePath(fmt.Sprintf("https://%s", config.ESIHost))
		structureHuntURL = fmt.Sprintf("https://%s/api/structure/all", config.StructureHuntHost)
	}

	return esiClient, genericClient, structureHuntURL
}

// Init DB and start endpoint.
func startEndpoint(config Config) {
	db, err := bolt.Open(config.DBPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		panic(err)
	}

	esiClient, genericClient, url := getClients(config)

	locations.Initialize(esiClient,
		genericClient,
		url,
		db)

	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	router.Use(cors.Default())
	router.Use(ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true))

	v1 := router.Group("/api/static-data/v1")
	v1.POST("/location/", locations.GetLocationsEndpoint)

	router.Run(":" + config.Port)
}
<commit_msg>Bumped-up timeout due to ESI being slow sometimes<commit_after>package main

import (
	"fmt"
	"net/http"
	"runtime"
	"time"

	"github.com/antihax/goesi"

	"github.com/EVE-Tools/element43/go/lib/transport"
	"github.com/EVE-Tools/static-data/lib/locations"

	"github.com/boltdb/bolt"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/contrib/ginrus"
	"github.com/gin-gonic/gin"
	"github.com/kelseyhightower/envconfig"
	"github.com/sirupsen/logrus"
)

// Config holds the application's configuration info from the environment.
type Config struct {
	DBPath            string `default:"static-data.db" envconfig:"db_path"`
	LogLevel          string `default:"info" envconfig:"log_level"`
	Port              string `default:"8000" envconfig:"port"`
	ESIHost           string `default:"esi.tech.ccp.is" envconfig:"esi_host"`
	StructureHuntHost string `default:"stop.hammerti.me.uk" envconfig:"structure_hunt_host"`
	DisableTLS        bool   `default:"false" envconfig:"disable_tls"`
}

func main() {
	config := loadConfig()
	startEndpoint(config)

	// Terminate this goroutine, crash if all other goroutines exited
	runtime.Goexit()
}

// Load configuration from environment
func loadConfig() Config {
	config := Config{}
	envconfig.MustProcess("STATIC_DATA", &config)

	logLevel, err := logrus.ParseLevel(config.LogLevel)
	if err != nil {
		panic(err)
	}

	logrus.SetLevel(logLevel)
	logrus.Debugf("Config: %q", config)
	return config
}

// getClients generates API clients and base URLs
func getClients(config Config) (*goesi.APIClient, *http.Client, string) {
	const userAgent string = "Element43/static-data (element-43.com)"
	const timeout time.Duration = time.Duration(time.Second * 30)
	var structureHuntURL string

	// Initialize clients
	genericClient := &http.Client{
		Timeout:   time.Minute,
		Transport: transport.NewTransport(userAgent),
	}

	httpClientESI := &http.Client{
		Timeout:   timeout,
		Transport: transport.NewESITransport(userAgent, timeout),
	}

	esiClient := goesi.NewAPIClient(httpClientESI, userAgent)

	if config.DisableTLS {
		esiClient.ChangeBasePath(fmt.Sprintf("http://%s:443", config.ESIHost))
		structureHuntURL = fmt.Sprintf("http://%s:443/api/structure/all", config.StructureHuntHost)
	} else {
		esiClient.ChangeBasePath(fmt.Sprintf("https://%s", config.ESIHost))
		structureHuntURL = fmt.Sprintf("https://%s/api/structure/all", config.StructureHuntHost)
	}

	return esiClient, genericClient, structureHuntURL
}

// Init DB and start endpoint.
func startEndpoint(config Config) {
	db, err := bolt.Open(config.DBPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		panic(err)
	}

	esiClient, genericClient, url := getClients(config)

	locations.Initialize(esiClient,
		genericClient,
		url,
		db)

	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	router.Use(cors.Default())
	router.Use(ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true))

	v1 := router.Group("/api/static-data/v1")
	v1.POST("/location/", locations.GetLocationsEndpoint)

	router.Run(":" + config.Port)
}
<|endoftext|>


<commit_before>/*
Package stacksignal registers a signal handler for SIGUSR1.
Whenever the importing program receives SIGUSR1, a full
stacktrace of all goroutines will be printed to StdErr.

Since there are no functions to use, the import line should
be

	import _ "github.com/surma/stacksignal"
*/
package stacksignal

import (
	"os"
	"os/signal"
	"runtime"
	"syscall"
)

const (
	VERSION = "1.0.0"
)

func init() {
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGUSR1)
		buf := make([]byte, 1024*16)
		for _ = range c {
			runtime.Stack(buf, true)
			os.Stderr.Write(buf)
		}
	}()
}
<commit_msg>Be memory conservative<commit_after>/*
Package stacksignal registers a signal handler for SIGUSR1.
Whenever the importing program receives SIGUSR1, a full
stacktrace of all goroutines will be printed to StdErr.

Since there are no functions to use, the import line should
be

	import _ "github.com/surma/stacksignal"
*/
package stacksignal

import (
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
)

const (
	VERSION = "1.0.0"
)

func init() {
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGUSR1)
		n := 512
		for _ = range c {
			buf := make([]byte, n)
			for {
				m := runtime.Stack(buf, true)
				if m < n {
					break
				}
				n *= 2
				buf = make([]byte, n)
			}
			fmt.Fprintln(os.Stderr, "=== Begin stack trace")
			fmt.Fprintln(os.Stderr, string(buf))
			fmt.Fprintln(os.Stderr, "=== End stack trace")
		}
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	log "github.com/Sirupsen/logrus"
	"github.com/evalphobia/logrus_sentry"
	"time"

	"github.com/pagarme/teleport/applier"
	"github.com/pagarme/teleport/batcher"
	"github.com/pagarme/teleport/client"
	"github.com/pagarme/teleport/config"
	"github.com/pagarme/teleport/database"
	"github.com/pagarme/teleport/ddlwatcher"
	"github.com/pagarme/teleport/loader"
	"github.com/pagarme/teleport/server"
	"github.com/pagarme/teleport/transmitter"
	"github.com/pagarme/teleport/vacuum"
)

func main() {
	// Startup message. It's useful to get the logs of the last successful run.
	// In order to use it, run `docker-compose logs (source|target) | sed -n '/Teleport Started/{h;b};H;${x;p}'`
	log.Info("[Teleport Started]")

	// Parse config
	configPath := flag.String("config", "config.yml", "config file path")
	mode := flag.String("mode", "replication", "teleport mode [replication|initial-load]")
	loadTarget := flag.String("load-target", "", "target to perform initial load [target name]")
	flag.Parse()

	// Load config file
	config := config.New()
	err := config.ReadFromFile(*configPath)

	if err != nil {
		log.Panicf("Error opening config file '%s': %v", *configPath, err)
	}

	if config.SentryEndpoint != "" {
		hook, err := logrus_sentry.NewSentryHook(config.SentryEndpoint, []log.Level{
			log.PanicLevel,
			log.FatalLevel,
			log.ErrorLevel,
			log.InfoLevel,
		})

		if err != nil {
			log.Panicf("Error initializing sentry: %v", err)
		}

		log.AddHook(hook)
	}

	// Some processing intervals only make sense when there are actually
	// targets to send data to.

	invalidInterval := false

	if len(config.Targets) > 0 {
		invalidInterval = invalidInterval ||
			config.ProcessingIntervals.Batcher == 0 ||
			config.ProcessingIntervals.Transmitter == 0

		if !config.UseEventTriggers {
			invalidInterval = invalidInterval || config.ProcessingIntervals.DdlWatcher == 0
		}
	}

	invalidInterval = invalidInterval ||
		config.ProcessingIntervals.Applier == 0 ||
		config.ProcessingIntervals.Vacuum == 0

	if invalidInterval {
		log.Panicf("Invalid config value 0 for ProcessingInterval")
	}

	if config.BatchSize == 0 {
		log.Panicf("Invalid config value 0 for BatchSize")
	}

	db := database.New(config.Database)

	// Start db
	if err = db.Start(); err != nil {
		log.Panicf("Error starting database: %v", err)
	}

	targets := make(map[string]*client.Client)

	// Create a new client for each target
	// Install triggers for each target
	for key, target := range config.Targets {
		targets[key] = client.New(target)
		db.InstallTriggers(targets[key].TargetExpression)
	}

	if *mode == "replication" {
		// Only start the following coroutines if there are targets to send data to
		if len(targets) > 0 {
			// Start batcher on a separate goroutine
			batcher := batcher.New(db, targets, config.MaxEventsPerBatch)
			go batcher.Watch(time.Duration(config.ProcessingIntervals.Batcher) * time.Millisecond)

			// Start transmitter on a separate goroutine
			transmitter := transmitter.New(db, targets)
			go transmitter.Watch(time.Duration(config.ProcessingIntervals.Transmitter) * time.Millisecond)

			// Start DDL watcher on a separate goroutine
			ddlwatcher := ddlwatcher.New(db)
			go ddlwatcher.Watch(time.Duration(config.ProcessingIntervals.DdlWatcher) * time.Millisecond)
		}

		// Start applier on a separate goroutine
		applier := applier.New(db, config.BatchSize)
		go applier.Watch(time.Duration(config.ProcessingIntervals.Applier) * time.Millisecond)

		// Start vacuum on a separate goroutine
		vacuum := vacuum.New(db)
		go vacuum.Watch(time.Duration(config.ProcessingIntervals.Vacuum) * time.Millisecond)

		// Start HTTP server for receiving incoming requests
		server := server.New(db, config.ServerHTTP)

		// Start HTTP server
		if err = server.Start(); err != nil {
			log.Panicf("Error starting HTTP server: %v", err)
		}
	} else if *mode == "initial-load" {
		target, ok := targets[*loadTarget]

		if !ok {
			log.Panicf("Error starting loader: target %s not found!", *loadTarget)
		}

		loader := loader.New(db, target, *loadTarget, config.BatchSize, config.MaxEventsPerBatch)
		err := loader.Load()

		if err != nil {
			log.Errorf("Error creating events: %#v", err)
		}
	}
}
<commit_msg>Refactor processing interval logic to separate function<commit_after>package main

import (
	"flag"
	log "github.com/Sirupsen/logrus"
	"github.com/evalphobia/logrus_sentry"
	"time"

	"github.com/pagarme/teleport/applier"
	"github.com/pagarme/teleport/batcher"
	"github.com/pagarme/teleport/client"
	"github.com/pagarme/teleport/config"
	"github.com/pagarme/teleport/database"
	"github.com/pagarme/teleport/ddlwatcher"
	"github.com/pagarme/teleport/loader"
	"github.com/pagarme/teleport/server"
	"github.com/pagarme/teleport/transmitter"
	"github.com/pagarme/teleport/vacuum"
)

func main() {
	// Startup message. It's useful to get the logs of the last successful run.
	// In order to use it, run `docker-compose logs (source|target) | sed -n '/Teleport Started/{h;b};H;${x;p}'`
	log.Info("[Teleport Started]")

	// Parse config
	configPath := flag.String("config", "config.yml", "config file path")
	mode := flag.String("mode", "replication", "teleport mode [replication|initial-load]")
	loadTarget := flag.String("load-target", "", "target to perform initial load [target name]")
	flag.Parse()

	// Load config file
	config := config.New()
	err := config.ReadFromFile(*configPath)

	if err != nil {
		log.Panicf("Error opening config file '%s': %v", *configPath, err)
	}

	if config.SentryEndpoint != "" {
		hook, err := logrus_sentry.NewSentryHook(config.SentryEndpoint, []log.Level{
			log.PanicLevel,
			log.FatalLevel,
			log.ErrorLevel,
			log.InfoLevel,
		})

		if err != nil {
			log.Panicf("Error initializing sentry: %v", err)
		}

		log.AddHook(hook)
	}

	if invalidProcessingIntervals(config) {
		log.Panicf("Invalid config value 0 for ProcessingInterval")
	}

	if config.BatchSize == 0 {
		log.Panicf("Invalid config value 0 for BatchSize")
	}

	db := database.New(config.Database)

	// Start db
	if err = db.Start(); err != nil {
		log.Panicf("Error starting database: %v", err)
	}

	targets := make(map[string]*client.Client)

	// Create a new client for each target
	// Install triggers for each target
	for key, target := range config.Targets {
		targets[key] = client.New(target)
		db.InstallTriggers(targets[key].TargetExpression)
	}

	if *mode == "replication" {
		// Only start the following coroutines if there are targets to send data to
		if len(targets) > 0 {
			// Start batcher on a separate goroutine
			batcher := batcher.New(db, targets, config.MaxEventsPerBatch)
			go batcher.Watch(time.Duration(config.ProcessingIntervals.Batcher) * time.Millisecond)

			// Start transmitter on a separate goroutine
			transmitter := transmitter.New(db, targets)
			go transmitter.Watch(time.Duration(config.ProcessingIntervals.Transmitter) * time.Millisecond)

			// Start DDL watcher on a separate goroutine
			ddlwatcher := ddlwatcher.New(db)
			go ddlwatcher.Watch(time.Duration(config.ProcessingIntervals.DdlWatcher) * time.Millisecond)
		}

		// Start applier on a separate goroutine
		applier := applier.New(db, config.BatchSize)
		go applier.Watch(time.Duration(config.ProcessingIntervals.Applier) * time.Millisecond)

		// Start vacuum on a separate goroutine
		vacuum := vacuum.New(db)
		go vacuum.Watch(time.Duration(config.ProcessingIntervals.Vacuum) * time.Millisecond)

		// Start HTTP server for receiving incoming requests
		server := server.New(db, config.ServerHTTP)

		// Start HTTP server
		if err = server.Start(); err != nil {
			log.Panicf("Error starting HTTP server: %v", err)
		}
	} else if *mode == "initial-load" {
		target, ok := targets[*loadTarget]

		if !ok {
			log.Panicf("Error starting loader: target %s not found!", *loadTarget)
		}

		loader := loader.New(db, target, *loadTarget, config.BatchSize, config.MaxEventsPerBatch)
		err := loader.Load()

		if err != nil {
			log.Errorf("Error creating events: %#v", err)
		}
	}
}

func invalidProcessingIntervals(config *config.Config) bool {
	// Some processing intervals only make sense when there are actually
	// targets to send data to.
	if len(config.Targets) > 0 {
		if config.ProcessingIntervals.Batcher <= 0 {
			return true
		}

		if config.ProcessingIntervals.Transmitter <= 0 {
			return true
		}

		if !config.UseEventTriggers && config.ProcessingIntervals.DdlWatcher <= 0 {
			return true
		}
	}

	if config.ProcessingIntervals.Applier <= 0 {
		return true
	}

	if config.ProcessingIntervals.Vacuum <= 0 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
)

var nbPages int
var cat = false
var outFile string
var inFile string

func main() {

	gtk.Init(nil)
	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetPosition(gtk.WIN_POS_CENTER)
	window.SetTitle("STOBS")
	window.SetIconName("gtk-dialog-info")
	window.Connect("destroy", func(ctx *glib.CallbackContext) {
		defer os.Remove(inFile)
		defer os.Remove(outFile)
		gtk.MainQuit()
	})

	// TITLE
	label := gtk.NewLabel("organisez vos PDF en Recto/Verso")
	label.ModifyFontEasy("DejaVu Serif 14")

	// label info fichier
	lblPage := gtk.NewLabel("")

	// label info
	lblInfo := gtk.NewLabel("Par défaut la première page Verso est situé à la moitié")

	// txtBox file
	lblFileName := gtk.NewLabel("Nom du fichier: ")
	fileName := gtk.NewLabel("")

	lblVerso := gtk.NewLabel("Indiquer la première page Verso: ")
	txtVerso := gtk.NewEntry()
	txtVerso.Connect("changed", func() {
		_, err := strconv.Atoi(txtVerso.GetText())
		if err != nil {
			txtVerso.SetText("")
		}
	})

	// bouton ouverture file dialog
	btOpenFile := gtk.NewButtonWithLabel("Ouvrir")
	btOpenFile.Clicked(func() {
		//-----------------------------------------------------
		// boite de dialog selection du fichier
		filechooserdialog := gtk.NewFileChooserDialog(
			"Choose File...",
			btOpenFile.GetTopLevelAsWindow(),
			gtk.FILE_CHOOSER_ACTION_OPEN,
			gtk.STOCK_OK,
			gtk.RESPONSE_ACCEPT)
		filter := gtk.NewFileFilter()
		filter.AddPattern("*.pdf")
		filechooserdialog.AddFilter(filter)
		filechooserdialog.Response(func() {
			if filechooserdialog.GetFilename() != "" {
				fileName.SetText(filechooserdialog.GetFilename())
				nbPages = getNumberOfPAges(filechooserdialog.GetFilename())
				lblPage.SetText("Le fichier séléctionné contient " + strconv.Itoa(nbPages) + " pages.")
			}

			//normalizeFileName(fileName.GetText())
			createTempFile()
			saveFile(inFile, fileName.GetText())
			filechooserdialog.Destroy()
		})
		filechooserdialog.Run()
	})

	//btSave
	btSave := gtk.NewButtonWithLabel("Enregistrer")
	btSave.Clicked(func() {

		cat = catFile(fileName, txtVerso)

		if cat == true {
			file := strings.Replace(fileName.GetText(), ".pdf", "_recto_verso_ok.pdf", 1)
			saveFile(file, outFile)
			dial := gtk.NewMessageDialog(window, 1, 1, 1, "La modification du PDF a été effectué avec succès.")
			dial.Response(func() {
				dial.Destroy()
				cat = false
			})

			dial.Run()
		}
	})

	//btn Visualiser le fichier
	btShowFile := gtk.NewButtonWithLabel("Visualiser le fichier")
	btShowFile.Clicked(func() {
		if fileName.GetText() != "" {
			cat = catFile(fileName, txtVerso)
			if cat {
				displayfile(outFile)
			} else {
				displayfile(inFile)
			}
		}
	})

	//btn Visualiser le fichier original
	btShowOriginalFile := gtk.NewButtonWithLabel("Visualiser l'original")
	btShowOriginalFile.Clicked(func() {
		if fileName.GetText() != "" {
			displayfile(inFile)
		}
	})

	//btSave
	btCancel := gtk.NewButtonWithLabel("Annuler")
	btCancel.Clicked(func() {
		gtk.MainQuit()
	})

	// creation du conteneur Principal
	vbox := gtk.NewVBox(false, 1)
	vpaned := gtk.NewVPaned()
	vpaned.SetSizeRequest(600, 530)
	vboxContent := gtk.NewVBox(false, 1)

	frameFile := gtk.NewFrame("Fichier")
	fBoxFile := gtk.NewVBox(false, 1)
	frameFile.Add(fBoxFile)

	frameOpt := gtk.NewFrame("Options")
	fBoxOpt := gtk.NewVBox(false, 1)
	frameOpt.Add(fBoxOpt)

	vboxSys := gtk.NewHBox(false, 1)
	vboxSys.Add(btCancel)
	vboxSys.Add(btSave)

	vboxContent.Add(frameFile)
	vboxContent.Add(frameOpt)

	fileBox1 := gtk.NewHBox(false, 10)
	fileBox1.Add(lblFileName)
	fileBox1.Add(fileName)

	fileBox2 := gtk.NewHBox(false, 10)
	fileBox2.Add(lblPage)

	fileBox3 := gtk.NewHBox(false, 10)
	fileBox3.Add(btShowOriginalFile)
	fileBox3.Add(btOpenFile)

	fBoxFile.PackStart(fileBox1, false, false, 10)
	fBoxFile.PackStart(fileBox2, false, false, 10)
	fBoxFile.PackStart(fileBox3, false, false, 10)

	optBox1 := gtk.NewHBox(false, 10)
	optBox1.Add(lblVerso)
	optBox1.Add(txtVerso)

	fBoxOpt.PackStart(optBox1, false, false, 10)
	fBoxOpt.PackStart(lblInfo, false, false, 10)
	fBoxOpt.PackStart(btShowFile, false, false, 10)

	vpaned.Pack1(vboxContent, false, false)

	vbox.Add(label)
	vbox.Add(vpaned)
	vbox.Add(vboxSys)

	window.Add(vbox)
	window.SetSizeRequest(600, 600)
	window.ShowAll()
	gtk.Main()

}

func getNumberOfPAges(filename string) int {

	cmd := exec.Command("pdftk", filename, "dump_data")
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	res := strings.Split(out.String(), "\n")
	var fileInfo map[string]string
	fileInfo = make(map[string]string)
	for i := 0; i < len(res); i++ {
		value := strings.Split(res[i], ": ")
		if len(value) == 2 {
			fileInfo[value[0]] = value[1]
		}
	}
	ret, err := strconv.Atoi(fileInfo["NumberOfPages"])
	if err != nil {
		return 0
	}
	return ret
}

func catFile(fileName *gtk.Label, txtVerso *gtk.Entry) bool {
	var cmd *exec.Cmd

	if fileName.GetText() != "" {

		nbVerso := int(math.Ceil(float64(nbPages/2)) + 1)

		if txtVerso.GetText() != "" {
			nbVerso, _ = strconv.Atoi(txtVerso.GetText())
		}

		if nbVerso < nbPages {
			j := nbVerso

			cmdText := "cat "
			for i := 1; i < nbPages; i++ {
				if i < nbVerso {
					cmdText += " " + strconv.Itoa(i)
				}
				if j <= nbPages {
					cmdText += " " + strconv.Itoa(j)
				}
				j++
			}

			cmd = exec.Command("bash", "-c", "pdftk "+inFile+" "+cmdText+" output "+outFile)
			ko := cmd.Run()

			if ko != nil {
				return false
			}
			return true
		}
	}
	return false
}

func displayfile(file string) {
	var cmd *exec.Cmd

	if runtime.GOOS == "linux" {
		cmd = exec.Command("xdg-open", file)
	} else if runtime.GOOS == "windows" {
		cmd = exec.Command("start", file)
	}
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}

/*
**
**  Create in and out temporary Files for safety manipulations
**
**/

func createTempFile() {

	//creating temp file
	in, err := ioutil.TempFile("", "in.pdf")

	out, err := ioutil.TempFile("", "out.pdf")

	if err != nil {
		log.Fatal(err)
	}

	if inFile != "" && outFile != "" {
		os.Remove(inFile)
		os.Remove(outFile)
	}
	inFile = in.Name()
	outFile = out.Name()

}

/*
** Copy the content of the input file in the output file
**
** @Params filename string - output file
** @Params input string - input file for content
**/
func saveFile(filename string, input string) {
	in, err := ioutil.ReadFile(input)
	if err != nil {
		log.Fatal(err)
	}

	ioutil.WriteFile(filename, in, 0666)
}
<commit_msg>Minor chages<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
)

var nbPages int
var cat = false
var outFile string
var inFile string

func main() {

	gtk.Init(nil)
	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetPosition(gtk.WIN_POS_CENTER)
	window.SetTitle("STOBS")
	window.SetIconName("gtk-dialog-info")
	window.Connect("destroy", func(ctx *glib.CallbackContext) {
		defer os.Remove(inFile)
		defer os.Remove(outFile)
		gtk.MainQuit()
	})

	// TITLE
	label := gtk.NewLabel("Convertir un PDF en Recto/Verso")
	label.ModifyFontEasy("DejaVu Serif 14")

	// label info fichier
	lblPage := gtk.NewLabel("")

	// label info
	lblInfo := gtk.NewLabel("Par défaut la première page Verso est situé à la moitié")

	// txtBox file
	lblFileName := gtk.NewLabel("Nom du fichier: ")
	fileName := gtk.NewLabel("")

	lblVerso := gtk.NewLabel("Indiquer la première page Verso: ")
	txtVerso := gtk.NewEntry()
	txtVerso.Connect("changed", func() {
		_, err := strconv.Atoi(txtVerso.GetText())
		if err != nil {
			txtVerso.SetText("")
		}
	})

	// bouton ouverture file dialog
	btOpenFile := gtk.NewButtonWithLabel("Ouvrir")
	btOpenFile.Clicked(func() {
		//-----------------------------------------------------
		// boite de dialog selection du fichier
		filechooserdialog := gtk.NewFileChooserDialog(
			"Choose File...",
			btOpenFile.GetTopLevelAsWindow(),
			gtk.FILE_CHOOSER_ACTION_OPEN,
			gtk.STOCK_OK,
			gtk.RESPONSE_ACCEPT)
		filter := gtk.NewFileFilter()
		filter.AddPattern("*.pdf")
		filechooserdialog.AddFilter(filter)
		filechooserdialog.Response(func() {
			if filechooserdialog.GetFilename() != "" {
				fileName.SetText(filechooserdialog.GetFilename())
				nbPages = getNumberOfPAges(filechooserdialog.GetFilename())
				lblPage.SetText("Le fichier séléctionné contient " + strconv.Itoa(nbPages) + " pages.")
			}

			//normalizeFileName(fileName.GetText())
			createTempFile()
			saveFile(inFile, fileName.GetText())
			filechooserdialog.Destroy()
		})
		filechooserdialog.Run()
	})

	//btSave
	btSave := gtk.NewButtonWithLabel("Enregistrer")
	btSave.Clicked(func() {

		cat = catFile(fileName, txtVerso)

		if cat == true {
			file := strings.Replace(fileName.GetText(), ".pdf", "_recto_verso.pdf", 1)
			saveFile(file, outFile)
			dial := gtk.NewMessageDialog(window, 1, 1, 1, "Le PDF recto/verso généré est "+file)
			dial.Response(func() {
				dial.Destroy()
				cat = false
			})

			dial.Run()
		}
	})

	//btn Visualiser le fichier
	btShowFile := gtk.NewButtonWithLabel("Visualiser le fichier")
	btShowFile.Clicked(func() {
		if fileName.GetText() != "" {
			cat = catFile(fileName, txtVerso)
			if cat {
				displayfile(outFile)
			} else {
				displayfile(inFile)
			}
		}
	})

	//btn Visualiser le fichier original
	btShowOriginalFile := gtk.NewButtonWithLabel("Visualiser l'original")
	btShowOriginalFile.Clicked(func() {
		if fileName.GetText() != "" {
			displayfile(inFile)
		}
	})

	//btSave
	btCancel := gtk.NewButtonWithLabel("Annuler")
	btCancel.Clicked(func() {
		gtk.MainQuit()
	})

	// creation du conteneur Principal
	vbox := gtk.NewVBox(false, 1)
	vpaned := gtk.NewVPaned()
	vpaned.SetSizeRequest(600, 530)
	vboxContent := gtk.NewVBox(false, 1)

	frameFile := gtk.NewFrame("Fichier")
	fBoxFile := gtk.NewVBox(false, 1)
	frameFile.Add(fBoxFile)

	frameOpt := gtk.NewFrame("Options")
	fBoxOpt := gtk.NewVBox(false, 1)
	frameOpt.Add(fBoxOpt)

	vboxSys := gtk.NewHBox(false, 1)
	vboxSys.Add(btCancel)
	vboxSys.Add(btSave)

	vboxContent.Add(frameFile)
	vboxContent.Add(frameOpt)

	fileBox1 := gtk.NewHBox(false, 10)
	fileBox1.Add(lblFileName)
	fileBox1.Add(fileName)

	fileBox2 := gtk.NewHBox(false, 10)
	fileBox2.Add(lblPage)

	fileBox3 := gtk.NewHBox(false, 10)
	fileBox3.Add(btShowOriginalFile)
	fileBox3.Add(btOpenFile)

	fBoxFile.PackStart(fileBox1, false, false, 10)
	fBoxFile.PackStart(fileBox2, false, false, 10)
	fBoxFile.PackStart(fileBox3, false, false, 10)

	optBox1 := gtk.NewHBox(false, 10)
	optBox1.Add(lblVerso)
	optBox1.Add(txtVerso)

	fBoxOpt.PackStart(optBox1, false, false, 10)
	fBoxOpt.PackStart(lblInfo, false, false, 10)
	fBoxOpt.PackStart(btShowFile, false, false, 10)

	vpaned.Pack1(vboxContent, false, false)

	vbox.Add(label)
	vbox.Add(vpaned)
	vbox.Add(vboxSys)

	window.Add(vbox)
	window.SetSizeRequest(600, 600)
	window.ShowAll()
	gtk.Main()

}

func getNumberOfPAges(filename string) int {

	cmd := exec.Command("pdftk", filename, "dump_data")
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	res := strings.Split(out.String(), "\n")
	var fileInfo map[string]string
	fileInfo = make(map[string]string)
	for i := 0; i < len(res); i++ {
		value := strings.Split(res[i], ": ")
		if len(value) == 2 {
			fileInfo[value[0]] = value[1]
		}
	}
	ret, err := strconv.Atoi(fileInfo["NumberOfPages"])
	if err != nil {
		return 0
	}
	return ret
}

func catFile(fileName *gtk.Label, txtVerso *gtk.Entry) bool {
	var cmd *exec.Cmd

	if fileName.GetText() != "" {

		nbVerso := int(math.Ceil(float64(nbPages/2)) + 1)

		if txtVerso.GetText() != "" {
			nbVerso, _ = strconv.Atoi(txtVerso.GetText())
		}

		if nbVerso < nbPages {
			j := nbVerso

			cmdText := "cat "
			for i := 1; i < nbPages; i++ {
				if i < nbVerso {
					cmdText += " " + strconv.Itoa(i)
				}
				if j <= nbPages {
					cmdText += " " + strconv.Itoa(j)
				}
				j++
			}

			cmd = exec.Command("bash", "-c", "pdftk "+inFile+" "+cmdText+" output "+outFile)
			ko := cmd.Run()

			if ko != nil {
				return false
			}
			return true
		}
	}
	return false
}

func displayfile(file string) {
	var cmd *exec.Cmd

	if runtime.GOOS == "linux" {
		cmd = exec.Command("xdg-open", file)
	} else if runtime.GOOS == "windows" {
		cmd = exec.Command("start", file)
	}
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}

/*
**
**  Create in and out temporary Files for safety manipulations
**
**/

func createTempFile() {

	//creating temp file
	in, err := ioutil.TempFile("", "in.pdf")

	out, err := ioutil.TempFile("", "out.pdf")

	if err != nil {
		log.Fatal(err)
	}

	if inFile != "" && outFile != "" {
		os.Remove(inFile)
		os.Remove(outFile)
	}
	inFile = in.Name()
	outFile = out.Name()

}

/*
** Copy the content of the input file in the output file
**
** @Params filename string - output file
** @Params input string - input file for content
**/
func saveFile(filename string, input string) {
	in, err := ioutil.ReadFile(input)
	if err != nil {
		log.Fatal(err)
	}

	ioutil.WriteFile(filename, in, 0666)
}
<|endoftext|>