<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main implements an injection function for resource reservations and
// is run with `kustomize config run -- DIR/`.
package main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"

	multierr "github.com/hashicorp/go-multierror"
	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
	"sigs.k8s.io/kustomize/kyaml/yaml"
)

const (
	loggingServiceValue    = "logging.googleapis.com/kubernetes"
	monitoringServiceValue = "monitoring.googleapis.com/kubernetes"
	containerClusterKind   = "ContainerCluster"
	containerNodePoolKind  = "ContainerNodePool"
	apiGroup               = "container.cnrm.cloud.google.com"
)

var supportedReleaseChannels = []string{"REGULAR", "RAPID", "STABLE"}
var n1CustomMachineTypeRegex = regexp.MustCompile(`(\w+)-(\d+)-(\d+)`)
var customMachineTypeRegex = regexp.MustCompile(`(\w+)-(\w+)-(\d+)-(\d+)`)
var machineTypeRegex = regexp.MustCompile(`(\w+)-(\w+)-(\d+)`)
var valueWithComment = regexp.MustCompile(`\s*(\S+)(\s+#.*)?`)

func main() {
	rw := &kio.ByteReadWriter{Reader: os.Stdin, Writer: os.Stdout, KeepReaderAnnotations: true}
	p := kio.Pipeline{
		Inputs:  []kio.Reader{rw},       // read the inputs into a slice
		Filters: []kio.Filter{filter{}}, // run the enableASM into the inputs
		Outputs: []kio.Writer{rw}}       // copy the inputs to the output
	if err := p.Execute(); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}

// filter implements kio.Filter
type filter struct{}

// Filter injects new filters into container cluster and nodepool.
func (filter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
	var errList []error

	for _, r := range in {
		if errs := validate(r); len(errs) != 0 {
			errList = append(errList, errs...)
		}
	}
	if errs := multierr.Append(nil, errList...); errs != nil {
		return nil, errs
	}
	return in, nil
}

// https://cloud.google.com/service-mesh/docs/gke-install-existing-cluster#setting_up_your_project
func validate(r *yaml.RNode) []error {

	var errList []error

	meta, err := r.GetMeta()
	if err != nil {
		errList = append(errList, err)
		return errList
	}

	if strings.HasPrefix(meta.ApiVersion, apiGroup) && meta.Kind == containerClusterKind {

		// validate if Cloud Monitoring and Logging are enabled
		if err := validateNodeValue(r, meta, loggingServiceValue, "spec", "loggingService"); err != nil {
			errList = append(errList, err)
		}
		if err := validateNodeValue(r, meta, monitoringServiceValue, "spec", "monitoringService"); err != nil {
			errList = append(errList, err)
		}

		// validate if Workload Identity is enabled
		if _, err := validateNodeExists(r, meta, "spec", "workloadIdentity", "identityNamespace"); err != nil {
			errList = append(errList, err)
		}

		// validate if mesh_id lable is set
		if _, err := validateNodeExists(r, meta, "spec", "labels", "mesh_id"); err != nil {
			errList = append(errList, err)
		}

		// validate release channel
		if err := validateReleaseChannel(r, meta, supportedReleaseChannels, "spec", "releaseChannel", "channel"); err != nil {
			errList = append(errList, err)
		}

		// validate machine type
		if err := validateMachineType(r, meta); err != nil {
			errList = append(errList, err)
		}
	}

	if strings.HasPrefix(meta.ApiVersion, apiGroup) && meta.Kind == containerNodePoolKind {
		if err := validateNodeValueGreaterThan(r, meta, 3, "ASM requires at least four nodes. If you need to add nodes, see https://bit.ly/2RnVL2T", "spec", "nodeCount"); err != nil {
			errList = append(errList, err)
		}

		// validate machine type
		if err := validateMachineType(r, meta); err != nil {
			errList = append(errList, err)
		}
	}
	return errList
}

func validateNodeValue(r *yaml.RNode, meta yaml.ResourceMeta, expected string, path ...string) error {
	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	pathString := strings.Join(path, ".")
	value, err := stripValueComment(node, r, meta, pathString)
	if err != nil {
		return err
	}

	if value != expected {
		return fmt.Errorf(
			"unsupported %s value in %s %s (%s [%s]), expected: %s, actual: %s",
			pathString, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation],
			expected,
			value)
	}
	return nil
}

