<commit_before>/*
 * Copyright © 2016-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 *
 * 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.
 *
 * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @license 	Apache-2.0
 */

package sql

import migrate "github.com/rubenv/sql-migrate"

type Statements struct {
	Migrations                    *migrate.MemoryMigrationSource
	QueryInsertPolicy             string
	QueryInsertPolicyActions      string
	QueryInsertPolicyActionsRel   string
	QueryInsertPolicyResources    string
	QueryInsertPolicyResourcesRel string
	QueryInsertPolicySubjects     string
	QueryInsertPolicySubjectsRel  string
	QueryPoliciesForSubject       string
	QueryPoliciesForResource      string
}

var sharedMigrations = []*migrate.Migration{
	{
		Id: "1",
		Up: []string{
			`CREATE TABLE IF NOT EXISTS ladon_policy (
				id           varchar(255) NOT NULL PRIMARY KEY,
				description  text NOT NULL,
				effect       text NOT NULL CHECK (effect='allow' OR effect='deny'),
				conditions	 text NOT NULL
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_subject (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_permission (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_resource (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
		},
		Down: []string{
			"DROP TABLE ladon_policy",
			"DROP TABLE ladon_policy_subject",
			"DROP TABLE ladon_policy_permission",
			"DROP TABLE ladon_policy_resource",
		},
	},
	{
		Id: "2",
		Up: []string{
			`CREATE TABLE IF NOT EXISTS ladon_subject (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_action (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_resource (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_subject_rel (
				policy   varchar(255) NOT NULL,
				subject  varchar(64) NOT NULL,
				PRIMARY KEY (policy, subject),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (subject) REFERENCES ladon_subject(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_action_rel (
				policy  varchar(255) NOT NULL,
				action  varchar(64) NOT NULL,
				PRIMARY KEY (policy, action),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (action) REFERENCES ladon_action(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_resource_rel (
				policy    varchar(255) NOT NULL,
				resource  varchar(64) NOT NULL,
				PRIMARY KEY (policy, resource),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (resource) REFERENCES ladon_resource(id) ON DELETE CASCADE
			)`,
		},
		Down: []string{},
	},
}

var Migrations = map[string]Statements{
	"postgres": {
		Migrations: &migrate.MemoryMigrationSource{
			Migrations: []*migrate.Migration{
				sharedMigrations[0],
				sharedMigrations[1],
				{
					Id: "3",
					Up: []string{
						"CREATE INDEX ladon_subject_compiled_idx ON ladon_subject (compiled text_pattern_ops)",
						"CREATE INDEX ladon_permission_compiled_idx ON ladon_action (compiled text_pattern_ops)",
						"CREATE INDEX ladon_resource_compiled_idx ON ladon_resource (compiled text_pattern_ops)",
					},
					Down: []string{
						"DROP INDEX ladon_subject_compiled_idx",
						"DROP INDEX ladon_permission_compiled_idx",
						"DROP INDEX ladon_resource_compiled_idx",
					},
				},
				{
					Id: "4",
					Up: []string{
						"ALTER TABLE ladon_policy ADD COLUMN meta json",
					},
					Down: []string{
						"ALTER TABLE ladon_policy DROP COLUMN IF EXISTS meta",
					},
				},
			},
		},
		QueryInsertPolicy:             `INSERT INTO ladon_policy(id, description, effect, conditions, meta) SELECT $1::varchar, $2, $3, $4, $5 WHERE NOT EXISTS (SELECT 1 FROM ladon_policy WHERE id = $1)`,
		QueryInsertPolicyActions:      `INSERT INTO ladon_action (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_action WHERE id = $1)`,
		QueryInsertPolicyActionsRel:   `INSERT INTO ladon_policy_action_rel (policy, action) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_action_rel WHERE policy = $1 AND action = $2)`,
		QueryInsertPolicyResources:    `INSERT INTO ladon_resource (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_resource WHERE id = $1)`,
		QueryInsertPolicyResourcesRel: `INSERT INTO ladon_policy_resource_rel (policy, resource) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_resource_rel WHERE policy = $1 AND resource = $2)`,
		QueryInsertPolicySubjects:     `INSERT INTO ladon_subject (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_subject WHERE id = $1)`,
		QueryInsertPolicySubjectsRel:  `INSERT INTO ladon_policy_subject_rel (policy, subject) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_subject_rel WHERE policy = $1 AND subject = $2)`,
		QueryPoliciesForSubject: `
		SELECT
			p.id,
			p.effect,
			p.conditions,
			p.description,
			p.meta,
			subject.template AS subject,
			resource.template AS resource,
			action.template AS action
		FROM
			ladon_policy AS p

			INNER JOIN ladon_policy_subject_rel AS rs ON rs.policy = p.id
			LEFT JOIN ladon_policy_action_rel AS ra ON ra.policy = p.id
			LEFT JOIN ladon_policy_resource_rel AS rr ON rr.policy = p.id

			INNER JOIN ladon_subject AS subject ON rs.subject = subject.id
			LEFT JOIN ladon_action AS action ON ra.action = action.id
			LEFT JOIN ladon_resource AS resource ON rr.resource = resource.id
		WHERE
			(subject.has_regex IS NOT TRUE AND subject.template = $1)
			OR
			(subject.has_regex IS TRUE AND $2 ~ subject.compiled)`,
		QueryPoliciesForResource: `
		SELECT
			p.id,
			p.effect,
			p.conditions,
			p.description,
			p.meta,
			subject.template AS subject,
			resource.template AS resource,
			action.template AS action
		FROM
			ladon_policy AS p

			INNER JOIN ladon_policy_subject_rel AS rs ON rs.policy = p.id
			LEFT JOIN ladon_policy_action_rel AS ra ON ra.policy = p.id
			LEFT JOIN ladon_policy_resource_rel AS rr ON rr.policy = p.id

			INNER JOIN ladon_subject AS subject ON rs.subject = subject.id
			LEFT JOIN ladon_action AS action ON ra.action = action.id
			LEFT JOIN ladon_resource AS resource ON rr.resource = resource.id
		WHERE
			(resource.has_regex IS NOT TRUE AND resource.template = $1)
			OR
			(resource.has_regex IS TRUE AND $2 ~ resource.compiled)`,
	},
	"mysql": {
		Migrations: &migrate.MemoryMigrationSource{
			Migrations: []*migrate.Migration{
				sharedMigrations[0],
				sharedMigrations[1],
				{
					Id: "3",
					Up: []string{
						"CREATE FULLTEXT INDEX ladon_subject_compiled_idx ON ladon_subject (compiled)",
						"CREATE FULLTEXT INDEX ladon_action_compiled_idx ON ladon_action (compiled)",
						"CREATE FULLTEXT INDEX ladon_resource_compiled_idx ON ladon_resource (compiled)",
					},
					Down: []string{
						"DROP INDEX ladon_subject_compiled_idx",
						"DROP INDEX ladon_permission_compiled_idx",
						"DROP INDEX ladon_resource_compiled_idx",
					},
				},
				{
					Id: "4",
					Up: []string{
						"ALTER TABLE ladon_policy ADD COLUMN meta text",
					},
					Down: []string{
						"ALTER TABLE ladon_policy DROP COLUMN meta",
					},
				},
			},
		},
		QueryInsertPolicy:             `INSERT IGNORE INTO ladon_policy (id, description, effect, conditions, meta) VALUES(?,?,?,?,?)`,
		QueryInsertPolicyActions:      `INSERT IGNORE INTO ladon_action (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicyActionsRel:   `INSERT IGNORE INTO ladon_policy_action_rel (policy, action) VALUES(?,?)`,
		QueryInsertPolicyResources:    `INSERT IGNORE INTO ladon_resource (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicyResourcesRel: `INSERT IGNORE INTO ladon_policy_resource_rel (policy, resource) VALUES(?,?)`,
		QueryInsertPolicySubjects:     `INSERT IGNORE INTO ladon_subject (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicySubjectsRel:  `INSERT IGNORE INTO ladon_policy_subject_rel (policy, subject) VALUES(?,?)`,
		QueryPoliciesForSubject: `
		SELECT
			p.id,
			p.effect,
			p.conditions,
			p.description,
			p.meta,
			subject.template AS subject,
			resource.template AS resource,
			action.template AS action
		FROM
			ladon_policy AS p

			INNER JOIN ladon_policy_subject_rel AS rs ON rs.policy = p.id
			LEFT JOIN ladon_policy_action_rel AS ra ON ra.policy = p.id
			LEFT JOIN ladon_policy_resource_rel AS rr ON rr.policy = p.id

			INNER JOIN ladon_subject AS subject ON rs.subject = subject.id
			LEFT JOIN ladon_action AS action ON ra.action = action.id
			LEFT JOIN ladon_resource AS resource ON rr.resource = resource.id
		WHERE
			(subject.has_regex = 0 AND subject.template = ?)
			OR
			(subject.has_regex = 1 AND ? REGEXP BINARY subject.compiled)`,
		QueryPoliciesForResource: `
		SELECT
			p.id,
			p.effect,
			p.conditions,
			p.description,
			p.meta,
			subject.template AS subject,
			resource.template AS resource,
			action.template AS action
		FROM
			ladon_policy AS p

			INNER JOIN ladon_policy_subject_rel AS rs ON rs.policy = p.id
			LEFT JOIN ladon_policy_action_rel AS ra ON ra.policy = p.id
			LEFT JOIN ladon_policy_resource_rel AS rr ON rr.policy = p.id

			INNER JOIN ladon_subject AS subject ON rs.subject = subject.id
			LEFT JOIN ladon_action AS action ON ra.action = action.id
			LEFT JOIN ladon_resource AS resource ON rr.resource = resource.id
		WHERE
			(resource.has_regex = 0 AND resource.template = ?)
			OR
			(resource.has_regex = 1 AND ? REGEXP BINARY resource.compiled)`,
	},
}
<commit_msg>sql: Remove some repetitions in the databases file.<commit_after>/*
 * Copyright © 2016-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 *
 * 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.
 *
 * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
 * @license 	Apache-2.0
 */

package sql

import (
	"fmt"

	migrate "github.com/rubenv/sql-migrate"
)

type Statements struct {
	Migrations                    *migrate.MemoryMigrationSource
	QueryInsertPolicy             string
	QueryInsertPolicyActions      string
	QueryInsertPolicyActionsRel   string
	QueryInsertPolicyResources    string
	QueryInsertPolicyResourcesRel string
	QueryInsertPolicySubjects     string
	QueryInsertPolicySubjectsRel  string
	QueryPoliciesForSubject       string
	QueryPoliciesForResource      string
}

func createQueryPolicies(objectToQueryFor, db string) string {
	if objectToQueryFor != "subject" && objectToQueryFor != "resource" {
		panic(fmt.Sprintf("Cannot call createQueryPolicies for %s", objectToQueryFor))
	}
	var whereClause string
	if db == "postgres" {
		whereClause = fmt.Sprintf(`
			WHERE
				(%[1]s.has_regex IS NOT TRUE AND %[1]s.template = $1)
				OR
				(%[1]s.has_regex IS TRUE AND $2 ~ %[1]s.compiled)`,
			objectToQueryFor)
	} else if db == "mysql" {
		whereClause = fmt.Sprintf(`
			WHERE
				(%[1]s.has_regex = 0 AND %[1]s.template = ?)
				OR
				(%[1]s.has_regex = 1 AND ? REGEXP BINARY %[1]s.compiled)`,
			objectToQueryFor)
	} else {
		panic(fmt.Sprintf("Cannot call createQueryPolicies for db:%s", db))
	}
	return `
			SELECT
				p.id,
				p.effect,
				p.conditions,
				p.description,
				p.meta,
				subject.template AS subject,
				resource.template AS resource,
				action.template AS action
			FROM
				ladon_policy AS p

				INNER JOIN ladon_policy_subject_rel AS rs ON rs.policy = p.id
				LEFT JOIN ladon_policy_action_rel AS ra ON ra.policy = p.id
				LEFT JOIN ladon_policy_resource_rel AS rr ON rr.policy = p.id

				INNER JOIN ladon_subject AS subject ON rs.subject = subject.id
				LEFT JOIN ladon_action AS action ON ra.action = action.id
				LEFT JOIN ladon_resource AS resource ON rr.resource = resource.id` + whereClause
}

var sharedMigrations = []*migrate.Migration{
	{
		Id: "1",
		Up: []string{
			`CREATE TABLE IF NOT EXISTS ladon_policy (
				id           varchar(255) NOT NULL PRIMARY KEY,
				description  text NOT NULL,
				effect       text NOT NULL CHECK (effect='allow' OR effect='deny'),
				conditions	 text NOT NULL
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_subject (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_permission (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_resource (
				compiled text NOT NULL,
				template varchar(1023) NOT NULL,
				policy   varchar(255) NOT NULL,
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE
			)`,
		},
		Down: []string{
			"DROP TABLE ladon_policy",
			"DROP TABLE ladon_policy_subject",
			"DROP TABLE ladon_policy_permission",
			"DROP TABLE ladon_policy_resource",
		},
	},
	{
		Id: "2",
		Up: []string{
			`CREATE TABLE IF NOT EXISTS ladon_subject (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_action (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_resource (
				id          varchar(64) NOT NULL PRIMARY KEY,
				has_regex   bool NOT NULL,
				compiled    varchar(511) NOT NULL UNIQUE,
				template    varchar(511) NOT NULL UNIQUE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_subject_rel (
				policy   varchar(255) NOT NULL,
				subject  varchar(64) NOT NULL,
				PRIMARY KEY (policy, subject),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (subject) REFERENCES ladon_subject(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_action_rel (
				policy  varchar(255) NOT NULL,
				action  varchar(64) NOT NULL,
				PRIMARY KEY (policy, action),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (action) REFERENCES ladon_action(id) ON DELETE CASCADE
			)`,
			`CREATE TABLE IF NOT EXISTS ladon_policy_resource_rel (
				policy    varchar(255) NOT NULL,
				resource  varchar(64) NOT NULL,
				PRIMARY KEY (policy, resource),
				FOREIGN KEY (policy) REFERENCES ladon_policy(id) ON DELETE CASCADE,
				FOREIGN KEY (resource) REFERENCES ladon_resource(id) ON DELETE CASCADE
			)`,
		},
		Down: []string{},
	},
}

var Migrations = map[string]Statements{
	"postgres": {
		Migrations: &migrate.MemoryMigrationSource{
			Migrations: []*migrate.Migration{
				sharedMigrations[0],
				sharedMigrations[1],
				{
					Id: "3",
					Up: []string{
						"CREATE INDEX ladon_subject_compiled_idx ON ladon_subject (compiled text_pattern_ops)",
						"CREATE INDEX ladon_permission_compiled_idx ON ladon_action (compiled text_pattern_ops)",
						"CREATE INDEX ladon_resource_compiled_idx ON ladon_resource (compiled text_pattern_ops)",
					},
					Down: []string{
						"DROP INDEX ladon_subject_compiled_idx",
						"DROP INDEX ladon_permission_compiled_idx",
						"DROP INDEX ladon_resource_compiled_idx",
					},
				},
				{
					Id: "4",
					Up: []string{
						"ALTER TABLE ladon_policy ADD COLUMN meta json",
					},
					Down: []string{
						"ALTER TABLE ladon_policy DROP COLUMN IF EXISTS meta",
					},
				},
			},
		},
		QueryInsertPolicy:             `INSERT INTO ladon_policy(id, description, effect, conditions, meta) SELECT $1::varchar, $2, $3, $4, $5 WHERE NOT EXISTS (SELECT 1 FROM ladon_policy WHERE id = $1)`,
		QueryInsertPolicyActions:      `INSERT INTO ladon_action (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_action WHERE id = $1)`,
		QueryInsertPolicyActionsRel:   `INSERT INTO ladon_policy_action_rel (policy, action) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_action_rel WHERE policy = $1 AND action = $2)`,
		QueryInsertPolicyResources:    `INSERT INTO ladon_resource (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_resource WHERE id = $1)`,
		QueryInsertPolicyResourcesRel: `INSERT INTO ladon_policy_resource_rel (policy, resource) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_resource_rel WHERE policy = $1 AND resource = $2)`,
		QueryInsertPolicySubjects:     `INSERT INTO ladon_subject (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_subject WHERE id = $1)`,
		QueryInsertPolicySubjectsRel:  `INSERT INTO ladon_policy_subject_rel (policy, subject) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_subject_rel WHERE policy = $1 AND subject = $2)`,
		QueryPoliciesForSubject:       createQueryPolicies("subject", "postgres"),
		QueryPoliciesForResource:      createQueryPolicies("resource", "postgres"),
	},
	"mysql": {
		Migrations: &migrate.MemoryMigrationSource{
			Migrations: []*migrate.Migration{
				sharedMigrations[0],
				sharedMigrations[1],
				{
					Id: "3",
					Up: []string{
						"CREATE FULLTEXT INDEX ladon_subject_compiled_idx ON ladon_subject (compiled)",
						"CREATE FULLTEXT INDEX ladon_action_compiled_idx ON ladon_action (compiled)",
						"CREATE FULLTEXT INDEX ladon_resource_compiled_idx ON ladon_resource (compiled)",
					},
					Down: []string{
						"DROP INDEX ladon_subject_compiled_idx",
						"DROP INDEX ladon_permission_compiled_idx",
						"DROP INDEX ladon_resource_compiled_idx",
					},
				},
				{
					Id: "4",
					Up: []string{
						"ALTER TABLE ladon_policy ADD COLUMN meta text",
					},
					Down: []string{
						"ALTER TABLE ladon_policy DROP COLUMN meta",
					},
				},
			},
		},
		QueryInsertPolicy:             `INSERT IGNORE INTO ladon_policy (id, description, effect, conditions, meta) VALUES(?,?,?,?,?)`,
		QueryInsertPolicyActions:      `INSERT IGNORE INTO ladon_action (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicyActionsRel:   `INSERT IGNORE INTO ladon_policy_action_rel (policy, action) VALUES(?,?)`,
		QueryInsertPolicyResources:    `INSERT IGNORE INTO ladon_resource (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicyResourcesRel: `INSERT IGNORE INTO ladon_policy_resource_rel (policy, resource) VALUES(?,?)`,
		QueryInsertPolicySubjects:     `INSERT IGNORE INTO ladon_subject (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
		QueryInsertPolicySubjectsRel:  `INSERT IGNORE INTO ladon_policy_subject_rel (policy, subject) VALUES(?,?)`,
		QueryPoliciesForSubject:       createQueryPolicies("subject", "mysql"),
		QueryPoliciesForResource:      createQueryPolicies("resource", "mysql"),
	},
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-daq Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package tsl2591 provides access to the TSL2591 sensor, over I2C/SMBus for RaspBerry.
package tsl2591

import (
	"math"
	"time"

	"github.com/go-daq/smbus"
)

// IntegTimeValue describes the integration time used while extracting data
// from sensor.
type IntegTimeValue uint8

const (
	IntegTime100ms IntegTimeValue = 0x00
	IntegTime200ms IntegTimeValue = 0x01
	IntegTime300ms IntegTimeValue = 0x02
	IntegTime400ms IntegTimeValue = 0x03
	IntegTime500ms IntegTimeValue = 0x04
	IntegTime600ms IntegTimeValue = 0x05
)

// GainValue describes the gain value used while extracting data from sensor data.
type GainValue uint8

const (
	GainLow  GainValue = 0x00 // Low gain (1x)
	GainMed  GainValue = 0x10 // Medium gain (25x)
	GainHigh GainValue = 0x20 // High gain (428x)
	GainMax  GainValue = 0x30 // Maximum gain (9876x)
)

// Device is a TSL2591 sensor.
type Device struct {
	conn  *smbus.Conn // connection to smbus
	addr  uint8       // sensor address
	integ uint8       // integration time in ms
	gain  uint8
}

// Open opens a connection to the TSL2591 sensor device at address addr
// on the provided SMBus.
func Open(conn *smbus.Conn, addr uint8, integ IntegTimeValue, gain GainValue) (*Device, error) {
	var err error

	dev := Device{
		conn: conn,
		addr: addr,
	}

	err = dev.setTiming(integ)
	if err != nil {
		return nil, err
	}

	err = dev.setGain(gain)
	if err != nil {
		return nil, err
	}

	err = dev.disable()
	if err != nil {
		return nil, err
	}

	return &dev, nil
}

func (dev *Device) Close() error {
	return dev.conn.Close()
}

func (dev *Device) enable() error {
	return dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegEnable,
		EnablePowerON|EnableAEN|EnableAIEN,
	)
}

func (dev *Device) disable() error {
	return dev.conn.WriteReg(dev.addr, CmdBit|RegEnable, EnablePowerOFF)
}

func (dev *Device) setTiming(integ IntegTimeValue) error {
	err := dev.enable()
	if err != nil {
		return err
	}

	dev.integ = uint8(integ)

	err = dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegControl,
		dev.integ|dev.gain,
	)
	if err != nil {
		return err
	}

	return dev.disable()
}

func (dev *Device) setGain(gain GainValue) error {
	var err error

	err = dev.enable()
	if err != nil {
		return err
	}

	dev.gain = uint8(gain)

	err = dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegControl,
		dev.integ|dev.gain,
	)
	if err != nil {
		return err
	}

	return dev.disable()
}

// Gain returns the gain register value.
func (dev *Device) Gain() GainValue {
	return GainValue(dev.gain)
}

// Timing returns the integration time register value.
func (dev *Device) Timing() IntegTimeValue {
	return IntegTimeValue(dev.integ)
}

func (dev *Device) Lux(full, ir uint16) float64 {
	if full == 0xFFFF || ir == 0xFFFF {
		// overflow
		return 0
	}

	atime := 100.0
	switch IntegTimeValue(dev.integ) {
	case IntegTime100ms:
		atime = 100.0
	case IntegTime200ms:
		atime = 200.0
	case IntegTime300ms:
		atime = 300.0
	case IntegTime400ms:
		atime = 400.0
	case IntegTime500ms:
		atime = 500.0
	case IntegTime600ms:
		atime = 600.0
	}

	again := 1.0
	switch GainValue(dev.gain) {
	case GainLow:
		again = 1
	case GainMed:
		again = 25
	case GainHigh:
		again = 428
	case GainMax:
		again = 9876
	}

	cpl := (atime * again) / LuxDF
	lux1 := (float64(full) - (LuxCoefB * float64(ir))) / cpl
	lux2 := ((LuxCoefC * float64(full)) - (LuxCoefD * float64(ir))) / cpl

	return math.Max(lux1, lux2)
}

func (dev *Device) FullLuminosity() (uint16, uint16, error) {
	err := dev.enable()
	time.Sleep((120*time.Duration(dev.integ) + 1) * time.Millisecond)
	if err != nil {
		return 0, 0, err
	}

	full, err := dev.conn.ReadWord(dev.addr, CmdBit|RegChan0Low)
	if err != nil {
		return 0, 0, err
	}

	ir, err := dev.conn.ReadWord(dev.addr, CmdBit|RegChan1Low)
	if err != nil {
		return 0, 0, err
	}

	err = dev.disable()
	if err != nil {
		return 0, 0, err
	}

	return full, ir, nil
}

// List of register commands
const (
	Addr           uint8 = 0x29
	ReadBit        uint8 = 0x01
	CmdBit         uint8 = 0xA0 // bits 7 and 5 for "command normal"
	ClearBit       uint8 = 0x40 // clears any pending interrupt (write 1 to clear)
	WordBit        uint8 = 0x20 // 1 = read/write word (rather than byte)
	BlockBit       uint8 = 0x10 // 1 = using block read/write
	EnablePowerON  uint8 = 0x01
	EnablePowerOFF uint8 = 0x00
	EnableAEN      uint8 = 0x02
	EnableAIEN     uint8 = 0x10
	ControlReset   uint8 = 0x80

	RegEnable          uint8 = 0x00
	RegControl         uint8 = 0x01
	RegThreshholdLLow  uint8 = 0x02
	RegThreshholdLHigh uint8 = 0x03
	RegThreshholdHLow  uint8 = 0x04
	RegThreshholdHHigh uint8 = 0x05
	RegInterrupt       uint8 = 0x06
	RegCRC             uint8 = 0x08
	RegID              uint8 = 0x0A
	RegChan0Low        uint8 = 0x14
	RegChan0High       uint8 = 0x15
	RegChan1Low        uint8 = 0x16
	RegChan1High       uint8 = 0x17

	LuxDF    = 408.0
	LuxCoefB = 1.64 // CH0 coefficient
	LuxCoefC = 0.59 // CH1 coefficient A
	LuxCoefD = 0.86 // CH2 coefficient B
)
<commit_msg>smbus/sensor/tsl2591: fix too short sleep time<commit_after>// Copyright 2017 The go-daq Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package tsl2591 provides access to the TSL2591 sensor, over I2C/SMBus for RaspBerry.
package tsl2591

import (
	"math"
	"time"

	"github.com/go-daq/smbus"
)

// IntegTimeValue describes the integration time used while extracting data
// from sensor.
type IntegTimeValue uint8

const (
	IntegTime100ms IntegTimeValue = 0x00
	IntegTime200ms IntegTimeValue = 0x01
	IntegTime300ms IntegTimeValue = 0x02
	IntegTime400ms IntegTimeValue = 0x03
	IntegTime500ms IntegTimeValue = 0x04
	IntegTime600ms IntegTimeValue = 0x05
)

// GainValue describes the gain value used while extracting data from sensor data.
type GainValue uint8

const (
	GainLow  GainValue = 0x00 // Low gain (1x)
	GainMed  GainValue = 0x10 // Medium gain (25x)
	GainHigh GainValue = 0x20 // High gain (428x)
	GainMax  GainValue = 0x30 // Maximum gain (9876x)
)

// Device is a TSL2591 sensor.
type Device struct {
	conn  *smbus.Conn // connection to smbus
	addr  uint8       // sensor address
	integ uint8       // integration time in ms
	gain  uint8
}

// Open opens a connection to the TSL2591 sensor device at address addr
// on the provided SMBus.
func Open(conn *smbus.Conn, addr uint8, integ IntegTimeValue, gain GainValue) (*Device, error) {
	var err error

	dev := Device{
		conn: conn,
		addr: addr,
	}

	err = dev.setTiming(integ)
	if err != nil {
		return nil, err
	}

	err = dev.setGain(gain)
	if err != nil {
		return nil, err
	}

	err = dev.disable()
	if err != nil {
		return nil, err
	}

	return &dev, nil
}

func (dev *Device) Close() error {
	return dev.conn.Close()
}

func (dev *Device) enable() error {
	return dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegEnable,
		EnablePowerON|EnableAEN|EnableAIEN,
	)
}

func (dev *Device) disable() error {
	return dev.conn.WriteReg(dev.addr, CmdBit|RegEnable, EnablePowerOFF)
}

func (dev *Device) setTiming(integ IntegTimeValue) error {
	err := dev.enable()
	if err != nil {
		return err
	}

	dev.integ = uint8(integ)

	err = dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegControl,
		dev.integ|dev.gain,
	)
	if err != nil {
		return err
	}

	return dev.disable()
}

func (dev *Device) setGain(gain GainValue) error {
	var err error

	err = dev.enable()
	if err != nil {
		return err
	}

	dev.gain = uint8(gain)

	err = dev.conn.WriteReg(
		dev.addr,
		CmdBit|RegControl,
		dev.integ|dev.gain,
	)
	if err != nil {
		return err
	}

	return dev.disable()
}

// Gain returns the gain register value.
func (dev *Device) Gain() GainValue {
	return GainValue(dev.gain)
}

// Timing returns the integration time register value.
func (dev *Device) Timing() IntegTimeValue {
	return IntegTimeValue(dev.integ)
}

func (dev *Device) Lux(full, ir uint16) float64 {
	if full == 0xFFFF || ir == 0xFFFF {
		// overflow
		return 0
	}

	atime := 100.0
	switch IntegTimeValue(dev.integ) {
	case IntegTime100ms:
		atime = 100.0
	case IntegTime200ms:
		atime = 200.0
	case IntegTime300ms:
		atime = 300.0
	case IntegTime400ms:
		atime = 400.0
	case IntegTime500ms:
		atime = 500.0
	case IntegTime600ms:
		atime = 600.0
	}

	again := 1.0
	switch GainValue(dev.gain) {
	case GainLow:
		again = 1
	case GainMed:
		again = 25
	case GainHigh:
		again = 428
	case GainMax:
		again = 9876
	}

	cpl := (atime * again) / LuxDF
	lux1 := (float64(full) - (LuxCoefB * float64(ir))) / cpl
	lux2 := ((LuxCoefC * float64(full)) - (LuxCoefD * float64(ir))) / cpl

	return math.Max(lux1, lux2)
}

func (dev *Device) FullLuminosity() (uint16, uint16, error) {
	err := dev.enable()
	if err != nil {
		return 0, 0, err
	}
	time.Sleep(((120*time.Duration(dev.integ))*time.Millisecond + 1) * time.Second)
	if err != nil {
		return 0, 0, err
	}

	full, err := dev.conn.ReadWord(dev.addr, CmdBit|RegChan0Low)
	if err != nil {
		return 0, 0, err
	}

	ir, err := dev.conn.ReadWord(dev.addr, CmdBit|RegChan1Low)
	if err != nil {
		return 0, 0, err
	}

	err = dev.disable()
	if err != nil {
		return 0, 0, err
	}

	return full, ir, nil
}

// List of register commands
const (
	Addr           uint8 = 0x29
	ReadBit        uint8 = 0x01
	CmdBit         uint8 = 0xA0 // bits 7 and 5 for "command normal"
	ClearBit       uint8 = 0x40 // clears any pending interrupt (write 1 to clear)
	WordBit        uint8 = 0x20 // 1 = read/write word (rather than byte)
	BlockBit       uint8 = 0x10 // 1 = using block read/write
	EnablePowerON  uint8 = 0x01
	EnablePowerOFF uint8 = 0x00
	EnableAEN      uint8 = 0x02
	EnableAIEN     uint8 = 0x10
	ControlReset   uint8 = 0x80

	RegEnable          uint8 = 0x00
	RegControl         uint8 = 0x01
	RegThreshholdLLow  uint8 = 0x02
	RegThreshholdLHigh uint8 = 0x03
	RegThreshholdHLow  uint8 = 0x04
	RegThreshholdHHigh uint8 = 0x05
	RegInterrupt       uint8 = 0x06
	RegCRC             uint8 = 0x08
	RegID              uint8 = 0x0A
	RegChan0Low        uint8 = 0x14
	RegChan0High       uint8 = 0x15
	RegChan1Low        uint8 = 0x16
	RegChan1High       uint8 = 0x17

	LuxDF    = 408.0
	LuxCoefB = 1.64 // CH0 coefficient
	LuxCoefC = 0.59 // CH1 coefficient A
	LuxCoefD = 0.86 // CH2 coefficient B
)
<|endoftext|>


<commit_before>package oauth_test

import (
	"log"
	"testing"

	"github.com/RichardKnop/go-oauth2-server/config"
	"github.com/RichardKnop/go-oauth2-server/database"
	"github.com/RichardKnop/go-oauth2-server/oauth"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

var testFixtures = []string{
	"fixtures/scopes.yml",
	"fixtures/test_clients.yml",
	"fixtures/test_users.yml",
}

// db migrations needed for tests
var testMigrations = []func(*gorm.DB) error{
	oauth.MigrateAll,
}

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *oauth.Service
	clients []*oauth.Client
	users   []*oauth.User
	router  *mux.Router
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {

	// Initialise the config
	suite.cnf = config.NewConfig(false, false)

	// Create the test database
	db, err := database.CreateTestDatabase(testDbPath, testMigrations, testFixtures)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = db

	// Fetch test client
	suite.clients = make([]*oauth.Client, 0)
	if err := suite.db.Order("id").Find(&suite.clients).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch test users
	suite.users = make([]*oauth.User, 0)
	if err := suite.db.Order("id").Find(&suite.users).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = oauth.NewService(suite.cnf, suite.db)

	// Register routes
	suite.router = mux.NewRouter()
	oauth.RegisterRoutes(suite.router, suite.service)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(new(oauth.AuthorizationCode))
	suite.db.Unscoped().Delete(new(oauth.RefreshToken))
	suite.db.Unscoped().Delete(new(oauth.AccessToken))
	suite.db.Unscoped().Not("id", []int64{1, 2}).Delete(new(oauth.User))
	suite.db.Unscoped().Not("id", []int64{1, 2, 3}).Delete(new(oauth.Client))
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<commit_msg>Oauth suite test small refactor.<commit_after>package oauth_test

import (
	"log"
	"os"
	"testing"

	"github.com/RichardKnop/go-oauth2-server/config"
	"github.com/RichardKnop/go-oauth2-server/database"
	"github.com/RichardKnop/go-oauth2-server/oauth"
	"github.com/gorilla/mux"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

var testFixtures = []string{
	"./oauth/fixtures/scopes.yml",
	"./oauth/fixtures/test_clients.yml",
	"./oauth/fixtures/test_users.yml",
}

// db migrations needed for tests
var testMigrations = []func(*gorm.DB) error{
	oauth.MigrateAll,
}

func init() {
	if err := os.Chdir("../"); err != nil {
		log.Fatal(err)
	}
}

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *oauth.Service
	clients []*oauth.Client
	users   []*oauth.User
	router  *mux.Router
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {

	// Initialise the config
	suite.cnf = config.NewConfig(false, false)

	// Create the test database
	db, err := database.CreateTestDatabase(testDbPath, testMigrations, testFixtures)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = db

	// Fetch test client
	suite.clients = make([]*oauth.Client, 0)
	if err := suite.db.Order("id").Find(&suite.clients).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch test users
	suite.users = make([]*oauth.User, 0)
	if err := suite.db.Order("id").Find(&suite.users).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = oauth.NewService(suite.cnf, suite.db)

	// Register routes
	suite.router = mux.NewRouter()
	oauth.RegisterRoutes(suite.router, suite.service)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(new(oauth.AuthorizationCode))
	suite.db.Unscoped().Delete(new(oauth.RefreshToken))
	suite.db.Unscoped().Delete(new(oauth.AccessToken))
	suite.db.Unscoped().Not("id", []int64{1, 2}).Delete(new(oauth.User))
	suite.db.Unscoped().Not("id", []int64{1, 2, 3}).Delete(new(oauth.Client))
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<|endoftext|>


<commit_before>package container

import (
	"strings"

	"github.com/fsouza/go-dockerclient"
	"github.com/mesos/mesos-go/api/v1/lib"
)

// DockerContainerizer represents a docker containerizer
type DockerContainerizer struct {
	Client *docker.Client
}

// NewDockerContainerizer initializes a new docker containerizer
func NewDockerContainerizer(socket string) (*DockerContainerizer, error) {
	// If socket is given without an explicit protocol such as tpc:// or http://,
	// we use unix:// one
	if strings.HasPrefix(socket, "/") {
		socket = "unix://" + socket
	}

	client, err := docker.NewClient(socket)
	if err != nil {
		return nil, err
	}

	return &DockerContainerizer{
		Client: client,
	}, nil
}

// ContainerRun launches a new container with the given containerizer
func (c *DockerContainerizer) ContainerRun(info Info) (string, error) {
	// Define network mode
	var networkMode string
	switch info.TaskInfo.GetContainer().GetDocker().GetNetwork() {
	case mesos.ContainerInfo_DockerInfo_HOST:
		networkMode = "host"
		break
	case mesos.ContainerInfo_DockerInfo_BRIDGE:
		networkMode = "bridge"
		break
	case mesos.ContainerInfo_DockerInfo_NONE:
		networkMode = "none"
		break
	case mesos.ContainerInfo_DockerInfo_USER:
		networkMode = "user"
		break
	}

	// Prepare container
	container, err := c.Client.CreateContainer(docker.CreateContainerOptions{
		Config: &docker.Config{
			CPUShares: int64(info.CPUSharesLimit),
			Image:     info.TaskInfo.GetContainer().GetDocker().GetImage(),
			Memory:    int64(info.MemoryLimit),
		},
		HostConfig: &docker.HostConfig{
			NetworkMode: networkMode,
			Privileged:  info.TaskInfo.GetContainer().GetDocker().GetPrivileged(),
		},
	})

	if err != nil {
		return "", err
	}

	err = c.Client.StartContainer(container.ID, nil)
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

// ContainerStop stops the given container
func (c *DockerContainerizer) ContainerStop(id string) error {
	return c.Client.StopContainer(id, 0)
}
<commit_msg>Manage docker ports binding<commit_after>package container

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/fsouza/go-dockerclient"
	"github.com/mesos/mesos-go/api/v1/lib"
)

// DockerContainerizer represents a docker containerizer
type DockerContainerizer struct {
	Client *docker.Client
}

// NewDockerContainerizer initializes a new docker containerizer
func NewDockerContainerizer(socket string) (*DockerContainerizer, error) {
	// If socket is given without an explicit protocol such as tpc:// or http://,
	// we use unix:// one
	if strings.HasPrefix(socket, "/") {
		socket = "unix://" + socket
	}

	client, err := docker.NewClient(socket)
	if err != nil {
		return nil, err
	}

	return &DockerContainerizer{
		Client: client,
	}, nil
}

// ContainerRun launches a new container with the given containerizer
func (c *DockerContainerizer) ContainerRun(info Info) (string, error) {
	// Define network mode
	var networkMode string
	switch info.TaskInfo.GetContainer().GetDocker().GetNetwork() {
	case mesos.ContainerInfo_DockerInfo_HOST:
		networkMode = "host"
		break
	case mesos.ContainerInfo_DockerInfo_BRIDGE:
		networkMode = "bridge"
		break
	case mesos.ContainerInfo_DockerInfo_NONE:
		networkMode = "none"
		break
	case mesos.ContainerInfo_DockerInfo_USER:
		networkMode = "user"
		break
	}

	// Define ports mappings
	portsMappings := make(map[docker.Port][]docker.PortBinding)
	for _, mapping := range info.TaskInfo.GetContainer().GetDocker().GetPortMappings() {
		containerPort := docker.Port(fmt.Sprintf("%d/%s", mapping.GetContainerPort(), mapping.GetProtocol())) // ContainerPort needs to have the form port/protocol (eg. 80/tcp)
		hostPort := strconv.Itoa(int(mapping.HostPort))
		portsMappings[containerPort] = []docker.PortBinding{
			docker.PortBinding{
				HostPort: hostPort,
			},
		}
	}

	// Prepare container
	container, err := c.Client.CreateContainer(docker.CreateContainerOptions{
		Config: &docker.Config{
			CPUShares: int64(info.CPUSharesLimit),
			Image:     info.TaskInfo.GetContainer().GetDocker().GetImage(),
			Memory:    int64(info.MemoryLimit),
		},
		HostConfig: &docker.HostConfig{
			NetworkMode:  networkMode,
			PortBindings: portsMappings,
			Privileged:   info.TaskInfo.GetContainer().GetDocker().GetPrivileged(),
		},
	})

	if err != nil {
		return "", err
	}

	// Start the container
	logrus.WithFields(logrus.Fields{
		"NetworkMode":   networkMode,
		"PortsMappings": portsMappings,
	}).Debug("Starting docker container")
	err = c.Client.StartContainer(container.ID, nil)
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

// ContainerStop stops the given container
func (c *DockerContainerizer) ContainerStop(id string) error {
	return c.Client.StopContainer(id, 0)
}
<|endoftext|>


<commit_before>package services_test

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

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

	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
	testhelpers "github.com/maximilien/softlayer-go/test_helpers"
)

var _ = Describe("SoftLayer Services", func() {
	var (
		err error

		accountService      softlayer.SoftLayer_Account_Service
		virtualGuestService softlayer.SoftLayer_Virtual_Guest_Service
	)

	BeforeEach(func() {
		accountService, err = testhelpers.CreateAccountService()
		Expect(err).ToNot(HaveOccurred())
		Expect(accountService).ToNot(BeNil())

		virtualGuestService, err = testhelpers.CreateVirtualGuestService()
		Expect(err).ToNot(HaveOccurred())
		Expect(virtualGuestService).ToNot(BeNil())
	})

	Context("uses SoftLayer_Account to list current virtual: disk images, guests, ssh keys, and network storage", func() {
		It("returns an array of SoftLayer_Virtual_Guest disk images", func() {
			virtualDiskImages, err := accountService.GetVirtualDiskImages()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(virtualDiskImages)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Virtual_Guest objects", func() {
			virtualGuests, err := accountService.GetVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(virtualGuests)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Virtual_Guest network storage", func() {
			networkStorageArray, err := accountService.GetNetworkStorage()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(networkStorageArray)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Ssh_Keys objects", func() {
			sshKeys, err := accountService.GetSshKeys()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(sshKeys)).To(BeNumerically(">=", 0))
		})
	})

	Context("uses SoftLayer_Account to create and then delete a an ssh key", func() {
		BeforeEach(func() {
			err := testhelpers.FindAndDeleteTestSshKeys()
			Expect(err).ToNot(HaveOccurred())
		})

		AfterEach(func() {
			err := testhelpers.FindAndDeleteTestSshKeys()
			Expect(err).ToNot(HaveOccurred())
		})

		It("creates the ssh key and verify it is present and then deletes it", func() {
			sshKeyPath := os.Getenv("SOFTLAYER_GO_TEST_SSH_KEY_PATH")
			Expect(sshKeyPath).ToNot(Equal(""), "SOFTLAYER_GO_TEST_SSH_KEY_PATH env variable is not set")

			testSshKeyValue, err := ioutil.ReadFile(sshKeyPath)
			Expect(err).ToNot(HaveOccurred())

			sshKey := datatypes.SoftLayer_Security_Ssh_Key{
				Key:   strings.Trim(string(testSshKeyValue), "\n"),
				Label: testhelpers.TEST_LABEL_PREFIX,
				Notes: testhelpers.TEST_NOTES_PREFIX,
			}

			sshKeyService, err := testhelpers.CreateSecuritySshKeyService()
			Expect(err).ToNot(HaveOccurred())

			//Create ssh key
			createdSshKey, err := sshKeyService.CreateObject(sshKey)
			Expect(err).ToNot(HaveOccurred())
			Expect(createdSshKey.Key).To(Equal(sshKey.Key), "key")
			Expect(createdSshKey.Label).To(Equal(sshKey.Label), "label")
			Expect(createdSshKey.Notes).To(Equal(sshKey.Notes), "notes")
			Expect(createdSshKey.CreateDate).ToNot(BeNil(), "createDate")
			Expect(createdSshKey.Fingerprint).ToNot(Equal(""), "fingerprint")
			Expect(createdSshKey.Id).To(BeNumerically(">", 0), "id")
			Expect(createdSshKey.ModifyDate).To(BeNil(), "modifyDate")

			//Delete ssh key
			deleted, err := sshKeyService.DeleteObject(createdSshKey.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())
		})
	})

	XContext("uses SoftLayer_Account to create and then delete a virtual guest instance", func() {
		BeforeEach(func() {
			err := testhelpers.FindAndDeleteTestVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
		})

		AfterEach(func() {
			err := testhelpers.FindAndDeleteTestVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
		})

		XIt("creates the virtual guest instance and waits for it to be active", func() {
			virtualGuestTemplate := datatypes.SoftLayer_Virtual_Guest_Template{
				Hostname:  "test",
				Domain:    "softlayergo.com",
				StartCpus: 1,
				MaxMemory: 1024,
				Datacenter: datatypes.Datacenter{
					Name: "ams01",
				},
				HourlyBillingFlag:            true,
				LocalDiskFlag:                true,
				OperatingSystemReferenceCode: "UBUNTU_LATEST",
			}

			virtualGuestService, err := testhelpers.CreateVirtualGuestService()
			Expect(err).ToNot(HaveOccurred())

			_, err = virtualGuestService.CreateObject(virtualGuestTemplate)
			Expect(err).ToNot(HaveOccurred())

			//Clean up
		})

		It("deletes the virtual guest instance if it is running", func() {
			Expect(false).To(BeTrue())
		})
	})

	XContext("uses SoftLayer_Account to create a new instance and network storage and attach them", func() {
		It("creates the virtual guest instance and waits for it to be active", func() {
			Expect(false).To(BeTrue())
		})

		It("creates the disk storage and attaches it to the instance", func() {
			Expect(false).To(BeTrue())
		})

		It("deletes the virtual guest instance if it is running", func() {
			Expect(false).To(BeTrue())
		})

		It("detaches and deletes the network storage if available", func() {
			Expect(false).To(BeTrue())
		})
	})
})
<commit_msg>completed create/delete VG tests though need to implement editObject to mark VGs<commit_after>package services_test

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

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

	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
	testhelpers "github.com/maximilien/softlayer-go/test_helpers"
)

var _ = Describe("SoftLayer Services", func() {
	var (
		err error

		accountService      softlayer.SoftLayer_Account_Service
		virtualGuestService softlayer.SoftLayer_Virtual_Guest_Service
	)

	BeforeEach(func() {
		accountService, err = testhelpers.CreateAccountService()
		Expect(err).ToNot(HaveOccurred())
		Expect(accountService).ToNot(BeNil())

		virtualGuestService, err = testhelpers.CreateVirtualGuestService()
		Expect(err).ToNot(HaveOccurred())
		Expect(virtualGuestService).ToNot(BeNil())
	})

	Context("uses SoftLayer_Account to list current virtual: disk images, guests, ssh keys, and network storage", func() {
		It("returns an array of SoftLayer_Virtual_Guest disk images", func() {
			virtualDiskImages, err := accountService.GetVirtualDiskImages()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(virtualDiskImages)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Virtual_Guest objects", func() {
			virtualGuests, err := accountService.GetVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(virtualGuests)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Virtual_Guest network storage", func() {
			networkStorageArray, err := accountService.GetNetworkStorage()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(networkStorageArray)).To(BeNumerically(">=", 0))
		})

		It("returns an array of SoftLayer_Ssh_Keys objects", func() {
			sshKeys, err := accountService.GetSshKeys()
			Expect(err).ToNot(HaveOccurred())
			Expect(len(sshKeys)).To(BeNumerically(">=", 0))
		})
	})

	Context("uses SoftLayer_Account to create and then delete a an ssh key", func() {
		BeforeEach(func() {
			err := testhelpers.FindAndDeleteTestSshKeys()
			Expect(err).ToNot(HaveOccurred())
		})

		AfterEach(func() {
			err := testhelpers.FindAndDeleteTestSshKeys()
			Expect(err).ToNot(HaveOccurred())
		})

		It("creates the ssh key and verify it is present and then deletes it", func() {
			sshKeyPath := os.Getenv("SOFTLAYER_GO_TEST_SSH_KEY_PATH")
			Expect(sshKeyPath).ToNot(Equal(""), "SOFTLAYER_GO_TEST_SSH_KEY_PATH env variable is not set")

			testSshKeyValue, err := ioutil.ReadFile(sshKeyPath)
			Expect(err).ToNot(HaveOccurred())

			sshKey := datatypes.SoftLayer_Security_Ssh_Key{
				Key:   strings.Trim(string(testSshKeyValue), "\n"),
				Label: testhelpers.TEST_LABEL_PREFIX,
				Notes: testhelpers.TEST_NOTES_PREFIX,
			}

			sshKeyService, err := testhelpers.CreateSecuritySshKeyService()
			Expect(err).ToNot(HaveOccurred())

			//Create ssh key
			createdSshKey, err := sshKeyService.CreateObject(sshKey)
			Expect(err).ToNot(HaveOccurred())
			Expect(createdSshKey.Key).To(Equal(sshKey.Key), "key")
			Expect(createdSshKey.Label).To(Equal(sshKey.Label), "label")
			Expect(createdSshKey.Notes).To(Equal(sshKey.Notes), "notes")
			Expect(createdSshKey.CreateDate).ToNot(BeNil(), "createDate")
			Expect(createdSshKey.Fingerprint).ToNot(Equal(""), "fingerprint")
			Expect(createdSshKey.Id).To(BeNumerically(">", 0), "id")
			Expect(createdSshKey.ModifyDate).To(BeNil(), "modifyDate")

			//Delete ssh key
			deleted, err := sshKeyService.DeleteObject(createdSshKey.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())
		})
	})

	Context("uses SoftLayer_Account to create and then delete a virtual guest instance", func() {
		var (
			TIMEOUT          time.Duration
			POLLING_INTERVAL time.Duration
		)

		BeforeEach(func() {
			TIMEOUT = 5 * time.Minute
			POLLING_INTERVAL = 10 * time.Second

			err := testhelpers.FindAndDeleteTestVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
		})

		AfterEach(func() {
			err := testhelpers.FindAndDeleteTestVirtualGuests()
			Expect(err).ToNot(HaveOccurred())
		})

		It("creates the virtual guest instance and waits for it to be active then delete it", func() {
			virtualGuestTemplate := datatypes.SoftLayer_Virtual_Guest_Template{
				Hostname:  "test",
				Domain:    "softlayergo.com",
				StartCpus: 1,
				MaxMemory: 1024,
				Datacenter: datatypes.Datacenter{
					Name: "ams01",
				},
				HourlyBillingFlag:            true,
				LocalDiskFlag:                true,
				OperatingSystemReferenceCode: "UBUNTU_LATEST",
			}

			virtualGuestService, err := testhelpers.CreateVirtualGuestService()
			Expect(err).ToNot(HaveOccurred())

			fmt.Printf("----> creating new virtual guest\n")
			virtualGuest, err := virtualGuestService.CreateObject(virtualGuestTemplate)
			Expect(err).ToNot(HaveOccurred())

			fmt.Printf("----> created virtual guest: %d\n", virtualGuest.Id)

			err = testhelpers.MarkVirtualGuestAsTest(virtualGuest)
			Expect(err).ToNot(HaveOccurred(), "Could not mark virtual guest as test")

			fmt.Printf("----> waiting for virtual guest: %d, until RUNNING\n", virtualGuest.Id)
			Eventually(func() string {
				vgPowerState, err := virtualGuestService.GetPowerState(virtualGuest.Id)
				Expect(err).ToNot(HaveOccurred())
				fmt.Printf("----> virtual guest: %d, has power state: %s\n", virtualGuest.Id, vgPowerState.KeyName)
				return vgPowerState.KeyName
			}, TIMEOUT, POLLING_INTERVAL).Should(Equal("RUNNING"), "failed waiting for virtual guest to be RUNNING")

			fmt.Printf("----> waiting for virtual guest to have not active transactions pending\n")
			Eventually(func() int {
				activeTransactions, err := virtualGuestService.GetActiveTransactions(virtualGuest.Id)
				Expect(err).ToNot(HaveOccurred())
				fmt.Printf("----> virtual guest: %d, has %d active transactions\n", virtualGuest.Id, len(activeTransactions))
				return len(activeTransactions)
			}, TIMEOUT, POLLING_INTERVAL).Should(Equal(0), "failed waiting for virtual guest to have no active transactions")

			fmt.Printf("----> deleting virtual guest: %d\n", virtualGuest.Id)
			deleted, err := virtualGuestService.DeleteObject(virtualGuest.Id)
			Expect(err).ToNot(HaveOccurred(), "Error deleting virtual guest")
			Expect(deleted).To(BeTrue())
		})
	})

	XContext("uses SoftLayer_Account to create a new instance and network storage and attach them", func() {
		It("creates the virtual guest instance and waits for it to be active", func() {
			Expect(false).To(BeTrue())
		})

		It("creates the disk storage and attaches it to the instance", func() {
			Expect(false).To(BeTrue())
		})

		It("deletes the virtual guest instance if it is running", func() {
			Expect(false).To(BeTrue())
		})

		It("detaches and deletes the network storage if available", func() {
			Expect(false).To(BeTrue())
		})
	})
})
<|endoftext|>


<commit_before>package backup

import (
	"archive/tar"
	"context"
	"github.com/apex/log"
	gzip "github.com/klauspost/pgzip"
	"github.com/pkg/errors"
	"github.com/remeh/sizedwaitgroup"
	"golang.org/x/sync/errgroup"
	"io"
	"os"
	"runtime"
	"strings"
	"sync"
)

type Archive struct {
	sync.Mutex

	TrimPrefix string
	Files      *IncludedFiles
}

// Creates an archive at dst with all of the files defined in the included files struct.
func (a *Archive) Create(dst string, ctx context.Context) (os.FileInfo, error) {
	f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	defer f.Close()

	maxCpu := runtime.NumCPU() / 2
	if maxCpu > 4 {
		maxCpu = 4
	}

	gzw, _ := gzip.NewWriterLevel(f, gzip.BestSpeed)
	_ = gzw.SetConcurrency(1 << 20, maxCpu)

	defer gzw.Flush()
	defer gzw.Close()

	tw := tar.NewWriter(gzw)
	defer tw.Flush()
	defer tw.Close()

	wg := sizedwaitgroup.New(10)
	g, ctx := errgroup.WithContext(ctx)
	// Iterate over all of the files to be included and put them into the archive. This is
	// done as a concurrent goroutine to speed things along. If an error is encountered at
	// any step, the entire process is aborted.
	for _, p := range a.Files.All() {
		p := p
		g.Go(func() error {
			wg.Add()
			defer wg.Done()

			select {
			case <-ctx.Done():
				return errors.WithStack(ctx.Err())
			default:
				return a.addToArchive(p, tw)
			}
		})
	}

	// Block until the entire routine is completed.
	if err := g.Wait(); err != nil {
		f.Close()

		// Attempt to remove the archive if there is an error, report that error to
		// the logger if it fails.
		if rerr := os.Remove(dst); rerr != nil && !os.IsNotExist(rerr) {
			log.WithField("location", dst).Warn("failed to delete corrupted backup archive")
		}

		return nil, errors.WithStack(err)
	}

	st, err := f.Stat()
	if err != nil {
		return nil, errors.WithStack(err)
	}

	return st, nil
}

// Adds a single file to the existing tar archive writer.
func (a *Archive) addToArchive(p string, w *tar.Writer) error {
	f, err := os.Open(p)
	if err != nil {
		return err
		return errors.WithStack(err)
	}
	defer f.Close()

	s, err := f.Stat()
	if err != nil {
		return errors.WithStack(err)
	}

	header := &tar.Header{
		// Trim the long server path from the name of the file so that the resulting
		// archive is exactly how the user would see it in the panel file manager.
		Name:    strings.TrimPrefix(p, a.TrimPrefix),
		Size:    s.Size(),
		Mode:    int64(s.Mode()),
		ModTime: s.ModTime(),
	}

	// These actions must occur sequentially, even if this function is called multiple
	// in parallel. You'll get some nasty panic's otherwise.
	a.Lock()
	defer a.Unlock()

	if err := w.WriteHeader(header); err != nil {
		return errors.WithStack(err)
	}

	buf := make([]byte, 4*1024)
	if _, err := io.CopyBuffer(w, f, buf); err != nil {
		return errors.WithStack(err)
	}

	return nil
}
<commit_msg>Don't blow up if a file gets removed during the backup<commit_after>package backup

import (
	"archive/tar"
	"context"
	"github.com/apex/log"
	gzip "github.com/klauspost/pgzip"
	"github.com/pkg/errors"
	"github.com/remeh/sizedwaitgroup"
	"golang.org/x/sync/errgroup"
	"io"
	"os"
	"runtime"
	"strings"
	"sync"
)

type Archive struct {
	sync.Mutex

	TrimPrefix string
	Files      *IncludedFiles
}

// Creates an archive at dst with all of the files defined in the included files struct.
func (a *Archive) Create(dst string, ctx context.Context) (os.FileInfo, error) {
	f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	defer f.Close()

	maxCpu := runtime.NumCPU() / 2
	if maxCpu > 4 {
		maxCpu = 4
	}

	gzw, _ := gzip.NewWriterLevel(f, gzip.BestSpeed)
	_ = gzw.SetConcurrency(1 << 20, maxCpu)

	defer gzw.Flush()
	defer gzw.Close()

	tw := tar.NewWriter(gzw)
	defer tw.Flush()
	defer tw.Close()

	wg := sizedwaitgroup.New(10)
	g, ctx := errgroup.WithContext(ctx)
	// Iterate over all of the files to be included and put them into the archive. This is
	// done as a concurrent goroutine to speed things along. If an error is encountered at
	// any step, the entire process is aborted.
	for _, p := range a.Files.All() {
		p := p
		g.Go(func() error {
			wg.Add()
			defer wg.Done()

			select {
			case <-ctx.Done():
				return errors.WithStack(ctx.Err())
			default:
				return a.addToArchive(p, tw)
			}
		})
	}

	// Block until the entire routine is completed.
	if err := g.Wait(); err != nil {
		f.Close()

		// Attempt to remove the archive if there is an error, report that error to
		// the logger if it fails.
		if rerr := os.Remove(dst); rerr != nil && !os.IsNotExist(rerr) {
			log.WithField("location", dst).Warn("failed to delete corrupted backup archive")
		}

		return nil, errors.WithStack(err)
	}

	st, err := f.Stat()
	if err != nil {
		return nil, errors.WithStack(err)
	}

	return st, nil
}

// Adds a single file to the existing tar archive writer.
func (a *Archive) addToArchive(p string, w *tar.Writer) error {
	f, err := os.Open(p)
	if err != nil {
		// If you try to backup something that no longer exists (got deleted somewhere during the process
		// but not by this process), just skip over it and don't kill the entire backup.
		if os.IsNotExist(err) {
			return nil
		}

		return errors.WithStack(err)
	}
	defer f.Close()

	s, err := f.Stat()
	if err != nil {
		// Same as above, don't kill the process just because the file no longer exists.
		if os.IsNotExist(err) {
			return nil
		}

		return errors.WithStack(err)
	}

	header := &tar.Header{
		// Trim the long server path from the name of the file so that the resulting
		// archive is exactly how the user would see it in the panel file manager.
		Name:    strings.TrimPrefix(p, a.TrimPrefix),
		Size:    s.Size(),
		Mode:    int64(s.Mode()),
		ModTime: s.ModTime(),
	}

	// These actions must occur sequentially, even if this function is called multiple
	// in parallel. You'll get some nasty panic's otherwise.
	a.Lock()
	defer a.Unlock()

	if err := w.WriteHeader(header); err != nil {
		return errors.WithStack(err)
	}

	buf := make([]byte, 4*1024)
	if _, err := io.CopyBuffer(w, f, buf); err != nil {
		return errors.WithStack(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package modify

import (
	"net/http"

	oas3 "github.com/getkin/kin-openapi/openapi3"
	"github.com/grokify/gotilla/net/urlutil"
)

func SpecDeleteProperties(spec *oas3.Swagger, md SpecMetadata) {
	for _, opID := range md.OperationIDs {
		SpecDeleteOperations(spec,
			func(urlpath, method string, op *oas3.Operation) bool {
				if op != nil && op.OperationID == opID {
					return true
				}
				return false
			})
		/*for _, pathItem := range spec.Paths {
			PathItemDeleteOperationID(pathItem, opID)
		}*/
	}
	for _, epDel := range md.Endpoints {
		SpecDeleteOperations(spec,
			func(urlpath, method string, op *oas3.Operation) bool {
				if op == nil {
					return false
				}
				if epDel == urlutil.EndpointString(urlpath, method, false) ||
					epDel == urlutil.EndpointString(urlpath, method, true) {
					return true
				}
				return false
			})
	}
	for _, schemaNameDel := range md.SchemaNames {
		for schemaNameTry := range spec.Components.Schemas {
			if schemaNameDel == schemaNameTry {
				delete(spec.Components.Schemas, schemaNameTry)
			}
		}
	}
}

func SpecDeleteOperations(spec *oas3.Swagger, delThis func(urlpath, method string, op *oas3.Operation) bool) {
	for urlpath, pathItem := range spec.Paths {
		if delThis(urlpath, http.MethodConnect, pathItem.Connect) {
			pathItem.Connect = nil
		}
		if delThis(urlpath, http.MethodDelete, pathItem.Delete) {
			pathItem.Delete = nil
		}
		if delThis(urlpath, http.MethodGet, pathItem.Get) {
			pathItem.Get = nil
		}
		if delThis(urlpath, http.MethodHead, pathItem.Head) {
			pathItem.Head = nil
		}
		if delThis(urlpath, http.MethodPatch, pathItem.Patch) {
			pathItem.Patch = nil
		}
		if delThis(urlpath, http.MethodPost, pathItem.Post) {
			pathItem.Post = nil
		}
		if delThis(urlpath, http.MethodPut, pathItem.Put) {
			pathItem.Put = nil
		}
		if delThis(urlpath, http.MethodTrace, pathItem.Trace) {
			pathItem.Trace = nil
		}
	}
}

func PathItemDeleteOperationID(pathItem *oas3.PathItem, opID string) {
	if pathItem.Connect != nil && pathItem.Connect.OperationID == opID {
		pathItem.Connect = nil
	}
	if pathItem.Delete != nil && pathItem.Delete.OperationID == opID {
		pathItem.Delete = nil
	}
	if pathItem.Get != nil && pathItem.Get.OperationID == opID {
		pathItem.Get = nil
	}
	if pathItem.Head != nil && pathItem.Head.OperationID == opID {
		pathItem.Head = nil
	}
	if pathItem.Patch != nil && pathItem.Patch.OperationID == opID {
		pathItem.Patch = nil
	}
	if pathItem.Post != nil && pathItem.Post.OperationID == opID {
		pathItem.Post = nil
	}
	if pathItem.Put != nil && pathItem.Put.OperationID == opID {
		pathItem.Put = nil
	}
	if pathItem.Trace != nil && pathItem.Trace.OperationID == opID {
		pathItem.Trace = nil
	}
}
<commit_msg>fix SpecDeleteOperations()<commit_after>package modify

import (
	"net/http"

	oas3 "github.com/getkin/kin-openapi/openapi3"
	"github.com/grokify/gotilla/net/urlutil"
)

func SpecDeleteProperties(spec *oas3.Swagger, md SpecMetadata) {
	for _, opID := range md.OperationIDs {
		SpecDeleteOperations(spec,
			func(urlpath, method string, op *oas3.Operation) bool {
				if op != nil && op.OperationID == opID {
					return true
				}
				return false
			})
		/*for _, pathItem := range spec.Paths {
			PathItemDeleteOperationID(pathItem, opID)
		}*/
	}
	for _, epDel := range md.Endpoints {
		SpecDeleteOperations(spec,
			func(urlpath, method string, op *oas3.Operation) bool {
				if op == nil {
					return false
				}
				if epDel == urlutil.EndpointString(urlpath, method, false) ||
					epDel == urlutil.EndpointString(urlpath, method, true) {
					return true
				}
				return false
			})
	}
	for _, schemaNameDel := range md.SchemaNames {
		for schemaNameTry := range spec.Components.Schemas {
			if schemaNameDel == schemaNameTry {
				delete(spec.Components.Schemas, schemaNameTry)
			}
		}
	}
}

func SpecDeleteOperations(spec *oas3.Swagger, delThis func(urlpath, method string, op *oas3.Operation) bool) {
	newPaths := oas3.Paths{}

	for urlpath, pathItem := range spec.Paths {
		newPathItem := oas3.PathItem{
			ExtensionProps: pathItem.ExtensionProps,
			Ref:            pathItem.Ref,
			Summary:        pathItem.Summary,
			Description:    pathItem.Description,
			Servers:        pathItem.Servers,
			Parameters:     pathItem.Parameters}
		if pathItem.Connect != nil && !delThis(urlpath, http.MethodConnect, pathItem.Connect) {
			newPathItem.Connect = pathItem.Connect
		}
		if pathItem.Delete != nil && !delThis(urlpath, http.MethodDelete, pathItem.Delete) {
			newPathItem.Delete = pathItem.Delete
		}
		if pathItem.Get != nil && !delThis(urlpath, http.MethodGet, pathItem.Get) {
			newPathItem.Get = pathItem.Get
		}
		if pathItem.Head != nil && !delThis(urlpath, http.MethodHead, pathItem.Head) {
			newPathItem.Head = pathItem.Head
		}
		if pathItem.Patch != nil && !delThis(urlpath, http.MethodPatch, pathItem.Patch) {
			newPathItem.Patch = pathItem.Patch
		}
		if pathItem.Post != nil && !delThis(urlpath, http.MethodPost, pathItem.Post) {
			newPathItem.Post = pathItem.Post
		}
		if pathItem.Put != nil && !delThis(urlpath, http.MethodPut, pathItem.Put) {
			newPathItem.Put = pathItem.Put
		}
		if pathItem.Trace != nil && !delThis(urlpath, http.MethodTrace, pathItem.Trace) {
			newPathItem.Trace = pathItem.Trace
		}
		if PathItemHasEndpoints(&newPathItem) {
			newPaths[urlpath] = &newPathItem
		}
	}
	spec.Paths = newPaths
}

func PathItemHasEndpoints(pathItem *oas3.PathItem) bool {
	if pathItem.Connect != nil || pathItem.Delete != nil ||
		pathItem.Get != nil || pathItem.Head != nil ||
		pathItem.Patch != nil || pathItem.Post != nil ||
		pathItem.Put != nil || pathItem.Trace != nil {
		return true
	}
	return false
}

func PathItemDeleteOperationID(pathItem *oas3.PathItem, opID string) {
	if pathItem.Connect != nil && pathItem.Connect.OperationID == opID {
		pathItem.Connect = nil
	}
	if pathItem.Delete != nil && pathItem.Delete.OperationID == opID {
		pathItem.Delete = nil
	}
	if pathItem.Get != nil && pathItem.Get.OperationID == opID {
		pathItem.Get = nil
	}
	if pathItem.Head != nil && pathItem.Head.OperationID == opID {
		pathItem.Head = nil
	}
	if pathItem.Patch != nil && pathItem.Patch.OperationID == opID {
		pathItem.Patch = nil
	}
	if pathItem.Post != nil && pathItem.Post.OperationID == opID {
		pathItem.Post = nil
	}
	if pathItem.Put != nil && pathItem.Put.OperationID == opID {
		pathItem.Put = nil
	}
	if pathItem.Trace != nil && pathItem.Trace.OperationID == opID {
		pathItem.Trace = nil
	}
}
<|endoftext|>


<commit_before>package geo

import (
	"testing"
)

func TestUnmarshalOpenCageGeocoderResponse(t *testing.T) {
	// TODO implement
}
<commit_msg>Adding in opencage geocoder testing coverage for utility functions<commit_after>package geo

import (
	"testing"
)

func TestSetOpencageAPIKey(t * testing.T) {
	SetOpenCageAPIKey("foo")
	if OpenCageAPIKey != "foo" {
		t.Errorf("Mismatched value for OpencageAPIKey.  Expected: 'foo', Actual: %s", OpenCageAPIKey)
	}
}

func TestSetOpenCageGeocodeURL(t *testing.T) {
	SetOpenCageGeocodeURL("foo")
	if opencageGeocodeURL != "foo" {
		t.Errorf("Mismatched value for googleGeocoeURL.  Expected: 'foo', Actual: %s", opencageGeocodeURL)
	}
}

func TestUnmarshalOpenCageGeocoderResponse(t *testing.T) {
	// TODO implement
}
<|endoftext|>


<commit_before>/* https://leetcode.com/problems/projection-area-of-3d-shapes/description/
On a N * N grid, we place some 1 * 1 * 1 cubes that are axis-aligned with the x, y, and z axes.

Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j).

Now we view the projection of these cubes onto the xy, yz, and zx planes.

A projection is like a shadow, that maps our 3 dimensional figure to a 2 dimensional plane.

Here, we are viewing the "shadow" when looking at the cubes from the top, the front, and the side.

Return the total area of all three projections.

Example 1:

	Input: [[2]]
	Output: 5

Example 2:

	Input: [[1,2],[3,4]]
	Output: 17
	Explanation:
	Here are the three projections ("shadows") of the shape made with each axis-aligned plane.
	https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/02/shadow.png

Example 3:

	Input: [[1,0],[0,2]]
	Output: 8

Example 4:

	Input: [[1,1,1],[1,0,1],[1,1,1]]
	Output: 14

Example 5:

	Input: [[2,2,2],[2,1,2],[2,2,2]]
	Output: 21

Note:

	1 <= grid.length = grid[0].length <= 50
	0 <= grid[i][j] <= 50
*/

package lmath

func projectionArea(grid [][]int) int {
	I, J := len(grid), len(grid[0])
	xx, xz, xyL := 0, 0, make([]int, J, J)
	for i := 0; i < I; i++ {
		tmp := 0
		for j := 0; j < J; j++ {
			if grid[i][j] != 0 {
				xx++
			}
			if grid[i][j] > tmp {
				tmp = grid[i][j]
			}
			if grid[i][j] > xyL[j] {
				xyL[j] = grid[i][j]
			}
		}
		xz += tmp
	}
	res := xx + xz
	for _, value := range xyL {
		res += value
	}
	return res
}
<commit_msg>refactor projectionArea<commit_after>/* https://leetcode.com/problems/projection-area-of-3d-shapes/description/
On a N * N grid, we place some 1 * 1 * 1 cubes that are axis-aligned with the x, y, and z axes.

Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j).

Now we view the projection of these cubes onto the xy, yz, and zx planes.

A projection is like a shadow, that maps our 3 dimensional figure to a 2 dimensional plane.

Here, we are viewing the "shadow" when looking at the cubes from the top, the front, and the side.

Return the total area of all three projections.

Example 1:

	Input: [[2]]
	Output: 5

Example 2:

	Input: [[1,2],[3,4]]
	Output: 17
	Explanation:
	Here are the three projections ("shadows") of the shape made with each axis-aligned plane.
	https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/02/shadow.png

Example 3:

	Input: [[1,0],[0,2]]
	Output: 8

Example 4:

	Input: [[1,1,1],[1,0,1],[1,1,1]]
	Output: 14

Example 5:

	Input: [[2,2,2],[2,1,2],[2,2,2]]
	Output: 21

Note:

	1 <= grid.length = grid[0].length <= 50
	0 <= grid[i][j] <= 50
*/

package lmath

func projectionArea(grid [][]int) int {
	I, J := len(grid), len(grid[0])
	xx, xz, xy := 0, 0, 0
	for i := 0; i < I; i++ {
		tmpXZ, tmpXY := 0, 0
		for j := 0; j < J; j++ {
			if grid[i][j] != 0 {
				xx++
			}
			if grid[i][j] > tmpXZ {
				tmpXZ = grid[i][j]
			}
			if grid[j][i] > tmpXY {
				tmpXY = grid[j][i]
			}
		}
		xz += tmpXZ
		xy += tmpXY
	}
	return xx + xz + xy
}
<|endoftext|>


<commit_before><commit_msg>Revert "feed: fallback to time.now()"<commit_after><|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/dbr65/goavro"
)

func bail(err error) {
	fmt.Fprintf(os.Stderr, "%s\n", err)
	os.Exit(1)
}

func usage(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
	}
	executable, err := os.Executable()
	if err != nil {
		executable = os.Args[0]
	}
	base := filepath.Base(executable)
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", base)
	fmt.Fprintf(os.Stderr, "\t%s [-v] [-summary] [-bc N] [-compression null|deflate|snappy] [-schema new-schema.avsc] source.avro destination.avro\n", base)
	fmt.Fprintf(os.Stderr, "\tWhen source.avro pathname is hyphen, %s will read from its standard input.\n", base)
	fmt.Fprintf(os.Stderr, "\tWhen destination.avro pathname is hyphen, %s will write to its standard output.\n", base)
	flag.PrintDefaults()
	os.Exit(2)
}

var (
	blockCount                      *int
	compressionName, schemaPathname *string
	summary, verbose                *bool
)

func init() {
	compressionName = flag.String("compression", "", "compression codec ('null', 'deflate', 'snappy'; default: use source compression)")
	blockCount = flag.Int("bc", 0, "max count of items in each block (default: use source block boundaries)")
	schemaPathname = flag.String("schema", "", "pathname to new schema (default: use source schema)")
	summary = flag.Bool("summary", false, "print summary information to stderr")
	verbose = flag.Bool("v", false, "print verbose information to stderr (implies: -summary)")
}

func main() {
	flag.Parse()

	if count := len(flag.Args()); count != 2 {
		usage(fmt.Errorf("wrong number of arguments: %d", count))
	}

	if *blockCount < 0 {
		usage(fmt.Errorf("count must be greater or equal to 0: %d", *blockCount))
	}

	if *verbose {
		*summary = true
	}

	var err error
	var fromF io.ReadCloser
	var toF io.WriteCloser

	if srcPathname := flag.Arg(0); srcPathname == "-" {
		stat, err := os.Stdin.Stat()
		if err != nil {
			bail(err)
		}
		if (stat.Mode() & os.ModeCharDevice) != 0 {
			usage(errors.New("cannot read from standard input when connected to terminal"))
		}
		fromF = os.Stdin
		if *summary {
			fmt.Fprintf(os.Stderr, "reading from stdin\n")
		}
	} else {
		fromF, err = os.Open(srcPathname)
		if err != nil {
			bail(err)
		}
		defer func(ioc io.Closer) {
			if err := ioc.Close(); err != nil {
				bail(err)
			}
		}(fromF)
		if *summary {
			fmt.Fprintf(os.Stderr, "reading from %s\n", flag.Arg(0))
		}
	}

	if destPathname := flag.Arg(1); destPathname == "-" {
		stat, err := os.Stdout.Stat()
		if err != nil {
			bail(err)
		}
		// if *verbose { // DEBUG
		// 	fmt.Fprintf(os.Stderr, "standard output mode: %v\n", stat.Mode())
		// }
		if (stat.Mode() & os.ModeCharDevice) != 0 {
			usage(errors.New("cannot send to standard output when connected to terminal"))
		}
		toF = os.Stdout
		if *summary {
			fmt.Fprintf(os.Stderr, "writing to stdout\n")
		}
	} else {
		toF, err = os.Create(destPathname)
		if err != nil {
			bail(err)
		}
		defer func(ioc io.Closer) {
			if err := ioc.Close(); err != nil {
				bail(err)
			}
		}(toF)
		if *summary {
			fmt.Fprintf(os.Stderr, "writing to %s\n", flag.Arg(1))
		}
	}

	// NOTE: Convert fromF to OCFReader
	ocfr, err := goavro.NewOCFReader(fromF)
	if err != nil {
		bail(err)
	}

	inputCompressionName := ocfr.CompressionName()
	outputCompressionName := inputCompressionName
	if *compressionName != "" {
		outputCompressionName = *compressionName
	}

	if *summary {
		fmt.Fprintf(os.Stderr, "input compression algorithm: %s\n", inputCompressionName)
		fmt.Fprintf(os.Stderr, "output compression algorithm: %s\n", outputCompressionName)
	}

	// NOTE: Either use schema from reader, or attempt to use new schema
	var outputSchema string
	if *schemaPathname == "" {
		outputSchema = ocfr.Codec().Schema()
	} else {
		schemaBytes, err := ioutil.ReadFile(*schemaPathname)
		if err != nil {
			bail(err)
		}
		outputSchema = string(schemaBytes)
	}

	// NOTE: Convert toF to OCFWriter
	ocfw, err := goavro.NewOCFWriter(goavro.OCFConfig{
		W:               toF,
		CompressionName: outputCompressionName,
		Schema:          outputSchema,
	})
	if err != nil {
		bail(err)
	}

	if err := transcode(ocfr, ocfw); err != nil {
		bail(err)
	}
}

func transcode(from *goavro.OCFReader, to *goavro.OCFWriter) error {
	var blocksRead, blocksWritten, itemsRead int

	var block []interface{}
	if *blockCount > 0 {
		block = make([]interface{}, 0, *blockCount)
	}

	for from.Scan() {
		datum, err := from.Read()
		if err != nil {
			break
		}

		itemsRead++
		block = append(block, datum)

		endOfBlock := from.RemainingBlockItems() == 0
		if endOfBlock {
			blocksRead++
			if *verbose {
				fmt.Fprintf(os.Stderr, "read block with %d items\n", len(block))
			}
		}

		// NOTE: When blockCount is 0, user wants each destination block to have
		// the same number of items as its corresponding source block. However,
		// when blockCount is greater than 0, user wants specified block count
		// sizes.
		if (*blockCount == 0 && endOfBlock) || (*blockCount > 0 && len(block) == *blockCount) {
			if err := writeBlock(to, block); err != nil {
				return err
			}
			blocksWritten++
			block = block[:0] // set slice length to 0 in order to re-use allocated underlying array
		}
	}

	var err error

	// append all remaining items (condition can only be true used when *blockCount > 0)
	if len(block) > 0 {
		if err = writeBlock(to, block); err == nil {
			blocksWritten++
		}
	}

	// if no write error, then return any read error encountered
	if err == nil {
		err = from.Err()
	}

	if *summary {
		fmt.Fprintf(os.Stderr, "read %d items\n", itemsRead)
		fmt.Fprintf(os.Stderr, "wrote %d blocks\n", blocksWritten)
	}

	return err
}

func writeBlock(to *goavro.OCFWriter, block []interface{}) error {
	if *verbose {
		fmt.Fprintf(os.Stderr, "writing block with %d items\n", len(block))
	}
	return to.Append(block)
}
<commit_msg>Update main.go<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/linkedin/goavro/v2"
)

func bail(err error) {
	fmt.Fprintf(os.Stderr, "%s\n", err)
	os.Exit(1)
}

func usage(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
	}
	executable, err := os.Executable()
	if err != nil {
		executable = os.Args[0]
	}
	base := filepath.Base(executable)
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", base)
	fmt.Fprintf(os.Stderr, "\t%s [-v] [-summary] [-bc N] [-compression null|deflate|snappy] [-schema new-schema.avsc] source.avro destination.avro\n", base)
	fmt.Fprintf(os.Stderr, "\tWhen source.avro pathname is hyphen, %s will read from its standard input.\n", base)
	fmt.Fprintf(os.Stderr, "\tWhen destination.avro pathname is hyphen, %s will write to its standard output.\n", base)
	flag.PrintDefaults()
	os.Exit(2)
}

var (
	blockCount                      *int
	compressionName, schemaPathname *string
	summary, verbose                *bool
)

func init() {
	compressionName = flag.String("compression", "", "compression codec ('null', 'deflate', 'snappy'; default: use source compression)")
	blockCount = flag.Int("bc", 0, "max count of items in each block (default: use source block boundaries)")
	schemaPathname = flag.String("schema", "", "pathname to new schema (default: use source schema)")
	summary = flag.Bool("summary", false, "print summary information to stderr")
	verbose = flag.Bool("v", false, "print verbose information to stderr (implies: -summary)")
}

func main() {
	flag.Parse()

	if count := len(flag.Args()); count != 2 {
		usage(fmt.Errorf("wrong number of arguments: %d", count))
	}

	if *blockCount < 0 {
		usage(fmt.Errorf("count must be greater or equal to 0: %d", *blockCount))
	}

	if *verbose {
		*summary = true
	}

	var err error
	var fromF io.ReadCloser
	var toF io.WriteCloser

	if srcPathname := flag.Arg(0); srcPathname == "-" {
		stat, err := os.Stdin.Stat()
		if err != nil {
			bail(err)
		}
		if (stat.Mode() & os.ModeCharDevice) != 0 {
			usage(errors.New("cannot read from standard input when connected to terminal"))
		}
		fromF = os.Stdin
		if *summary {
			fmt.Fprintf(os.Stderr, "reading from stdin\n")
		}
	} else {
		fromF, err = os.Open(srcPathname)
		if err != nil {
			bail(err)
		}
		defer func(ioc io.Closer) {
			if err := ioc.Close(); err != nil {
				bail(err)
			}
		}(fromF)
		if *summary {
			fmt.Fprintf(os.Stderr, "reading from %s\n", flag.Arg(0))
		}
	}

	if destPathname := flag.Arg(1); destPathname == "-" {
		stat, err := os.Stdout.Stat()
		if err != nil {
			bail(err)
		}
		// if *verbose { // DEBUG
		// 	fmt.Fprintf(os.Stderr, "standard output mode: %v\n", stat.Mode())
		// }
		if (stat.Mode() & os.ModeCharDevice) != 0 {
			usage(errors.New("cannot send to standard output when connected to terminal"))
		}
		toF = os.Stdout
		if *summary {
			fmt.Fprintf(os.Stderr, "writing to stdout\n")
		}
	} else {
		toF, err = os.Create(destPathname)
		if err != nil {
			bail(err)
		}
		defer func(ioc io.Closer) {
			if err := ioc.Close(); err != nil {
				bail(err)
			}
		}(toF)
		if *summary {
			fmt.Fprintf(os.Stderr, "writing to %s\n", flag.Arg(1))
		}
	}

	// NOTE: Convert fromF to OCFReader
	ocfr, err := goavro.NewOCFReader(fromF)
	if err != nil {
		bail(err)
	}

	inputCompressionName := ocfr.CompressionName()
	outputCompressionName := inputCompressionName
	if *compressionName != "" {
		outputCompressionName = *compressionName
	}

	if *summary {
		fmt.Fprintf(os.Stderr, "input compression algorithm: %s\n", inputCompressionName)
		fmt.Fprintf(os.Stderr, "output compression algorithm: %s\n", outputCompressionName)
	}

	// NOTE: Either use schema from reader, or attempt to use new schema
	var outputSchema string
	if *schemaPathname == "" {
		outputSchema = ocfr.Codec().Schema()
	} else {
		schemaBytes, err := ioutil.ReadFile(*schemaPathname)
		if err != nil {
			bail(err)
		}
		outputSchema = string(schemaBytes)
	}

	// NOTE: Convert toF to OCFWriter
	ocfw, err := goavro.NewOCFWriter(goavro.OCFConfig{
		W:               toF,
		CompressionName: outputCompressionName,
		Schema:          outputSchema,
	})
	if err != nil {
		bail(err)
	}

	if err := transcode(ocfr, ocfw); err != nil {
		bail(err)
	}
}

func transcode(from *goavro.OCFReader, to *goavro.OCFWriter) error {
	var blocksRead, blocksWritten, itemsRead int

	var block []interface{}
	if *blockCount > 0 {
		block = make([]interface{}, 0, *blockCount)
	}

	for from.Scan() {
		datum, err := from.Read()
		if err != nil {
			break
		}

		itemsRead++
		block = append(block, datum)

		endOfBlock := from.RemainingBlockItems() == 0
		if endOfBlock {
			blocksRead++
			if *verbose {
				fmt.Fprintf(os.Stderr, "read block with %d items\n", len(block))
			}
		}

		// NOTE: When blockCount is 0, user wants each destination block to have
		// the same number of items as its corresponding source block. However,
		// when blockCount is greater than 0, user wants specified block count
		// sizes.
		if (*blockCount == 0 && endOfBlock) || (*blockCount > 0 && len(block) == *blockCount) {
			if err := writeBlock(to, block); err != nil {
				return err
			}
			blocksWritten++
			block = block[:0] // set slice length to 0 in order to re-use allocated underlying array
		}
	}

	var err error

	// append all remaining items (condition can only be true used when *blockCount > 0)
	if len(block) > 0 {
		if err = writeBlock(to, block); err == nil {
			blocksWritten++
		}
	}

	// if no write error, then return any read error encountered
	if err == nil {
		err = from.Err()
	}

	if *summary {
		fmt.Fprintf(os.Stderr, "read %d items\n", itemsRead)
		fmt.Fprintf(os.Stderr, "wrote %d blocks\n", blocksWritten)
	}

	return err
}

func writeBlock(to *goavro.OCFWriter, block []interface{}) error {
	if *verbose {
		fmt.Fprintf(os.Stderr, "writing block with %d items\n", len(block))
	}
	return to.Append(block)
}
<|endoftext|>