func validateNodeExists(r *yaml.RNode, meta yaml.ResourceMeta, path ...string) (*yaml.RNode, error) {
	node, err := r.Pipe(yaml.Lookup(path...))
	if err != nil {
		s, _ := r.String()
		return nil, fmt.Errorf("%v: %s", err, s)
	}
	if node == nil {
		return node, fmt.Errorf(
			"%s missing in %s %s (%s [%s])",
			strings.Join(path, "."),
			meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}
	return node, nil
}

func stripValueComment(node *yaml.RNode, r *yaml.RNode, meta yaml.ResourceMeta, path string) (string, error) {
	value, err := node.String()
	if err != nil {
		s, _ := r.String()
		return "", fmt.Errorf("%v: %s", err, s)
	}
	group := valueWithComment.FindStringSubmatch(value)
	if len(group) < 3 {
		return "", fmt.Errorf("unknown format of %s: %s in %s %s (%s [%s])",
			path, value, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}
	return group[1], nil
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func validateNodeValueGreaterThan(r *yaml.RNode, meta yaml.ResourceMeta, min int, errorInfo string, path ...string) error {
	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	value, err := node.String()
	value = strings.TrimSpace(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	count, err := strconv.Atoi(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	if count <= min {
		return fmt.Errorf(
			"%s is %d in %s %s (%s [%s]). %s",
			strings.Join(path, "."),
			count,
			meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation],
			errorInfo)
	}
	return nil
}

func validateReleaseChannel(r *yaml.RNode, meta yaml.ResourceMeta, expected []string, path ...string) error {

	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	pathString := strings.Join(path, ".")
	value, err := stripValueComment(node, r, meta, pathString)
	if err != nil {
		return err
	}

	if contains(expected, value) {
		return nil
	}
	return fmt.Errorf(
		"unsupported %s value in %s %s (%s [%s]), expected: %s, actual: %s",
		strings.Join(path, "."),
		meta.Kind, meta.Name,
		meta.Annotations[kioutil.PathAnnotation],
		meta.Annotations[kioutil.IndexAnnotation],
		strings.Join(expected, ","),
		value)

}

func validateMachineType(r *yaml.RNode, meta yaml.ResourceMeta) error {
	node, err := validateNodeExists(r, meta, "spec", "nodeConfig", "machineType")
	if err != nil {
		return err
	}
	value, err := node.String()
	value = strings.TrimSpace(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}

	// n1 custom
	if strings.HasPrefix(value, "custom") {
		if err := validateCustomMachineType(r, meta, n1CustomMachineTypeRegex, value, 4, 2); err != nil {
			return err
		}
	} else if strings.Contains(value, "custom") { // n2, e2 custom
		if err := validateCustomMachineType(r, meta, customMachineTypeRegex, value, 5, 3); err != nil {
			return err
		}
	} else if strings.Contains(value, "micro") || strings.Contains(value, "small") || strings.Contains(value, "medium") {
		return unsupportedMachineTypeError(value, meta)
	} else {
		if err := validateCustomMachineType(r, meta, machineTypeRegex, value, 4, 3); err != nil {
			return err
		}
	}

	return nil
}

func validateCustomMachineType(r *yaml.RNode, meta yaml.ResourceMeta, reg *regexp.Regexp, value string, groupLen, vcpuIndex int) error {
	machineType := reg.FindStringSubmatch(value)
	if len(machineType) < groupLen {
		return fmt.Errorf("invalid machineType format: %s in %s %s (%s [%s])", value, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}

	vcpu, err := strconv.Atoi(machineType[vcpuIndex])
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	if vcpu < 4 {
		return unsupportedMachineTypeError(value, meta)
	}
	return nil
}

func unsupportedMachineTypeError(value string, meta yaml.ResourceMeta) error {
	return fmt.Errorf("unsupported machine type: %s in %s %s (%s [%s]). The minimum machine type is n1-standard-4, "+
		"which has four vCPUs. If the machine type for your cluster doesn't have at least four vCPUs, "+
		"change the machine type as described here https://bit.ly/2V0KPdu", value, meta.Kind, meta.Name,
		meta.Annotations[kioutil.PathAnnotation],
		meta.Annotations[kioutil.IndexAnnotation])
}
<commit_msg>Validate containerCluster's machineType only when exists<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main implements an injection function for resource reservations and
// is run with `kustomize config run -- DIR/`.
package main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"

	multierr "github.com/hashicorp/go-multierror"
	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
	"sigs.k8s.io/kustomize/kyaml/yaml"
)

const (
	loggingServiceValue    = "logging.googleapis.com/kubernetes"
	monitoringServiceValue = "monitoring.googleapis.com/kubernetes"
	containerClusterKind   = "ContainerCluster"
	containerNodePoolKind  = "ContainerNodePool"
	apiGroup               = "container.cnrm.cloud.google.com"
)

var supportedReleaseChannels = []string{"REGULAR", "RAPID", "STABLE"}
var n1CustomMachineTypeRegex = regexp.MustCompile(`(\w+)-(\d+)-(\d+)`)
var customMachineTypeRegex = regexp.MustCompile(`(\w+)-(\w+)-(\d+)-(\d+)`)
var machineTypeRegex = regexp.MustCompile(`(\w+)-(\w+)-(\d+)`)
var valueWithComment = regexp.MustCompile(`\s*(\S+)(\s+#.*)?`)

func main() {
	rw := &kio.ByteReadWriter{Reader: os.Stdin, Writer: os.Stdout, KeepReaderAnnotations: true}
	p := kio.Pipeline{
		Inputs:  []kio.Reader{rw},       // read the inputs into a slice
		Filters: []kio.Filter{filter{}}, // run the enableASM into the inputs
		Outputs: []kio.Writer{rw}}       // copy the inputs to the output
	if err := p.Execute(); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}

// filter implements kio.Filter
type filter struct{}

// Filter injects new filters into container cluster and nodepool.
func (filter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
	var errList []error

	for _, r := range in {
		if errs := validate(r); len(errs) != 0 {
			errList = append(errList, errs...)
		}
	}
	if errs := multierr.Append(nil, errList...); errs != nil {
		return nil, errs
	}
	return in, nil
}

// https://cloud.google.com/service-mesh/docs/gke-install-existing-cluster#setting_up_your_project
func validate(r *yaml.RNode) []error {

	var errList []error

	meta, err := r.GetMeta()
	if err != nil {
		errList = append(errList, err)
		return errList
	}

	if strings.HasPrefix(meta.ApiVersion, apiGroup) && meta.Kind == containerClusterKind {

		// validate if Cloud Monitoring and Logging are enabled
		if err := validateNodeValue(r, meta, loggingServiceValue, "spec", "loggingService"); err != nil {
			errList = append(errList, err)
		}
		if err := validateNodeValue(r, meta, monitoringServiceValue, "spec", "monitoringService"); err != nil {
			errList = append(errList, err)
		}

		// validate if Workload Identity is enabled
		if _, err := validateNodeExists(r, meta, "spec", "workloadIdentity", "identityNamespace"); err != nil {
			errList = append(errList, err)
		}

		// validate if mesh_id lable is set
		if _, err := validateNodeExists(r, meta, "spec", "labels", "mesh_id"); err != nil {
			errList = append(errList, err)
		}

		// validate release channel
		if err := validateReleaseChannel(r, meta, supportedReleaseChannels, "spec", "releaseChannel", "channel"); err != nil {
			errList = append(errList, err)
		}

		// validate machine type
		if err := validateMachineType(r, meta, false); err != nil {
			errList = append(errList, err)
		}
	}

	if strings.HasPrefix(meta.ApiVersion, apiGroup) && meta.Kind == containerNodePoolKind {
		if err := validateNodeValueGreaterThan(r, meta, 3, "ASM requires at least four nodes. If you need to add nodes, see https://bit.ly/2RnVL2T", "spec", "nodeCount"); err != nil {
			errList = append(errList, err)
		}

		// validate machine type
		if err := validateMachineType(r, meta, true); err != nil {
			errList = append(errList, err)
		}
	}
	return errList
}

func validateNodeValue(r *yaml.RNode, meta yaml.ResourceMeta, expected string, path ...string) error {
	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	pathString := strings.Join(path, ".")
	value, err := stripValueComment(node, r, meta, pathString)
	if err != nil {
		return err
	}

	if value != expected {
		return fmt.Errorf(
			"unsupported %s value in %s %s (%s [%s]), expected: %s, actual: %s",
			pathString, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation],
			expected,
			value)
	}
	return nil
}

func validateNodeExists(r *yaml.RNode, meta yaml.ResourceMeta, path ...string) (*yaml.RNode, error) {
	node, err := r.Pipe(yaml.Lookup(path...))
	if err != nil {
		s, _ := r.String()
		return nil, fmt.Errorf("%v: %s", err, s)
	}
	if node == nil {
		return node, fmt.Errorf(
			"%s missing in %s %s (%s [%s])",
			strings.Join(path, "."),
			meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}
	return node, nil
}

func stripValueComment(node *yaml.RNode, r *yaml.RNode, meta yaml.ResourceMeta, path string) (string, error) {
	value, err := node.String()
	if err != nil {
		s, _ := r.String()
		return "", fmt.Errorf("%v: %s", err, s)
	}
	group := valueWithComment.FindStringSubmatch(value)
	if len(group) < 3 {
		return "", fmt.Errorf("unknown format of %s: %s in %s %s (%s [%s])",
			path, value, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}
	return group[1], nil
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func validateNodeValueGreaterThan(r *yaml.RNode, meta yaml.ResourceMeta, min int, errorInfo string, path ...string) error {
	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	value, err := node.String()
	value = strings.TrimSpace(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	count, err := strconv.Atoi(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	if count <= min {
		return fmt.Errorf(
			"%s is %d in %s %s (%s [%s]). %s",
			strings.Join(path, "."),
			count,
			meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation],
			errorInfo)
	}
	return nil
}

func validateReleaseChannel(r *yaml.RNode, meta yaml.ResourceMeta, expected []string, path ...string) error {

	node, err := validateNodeExists(r, meta, path...)
	if err != nil {
		return err
	}
	pathString := strings.Join(path, ".")
	value, err := stripValueComment(node, r, meta, pathString)
	if err != nil {
		return err
	}

	if contains(expected, value) {
		return nil
	}
	return fmt.Errorf(
		"unsupported %s value in %s %s (%s [%s]), expected: %s, actual: %s",
		strings.Join(path, "."),
		meta.Kind, meta.Name,
		meta.Annotations[kioutil.PathAnnotation],
		meta.Annotations[kioutil.IndexAnnotation],
		strings.Join(expected, ","),
		value)

}

func validateMachineType(r *yaml.RNode, meta yaml.ResourceMeta, mustExist bool) error {
	node, err := validateNodeExists(r, meta, "spec", "nodeConfig", "machineType")
	if err != nil {
		if mustExist {
			return err
		} else {
			return nil
		}
	}
	value, err := node.String()
	value = strings.TrimSpace(value)
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}

	// n1 custom
	if strings.HasPrefix(value, "custom") {
		if err := validateCustomMachineType(r, meta, n1CustomMachineTypeRegex, value, 4, 2); err != nil {
			return err
		}
	} else if strings.Contains(value, "custom") { // n2, e2 custom
		if err := validateCustomMachineType(r, meta, customMachineTypeRegex, value, 5, 3); err != nil {
			return err
		}
	} else if strings.Contains(value, "micro") || strings.Contains(value, "small") || strings.Contains(value, "medium") {
		return unsupportedMachineTypeError(value, meta)
	} else {
		if err := validateCustomMachineType(r, meta, machineTypeRegex, value, 4, 3); err != nil {
			return err
		}
	}

	return nil
}

func validateCustomMachineType(r *yaml.RNode, meta yaml.ResourceMeta, reg *regexp.Regexp, value string, groupLen, vcpuIndex int) error {
	machineType := reg.FindStringSubmatch(value)
	if len(machineType) < groupLen {
		return fmt.Errorf("invalid machineType format: %s in %s %s (%s [%s])", value, meta.Kind, meta.Name,
			meta.Annotations[kioutil.PathAnnotation],
			meta.Annotations[kioutil.IndexAnnotation])
	}

	vcpu, err := strconv.Atoi(machineType[vcpuIndex])
	if err != nil {
		s, _ := r.String()
		return fmt.Errorf("%v: %s", err, s)
	}
	if vcpu < 4 {
		return unsupportedMachineTypeError(value, meta)
	}
	return nil
}

func unsupportedMachineTypeError(value string, meta yaml.ResourceMeta) error {
	return fmt.Errorf("unsupported machine type: %s in %s %s (%s [%s]). The minimum machine type is n1-standard-4, "+
		"which has four vCPUs. If the machine type for your cluster doesn't have at least four vCPUs, "+
		"change the machine type as described here https://bit.ly/2V0KPdu", value, meta.Kind, meta.Name,
		meta.Annotations[kioutil.PathAnnotation],
		meta.Annotations[kioutil.IndexAnnotation])
}
<|endoftext|>


<commit_before>package main

import (
	c3to10 "eaciit/wfdemo-git/processapp/threeextractor/convert3secto10min/lib"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/eaciit/database/base"
	"github.com/eaciit/orm"
	"github.com/fsnotify/fsnotify"
	// "github.com/metakeule/fmtdate"
	//dc "eaciit/wfdemo-git/processapp/threeextractor/dataconversion"
	"archive/tar"
	"archive/zip"
	"bytes"
	. "eaciit/wfdemo-git/processapp/watcher/controllers"
	"time"

	tk "github.com/eaciit/toolkit"
)

const (
	NOK = "NOK"
	OK  = "OK"
	// TIME_FORMAT_STR = "DDMMYYhhmmss"
)

type Command struct {
	Action  string
	Command string
	Success string
	Fail    string
}
type Configuration struct {
	Draft    string
	Process  string
	Fail     string
	Success  string
	Errors   string
	Archive  string
	Commands []Command
}

var (
	conn    base.IConnection
	ctx     *orm.DataContext
	conf    Configuration
	mux     = &sync.Mutex{}
	pathSep = string(os.PathSeparator)
)

func main() {

	fmt.Println(".." + pathSep + "conf" + pathSep + "receiver-config.json")

	file, _ := os.Open(".." + pathSep + "conf" + pathSep + "receiver-config.json")
	decoder := json.NewDecoder(file)
	err := decoder.Decode(&conf)

	if err != nil {
		panic(err)
	}

	// now, _ := time.Parse("2006-1-2 15:4:05", "2016-10-22 23:57:30")
	// tenMinInfo := GenTenMinuteInfo(now)

	// log.Printf("%#v \n", tenMinInfo)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("Starting the app..\n")

	log.Println()
	log.Printf("Draft: %v\n", conf.Draft)
	log.Printf("Process: %v\n", conf.Process)
	log.Printf("Fail: %v\n", conf.Fail)
	log.Printf("Success: %v\n", conf.Success)
	log.Printf("Errors: %v\n", conf.Errors)
	log.Println()

	/*db, _ := PrepareConnection()
	base := new(BaseController)
	base.Ctx = orm.New(db)
	defer base.Ctx.Close()

	log.Println("xxx")

	new(GenTenFromThreeSecond).Generate(base, "sample.csv")*/

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				// log.Println("event:", event)
				if event.Op&fsnotify.Create == fsnotify.Create {
					go processFile(event.Name, conf.Commands)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	// watch draft
	err = watcher.Add(conf.Draft)
	if err != nil {
		log.Fatal(err)
	}

	// watch process
	err = watcher.Add(conf.Process)
	if err != nil {
		log.Fatal(err)
	}

	/*// watch fail
	err = watcher.Add("/Users/frezadev/Documents/watch/fail")
	if err != nil {
		log.Fatal(err)
	}

	// watch success
	err = watcher.Add("/Users/frezadev/Documents/watch/success")
	if err != nil {
		log.Fatal(err)
	}*/
	<-done
}

func processFile(filePath string, com []Command) {
	// dt := time.Now()
	// dtStr := fmtdate.Format(TIME_FORMAT_STR, dt)
	fmt.Println(" >>> Process : ", filePath)
	for true {
		byteOut, err := runCMD("lsof " + filePath)
		if err != nil {
			log.Print("Gagal")
		}
		if len(byteOut) == 0 {
			break
		} else {
			fmt.Println(string(byteOut))
			time.Sleep(200 * time.Millisecond)
		}

	}
	file := strings.Split(filePath, pathSep)
	fileName := file[len(file)-1]

	if strings.Contains(fileName, ".csv") {
		time.Sleep(100 * time.Millisecond)
		log.Printf("Proccess file: %v \n", filePath)
		var action Command

		if strings.Contains(filePath, conf.Draft) {
			action = com[0]
		} else if strings.Contains(filePath, conf.Process) {
			action = com[1]
		}

		// log.Printf("action: %v \n", action)

		next := action.Action
	done:

		for {
			log.Printf("\n\nnext: %v \n", next)

			if next == "DONE" {
				break done
			} else {
				for _, act := range com {
					//fmt.Println("PPPP")
					if act.Action == next {
						next = run(act, fileName)

						break
					}
				}
			}
		}

		log.Printf("DONE for file: %v\n", filePath)
	} else if strings.Contains(fileName, ".tar") {
		time.Sleep(100 * time.Millisecond)
		untar(filePath, conf.Draft)
		_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
	} else if strings.Contains(fileName, ".zip") {
		time.Sleep(100 * time.Millisecond)
		e := unzip(filePath, conf.Draft)
		if e != nil {
			log.Printf("%s - %s", filepath, e.Error())
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Errors))
		} else {
			fmt.Println("Unzip Done")
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
		}
	}
}

func untar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("ERR: %#v \n", err.Error())
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		// log.Printf("path: %#v \n", path)
		// log.Printf("info: %#v \n", info)
		if strings.Contains(info.Name(), ".csv") {
			if info.IsDir() {
				if err = os.MkdirAll(path, info.Mode()); err != nil {
					return err
				}
				continue
			}

			file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(file, tarReader)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func unzip(archive, target string) error {
	fmt.Println("Unzip", archive, target)
	reader, err := zip.OpenReader(archive)
	if err != nil {
		return err
	}

	if err := os.MkdirAll(target, 0755); err != nil {
		return err
	}

	for _, file := range reader.File {
		if strings.Contains(file.Name, ".csv") {

			path := filepath.Join(target, file.Name)
			fileReader, err := file.Open()

			if err != nil {
				log.Printf("ERR: %#v \n", err.Error())
				return err
			}
			defer fileReader.Close()

			targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
			if err != nil {
				return err
			}
			defer targetFile.Close()

			if _, err := io.Copy(targetFile, fileReader); err != nil {
				return err
			}
		}
	}

	reader.Close()
	return nil
}

func runCMD(cmdStr string) (out []byte, err error) {
	if pathSep == "\\" {
		cmdStr = strings.Replace(cmdStr, "\\", "/", -1)

	}

	if !strings.Contains(cmdStr, "lsof") {
		fmt.Println("sh", "-c", cmdStr)
	}

	var errBuff bytes.Buffer
	cmd := exec.Command("sh", "-c", cmdStr)
	cmd.Stderr = &errBuff
	//cmd.Run()
	//cmd.Path = os.Getenv("Path")
	//fmt.Println(cmd.Path)
	out, err = cmd.Output()
	if err != nil {
		fmt.Println(errBuff.String())
	}
	return
}

func run(action Command, file string) (next string) {
	cmdStr := ""
	runCommand := true
	log.Printf("run: %v | %v \n", action, file)
	// mux.Lock()

	if action.Action == "COPY_TO_PROCESS" {
		cmdStr = fmt.Sprintf(action.Command, conf.Draft+pathSep+file, conf.Process+pathSep+file)
	} else if action.Action == "COPY_TO_SUCCESS" {
		runCommand = doProcess(conf.Process + pathSep + file)

		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Success+pathSep+file)
	} else if action.Action == "COPY_TO_FAIL" {
		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Fail+pathSep+file)
	}
	//log.Printf("cmdstr: %v \n", cmdStr)
	// mux.Unlock()

	if runCommand {
		out, err := runCMD(cmdStr)

		if out != nil {
			log.Printf("%v \n", out)
		}

		if err != nil {
			log.Printf("result: %v %s\n%s", err.Error(), cmdStr, string(out))
			next = action.Success
		} else {
			next = action.Success
		}
	} else {
		log.Println("DONE")
		next = action.Fail
	}

	// log.Printf("next: %v \n", next)

	return
}

func doProcess(file string) (success bool) {
	log.Printf("doProcess: %v \n", file)
	db, e := PrepareConnection()
	if e != nil {
		log.Printf("ERROR on Process: %v\n", e.Error())
		success = false
	} else {
		//start := time.Now()
		base := new(BaseController)
		base.Ctx = orm.New(db)
		defer base.Ctx.Close()

		anFile := strings.Split(file, pathSep)
		fileName := anFile[len(anFile)-1]

		muxDo := &sync.Mutex{}

		muxDo.Lock()
		errorLine := new(ConvScadaTreeSecs).Generate(base, file)
		WriteWatcherErrors(errorLine, fileName, conf.Errors)
		log.Println("ConvScadaTreeSecs: DONE")
		muxDo.Unlock()
		log.Println("Begin Converting ", file)
		err := c3to10.Generate(tk.M{}.Set("selector", "file").Set("file", fileName))
		if err != nil {
			tk.Println(err)
		} else {
			tk.Println(">> DONE <<")
		}

		// errorLine = tk.M{}
		// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
		// WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
		// log.Println("GenTenFromThreeSecond: DONE")

		/*
			muxDo.Lock()
			errorLine = tk.M{}
			conv := dc.NewDataConversion(base.Ctx)
			errorLine = conv.Generate(fileName)
			// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
			WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
			log.Printf("GenTenFromThreeSecond: %v DONE | in %v seconds \n", file, time.Now().Sub(start).Seconds())
			success = true
			muxDo.Unlock()*/
	}

	return
}
<commit_msg>bug fix #2<commit_after>package main

import (
	c3to10 "eaciit/wfdemo-git/processapp/threeextractor/convert3secto10min/lib"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/eaciit/database/base"
	"github.com/eaciit/orm"
	"github.com/fsnotify/fsnotify"
	// "github.com/metakeule/fmtdate"
	//dc "eaciit/wfdemo-git/processapp/threeextractor/dataconversion"
	"archive/tar"
	"archive/zip"
	"bytes"
	. "eaciit/wfdemo-git/processapp/watcher/controllers"
	"time"

	tk "github.com/eaciit/toolkit"
)

const (
	NOK = "NOK"
	OK  = "OK"
	// TIME_FORMAT_STR = "DDMMYYhhmmss"
)

type Command struct {
	Action  string
	Command string
	Success string
	Fail    string
}
type Configuration struct {
	Draft    string
	Process  string
	Fail     string
	Success  string
	Errors   string
	Archive  string
	Commands []Command
}

var (
	conn    base.IConnection
	ctx     *orm.DataContext
	conf    Configuration
	mux     = &sync.Mutex{}
	pathSep = string(os.PathSeparator)
)

func main() {

	fmt.Println(".." + pathSep + "conf" + pathSep + "receiver-config.json")

	file, _ := os.Open(".." + pathSep + "conf" + pathSep + "receiver-config.json")
	decoder := json.NewDecoder(file)
	err := decoder.Decode(&conf)

	if err != nil {
		panic(err)
	}

	// now, _ := time.Parse("2006-1-2 15:4:05", "2016-10-22 23:57:30")
	// tenMinInfo := GenTenMinuteInfo(now)

	// log.Printf("%#v \n", tenMinInfo)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("Starting the app..\n")

	log.Println()
	log.Printf("Draft: %v\n", conf.Draft)
	log.Printf("Process: %v\n", conf.Process)
	log.Printf("Fail: %v\n", conf.Fail)
	log.Printf("Success: %v\n", conf.Success)
	log.Printf("Errors: %v\n", conf.Errors)
	log.Println()

	/*db, _ := PrepareConnection()
	base := new(BaseController)
	base.Ctx = orm.New(db)
	defer base.Ctx.Close()

	log.Println("xxx")

	new(GenTenFromThreeSecond).Generate(base, "sample.csv")*/

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				// log.Println("event:", event)
				if event.Op&fsnotify.Create == fsnotify.Create {
					go processFile(event.Name, conf.Commands)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	// watch draft
	err = watcher.Add(conf.Draft)
	if err != nil {
		log.Fatal(err)
	}

	// watch process
	err = watcher.Add(conf.Process)
	if err != nil {
		log.Fatal(err)
	}

	/*// watch fail
	err = watcher.Add("/Users/frezadev/Documents/watch/fail")
	if err != nil {
		log.Fatal(err)
	}

	// watch success
	err = watcher.Add("/Users/frezadev/Documents/watch/success")
	if err != nil {
		log.Fatal(err)
	}*/
	<-done
}

func processFile(filePath string, com []Command) {
	// dt := time.Now()
	// dtStr := fmtdate.Format(TIME_FORMAT_STR, dt)
	fmt.Println(" >>> Process : ", filePath)
	for true {
		byteOut, err := runCMD("lsof " + filePath)
		if err != nil {
			log.Print("Gagal")
		}
		if len(byteOut) == 0 {
			break
		} else {
			fmt.Println(string(byteOut))
			time.Sleep(200 * time.Millisecond)
		}

	}
	file := strings.Split(filePath, pathSep)
	fileName := file[len(file)-1]

	if strings.Contains(fileName, ".csv") {
		time.Sleep(100 * time.Millisecond)
		log.Printf("Proccess file: %v \n", filePath)
		var action Command

		if strings.Contains(filePath, conf.Draft) {
			action = com[0]
		} else if strings.Contains(filePath, conf.Process) {
			action = com[1]
		}

		// log.Printf("action: %v \n", action)

		next := action.Action
	done:

		for {
			log.Printf("\n\nnext: %v \n", next)

			if next == "DONE" {
				break done
			} else {
				for _, act := range com {
					//fmt.Println("PPPP")
					if act.Action == next {
						next = run(act, fileName)

						break
					}
				}
			}
		}

		log.Printf("DONE for file: %v\n", filePath)
	} else if strings.Contains(fileName, ".tar") {
		time.Sleep(100 * time.Millisecond)
		untar(filePath, conf.Draft)
		_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
	} else if strings.Contains(fileName, ".zip") {
		time.Sleep(100 * time.Millisecond)
		e := unzip(filePath, conf.Draft)
		if e != nil {
			log.Printf("%s - %s", filePath, e.Error())
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Errors))
		} else {
			fmt.Println("Unzip Done")
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
		}
	}
}

func untar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("ERR: %#v \n", err.Error())
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		// log.Printf("path: %#v \n", path)
		// log.Printf("info: %#v \n", info)
		if strings.Contains(info.Name(), ".csv") {
			if info.IsDir() {
				if err = os.MkdirAll(path, info.Mode()); err != nil {
					return err
				}
				continue
			}

			file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(file, tarReader)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func unzip(archive, target string) error {
	fmt.Println("Unzip", archive, target)
	reader, err := zip.OpenReader(archive)
	if err != nil {
		return err
	}

	if err := os.MkdirAll(target, 0755); err != nil {
		return err
	}

	for _, file := range reader.File {
		if strings.Contains(file.Name, ".csv") {

			path := filepath.Join(target, file.Name)
			fileReader, err := file.Open()

			if err != nil {
				log.Printf("ERR: %#v \n", err.Error())
				return err
			}
			defer fileReader.Close()

			targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
			if err != nil {
				return err
			}
			defer targetFile.Close()

			if _, err := io.Copy(targetFile, fileReader); err != nil {
				return err
			}
		}
	}

	reader.Close()
	return nil
}

func runCMD(cmdStr string) (out []byte, err error) {
	if pathSep == "\\" {
		cmdStr = strings.Replace(cmdStr, "\\", "/", -1)

	}

	if !strings.Contains(cmdStr, "lsof") {
		fmt.Println("sh", "-c", cmdStr)
	}

	var errBuff bytes.Buffer
	cmd := exec.Command("sh", "-c", cmdStr)
	cmd.Stderr = &errBuff
	//cmd.Run()
	//cmd.Path = os.Getenv("Path")
	//fmt.Println(cmd.Path)
	out, err = cmd.Output()
	if err != nil {
		fmt.Println(errBuff.String())
	}
	return
}

func run(action Command, file string) (next string) {
	cmdStr := ""
	runCommand := true
	log.Printf("run: %v | %v \n", action, file)
	// mux.Lock()

	if action.Action == "COPY_TO_PROCESS" {
		cmdStr = fmt.Sprintf(action.Command, conf.Draft+pathSep+file, conf.Process+pathSep+file)
	} else if action.Action == "COPY_TO_SUCCESS" {
		runCommand = doProcess(conf.Process + pathSep + file)

		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Success+pathSep+file)
	} else if action.Action == "COPY_TO_FAIL" {
		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Fail+pathSep+file)
	}
	//log.Printf("cmdstr: %v \n", cmdStr)
	// mux.Unlock()

	if runCommand {
		out, err := runCMD(cmdStr)

		if out != nil {
			log.Printf("%v \n", out)
		}

		if err != nil {
			log.Printf("result: %v %s\n%s", err.Error(), cmdStr, string(out))
			next = action.Success
		} else {
			next = action.Success
		}
	} else {
		log.Println("DONE")
		next = action.Fail
	}

	// log.Printf("next: %v \n", next)

	return
}

func doProcess(file string) (success bool) {
	log.Printf("doProcess: %v \n", file)
	db, e := PrepareConnection()
	if e != nil {
		log.Printf("ERROR on Process: %v\n", e.Error())
		success = false
	} else {
		//start := time.Now()
		base := new(BaseController)
		base.Ctx = orm.New(db)
		defer base.Ctx.Close()

		anFile := strings.Split(file, pathSep)
		fileName := anFile[len(anFile)-1]

		muxDo := &sync.Mutex{}

		muxDo.Lock()
		errorLine := new(ConvScadaTreeSecs).Generate(base, file)
		WriteWatcherErrors(errorLine, fileName, conf.Errors)
		log.Println("ConvScadaTreeSecs: DONE")
		muxDo.Unlock()
		log.Println("Begin Converting ", file)
		err := c3to10.Generate(tk.M{}.Set("selector", "file").Set("file", fileName))
		if err != nil {
			tk.Println(err)
		} else {
			tk.Println(">> DONE <<")
		}

		// errorLine = tk.M{}
		// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
		// WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
		// log.Println("GenTenFromThreeSecond: DONE")

		/*
			muxDo.Lock()
			errorLine = tk.M{}
			conv := dc.NewDataConversion(base.Ctx)
			errorLine = conv.Generate(fileName)
			// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
			WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
			log.Printf("GenTenFromThreeSecond: %v DONE | in %v seconds \n", file, time.Now().Sub(start).Seconds())
			success = true
			muxDo.Unlock()*/
	}

	return
}
<|endoftext|>


<commit_before>package projects

import (
	"database/sql"
	"net/http"

	"github.com/ansible-semaphore/semaphore/db"
	"github.com/ansible-semaphore/semaphore/util"
	"github.com/castawaylabs/mulekick"
	"github.com/gorilla/context"
	"github.com/masterminds/squirrel"
)

func InventoryMiddleware(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	inventoryID, err := util.GetIntParam("inventory_id", w, r)
	if err != nil {
		return
	}

	query, args, _ := squirrel.Select("*").
		From("project__inventory").
		Where("project_id=?", project.ID).
		Where("id=?", inventoryID).
		ToSql()

	var inventory db.Inventory
	if err := db.Mysql.SelectOne(&inventory, query, args...); err != nil {
		if err == sql.ErrNoRows {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		panic(err)
	}

	context.Set(r, "inventory", inventory)
}

func GetInventory(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	var inv []db.Inventory

	sort := r.URL.Query().Get("sort")
	order := r.URL.Query().Get("order")

	if order != "asc" && order != "desc" {
		order = "asc"
	}

	q := squirrel.Select("*").
			From("project__inventory pi")

	switch sort {
	case "name", "type":
		q = q.Where("pi.project_id=?", project.ID).
			OrderBy("pi." + sort + " " + order)
	default:
		q = q.Where("pi.project_id=?", project.ID).
		OrderBy("pi.name " + order)
	}

	query, args, _ := q.ToSql()

	if _, err := db.Mysql.Select(&inv, query, args...); err != nil {
		panic(err)
	}

	mulekick.WriteJSON(w, http.StatusOK, inv)
}

func AddInventory(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	var inventory struct {
		Name      string `json:"name" binding:"required"`
		KeyID     *int   `json:"key_id"`
		SshKeyID  int    `json:"ssh_key_id"`
		Type      string `json:"type"`
		Inventory string `json:"inventory"`
	}

	if err := mulekick.Bind(w, r, &inventory); err != nil {
		return
	}

	switch inventory.Type {
	case "static", "file":
		break
	default:
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	res, err := db.Mysql.Exec("insert into project__inventory set project_id=?, name=?, type=?, key_id=?, ssh_key_id=?, inventory=?", project.ID, inventory.Name, inventory.Type, inventory.KeyID, inventory.SshKeyID, inventory.Inventory)
	if err != nil {
		panic(err)
	}

	insertID, _ := res.LastInsertId()
	insertIDInt := int(insertID)
	objType := "inventory"

	desc := "Inventory " + inventory.Name + " created"
	if err := (db.Event{
		ProjectID:   &project.ID,
		ObjectType:  &objType,
		ObjectID:    &insertIDInt,
		Description: &desc,
	}.Insert()); err != nil {
		panic(err)
	}

	inv := db.Inventory{
		ID: insertIDInt,
		Name: inventory.Name,
		ProjectID: project.ID,
		Inventory: inventory.Inventory,
		KeyID: inventory.KeyID,
		SshKeyID: &inventory.SshKeyID,
		Type: inventory.Type,
	}

	mulekick.WriteJSON(w, http.StatusCreated, inv)
}

func UpdateInventory(w http.ResponseWriter, r *http.Request) {
	oldInventory := context.Get(r, "inventory").(db.Inventory)

	var inventory struct {
		Name      string `json:"name" binding:"required"`
		KeyID     *int   `json:"key_id"`
		SshKeyID  int    `json:"ssh_key_id"`
		Type      string `json:"type"`
		Inventory string `json:"inventory"`
	}

	if err := mulekick.Bind(w, r, &inventory); err != nil {
		return
	}

	switch inventory.Type {
	case "static", "file":
		break
	default:
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if _, err := db.Mysql.Exec("update project__inventory set name=?, type=?, key_id=?, ssh_key_id=?, inventory=? where id=?", inventory.Name, inventory.Type, inventory.KeyID, inventory.SshKeyID, inventory.Inventory, oldInventory.ID); err != nil {
		panic(err)
	}

	desc := "Inventory " + inventory.Name + " updated"
	objType := "inventory"
	if err := (db.Event{
		ProjectID:   &oldInventory.ProjectID,
		Description: &desc,
		ObjectID:    &oldInventory.ID,
		ObjectType:  &objType,
	}.Insert()); err != nil {
		panic(err)
	}

	w.WriteHeader(http.StatusNoContent)
}

func RemoveInventory(w http.ResponseWriter, r *http.Request) {
	inventory := context.Get(r, "inventory").(db.Inventory)

	templatesC, err := db.Mysql.SelectInt("select count(1) from project__template where project_id=? and inventory_id=?", inventory.ProjectID, inventory.ID)
	if err != nil {
		panic(err)
	}

	if templatesC > 0 {
		if len(r.URL.Query().Get("setRemoved")) == 0 {
			mulekick.WriteJSON(w, http.StatusBadRequest, map[string]interface{}{
				"error": "Inventory is in use by one or more templates",
				"inUse": true,
			})

			return
		}

		if _, err := db.Mysql.Exec("update project__inventory set removed=1 where id=?", inventory.ID); err != nil {
			panic(err)
		}

		w.WriteHeader(http.StatusNoContent)
		return
	}

	if _, err := db.Mysql.Exec("delete from project__inventory where id=?", inventory.ID); err != nil {
		panic(err)
	}

	desc := "Inventory " + inventory.Name + " deleted"
	if err := (db.Event{
		ProjectID:   &inventory.ProjectID,
		Description: &desc,
	}.Insert()); err != nil {
		panic(err)
	}

	w.WriteHeader(http.StatusNoContent)
}
<commit_msg>Validate inventory path before save<commit_after>package projects

import (
	"database/sql"
	"net/http"

	"github.com/ansible-semaphore/semaphore/db"
	"github.com/ansible-semaphore/semaphore/util"
	"github.com/castawaylabs/mulekick"
	"github.com/gorilla/context"
	"github.com/masterminds/squirrel"
	"path/filepath"
	"strings"
)

func InventoryMiddleware(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	inventoryID, err := util.GetIntParam("inventory_id", w, r)
	if err != nil {
		return
	}

	query, args, _ := squirrel.Select("*").
		From("project__inventory").
		Where("project_id=?", project.ID).
		Where("id=?", inventoryID).
		ToSql()

	var inventory db.Inventory
	if err := db.Mysql.SelectOne(&inventory, query, args...); err != nil {
		if err == sql.ErrNoRows {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		panic(err)
	}

	context.Set(r, "inventory", inventory)
}

func GetInventory(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	var inv []db.Inventory

	sort := r.URL.Query().Get("sort")
	order := r.URL.Query().Get("order")

	if order != "asc" && order != "desc" {
		order = "asc"
	}

	q := squirrel.Select("*").
			From("project__inventory pi")

	switch sort {
	case "name", "type":
		q = q.Where("pi.project_id=?", project.ID).
			OrderBy("pi." + sort + " " + order)
	default:
		q = q.Where("pi.project_id=?", project.ID).
		OrderBy("pi.name " + order)
	}

	query, args, _ := q.ToSql()

	if _, err := db.Mysql.Select(&inv, query, args...); err != nil {
		panic(err)
	}

	mulekick.WriteJSON(w, http.StatusOK, inv)
}

func AddInventory(w http.ResponseWriter, r *http.Request) {
	project := context.Get(r, "project").(db.Project)
	var inventory struct {
		Name      string `json:"name" binding:"required"`
		KeyID     *int   `json:"key_id"`
		SshKeyID  int    `json:"ssh_key_id"`
		Type      string `json:"type"`
		Inventory string `json:"inventory"`
	}

	if err := mulekick.Bind(w, r, &inventory); err != nil {
		return
	}

	switch inventory.Type {
	case "static", "file":
		break
	default:
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	res, err := db.Mysql.Exec("insert into project__inventory set project_id=?, name=?, type=?, key_id=?, ssh_key_id=?, inventory=?", project.ID, inventory.Name, inventory.Type, inventory.KeyID, inventory.SshKeyID, inventory.Inventory)
	if err != nil {
		panic(err)
	}

	insertID, _ := res.LastInsertId()
	insertIDInt := int(insertID)
	objType := "inventory"

	desc := "Inventory " + inventory.Name + " created"
	if err := (db.Event{
		ProjectID:   &project.ID,
		ObjectType:  &objType,
		ObjectID:    &insertIDInt,
		Description: &desc,
	}.Insert()); err != nil {
		panic(err)
	}

	inv := db.Inventory{
		ID: insertIDInt,
		Name: inventory.Name,
		ProjectID: project.ID,
		Inventory: inventory.Inventory,
		KeyID: inventory.KeyID,
		SshKeyID: &inventory.SshKeyID,
		Type: inventory.Type,
	}

	mulekick.WriteJSON(w, http.StatusCreated, inv)
}

func isValidInventoryPath(path string) bool {
	if currentPath, err := filepath.Abs("./"); err != nil {
		return false
	} else if absPath, err := filepath.Abs(path); err != nil {
		return false
	} else if relPath, err := filepath.Rel(currentPath, absPath); err != nil {
		return false
	} else {
		ret := !strings.HasPrefix(relPath, "..")
		return ret
	}
}

func UpdateInventory(w http.ResponseWriter, r *http.Request) {
	oldInventory := context.Get(r, "inventory").(db.Inventory)

	var inventory struct {
		Name      string `json:"name" binding:"required"`
		KeyID     *int   `json:"key_id"`
		SshKeyID  int    `json:"ssh_key_id"`
		Type      string `json:"type"`
		Inventory string `json:"inventory"`
	}

	if err := mulekick.Bind(w, r, &inventory); err != nil {
		return
	}

	switch inventory.Type {
	case "static":
		break
	case "file":
		if !isValidInventoryPath(inventory.Inventory) {
			panic("Invalid inventory path")
		}
		break
	default:
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if _, err := db.Mysql.Exec("update project__inventory set name=?, type=?, key_id=?, ssh_key_id=?, inventory=? where id=?", inventory.Name, inventory.Type, inventory.KeyID, inventory.SshKeyID, inventory.Inventory, oldInventory.ID); err != nil {
		panic(err)
	}

	desc := "Inventory " + inventory.Name + " updated"
	objType := "inventory"
	if err := (db.Event{
		ProjectID:   &oldInventory.ProjectID,
		Description: &desc,
		ObjectID:    &oldInventory.ID,
		ObjectType:  &objType,
	}.Insert()); err != nil {
		panic(err)
	}

	w.WriteHeader(http.StatusNoContent)
}

func RemoveInventory(w http.ResponseWriter, r *http.Request) {
	inventory := context.Get(r, "inventory").(db.Inventory)

	templatesC, err := db.Mysql.SelectInt("select count(1) from project__template where project_id=? and inventory_id=?", inventory.ProjectID, inventory.ID)
	if err != nil {
		panic(err)
	}

	if templatesC > 0 {
		if len(r.URL.Query().Get("setRemoved")) == 0 {
			mulekick.WriteJSON(w, http.StatusBadRequest, map[string]interface{}{
				"error": "Inventory is in use by one or more templates",
				"inUse": true,
			})

			return
		}

		if _, err := db.Mysql.Exec("update project__inventory set removed=1 where id=?", inventory.ID); err != nil {
			panic(err)
		}

		w.WriteHeader(http.StatusNoContent)
		return
	}

	if _, err := db.Mysql.Exec("delete from project__inventory where id=?", inventory.ID); err != nil {
		panic(err)
	}

	desc := "Inventory " + inventory.Name + " deleted"
	if err := (db.Event{
		ProjectID:   &inventory.ProjectID,
		Description: &desc,
	}.Insert()); err != nil {
		panic(err)
	}

	w.WriteHeader(http.StatusNoContent)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"encoding/json"
	"net"
	"time"
	"flag"
	"runtime"

	"golang.org/x/net/ipv4"
	"gopkg.in/cheggaaa/pb.v1"
)

type TokenCookie struct {
	Host  string `json:"host"`
	Time  string `json:"time"`
	Token string `json:"token"`
	DSCP  int    `json:"dscp"`
	TTL   int    `json:"ttl"`
	Description string `json:"description"`
	OS string `json:"os"`
}

type DSCP struct {
	Name string
	Value int
}

func main() {
	//url := "http://trace.erg.abdn.ac.uk/start"
	url := "http://trace.enoti.me/start"
	port := "60606"

	dscp_map := [21]DSCP{
		{Name:"BE",   Value:0x00},
		{Name:"EF",   Value:0x2e},
		{Name:"CS1",  Value:0x08},
		{Name:"CS2",  Value:0x10},
		{Name:"CS3",  Value:0x18},
		{Name:"CS4",  Value:0x20},
		{Name:"CS5",  Value:0x28},
		{Name:"CS6",  Value:0x30},
		{Name:"CS7",  Value:0x38},
		{Name:"AF11", Value:0x0a},
		{Name:"AF12", Value:0x0c},
		{Name:"AF13", Value:0x0e},
		{Name:"AF21", Value:0x12},
		{Name:"AF22", Value:0x14},
		{Name:"AF23", Value:0x16},
		{Name:"AF31", Value:0x1a},
		{Name:"AF32", Value:0x1c},
		{Name:"AF33", Value:0x1e},
		{Name:"AF41", Value:0x22},
		{Name:"AF42", Value:0x24},
		{Name:"AF43", Value:0x26},
	}

	description := flag.String("description", "Not given", "Wifi on a Bus")
	flag.Parse()
	fmt.Println("description:", *description)

	fmt.Printf("connecting to %s .  .  . ", url)
	res, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf(". . ... done\n")
	data, err := ioutil.ReadAll(res.Body)

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

	if res.StatusCode != 200 {
		fmt.Printf("Server returned %v please try running this tool another time\n", res.StatusCode)
		return
	}

	var token TokenCookie
	err = json.Unmarshal(data, &token)

	if err != nil {
		fmt.Println("Server didn't return a valid token, you may have to pass a captive portal")
		fmt.Println("error:", err)
		fmt.Println(data)
		return
	}

	fmt.Printf("received token:\n %+v\n", token)
	token.Description = *description
	token.TTL = 64
	token.OS = runtime.GOOS

	//conn, err := net.Dial("udp", "trace.enoti.me:60606")
	conn, err := net.Dial("udp", url + ":" + port)

	start := time.Now()
	send_count := 10

	fmt.Println("Sending Datagrams")
	bar := pb.StartNew(10 * len(dscp_map))
    for _, mark := range dscp_map {
		token.DSCP = mark.Value

		if err := ipv4.NewConn(conn).SetTOS(token.DSCP << 2); err != nil {
			fmt.Printf("Some error %v", err)
			return
		}

		if err != nil {
			fmt.Printf("Some error %v", err)
			return
		}

		for i := 1; i <= send_count ; i++ {
			json.NewEncoder(conn).Encode(token)
			time.Sleep(time.Millisecond * 200)
			bar.Increment()
		}
	}
	bar.Finish()
	conn.Close()

	fmt.Printf("%v Datagrams representing %v DSCP Marks sent in %v\n",
		len(dscp_map) * send_count,
		len(dscp_map),
		time.Since(start))
	fmt.Println("Thank you for helping make the internet better")
}
<commit_msg>Centralise client config in main()<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"encoding/json"
	"net"
	"time"
	"flag"
	"runtime"

	"golang.org/x/net/ipv4"
	"gopkg.in/cheggaaa/pb.v1"
)

type TokenCookie struct {
	Host  string `json:"host"`
	Time  string `json:"time"`
	Token string `json:"token"`
	DSCP  int    `json:"dscp"`
	TTL   int    `json:"ttl"`
	Description string `json:"description"`
	OS string `json:"os"`
}

type DSCP struct {
	Name string
	Value int
}

func main() {
	url := "http://trace.erg.abdn.ac.uk/start"
	port := "60606"
	send_count := 10

	dscp_map := [21]DSCP{
		{Name:"BE",   Value:0x00},
		{Name:"EF",   Value:0x2e},
		{Name:"CS1",  Value:0x08},
		{Name:"CS2",  Value:0x10},
		{Name:"CS3",  Value:0x18},
		{Name:"CS4",  Value:0x20},
		{Name:"CS5",  Value:0x28},
		{Name:"CS6",  Value:0x30},
		{Name:"CS7",  Value:0x38},
		{Name:"AF11", Value:0x0a},
		{Name:"AF12", Value:0x0c},
		{Name:"AF13", Value:0x0e},
		{Name:"AF21", Value:0x12},
		{Name:"AF22", Value:0x14},
		{Name:"AF23", Value:0x16},
		{Name:"AF31", Value:0x1a},
		{Name:"AF32", Value:0x1c},
		{Name:"AF33", Value:0x1e},
		{Name:"AF41", Value:0x22},
		{Name:"AF42", Value:0x24},
		{Name:"AF43", Value:0x26},
	}

	description := flag.String("description", "Not given", "Wifi on a Bus")
	flag.Parse()
	fmt.Println("description:", *description)

	fmt.Printf("connecting to %s .  .  . ", url)
	res, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf(". . ... done\n")
	data, err := ioutil.ReadAll(res.Body)

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

	if res.StatusCode != 200 {
		fmt.Printf("Server returned %v please try running this tool another time\n", res.StatusCode)
		return
	}

	var token TokenCookie
	err = json.Unmarshal(data, &token)

	if err != nil {
		fmt.Println("Server didn't return a valid token, you may have to pass a captive portal")
		fmt.Println("error:", err)
		fmt.Println(data)
		return
	}

	fmt.Printf("received token:\n %+v\n", token)
	token.Description = *description
	token.TTL = 64
	token.OS = runtime.GOOS

	//conn, err := net.Dial("udp", "trace.enoti.me:60606")
	conn, err := net.Dial("udp", url + ":" + port)

	start := time.Now()

	fmt.Println("Sending Datagrams")
	bar := pb.StartNew(send_count * len(dscp_map))
    for _, mark := range dscp_map {
		token.DSCP = mark.Value

		if err := ipv4.NewConn(conn).SetTOS(token.DSCP << 2); err != nil {
			fmt.Printf("Some error %v", err)
			return
		}

		if err != nil {
			fmt.Printf("Some error %v", err)
			return
		}

		for i := 1; i <= send_count ; i++ {
			json.NewEncoder(conn).Encode(token)
			time.Sleep(time.Millisecond * 200)
			bar.Increment()
		}
	}
	bar.Finish()
	conn.Close()

	fmt.Printf("%v Datagrams representing %v DSCP Marks sent in %v\n",
		len(dscp_map) * send_count,
		len(dscp_map),
		time.Since(start))
	fmt.Println("Thank you for helping make the internet better")
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"context"

	"github.com/hashicorp/terraform/helper/schema"
	oci_core "github.com/oracle/oci-go-sdk/core"

	"github.com/oracle/terraform-provider-oci/crud"
)

func ImagesDataSource() *schema.Resource {
	return &schema.Resource{
		Read: readImages,
		Schema: map[string]*schema.Schema{
			"filter": dataSourceFiltersSchema(),
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"display_name": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"limit": {
				Type:       schema.TypeInt,
				Optional:   true,
				Deprecated: crud.FieldDeprecated("limit"),
			},
			"operating_system": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"operating_system_version": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"page": {
				Type:       schema.TypeString,
				Optional:   true,
				Deprecated: crud.FieldDeprecated("page"),
			},
			"shape": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"state": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"images": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     ImageResource(),
			},
		},
	}
}

func readImages(d *schema.ResourceData, m interface{}) error {
	sync := &ImagesDataSourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).computeClient

	return crud.ReadResource(sync)
}

type ImagesDataSourceCrud struct {
	D      *schema.ResourceData
	Client *oci_core.ComputeClient
	Res    *oci_core.ListImagesResponse
}

func (s *ImagesDataSourceCrud) VoidState() {
	s.D.SetId("")
}

func (s *ImagesDataSourceCrud) Get() error {
	request := oci_core.ListImagesRequest{}

	if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
		tmp := compartmentId.(string)
		request.CompartmentId = &tmp
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if limit, ok := s.D.GetOkExists("limit"); ok {
		tmp := limit.(int)
		request.Limit = &tmp
	}

	if operatingSystem, ok := s.D.GetOkExists("operating_system"); ok {
		tmp := operatingSystem.(string)
		request.OperatingSystem = &tmp
	}

	if operatingSystemVersion, ok := s.D.GetOkExists("operating_system_version"); ok {
		tmp := operatingSystemVersion.(string)
		request.OperatingSystemVersion = &tmp
	}

	if page, ok := s.D.GetOkExists("page"); ok {
		tmp := page.(string)
		request.Page = &tmp
	}

	if shape, ok := s.D.GetOkExists("shape"); ok {
		tmp := shape.(string)
		request.Shape = &tmp
	}

	if state, ok := s.D.GetOkExists("state"); ok {
		request.LifecycleState = oci_core.ImageLifecycleStateEnum(state.(string))
	}

	request.RequestMetadata.RetryPolicy = getRetryPolicy(false, "core")

	response, err := s.Client.ListImages(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response
	request.Page = s.Res.OpcNextPage

	for request.Page != nil {
		listResponse, err := s.Client.ListImages(context.Background(), request)
		if err != nil {
			return err
		}

		s.Res.Items = append(s.Res.Items, listResponse.Items...)
		request.Page = listResponse.OpcNextPage
	}

	return nil
}

func (s *ImagesDataSourceCrud) SetData() {
	if s.Res == nil {
		return
	}

	s.D.SetId(crud.GenerateDataSourceID())
	resources := []map[string]interface{}{}

	for _, r := range s.Res.Items {
		image := map[string]interface{}{
			// "compartment_id": *r.CompartmentId,
		}

		// The spec marks compartmentId as a required field, but the service doesn't return it for official images.
		if r.CompartmentId != nil {
			image["compartment_id"] = *r.CompartmentId
		}

		if r.BaseImageId != nil {
			image["base_image_id"] = *r.BaseImageId
		}

		if r.CreateImageAllowed != nil {
			image["create_image_allowed"] = *r.CreateImageAllowed
		}

		if r.DisplayName != nil {
			image["display_name"] = *r.DisplayName
		}

		if r.Id != nil {
			image["id"] = *r.Id
		}

		image["launch_mode"] = r.LaunchMode

		if r.LaunchOptions != nil {
			image["launch_options"] = []interface{}{LaunchOptionsToMap(r.LaunchOptions)}
		}

		if r.OperatingSystem != nil {
			image["operating_system"] = *r.OperatingSystem
		}

		if r.OperatingSystemVersion != nil {
			image["operating_system_version"] = *r.OperatingSystemVersion
		}

		if r.SizeInMBs != nil {
			image["size_in_mbs"] = *r.SizeInMBs
		}

		image["state"] = r.LifecycleState

		image["time_created"] = r.TimeCreated.String()

		resources = append(resources, image)
	}

	if f, fOk := s.D.GetOkExists("filter"); fOk {
		resources = ApplyFilters(f.(*schema.Set), resources)
	}

	if err := s.D.Set("images", resources); err != nil {
		panic(err)
	}

	return
}
<commit_msg>minor goimports formatting<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"context"

	"github.com/hashicorp/terraform/helper/schema"
	oci_core "github.com/oracle/oci-go-sdk/core"

	"github.com/oracle/terraform-provider-oci/crud"
)

func ImagesDataSource() *schema.Resource {
	return &schema.Resource{
		Read: readImages,
		Schema: map[string]*schema.Schema{
			"filter": dataSourceFiltersSchema(),
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"display_name": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"limit": {
				Type:       schema.TypeInt,
				Optional:   true,
				Deprecated: crud.FieldDeprecated("limit"),
			},
			"operating_system": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"operating_system_version": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"page": {
				Type:       schema.TypeString,
				Optional:   true,
				Deprecated: crud.FieldDeprecated("page"),
			},
			"shape": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"state": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"images": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     ImageResource(),
			},
		},
	}
}

func readImages(d *schema.ResourceData, m interface{}) error {
	sync := &ImagesDataSourceCrud{}
	sync.D = d
	sync.Client = m.(*OracleClients).computeClient

	return crud.ReadResource(sync)
}

type ImagesDataSourceCrud struct {
	D      *schema.ResourceData
	Client *oci_core.ComputeClient
	Res    *oci_core.ListImagesResponse
}

func (s *ImagesDataSourceCrud) VoidState() {
	s.D.SetId("")
}

func (s *ImagesDataSourceCrud) Get() error {
	request := oci_core.ListImagesRequest{}

	if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
		tmp := compartmentId.(string)
		request.CompartmentId = &tmp
	}

	if displayName, ok := s.D.GetOkExists("display_name"); ok {
		tmp := displayName.(string)
		request.DisplayName = &tmp
	}

	if limit, ok := s.D.GetOkExists("limit"); ok {
		tmp := limit.(int)
		request.Limit = &tmp
	}

	if operatingSystem, ok := s.D.GetOkExists("operating_system"); ok {
		tmp := operatingSystem.(string)
		request.OperatingSystem = &tmp
	}

	if operatingSystemVersion, ok := s.D.GetOkExists("operating_system_version"); ok {
		tmp := operatingSystemVersion.(string)
		request.OperatingSystemVersion = &tmp
	}

	if page, ok := s.D.GetOkExists("page"); ok {
		tmp := page.(string)
		request.Page = &tmp
	}

	if shape, ok := s.D.GetOkExists("shape"); ok {
		tmp := shape.(string)
		request.Shape = &tmp
	}

	if state, ok := s.D.GetOkExists("state"); ok {
		request.LifecycleState = oci_core.ImageLifecycleStateEnum(state.(string))
	}

	request.RequestMetadata.RetryPolicy = getRetryPolicy(false, "core")

	response, err := s.Client.ListImages(context.Background(), request)
	if err != nil {
		return err
	}

	s.Res = &response
	request.Page = s.Res.OpcNextPage

	for request.Page != nil {
		listResponse, err := s.Client.ListImages(context.Background(), request)
		if err != nil {
			return err
		}

		s.Res.Items = append(s.Res.Items, listResponse.Items...)
		request.Page = listResponse.OpcNextPage
	}

	return nil
}

func (s *ImagesDataSourceCrud) SetData() {
	if s.Res == nil {
		return
	}

	s.D.SetId(crud.GenerateDataSourceID())
	resources := []map[string]interface{}{}

	for _, r := range s.Res.Items {
		image := map[string]interface{}{
		// "compartment_id": *r.CompartmentId,
		}

		// The spec marks compartmentId as a required field, but the service doesn't return it for official images.
		if r.CompartmentId != nil {
			image["compartment_id"] = *r.CompartmentId
		}

		if r.BaseImageId != nil {
			image["base_image_id"] = *r.BaseImageId
		}

		if r.CreateImageAllowed != nil {
			image["create_image_allowed"] = *r.CreateImageAllowed
		}

		if r.DisplayName != nil {
			image["display_name"] = *r.DisplayName
		}

		if r.Id != nil {
			image["id"] = *r.Id
		}

		image["launch_mode"] = r.LaunchMode

		if r.LaunchOptions != nil {
			image["launch_options"] = []interface{}{LaunchOptionsToMap(r.LaunchOptions)}
		}

		if r.OperatingSystem != nil {
			image["operating_system"] = *r.OperatingSystem
		}

		if r.OperatingSystemVersion != nil {
			image["operating_system_version"] = *r.OperatingSystemVersion
		}

		if r.SizeInMBs != nil {
			image["size_in_mbs"] = *r.SizeInMBs
		}

		image["state"] = r.LifecycleState

		image["time_created"] = r.TimeCreated.String()

		resources = append(resources, image)
	}

	if f, fOk := s.D.GetOkExists("filter"); fOk {
		resources = ApplyFilters(f.(*schema.Set), resources)
	}

	if err := s.D.Set("images", resources); err != nil {
		panic(err)
	}

	return
}
<|endoftext|>


<commit_before>package openstack

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
)

func resourceNetworkingPortV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingPortV2Create,
		Read:   resourceNetworkingPortV2Read,
		Update: resourceNetworkingPortV2Update,
		Delete: resourceNetworkingPortV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: envDefaultFuncAllowMissing("OS_REGION_NAME"),
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"network_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"admin_state_up": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: false,
				Computed: true,
			},
			"mac_address": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"tenant_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"device_owner": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"security_group_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				ForceNew: false,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},
			"device_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"fixed_ip": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: false,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"subnet_id": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"ip_address": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
		},
	}
}

func resourceNetworkingPortV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	createOpts := ports.CreateOpts{
		Name:           d.Get("name").(string),
		AdminStateUp:   resourcePortAdminStateUpV2(d),
		NetworkID:      d.Get("network_id").(string),
		MACAddress:     d.Get("mac_address").(string),
		TenantID:       d.Get("tenant_id").(string),
		DeviceOwner:    d.Get("device_owner").(string),
		SecurityGroups: resourcePortSecurityGroupsV2(d),
		DeviceID:       d.Get("device_id").(string),
		FixedIPs:       resourcePortFixedIpsV2(d),
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)
	p, err := ports.Create(networkingClient, createOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error creating OpenStack Neutron network: %s", err)
	}
	log.Printf("[INFO] Network ID: %s", p.ID)

	log.Printf("[DEBUG] Waiting for OpenStack Neutron Port (%s) to become available.", p.ID)

	stateConf := &resource.StateChangeConf{
		Target:     []string{"ACTIVE"},
		Refresh:    waitForNetworkPortActive(networkingClient, p.ID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(p.ID)

	return resourceNetworkingPortV2Read(d, meta)
}

func resourceNetworkingPortV2Read(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	p, err := ports.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		return CheckDeleted(d, err, "port")
	}

	log.Printf("[DEBUG] Retreived Port %s: %+v", d.Id(), p)

	d.Set("name", p.Name)
	d.Set("admin_state_up", p.AdminStateUp)
	d.Set("network_id", p.NetworkID)
	d.Set("mac_address", p.MACAddress)
	d.Set("tenant_id", p.TenantID)
	d.Set("device_owner", p.DeviceOwner)
	d.Set("security_group_ids", p.SecurityGroups)
	d.Set("device_id", p.DeviceID)
	d.Set("fixed_ip", p.FixedIPs)

	return nil
}

func resourceNetworkingPortV2Update(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	var updateOpts ports.UpdateOpts

	if d.HasChange("name") {
		updateOpts.Name = d.Get("name").(string)
	}

	if d.HasChange("admin_state_up") {
		updateOpts.AdminStateUp = resourcePortAdminStateUpV2(d)
	}

	if d.HasChange("device_owner") {
		updateOpts.DeviceOwner = d.Get("device_owner").(string)
	}

	if d.HasChange("security_group_ids") {
		updateOpts.SecurityGroups = resourcePortSecurityGroupsV2(d)
	}

	if d.HasChange("device_id") {
		updateOpts.DeviceID = d.Get("device_id").(string)
	}

	if d.HasChange("fixed_ip") {
		updateOpts.FixedIPs = resourcePortFixedIpsV2(d)
	}

	log.Printf("[DEBUG] Updating Port %s with options: %+v", d.Id(), updateOpts)

	_, err = ports.Update(networkingClient, d.Id(), updateOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error updating OpenStack Neutron Network: %s", err)
	}

	return resourceNetworkingPortV2Read(d, meta)
}

func resourceNetworkingPortV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE"},
		Target:     []string{"DELETED"},
		Refresh:    waitForNetworkPortDelete(networkingClient, d.Id()),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack Neutron Network: %s", err)
	}

	d.SetId("")
	return nil
}

func resourcePortSecurityGroupsV2(d *schema.ResourceData) []string {
	rawSecurityGroups := d.Get("security_group_ids").(*schema.Set)
	groups := make([]string, rawSecurityGroups.Len())
	for i, raw := range rawSecurityGroups.List() {
		groups[i] = raw.(string)
	}
	return groups
}

func resourcePortFixedIpsV2(d *schema.ResourceData) interface{} {
	rawIP := d.Get("fixed_ip").([]interface{})

	if len(rawIP) == 0 {
		return nil
	}

	ip := make([]ports.IP, len(rawIP))
	for i, raw := range rawIP {
		rawMap := raw.(map[string]interface{})
		ip[i] = ports.IP{
			SubnetID:  rawMap["subnet_id"].(string),
			IPAddress: rawMap["ip_address"].(string),
		}
	}
	return ip

}

func resourcePortAdminStateUpV2(d *schema.ResourceData) *bool {
	value := false

	if raw, ok := d.GetOk("admin_state_up"); ok && raw == true {
		value = true
	}

	return &value
}

func waitForNetworkPortActive(networkingClient *gophercloud.ServiceClient, portId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		p, err := ports.Get(networkingClient, portId).Extract()
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] OpenStack Neutron Port: %+v", p)
		if p.Status == "DOWN" || p.Status == "ACTIVE" {
			return p, "ACTIVE", nil
		}

		return p, p.Status, nil
	}
}

func waitForNetworkPortDelete(networkingClient *gophercloud.ServiceClient, portId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		log.Printf("[DEBUG] Attempting to delete OpenStack Neutron Port %s", portId)

		p, err := ports.Get(networkingClient, portId).Extract()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return p, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Port %s", portId)
				return p, "DELETED", nil
			}
		}

		err = ports.Delete(networkingClient, portId).ExtractErr()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return p, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Port %s", portId)
				return p, "DELETED", nil
			}
		}

		log.Printf("[DEBUG] OpenStack Port %s still active.\n", portId)
		return p, "ACTIVE", nil
	}
}
<commit_msg>provider/openstack Convert FixedIPS from struct to map for ResourceData<commit_after>package openstack

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
)

func resourceNetworkingPortV2() *schema.Resource {
	return &schema.Resource{
		Create: resourceNetworkingPortV2Create,
		Read:   resourceNetworkingPortV2Read,
		Update: resourceNetworkingPortV2Update,
		Delete: resourceNetworkingPortV2Delete,

		Schema: map[string]*schema.Schema{
			"region": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: envDefaultFuncAllowMissing("OS_REGION_NAME"),
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: false,
			},
			"network_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"admin_state_up": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: false,
				Computed: true,
			},
			"mac_address": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"tenant_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"device_owner": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"security_group_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				ForceNew: false,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},
			"device_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},
			"fixed_ip": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: false,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"subnet_id": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"ip_address": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
							Computed: true,
						},
					},
				},
			},
		},
	}
}

func resourceNetworkingPortV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	createOpts := ports.CreateOpts{
		Name:           d.Get("name").(string),
		AdminStateUp:   resourcePortAdminStateUpV2(d),
		NetworkID:      d.Get("network_id").(string),
		MACAddress:     d.Get("mac_address").(string),
		TenantID:       d.Get("tenant_id").(string),
		DeviceOwner:    d.Get("device_owner").(string),
		SecurityGroups: resourcePortSecurityGroupsV2(d),
		DeviceID:       d.Get("device_id").(string),
		FixedIPs:       resourcePortFixedIpsV2(d),
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)
	p, err := ports.Create(networkingClient, createOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error creating OpenStack Neutron network: %s", err)
	}
	log.Printf("[INFO] Network ID: %s", p.ID)

	log.Printf("[DEBUG] Waiting for OpenStack Neutron Port (%s) to become available.", p.ID)

	stateConf := &resource.StateChangeConf{
		Target:     []string{"ACTIVE"},
		Refresh:    waitForNetworkPortActive(networkingClient, p.ID),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()

	d.SetId(p.ID)

	return resourceNetworkingPortV2Read(d, meta)
}

func resourceNetworkingPortV2Read(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	p, err := ports.Get(networkingClient, d.Id()).Extract()
	if err != nil {
		return CheckDeleted(d, err, "port")
	}

	log.Printf("[DEBUG] Retreived Port %s: %+v", d.Id(), p)

	d.Set("name", p.Name)
	d.Set("admin_state_up", p.AdminStateUp)
	d.Set("network_id", p.NetworkID)
	d.Set("mac_address", p.MACAddress)
	d.Set("tenant_id", p.TenantID)
	d.Set("device_owner", p.DeviceOwner)
	d.Set("security_group_ids", p.SecurityGroups)
	d.Set("device_id", p.DeviceID)

	// Convert FixedIPs to list of map
	var ips []map[string]interface{}
	for _, ipObject := range p.FixedIPs {
		ip := make(map[string]interface{})
		ip["subnet_id"] = ipObject.SubnetID
		ip["ip_address"] = ipObject.IPAddress
		ips = append(ips, ip)
	}
	d.Set("fixed_ip", ips)

	return nil
}

func resourceNetworkingPortV2Update(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	var updateOpts ports.UpdateOpts

	if d.HasChange("name") {
		updateOpts.Name = d.Get("name").(string)
	}

	if d.HasChange("admin_state_up") {
		updateOpts.AdminStateUp = resourcePortAdminStateUpV2(d)
	}

	if d.HasChange("device_owner") {
		updateOpts.DeviceOwner = d.Get("device_owner").(string)
	}

	if d.HasChange("security_group_ids") {
		updateOpts.SecurityGroups = resourcePortSecurityGroupsV2(d)
	}

	if d.HasChange("device_id") {
		updateOpts.DeviceID = d.Get("device_id").(string)
	}

	if d.HasChange("fixed_ip") {
		updateOpts.FixedIPs = resourcePortFixedIpsV2(d)
	}

	log.Printf("[DEBUG] Updating Port %s with options: %+v", d.Id(), updateOpts)

	_, err = ports.Update(networkingClient, d.Id(), updateOpts).Extract()
	if err != nil {
		return fmt.Errorf("Error updating OpenStack Neutron Network: %s", err)
	}

	return resourceNetworkingPortV2Read(d, meta)
}

func resourceNetworkingPortV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE"},
		Target:     []string{"DELETED"},
		Refresh:    waitForNetworkPortDelete(networkingClient, d.Id()),
		Timeout:    2 * time.Minute,
		Delay:      5 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack Neutron Network: %s", err)
	}

	d.SetId("")
	return nil
}

func resourcePortSecurityGroupsV2(d *schema.ResourceData) []string {
	rawSecurityGroups := d.Get("security_group_ids").(*schema.Set)
	groups := make([]string, rawSecurityGroups.Len())
	for i, raw := range rawSecurityGroups.List() {
		groups[i] = raw.(string)
	}
	return groups
}

func resourcePortFixedIpsV2(d *schema.ResourceData) interface{} {
	rawIP := d.Get("fixed_ip").([]interface{})

	if len(rawIP) == 0 {
		return nil
	}

	ip := make([]ports.IP, len(rawIP))
	for i, raw := range rawIP {
		rawMap := raw.(map[string]interface{})
		ip[i] = ports.IP{
			SubnetID:  rawMap["subnet_id"].(string),
			IPAddress: rawMap["ip_address"].(string),
		}
	}
	return ip

}

func resourcePortAdminStateUpV2(d *schema.ResourceData) *bool {
	value := false

	if raw, ok := d.GetOk("admin_state_up"); ok && raw == true {
		value = true
	}

	return &value
}

func waitForNetworkPortActive(networkingClient *gophercloud.ServiceClient, portId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		p, err := ports.Get(networkingClient, portId).Extract()
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] OpenStack Neutron Port: %+v", p)
		if p.Status == "DOWN" || p.Status == "ACTIVE" {
			return p, "ACTIVE", nil
		}

		return p, p.Status, nil
	}
}

func waitForNetworkPortDelete(networkingClient *gophercloud.ServiceClient, portId string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		log.Printf("[DEBUG] Attempting to delete OpenStack Neutron Port %s", portId)

		p, err := ports.Get(networkingClient, portId).Extract()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return p, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Port %s", portId)
				return p, "DELETED", nil
			}
		}

		err = ports.Delete(networkingClient, portId).ExtractErr()
		if err != nil {
			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
			if !ok {
				return p, "ACTIVE", err
			}
			if errCode.Actual == 404 {
				log.Printf("[DEBUG] Successfully deleted OpenStack Port %s", portId)
				return p, "DELETED", nil
			}
		}

		log.Printf("[DEBUG] OpenStack Port %s still active.\n", portId)
		return p, "ACTIVE", nil
	}
}
<|endoftext|>