<commit_before>// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	strfmt "github.com/go-openapi/strfmt"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// MaterialConfiguration material configuration
// swagger:model MaterialConfiguration
type MaterialConfiguration struct {

	// absorptivity maximum
	AbsorptivityMaximum float64 `json:"absorptivityMaximum,omitempty"`

	// absorptivity minimum
	AbsorptivityMinimum float64 `json:"absorptivityMinimum,omitempty"`

	// absorptivity powder coeff a
	AbsorptivityPowderCoeffA float64 `json:"absorptivityPowderCoeffA,omitempty"`

	// absorptivity powder coeff b
	AbsorptivityPowderCoeffB float64 `json:"absorptivityPowderCoeffB,omitempty"`

	// absorptivity solid coeff a
	AbsorptivitySolidCoeffA float64 `json:"absorptivitySolidCoeffA,omitempty"`

	// absorptivity solid coeff b
	AbsorptivitySolidCoeffB float64 `json:"absorptivitySolidCoeffB,omitempty"`

	// anisotropic strain coefficient parallel
	// Required: true
	AnisotropicStrainCoefficientParallel *float64 `json:"anisotropicStrainCoefficientParallel"`

	// anisotropic strain coefficient perpendicular
	// Required: true
	AnisotropicStrainCoefficientPerpendicular *float64 `json:"anisotropicStrainCoefficientPerpendicular"`

	// anisotropic strain coefficient z
	// Required: true
	AnisotropicStrainCoefficientZ *float64 `json:"anisotropicStrainCoefficientZ"`

	// created time stamp, set server-side, read only field
	// Required: true
	Created *strfmt.DateTime `json:"created"`

	// creating user, set server-side, read only field
	// Required: true
	CreatedBy *string `json:"createdBy"`

	// elastic modulus
	// Required: true
	ElasticModulus *float64 `json:"elasticModulus"`

	// elastic modulus of base
	// Required: true
	ElasticModulusOfBase *float64 `json:"elasticModulusOfBase"`

	// hardening factor
	// Required: true
	HardeningFactor *float64 `json:"hardeningFactor"`

	// material configuration identifier
	ID int32 `json:"id,omitempty"`

	// liquidus temperature
	// Required: true
	LiquidusTemperature *float64 `json:"liquidusTemperature"`

	// Location where the lookup file is stored.  Set server side.  Only used internally.
	LookupFileLocation string `json:"lookupFileLocation,omitempty"`

	// material identifier for this material configuration
	// Required: true
	MaterialID *int32 `json:"materialId"`

	// material yield strength
	// Required: true
	MaterialYieldStrength *float64 `json:"materialYieldStrength"`

	// nucleation constant bulk
	// Required: true
	NucleationConstantBulk *float64 `json:"nucleationConstantBulk"`

	// nucleation constant interface
	// Required: true
	NucleationConstantInterface *float64 `json:"nucleationConstantInterface"`

	// penetration depth maximum
	PenetrationDepthMaximum float64 `json:"penetrationDepthMaximum,omitempty"`

	// penetration depth minimum
	PenetrationDepthMinimum float64 `json:"penetrationDepthMinimum,omitempty"`

	// penetration depth powder coeff a
	PenetrationDepthPowderCoeffA float64 `json:"penetrationDepthPowderCoeffA,omitempty"`

	// penetration depth powder coeff b
	PenetrationDepthPowderCoeffB float64 `json:"penetrationDepthPowderCoeffB,omitempty"`

	// penetration depth solid coeff a
	PenetrationDepthSolidCoeffA float64 `json:"penetrationDepthSolidCoeffA,omitempty"`

	// penetration depth solid coeff b
	PenetrationDepthSolidCoeffB float64 `json:"penetrationDepthSolidCoeffB,omitempty"`

	// poisson ratio
	// Required: true
	PoissonRatio *float64 `json:"poissonRatio"`

	// powder packing density
	PowderPackingDensity float64 `json:"powderPackingDensity,omitempty"`

	// purging gas convection coefficient
	// Required: true
	PurgingGasConvectionCoefficient *float64 `json:"purgingGasConvectionCoefficient"`

	// solid density at room temperature
	// Required: true
	SolidDensityAtRoomTemperature *float64 `json:"solidDensityAtRoomTemperature"`

	// solid specific heat at room temperature
	// Required: true
	SolidSpecificHeatAtRoomTemperature *float64 `json:"solidSpecificHeatAtRoomTemperature"`

	// solid thermal conductivity at room temperature
	// Required: true
	SolidThermalConductivityAtRoomTemperature *float64 `json:"solidThermalConductivityAtRoomTemperature"`

	// solidus temperature
	// Required: true
	SolidusTemperature *float64 `json:"solidusTemperature"`

	// support yield strength ratio
	// Required: true
	SupportYieldStrengthRatio *float64 `json:"supportYieldStrengthRatio"`

	// thermal expansion coefficient
	// Required: true
	ThermalExpansionCoefficient *float64 `json:"thermalExpansionCoefficient"`

	// vaporization temperature
	// Required: true
	VaporizationTemperature *float64 `json:"vaporizationTemperature"`

	// Location where tuning method lookup file is stored. Set server side. Only used internally.
	W0LookupFileLocation string `json:"w0LookupFileLocation,omitempty"`
}

// Validate validates this material configuration
func (m *MaterialConfiguration) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateAnisotropicStrainCoefficientParallel(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateAnisotropicStrainCoefficientPerpendicular(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateAnisotropicStrainCoefficientZ(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreated(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreatedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateElasticModulus(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateElasticModulusOfBase(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateHardeningFactor(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLiquidusTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateMaterialID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateMaterialYieldStrength(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateNucleationConstantBulk(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateNucleationConstantInterface(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validatePoissonRatio(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validatePurgingGasConvectionCoefficient(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidDensityAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidSpecificHeatAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidThermalConductivityAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidusTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSupportYieldStrengthRatio(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateThermalExpansionCoefficient(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateVaporizationTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientParallel(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientParallel", "body", m.AnisotropicStrainCoefficientParallel); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientPerpendicular(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientPerpendicular", "body", m.AnisotropicStrainCoefficientPerpendicular); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientZ(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientZ", "body", m.AnisotropicStrainCoefficientZ); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateCreated(formats strfmt.Registry) error {

	if err := validate.Required("created", "body", m.Created); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateCreatedBy(formats strfmt.Registry) error {

	if err := validate.Required("createdBy", "body", m.CreatedBy); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateElasticModulus(formats strfmt.Registry) error {

	if err := validate.Required("elasticModulus", "body", m.ElasticModulus); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateElasticModulusOfBase(formats strfmt.Registry) error {

	if err := validate.Required("elasticModulusOfBase", "body", m.ElasticModulusOfBase); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateHardeningFactor(formats strfmt.Registry) error {

	if err := validate.Required("hardeningFactor", "body", m.HardeningFactor); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateLiquidusTemperature(formats strfmt.Registry) error {

	if err := validate.Required("liquidusTemperature", "body", m.LiquidusTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateMaterialID(formats strfmt.Registry) error {

	if err := validate.Required("materialId", "body", m.MaterialID); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateMaterialYieldStrength(formats strfmt.Registry) error {

	if err := validate.Required("materialYieldStrength", "body", m.MaterialYieldStrength); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateNucleationConstantBulk(formats strfmt.Registry) error {

	if err := validate.Required("nucleationConstantBulk", "body", m.NucleationConstantBulk); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateNucleationConstantInterface(formats strfmt.Registry) error {

	if err := validate.Required("nucleationConstantInterface", "body", m.NucleationConstantInterface); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validatePoissonRatio(formats strfmt.Registry) error {

	if err := validate.Required("poissonRatio", "body", m.PoissonRatio); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validatePurgingGasConvectionCoefficient(formats strfmt.Registry) error {

	if err := validate.Required("purgingGasConvectionCoefficient", "body", m.PurgingGasConvectionCoefficient); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidDensityAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidDensityAtRoomTemperature", "body", m.SolidDensityAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidSpecificHeatAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidSpecificHeatAtRoomTemperature", "body", m.SolidSpecificHeatAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidThermalConductivityAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidThermalConductivityAtRoomTemperature", "body", m.SolidThermalConductivityAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidusTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidusTemperature", "body", m.SolidusTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSupportYieldStrengthRatio(formats strfmt.Registry) error {

	if err := validate.Required("supportYieldStrengthRatio", "body", m.SupportYieldStrengthRatio); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateThermalExpansionCoefficient(formats strfmt.Registry) error {

	if err := validate.Required("thermalExpansionCoefficient", "body", m.ThermalExpansionCoefficient); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateVaporizationTemperature(formats strfmt.Registry) error {

	if err := validate.Required("vaporizationTemperature", "body", m.VaporizationTemperature); err != nil {
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *MaterialConfiguration) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *MaterialConfiguration) UnmarshalBinary(b []byte) error {
	var res MaterialConfiguration
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
<commit_msg>Update to match simulation-api-specification 3.62.1<commit_after>// Code generated by go-swagger; DO NOT EDIT.

package models

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	strfmt "github.com/go-openapi/strfmt"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// MaterialConfiguration material configuration
// swagger:model MaterialConfiguration
type MaterialConfiguration struct {

	// absorptivity maximum
	AbsorptivityMaximum float64 `json:"absorptivityMaximum,omitempty"`

	// absorptivity minimum
	AbsorptivityMinimum float64 `json:"absorptivityMinimum,omitempty"`

	// absorptivity powder coeff a
	AbsorptivityPowderCoeffA float64 `json:"absorptivityPowderCoeffA,omitempty"`

	// absorptivity powder coeff b
	AbsorptivityPowderCoeffB float64 `json:"absorptivityPowderCoeffB,omitempty"`

	// absorptivity solid coeff a
	AbsorptivitySolidCoeffA float64 `json:"absorptivitySolidCoeffA,omitempty"`

	// absorptivity solid coeff b
	AbsorptivitySolidCoeffB float64 `json:"absorptivitySolidCoeffB,omitempty"`

	// anisotropic strain coefficient parallel
	// Required: true
	AnisotropicStrainCoefficientParallel *float64 `json:"anisotropicStrainCoefficientParallel"`

	// anisotropic strain coefficient perpendicular
	// Required: true
	AnisotropicStrainCoefficientPerpendicular *float64 `json:"anisotropicStrainCoefficientPerpendicular"`

	// anisotropic strain coefficient z
	// Required: true
	AnisotropicStrainCoefficientZ *float64 `json:"anisotropicStrainCoefficientZ"`

	// created time stamp, set server-side, read only field
	// Required: true
	Created *strfmt.DateTime `json:"created"`

	// creating user, set server-side, read only field
	// Required: true
	CreatedBy *string `json:"createdBy"`

	// elastic modulus
	// Required: true
	ElasticModulus *float64 `json:"elasticModulus"`

	// elastic modulus of base
	// Required: true
	ElasticModulusOfBase *float64 `json:"elasticModulusOfBase"`

	// hardening factor
	// Required: true
	HardeningFactor *float64 `json:"hardeningFactor"`

	// material configuration identifier
	ID int32 `json:"id,omitempty"`

	// liquidus temperature
	// Required: true
	LiquidusTemperature *float64 `json:"liquidusTemperature"`

	// Location where the lookup file is stored.  Set server side.  Only used internally.
	LookupFileLocation string `json:"lookupFileLocation,omitempty"`

	// material identifier for this material configuration
	// Required: true
	MaterialID *int32 `json:"materialId"`

	// material yield strength
	// Required: true
	MaterialYieldStrength *float64 `json:"materialYieldStrength"`

	// nucleation constant bulk
	// Required: true
	NucleationConstantBulk *float64 `json:"nucleationConstantBulk"`

	// nucleation constant interface
	// Required: true
	NucleationConstantInterface *float64 `json:"nucleationConstantInterface"`

	// penetration depth maximum
	PenetrationDepthMaximum float64 `json:"penetrationDepthMaximum,omitempty"`

	// penetration depth minimum
	PenetrationDepthMinimum float64 `json:"penetrationDepthMinimum,omitempty"`

	// penetration depth powder coeff a
	PenetrationDepthPowderCoeffA float64 `json:"penetrationDepthPowderCoeffA,omitempty"`

	// penetration depth powder coeff b
	PenetrationDepthPowderCoeffB float64 `json:"penetrationDepthPowderCoeffB,omitempty"`

	// penetration depth solid coeff a
	PenetrationDepthSolidCoeffA float64 `json:"penetrationDepthSolidCoeffA,omitempty"`

	// penetration depth solid coeff b
	PenetrationDepthSolidCoeffB float64 `json:"penetrationDepthSolidCoeffB,omitempty"`

	// poisson ratio
	// Required: true
	PoissonRatio *float64 `json:"poissonRatio"`

	// powder packing density
	PowderPackingDensity float64 `json:"powderPackingDensity,omitempty"`

	// purging gas convection coefficient
	// Required: true
	PurgingGasConvectionCoefficient *float64 `json:"purgingGasConvectionCoefficient"`

	// solid density at room temperature
	// Required: true
	SolidDensityAtRoomTemperature *float64 `json:"solidDensityAtRoomTemperature"`

	// solid specific heat at room temperature
	// Required: true
	SolidSpecificHeatAtRoomTemperature *float64 `json:"solidSpecificHeatAtRoomTemperature"`

	// solid thermal conductivity at room temperature
	// Required: true
	SolidThermalConductivityAtRoomTemperature *float64 `json:"solidThermalConductivityAtRoomTemperature"`

	// solidus temperature
	// Required: true
	SolidusTemperature *float64 `json:"solidusTemperature"`

	// strain scaling factor
	// Required: true
	StrainScalingFactor *float64 `json:"strainScalingFactor"`

	// support yield strength ratio
	// Required: true
	SupportYieldStrengthRatio *float64 `json:"supportYieldStrengthRatio"`

	// thermal expansion coefficient
	// Required: true
	ThermalExpansionCoefficient *float64 `json:"thermalExpansionCoefficient"`

	// vaporization temperature
	// Required: true
	VaporizationTemperature *float64 `json:"vaporizationTemperature"`

	// Location where tuning method lookup file is stored. Set server side. Only used internally.
	W0LookupFileLocation string `json:"w0LookupFileLocation,omitempty"`
}

// Validate validates this material configuration
func (m *MaterialConfiguration) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateAnisotropicStrainCoefficientParallel(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateAnisotropicStrainCoefficientPerpendicular(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateAnisotropicStrainCoefficientZ(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreated(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateCreatedBy(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateElasticModulus(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateElasticModulusOfBase(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateHardeningFactor(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateLiquidusTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateMaterialID(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateMaterialYieldStrength(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateNucleationConstantBulk(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateNucleationConstantInterface(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validatePoissonRatio(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validatePurgingGasConvectionCoefficient(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidDensityAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidSpecificHeatAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidThermalConductivityAtRoomTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSolidusTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateStrainScalingFactor(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSupportYieldStrengthRatio(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateThermalExpansionCoefficient(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateVaporizationTemperature(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientParallel(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientParallel", "body", m.AnisotropicStrainCoefficientParallel); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientPerpendicular(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientPerpendicular", "body", m.AnisotropicStrainCoefficientPerpendicular); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateAnisotropicStrainCoefficientZ(formats strfmt.Registry) error {

	if err := validate.Required("anisotropicStrainCoefficientZ", "body", m.AnisotropicStrainCoefficientZ); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateCreated(formats strfmt.Registry) error {

	if err := validate.Required("created", "body", m.Created); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateCreatedBy(formats strfmt.Registry) error {

	if err := validate.Required("createdBy", "body", m.CreatedBy); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateElasticModulus(formats strfmt.Registry) error {

	if err := validate.Required("elasticModulus", "body", m.ElasticModulus); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateElasticModulusOfBase(formats strfmt.Registry) error {

	if err := validate.Required("elasticModulusOfBase", "body", m.ElasticModulusOfBase); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateHardeningFactor(formats strfmt.Registry) error {

	if err := validate.Required("hardeningFactor", "body", m.HardeningFactor); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateLiquidusTemperature(formats strfmt.Registry) error {

	if err := validate.Required("liquidusTemperature", "body", m.LiquidusTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateMaterialID(formats strfmt.Registry) error {

	if err := validate.Required("materialId", "body", m.MaterialID); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateMaterialYieldStrength(formats strfmt.Registry) error {

	if err := validate.Required("materialYieldStrength", "body", m.MaterialYieldStrength); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateNucleationConstantBulk(formats strfmt.Registry) error {

	if err := validate.Required("nucleationConstantBulk", "body", m.NucleationConstantBulk); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateNucleationConstantInterface(formats strfmt.Registry) error {

	if err := validate.Required("nucleationConstantInterface", "body", m.NucleationConstantInterface); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validatePoissonRatio(formats strfmt.Registry) error {

	if err := validate.Required("poissonRatio", "body", m.PoissonRatio); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validatePurgingGasConvectionCoefficient(formats strfmt.Registry) error {

	if err := validate.Required("purgingGasConvectionCoefficient", "body", m.PurgingGasConvectionCoefficient); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidDensityAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidDensityAtRoomTemperature", "body", m.SolidDensityAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidSpecificHeatAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidSpecificHeatAtRoomTemperature", "body", m.SolidSpecificHeatAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidThermalConductivityAtRoomTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidThermalConductivityAtRoomTemperature", "body", m.SolidThermalConductivityAtRoomTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSolidusTemperature(formats strfmt.Registry) error {

	if err := validate.Required("solidusTemperature", "body", m.SolidusTemperature); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateStrainScalingFactor(formats strfmt.Registry) error {

	if err := validate.Required("strainScalingFactor", "body", m.StrainScalingFactor); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateSupportYieldStrengthRatio(formats strfmt.Registry) error {

	if err := validate.Required("supportYieldStrengthRatio", "body", m.SupportYieldStrengthRatio); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateThermalExpansionCoefficient(formats strfmt.Registry) error {

	if err := validate.Required("thermalExpansionCoefficient", "body", m.ThermalExpansionCoefficient); err != nil {
		return err
	}

	return nil
}

func (m *MaterialConfiguration) validateVaporizationTemperature(formats strfmt.Registry) error {

	if err := validate.Required("vaporizationTemperature", "body", m.VaporizationTemperature); err != nil {
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *MaterialConfiguration) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *MaterialConfiguration) UnmarshalBinary(b []byte) error {
	var res MaterialConfiguration
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
<|endoftext|>


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

package virtualips

import (
	"errors"
	"fmt"
	"path"
	"time"

	"github.com/control-center/serviced/coordinator/client"
	"github.com/control-center/serviced/domain/pool"
	"github.com/control-center/serviced/utils"
	"github.com/control-center/serviced/zzk"
	zkservice "github.com/control-center/serviced/zzk/service"
	"github.com/zenoss/glog"
)

const (
	zkVirtualIP            = "/virtualIPs"
	virtualInterfacePrefix = ":z"
	maxRetries             = 2
	waitTimeout            = 30 * time.Second
)

var (
	ErrInvalidVirtualIP = errors.New("invalid virtual ip")
)

func vippath(nodes ...string) string {
	p := append([]string{zkVirtualIP}, nodes...)
	return path.Join(p...)
}

type VirtualIPNode struct {
	*pool.VirtualIP
	version interface{}
}

// ID implements zzk.Node
func (node *VirtualIPNode) GetID() string {
	return node.IP
}

// Create implements zzk.Node
func (node *VirtualIPNode) Create(conn client.Connection) error {
	return AddVirtualIP(conn, node.VirtualIP)
}

// Update implements zzk.Node
func (node *VirtualIPNode) Update(conn client.Connection) error {
	return nil
}

func (node *VirtualIPNode) Version() interface{}           { return node.version }
func (node *VirtualIPNode) SetVersion(version interface{}) { node.version = version }

// VirtualIPHandler is the handler interface for virtual ip bindings on the host
type VirtualIPHandler interface {
	BindVirtualIP(*pool.VirtualIP, string) error
	UnbindVirtualIP(*pool.VirtualIP) error
	VirtualInterfaceMap(string) (map[string]*pool.VirtualIP, error)
}

// VirtualIPListener is the listener object for watching the zk object for
// virtual IP nodes
type VirtualIPListener struct {
	conn    client.Connection
	handler VirtualIPHandler
	hostID  string

	index chan uint
	ips   map[string]chan bool
	retry map[string]int
}

// NewVirtualIPListener instantiates a new VirtualIPListener object
func NewVirtualIPListener(handler VirtualIPHandler, hostID string) *VirtualIPListener {
	l := &VirtualIPListener{
		handler: handler,
		hostID:  hostID,
		index:   make(chan uint),
		ips:     make(map[string]chan bool),
	}

	// Index generator for bind interface
	// Clamp the index string length to 3 base 62 digits so that validation
	// methods can make sure the length of the VIP name doesn't exceed 15 chars.
	// Base 62 is used so that we can pack more indices into those 3 digits.
	go func(start uint) {
		for {
			l.index <- start
			start++
			if start > 238327 { // ZZZ in base 62
				start = 0
			}
		}
	}(0)

	return l
}

// GetConnection implements zzk.Listener
func (l *VirtualIPListener) SetConnection(conn client.Connection) { l.conn = conn }

// GetPath implements zzk.Listener
func (l *VirtualIPListener) GetPath(nodes ...string) string {
	return vippath(nodes...)
}

// Ready removes all virtual IPs that may be present
func (l *VirtualIPListener) Ready() error {
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return err
	}

	for _, vip := range vmap {
		if err := l.handler.UnbindVirtualIP(vip); err != nil {
			return err
		}
	}
	return nil
}

// Done implements zzk.Listener
func (l *VirtualIPListener) Done() {}

// PostProcess implements zzk.Listener
func (l *VirtualIPListener) PostProcess(p map[string]struct{}) {}

// Spawn implements zzk.Listener
func (l *VirtualIPListener) Spawn(shutdown <-chan interface{}, ip string) {
	// ensure that the retry sentinel has good initial state
	if l.retry == nil {
		l.retry = make(map[string]int)
	}
	if _, ok := l.retry[ip]; !ok {
		l.retry[ip] = maxRetries
	}

	// Check if this ip has exceeded the number of retries for this host
	if l.retry[ip] > maxRetries {
		glog.Warningf("Throttling acquisition of %s for %s", ip, l.hostID)
		select {
		case <-time.After(waitTimeout):
		case <-shutdown:
			return
		}
	}

	glog.V(2).Infof("Host %s waiting to acquire virtual ip %s", l.hostID, ip)
	// Try to take lead on the path
	leader, err := l.conn.NewLeader(l.GetPath(ip))
	if err != nil {
		glog.Errorf("Could not initialize leader node for ip %s: %s", ip, err)
		return
	}
	hlnode := zzk.HostLeader{
		HostID: l.hostID,
	}
	leaderDone := make(chan struct{})
	defer close(leaderDone)
	_, err = leader.TakeLead(&hlnode, leaderDone)
	if err != nil {
		glog.Errorf("Error while trying to acquire a lock for %s: %s", ip, err)
		return
	}
	defer l.stopInstances(ip)
	defer leader.ReleaseLead()

	select {
	case <-shutdown:
		return
	default:
	}

	// Check if the path still exists
	if exists, err := zzk.PathExists(l.conn, l.GetPath(ip)); err != nil {
		glog.Errorf("Error while checking ip %s: %s", ip, err)
		return
	} else if !exists {
		return
	}

	index := l.getIndex()
	done := make(chan struct{})
	defer func(channel *chan struct{}) { close(*channel) }(&done)
	for {
		var vip pool.VirtualIP
		event, err := l.conn.GetW(l.GetPath(ip), &VirtualIPNode{VirtualIP: &vip}, done)
		if err == client.ErrEmptyNode {
			glog.Errorf("Deleting empty node for ip %s", ip)
			RemoveVirtualIP(l.conn, ip)
			return
		} else if err != nil {
			glog.Errorf("Could not load virtual ip %s: %s", ip, err)
			return
		}

		glog.V(2).Infof("Host %s binding to %s", l.hostID, ip)
		rebind, err := l.bind(&vip, index)
		if err != nil {
			glog.Errorf("Could not bind to virtual ip %s: %s", ip, err)
			l.retry[ip]++
			return
		}

		if l.retry[ip] > 0 {
			l.retry[ip]--
		}

		select {
		case e := <-event:
			// If the virtual ip is changed, you need to update the bindings
			if err := l.unbind(ip); err != nil {
				glog.Errorf("Could not unbind to virtual ip %s: %s", ip, err)
				return
			}
			if e.Type == client.EventNodeDeleted {
				return
			}
			glog.V(4).Infof("virtual ip listener for %s received event: %v", ip, e)
		case <-rebind:
			// If the primary virtual IP is removed, all other virtual IPs on
			// that subnet are removed.  This is in place to restore the
			// virtual IPs that were removed soley by the removal of the
			// primary virtual IP.
			glog.V(2).Infof("Host %s rebinding to %s", l.hostID, ip)
		case <-shutdown:
			if err := l.unbind(ip); err != nil {
				glog.Errorf("Could not unbind to virtual ip %s: %s", ip, err)
			}
			return
		}

		close(done)
		done = make(chan struct{})
	}
}

func (l *VirtualIPListener) getIndex() uint {
	return <-l.index
}

func (l *VirtualIPListener) reset() {
	for _, ipChan := range l.ips {
		ipChan <- true
	}
}

func (l *VirtualIPListener) get(ip string) <-chan bool {
	l.ips[ip] = make(chan bool, 1)
	return l.ips[ip]
}

func (l *VirtualIPListener) bind(vip *pool.VirtualIP, index uint) (<-chan bool, error) {
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return nil, err
	}

	if _, ok := vmap[vip.IP]; !ok {
		if vip.BindInterface == "" {
			return nil, ErrInvalidVirtualIP
		}
		postfix := fmt.Sprintf("%03s", utils.Base62(index))
		vname := fmt.Sprintf("%s%s%s", vip.BindInterface, virtualInterfacePrefix, postfix)
		if err := l.handler.BindVirtualIP(vip, vname); err != nil {
			return nil, err
		}
	}

	return l.get(vip.IP), nil
}

func (l *VirtualIPListener) unbind(ip string) error {
	defer l.reset()
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return err
	}

	if vip, ok := vmap[ip]; ok {
		return l.handler.UnbindVirtualIP(vip)
	}

	return nil
}

func (l *VirtualIPListener) stopInstances(ip string) {
	glog.Infof("Stopping service instances using ip %s on host %s", ip, l.hostID)
	rss, err := zkservice.LoadRunningServicesByHost(l.conn, l.hostID)
	if err != nil {
		glog.Errorf("Could not load running instances on host %s: %s", l.hostID, err)
		return
	}
	for _, rs := range rss {
		if rs.IPAddress == ip {
			if err := zkservice.StopServiceInstance(l.conn, "", l.hostID, rs.ID); err != nil {
				glog.Warningf("Could not stop service instance %s on host %s: %s", rs.ID, l.hostID, err)
			}
		}
	}
}

func SyncVirtualIPs(conn client.Connection, virtualIPs []pool.VirtualIP) error {
	nodes := make([]zzk.Node, len(virtualIPs))
	for i := range virtualIPs {
		nodes[i] = &VirtualIPNode{VirtualIP: &virtualIPs[i]}
	}
	return zzk.Sync(conn, nodes, vippath())
}

func AddVirtualIP(conn client.Connection, virtualIP *pool.VirtualIP) error {
	var node VirtualIPNode
	path := vippath(virtualIP.IP)

	glog.V(1).Infof("Adding virtual ip to zookeeper: %s", path)
	if err := conn.Create(path, &node); err != nil {
		return err
	}
	node.VirtualIP = virtualIP
	return conn.Set(path, &node)
}

func RemoveVirtualIP(conn client.Connection, ip string) error {
	glog.V(1).Infof("Removing virtual ip from zookeeper: %s", vippath(ip))
	err := conn.Delete(vippath(ip))
	if err == nil || err == client.ErrNoNode {
		return nil
	}
	return err
}

func GetHostID(conn client.Connection, poolid, ip string) (string, error) {
	basepth := "/"
	if poolid != "" {
		basepth = path.Join("/pools", poolid)
	}
	leader, err := conn.NewLeader(path.Join(basepth, "/virtualIPs", ip))
	if err != nil {
		return "", err
	}
	return zzk.GetHostID(leader)
}
<commit_msg>virtual ips code to use zzk/service2 package<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package virtualips

import (
	"errors"
	"fmt"
	"path"
	"time"

	"github.com/control-center/serviced/coordinator/client"
	"github.com/control-center/serviced/domain/pool"
	"github.com/control-center/serviced/domain/service"
	"github.com/control-center/serviced/utils"
	"github.com/control-center/serviced/zzk"
	zkservice "github.com/control-center/serviced/zzk/service2"
	"github.com/zenoss/glog"
)

const (
	zkVirtualIP            = "/virtualIPs"
	virtualInterfacePrefix = ":z"
	maxRetries             = 2
	waitTimeout            = 30 * time.Second
)

var (
	ErrInvalidVirtualIP = errors.New("invalid virtual ip")
)

func vippath(nodes ...string) string {
	p := append([]string{zkVirtualIP}, nodes...)
	return path.Join(p...)
}

type VirtualIPNode struct {
	*pool.VirtualIP
	version interface{}
}

// ID implements zzk.Node
func (node *VirtualIPNode) GetID() string {
	return node.IP
}

// Create implements zzk.Node
func (node *VirtualIPNode) Create(conn client.Connection) error {
	return AddVirtualIP(conn, node.VirtualIP)
}

// Update implements zzk.Node
func (node *VirtualIPNode) Update(conn client.Connection) error {
	return nil
}

func (node *VirtualIPNode) Version() interface{}           { return node.version }
func (node *VirtualIPNode) SetVersion(version interface{}) { node.version = version }

// VirtualIPHandler is the handler interface for virtual ip bindings on the host
type VirtualIPHandler interface {
	BindVirtualIP(*pool.VirtualIP, string) error
	UnbindVirtualIP(*pool.VirtualIP) error
	VirtualInterfaceMap(string) (map[string]*pool.VirtualIP, error)
}

// VirtualIPListener is the listener object for watching the zk object for
// virtual IP nodes
type VirtualIPListener struct {
	conn    client.Connection
	handler VirtualIPHandler
	hostID  string

	index chan uint
	ips   map[string]chan bool
	retry map[string]int
}

// NewVirtualIPListener instantiates a new VirtualIPListener object
func NewVirtualIPListener(handler VirtualIPHandler, hostID string) *VirtualIPListener {
	l := &VirtualIPListener{
		handler: handler,
		hostID:  hostID,
		index:   make(chan uint),
		ips:     make(map[string]chan bool),
	}

	// Index generator for bind interface
	// Clamp the index string length to 3 base 62 digits so that validation
	// methods can make sure the length of the VIP name doesn't exceed 15 chars.
	// Base 62 is used so that we can pack more indices into those 3 digits.
	go func(start uint) {
		for {
			l.index <- start
			start++
			if start > 238327 { // ZZZ in base 62
				start = 0
			}
		}
	}(0)

	return l
}

// GetConnection implements zzk.Listener
func (l *VirtualIPListener) SetConnection(conn client.Connection) { l.conn = conn }

// GetPath implements zzk.Listener
func (l *VirtualIPListener) GetPath(nodes ...string) string {
	return vippath(nodes...)
}

// Ready removes all virtual IPs that may be present
func (l *VirtualIPListener) Ready() error {
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return err
	}

	for _, vip := range vmap {
		if err := l.handler.UnbindVirtualIP(vip); err != nil {
			return err
		}
	}
	return nil
}

// Done implements zzk.Listener
func (l *VirtualIPListener) Done() {}

// PostProcess implements zzk.Listener
func (l *VirtualIPListener) PostProcess(p map[string]struct{}) {}

// Spawn implements zzk.Listener
func (l *VirtualIPListener) Spawn(shutdown <-chan interface{}, ip string) {
	// ensure that the retry sentinel has good initial state
	if l.retry == nil {
		l.retry = make(map[string]int)
	}
	if _, ok := l.retry[ip]; !ok {
		l.retry[ip] = maxRetries
	}

	// Check if this ip has exceeded the number of retries for this host
	if l.retry[ip] > maxRetries {
		glog.Warningf("Throttling acquisition of %s for %s", ip, l.hostID)
		select {
		case <-time.After(waitTimeout):
		case <-shutdown:
			return
		}
	}

	glog.V(2).Infof("Host %s waiting to acquire virtual ip %s", l.hostID, ip)
	// Try to take lead on the path
	leader, err := l.conn.NewLeader(l.GetPath(ip))
	if err != nil {
		glog.Errorf("Could not initialize leader node for ip %s: %s", ip, err)
		return
	}
	hlnode := zzk.HostLeader{
		HostID: l.hostID,
	}
	leaderDone := make(chan struct{})
	defer close(leaderDone)
	_, err = leader.TakeLead(&hlnode, leaderDone)
	if err != nil {
		glog.Errorf("Error while trying to acquire a lock for %s: %s", ip, err)
		return
	}
	defer l.stopInstances(ip)
	defer leader.ReleaseLead()

	select {
	case <-shutdown:
		return
	default:
	}

	// Check if the path still exists
	if exists, err := zzk.PathExists(l.conn, l.GetPath(ip)); err != nil {
		glog.Errorf("Error while checking ip %s: %s", ip, err)
		return
	} else if !exists {
		return
	}

	index := l.getIndex()
	done := make(chan struct{})
	defer func(channel *chan struct{}) { close(*channel) }(&done)
	for {
		var vip pool.VirtualIP
		event, err := l.conn.GetW(l.GetPath(ip), &VirtualIPNode{VirtualIP: &vip}, done)
		if err == client.ErrEmptyNode {
			glog.Errorf("Deleting empty node for ip %s", ip)
			RemoveVirtualIP(l.conn, ip)
			return
		} else if err != nil {
			glog.Errorf("Could not load virtual ip %s: %s", ip, err)
			return
		}

		glog.V(2).Infof("Host %s binding to %s", l.hostID, ip)
		rebind, err := l.bind(&vip, index)
		if err != nil {
			glog.Errorf("Could not bind to virtual ip %s: %s", ip, err)
			l.retry[ip]++
			return
		}

		if l.retry[ip] > 0 {
			l.retry[ip]--
		}

		select {
		case e := <-event:
			// If the virtual ip is changed, you need to update the bindings
			if err := l.unbind(ip); err != nil {
				glog.Errorf("Could not unbind to virtual ip %s: %s", ip, err)
				return
			}
			if e.Type == client.EventNodeDeleted {
				return
			}
			glog.V(4).Infof("virtual ip listener for %s received event: %v", ip, e)
		case <-rebind:
			// If the primary virtual IP is removed, all other virtual IPs on
			// that subnet are removed.  This is in place to restore the
			// virtual IPs that were removed soley by the removal of the
			// primary virtual IP.
			glog.V(2).Infof("Host %s rebinding to %s", l.hostID, ip)
		case <-shutdown:
			if err := l.unbind(ip); err != nil {
				glog.Errorf("Could not unbind to virtual ip %s: %s", ip, err)
			}
			return
		}

		close(done)
		done = make(chan struct{})
	}
}

func (l *VirtualIPListener) getIndex() uint {
	return <-l.index
}

func (l *VirtualIPListener) reset() {
	for _, ipChan := range l.ips {
		ipChan <- true
	}
}

func (l *VirtualIPListener) get(ip string) <-chan bool {
	l.ips[ip] = make(chan bool, 1)
	return l.ips[ip]
}

func (l *VirtualIPListener) bind(vip *pool.VirtualIP, index uint) (<-chan bool, error) {
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return nil, err
	}

	if _, ok := vmap[vip.IP]; !ok {
		if vip.BindInterface == "" {
			return nil, ErrInvalidVirtualIP
		}
		postfix := fmt.Sprintf("%03s", utils.Base62(index))
		vname := fmt.Sprintf("%s%s%s", vip.BindInterface, virtualInterfacePrefix, postfix)
		if err := l.handler.BindVirtualIP(vip, vname); err != nil {
			return nil, err
		}
	}

	return l.get(vip.IP), nil
}

func (l *VirtualIPListener) unbind(ip string) error {
	defer l.reset()
	vmap, err := l.handler.VirtualInterfaceMap(virtualInterfacePrefix)
	if err != nil {
		return err
	}

	if vip, ok := vmap[ip]; ok {
		return l.handler.UnbindVirtualIP(vip)
	}

	return nil
}

func (l *VirtualIPListener) stopInstances(ip string) {
	glog.Infof("Stopping service instances using ip %s on host %s", ip, l.hostID)

	// Clean any bad host states
	if err := zkservice.CleanHostStates(l.conn, "", l.hostID); err != nil {
		glog.Errorf("Could not clean up host states for host %s: %s", l.hostID, err)
		return
	}

	// Get all of the instances running on that host
	ch, err := l.conn.Children(path.Join("/hosts", l.hostID, "instances"))
	if err != nil && err != client.ErrNoNode {
		glog.Errorf("Could not look up host states for host %s: %s", l.hostID, err)
		return
	}

	// Stop all instances with the assigned ip
	for _, stateID := range ch {
		_, serviceID, instanceID, err := zkservice.ParseStateID(stateID)
		if err != nil {
			// This shouldn't happen, but handle it anyway
			glog.Warningf("Could not look up host state %s: %s", stateID, err)
			continue
		}

		req := zkservice.StateRequest{
			PoolID:     "",
			HostID:     l.hostID,
			ServiceID:  serviceID,
			InstanceID: instanceID,
		}
		if err := zkservice.UpdateState(l.conn, req, func(s *zkservice.State) bool {
			if s.DesiredState != service.SVCStop {
				for _, export := range s.Exports {
					if a := export.Assignment; a != nil && a.IPAddress == ip {
						s.DesiredState = service.SVCStop
						return true
					}
				}
			}
			return false
		}); err != nil {
			glog.Warningf("Could not stop service state %s on host %s: %s", stateID, l.hostID, err)
			continue
		}
	}
}

func SyncVirtualIPs(conn client.Connection, virtualIPs []pool.VirtualIP) error {
	nodes := make([]zzk.Node, len(virtualIPs))
	for i := range virtualIPs {
		nodes[i] = &VirtualIPNode{VirtualIP: &virtualIPs[i]}
	}
	return zzk.Sync(conn, nodes, vippath())
}

func AddVirtualIP(conn client.Connection, virtualIP *pool.VirtualIP) error {
	var node VirtualIPNode
	path := vippath(virtualIP.IP)

	glog.V(1).Infof("Adding virtual ip to zookeeper: %s", path)
	if err := conn.Create(path, &node); err != nil {
		return err
	}
	node.VirtualIP = virtualIP
	return conn.Set(path, &node)
}

func RemoveVirtualIP(conn client.Connection, ip string) error {
	glog.V(1).Infof("Removing virtual ip from zookeeper: %s", vippath(ip))
	err := conn.Delete(vippath(ip))
	if err == nil || err == client.ErrNoNode {
		return nil
	}
	return err
}

func GetHostID(conn client.Connection, poolid, ip string) (string, error) {
	basepth := "/"
	if poolid != "" {
		basepth = path.Join("/pools", poolid)
	}
	leader, err := conn.NewLeader(path.Join(basepth, "/virtualIPs", ip))
	if err != nil {
		return "", err
	}
	return zzk.GetHostID(leader)
}
<|endoftext|>


<commit_before>// Copyright 2014 JustAdam (adambell7@gmail.com).  All rights reserved.
// License: MIT

package main

import (
	"testing"
)

func TestFail(t *testing.T) {
	t.Fail()
}
<commit_msg>LogWriter Write test<commit_after>// Copyright 2014, 2015 JustAdam (adambell7@gmail.com).  All rights reserved.
// License: MIT

package main

import (
	"bytes"
	"testing"
)

func TestLogWriterWrite(t *testing.T) {
	token := "XX-XX"
	lw := &LogWriter{
		logline: make(chan []byte),
		token:   token,
	}

	testWrites := []struct {
		s, e []byte
	}{
		{[]byte("this is a test"), []byte(token + "this is a test")},
	}

	for _, v := range testWrites {
		go lw.Write(v.s)
		s := <-lw.logline
		if !bytes.Equal(s, v.e) {
			t.Errorf("Expecting %s, got %s", v.e, s)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package entrypoint

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"k8s.io/test-infra/prow/errorutil"

	"github.com/sirupsen/logrus"
)

const (
	// InternalErrorCode is what we write to the marker file to
	// indicate that we failed to start the wrapped command
	InternalErrorCode = "127"

	// DefaultTimeout is the default timeout for the test
	// process before SIGINT is sent
	DefaultTimeout = 120 * time.Minute

	// DefaultGracePeriod is the default timeout for the test
	// process after SIGINT is sent before SIGKILL is sent
	DefaultGracePeriod = 15 * time.Second
)

var (
	// errTimedOut is used as the command's error when the command
	// is terminated after the timeout is reached
	errTimedOut = errors.New("process timed out")
)

// Run creates the artifact directory then executes the process as configured,
// writing the output to the process log and the exit code to the marker file
// on exit.
func (o Options) Run() error {
	if o.ArtifactDir != "" {
		if err := os.MkdirAll(o.ArtifactDir, os.ModePerm); err != nil {
			return errorutil.NewAggregate(
				fmt.Errorf("could not create artifact directory(%s): %v", o.ArtifactDir, err),
				o.mark(InternalErrorCode),
			)
		}
	}
	processLogFile, err := os.Create(o.ProcessLog)
	if err != nil {
		return errorutil.NewAggregate(
			fmt.Errorf("could not create process logfile(%s): %v", o.ProcessLog, err),
			o.mark(InternalErrorCode),
		)
	}

	output := io.MultiWriter(os.Stdout, processLogFile)
	logrus.SetOutput(output)

	executable := o.Args[0]
	var arguments []string
	if len(o.Args) > 1 {
		arguments = o.Args[1:]
	}
	command := exec.Command(executable, arguments...)
	command.Stderr = output
	command.Stdout = output
	if err := command.Start(); err != nil {
		return errorutil.NewAggregate(
			fmt.Errorf("could not start the process: %v", err),
			o.mark(InternalErrorCode),
		)
	}

	// if we get asked to terminate we need to forward
	// that to the wrapped process as if it timed out
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	timeout := optionOrDefault(o.Timeout, DefaultTimeout)
	gracePeriod := optionOrDefault(o.GracePeriod, DefaultGracePeriod)
	var commandErr error
	cancelled := false
	done := make(chan error)
	go func() {
		done <- command.Wait()
	}()
	select {
	case err := <-done:
		commandErr = err
	case <-time.After(timeout):
		logrus.Errorf("Process did not finish before %s timeout", timeout)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	case s := <-interrupt:
		logrus.Errorf("Entrypoint received interrupt: %v", s)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	}
	// Close the process logfile before writing the marker file to avoid racing
	// with the sidecar container.
	processLogFile.Close()

	var returnCode string
	if cancelled {
		returnCode = InternalErrorCode
		commandErr = errTimedOut
	} else {
		if status, ok := command.ProcessState.Sys().(syscall.WaitStatus); ok {
			returnCode = strconv.Itoa(status.ExitStatus())
		} else if commandErr == nil {
			returnCode = "0"
		} else {
			returnCode = "1"
			commandErr = fmt.Errorf("wrapped process failed: %v", commandErr)
		}
	}
	return errorutil.NewAggregate(commandErr, o.mark(returnCode))
}

func (o *Options) mark(exitCode string) error {
	if err := ioutil.WriteFile(o.MarkerFile, []byte(exitCode), os.ModePerm); err != nil {
		return fmt.Errorf("could not write to marker file(%s): %v", o.MarkerFile, err)
	}
	return nil
}

// optionOrDefault defaults to a value if option
// is the zero value
func optionOrDefault(option, defaultValue time.Duration) time.Duration {
	if option == 0 {
		return defaultValue
	}

	return option
}

func gracefullyTerminate(command *exec.Cmd, done <-chan error, gracePeriod time.Duration) {
	if err := command.Process.Signal(os.Interrupt); err != nil {
		logrus.WithError(err).Error("Could not interrupt process after timeout")
	}
	select {
	case <-done:
		logrus.Errorf("Process gracefully exited before %s grace period", gracePeriod)
		// but we ignore the output error as we will want errTimedOut
	case <-time.After(gracePeriod):
		logrus.Errorf("Process did not exit before %s grace period", gracePeriod)
		if err := command.Process.Kill(); err != nil {
			logrus.WithError(err).Error("Could not kill process after grace period")
		}
	}
}
<commit_msg>make podutils entrypoint less racy<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package entrypoint

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"k8s.io/test-infra/prow/errorutil"

	"github.com/sirupsen/logrus"
)

const (
	// InternalErrorCode is what we write to the marker file to
	// indicate that we failed to start the wrapped command
	InternalErrorCode = "127"

	// DefaultTimeout is the default timeout for the test
	// process before SIGINT is sent
	DefaultTimeout = 120 * time.Minute

	// DefaultGracePeriod is the default timeout for the test
	// process after SIGINT is sent before SIGKILL is sent
	DefaultGracePeriod = 15 * time.Second
)

var (
	// errTimedOut is used as the command's error when the command
	// is terminated after the timeout is reached
	errTimedOut = errors.New("process timed out")
)

// Run creates the artifact directory then executes the process as configured,
// writing the output to the process log and the exit code to the marker file
// on exit.
func (o Options) Run() error {
	if o.ArtifactDir != "" {
		if err := os.MkdirAll(o.ArtifactDir, os.ModePerm); err != nil {
			return errorutil.NewAggregate(
				fmt.Errorf("could not create artifact directory(%s): %v", o.ArtifactDir, err),
				o.mark(InternalErrorCode),
			)
		}
	}
	processLogFile, err := os.Create(o.ProcessLog)
	if err != nil {
		return errorutil.NewAggregate(
			fmt.Errorf("could not create process logfile(%s): %v", o.ProcessLog, err),
			o.mark(InternalErrorCode),
		)
	}

	output := io.MultiWriter(os.Stdout, processLogFile)
	logrus.SetOutput(output)

	executable := o.Args[0]
	var arguments []string
	if len(o.Args) > 1 {
		arguments = o.Args[1:]
	}
	command := exec.Command(executable, arguments...)
	command.Stderr = output
	command.Stdout = output
	if err := command.Start(); err != nil {
		return errorutil.NewAggregate(
			fmt.Errorf("could not start the process: %v", err),
			o.mark(InternalErrorCode),
		)
	}

	// if we get asked to terminate we need to forward
	// that to the wrapped process as if it timed out
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	timeout := optionOrDefault(o.Timeout, DefaultTimeout)
	gracePeriod := optionOrDefault(o.GracePeriod, DefaultGracePeriod)
	var commandErr error
	cancelled := false
	done := make(chan error)
	go func() {
		done <- command.Wait()
	}()
	select {
	case err := <-done:
		commandErr = err
	case <-time.After(timeout):
		logrus.Errorf("Process did not finish before %s timeout", timeout)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	case s := <-interrupt:
		logrus.Errorf("Entrypoint received interrupt: %v", s)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	}
	// Close the process logfile before writing the marker file to avoid racing
	// with the sidecar container.
	processLogFile.Close()

	var returnCode string
	if cancelled {
		returnCode = InternalErrorCode
		commandErr = errTimedOut
	} else {
		if status, ok := command.ProcessState.Sys().(syscall.WaitStatus); ok {
			returnCode = strconv.Itoa(status.ExitStatus())
		} else if commandErr == nil {
			returnCode = "0"
		} else {
			returnCode = "1"
			commandErr = fmt.Errorf("wrapped process failed: %v", commandErr)
		}
	}
	return errorutil.NewAggregate(commandErr, o.mark(returnCode))
}

func (o *Options) mark(exitCode string) error {
	// create temp file in the same directory as the desired marker file
	dir := filepath.Dir(o.MarkerFile)
	tempFile, err := ioutil.TempFile(dir, "temp-marker")
	if err != nil {
		return fmt.Errorf("could not create temp marker file in %s: %v", dir, err)
	}
	// write the exit code to the tempfile, sync to disk and close
	if _, err = tempFile.Write([]byte(exitCode)); err != nil {
		return fmt.Errorf("could not write to temp marker file (%s): %v", tempFile.Name(), err)
	}
	if err = tempFile.Sync(); err != nil {
		return fmt.Errorf("could not sync temp marker file (%s): %v", tempFile.Name(), err)
	}
	tempFile.Close()
	// set desired permission bits, then rename to the desired file name
	if err = os.Chmod(tempFile.Name(), os.ModePerm); err != nil {
		return fmt.Errorf("could not chmod (%x) temp marker file (%s): %v", os.ModePerm, tempFile.Name(), err)
	}
	if err := os.Rename(tempFile.Name(), o.MarkerFile); err != nil {
		return fmt.Errorf("could not move marker file to destination path (%s): %v", o.MarkerFile, err)
	}
	return nil
}

// optionOrDefault defaults to a value if option
// is the zero value
func optionOrDefault(option, defaultValue time.Duration) time.Duration {
	if option == 0 {
		return defaultValue
	}

	return option
}

func gracefullyTerminate(command *exec.Cmd, done <-chan error, gracePeriod time.Duration) {
	if err := command.Process.Signal(os.Interrupt); err != nil {
		logrus.WithError(err).Error("Could not interrupt process after timeout")
	}
	select {
	case <-done:
		logrus.Errorf("Process gracefully exited before %s grace period", gracePeriod)
		// but we ignore the output error as we will want errTimedOut
	case <-time.After(gracePeriod):
		logrus.Errorf("Process did not exit before %s grace period", gracePeriod)
		if err := command.Process.Kill(); err != nil {
			logrus.WithError(err).Error("Could not kill process after grace period")
		}
	}
}
<|endoftext|>


<commit_before>package tunnelproxy

import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"

	"koding/artifact"
	"koding/kites/common"
	"koding/kites/kloud/pkg/dnsclient"
	"koding/kites/kloud/utils"

	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/koding/ec2dynamicdata"
	"github.com/koding/kite"
	"github.com/koding/kite/config"
	"github.com/koding/logging"
	"github.com/koding/metrics"
	"github.com/koding/tunnel"
)

func publicIP() (string, error) {
	return ec2dynamicdata.GetMetadata(ec2dynamicdata.PublicIPv4)
}

type ServerOptions struct {
	// Server config.
	BaseVirtualHost string `json:"baseVirtualHost"`
	HostedZone      string `json:"hostedZone" required:"true"`
	AccessKey       string `json:"accessKey" required:"true"`
	SecretKey       string `json:"secretKey" required:"true"`

	// Server kite config.
	Port        int            `json:"port" required:"true"`
	Region      string         `json:"region" required:"true"`
	Environment string         `json:"environment" required:"true"`
	Config      *config.Config `json:"kiteConfig"`
	RegisterURL *url.URL       `json:"registerURL"`

	ServerAddr string `json:"serverAddr,omitempty"` // public IP
	Debug      bool   `json:"debug,omitempty"`
	Test       bool   `json:"test,omitempty"`

	Log     logging.Logger     `json:"-"`
	Metrics *metrics.DogStatsD `json:"-"`
}

// Server represents tunneling server that handles managing authorization
// of the tunneling sessions for the clients.
type Server struct {
	Server *tunnel.Server
	DNS    *dnsclient.Route53

	opts   *ServerOptions
	record *dnsclient.Record
}

// NewServer gives new tunneling server for the given options.
func NewServer(opts *ServerOptions) (*Server, error) {
	optsCopy := *opts

	if optsCopy.ServerAddr == "" {
		ip, err := publicIP()
		if err != nil {
			return nil, err
		}
		optsCopy.ServerAddr = ip
	}

	if optsCopy.Log == nil {
		optsCopy.Log = common.NewLogger("tunnelserver", optsCopy.Debug)
	}

	tunnelCfg := &tunnel.ServerConfig{
		Debug: optsCopy.Debug,
		Log:   optsCopy.Log,
	}
	server, err := tunnel.NewServer(tunnelCfg)
	if err != nil {
		return nil, err
	}

	dnsOpts := &dnsclient.Options{
		Creds:      credentials.NewStaticCredentials(optsCopy.AccessKey, optsCopy.SecretKey, ""),
		HostedZone: optsCopy.HostedZone,
		Log:        optsCopy.Log,
		Debug:      optsCopy.Debug,
	}
	dns, err := dnsclient.NewRoute53Client(dnsOpts)
	if err != nil {
		return nil, err
	}

	if optsCopy.BaseVirtualHost == "" {
		optsCopy.BaseVirtualHost = optsCopy.HostedZone
	}

	optsCopy.Log.Debug("Server options: %# v", &optsCopy)

	s := &Server{
		Server: server,
		DNS:    dns,
		opts:   &optsCopy,
		record: dnsclient.ParseRecord("", optsCopy.ServerAddr),
	}

	// perform the initial healthcheck during startup
	if err := s.checkDNS(); err != nil {
		s.opts.Log.Critical("%s", err)
	}

	return s, nil
}

// RegisterRequest represents request value for register method.
type RegisterRequest struct {
	// VirtualHost is a URL host requested by a client under which
	// new tunnel should be registered. The URL must be rooted
	// at <username>.<basehost> otherwise request will
	// be rejected.
	VirtualHost string `json:"virtualHost,omitempty"`
}

// RegisterResult represents response value for register method.
type RegisterResult struct {
	VirtualHost string `json:"virtualHost"`
	Secret      string `json:"identifier"`
	Domain      string `json:"domain"`
}

func (s *Server) checkDNS() error {
	domain := s.opts.BaseVirtualHost
	if host, _, err := net.SplitHostPort(domain); err == nil {
		domain = host
	}

	// check Route53 is setup correctly
	r, err := s.DNS.GetAll(domain)
	if err != nil {
		return fmt.Errorf("unable to list records for %q: %s", domain, err)
	}

	records := dnsclient.Records(r)

	serverFilter := &dnsclient.Record{
		Name: domain + ".",
	}

	rec := records.Filter(serverFilter)
	if len(rec) == 0 {
		return fmt.Errorf("no records found for %+v", serverFilter)
	}

	// Check if the tunnelserver has a wildcard domain. E.g. if base host for
	// the tunnelserver is devtunnel.koding.com, then we expect a CNAME
	// \052.devntunnel.koding.com is set to devtunnel.koding.com.
	clientsFilter := &dnsclient.Record{
		Name: "\\052." + domain + ".",
		Type: "CNAME",
	}

	rec = records.Filter(clientsFilter)
	if len(rec) == 0 {
		return fmt.Errorf("no records found for %+v", clientsFilter)
	}

	return nil
}

func (s *Server) HealthCheck(name string) http.HandlerFunc {
	return func(w http.ResponseWriter, _ *http.Request) {
		if err := s.checkDNS(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain")
		fmt.Fprintf(w, "%s is running with version: %s", name, artifact.VERSION)
	}
}

func (s *Server) virtualHost(user, virtualHost string) (string, error) {
	vhost := user + "." + s.opts.BaseVirtualHost

	if virtualHost != "" {
		if !strings.HasSuffix(virtualHost, vhost) {
			return "", fmt.Errorf("virtual host %q must be rooted at %q for user %s", virtualHost, vhost, user)
		}

		vhost = virtualHost
	}

	return vhost, nil
}

func (s *Server) domain(vhost string) string {
	if host, _, err := net.SplitHostPort(vhost); err == nil {
		return host
	}
	return vhost
}

// Register creates a virtual host and DNS record for the user.
func (s *Server) Register(r *kite.Request) (interface{}, error) {
	var req RegisterRequest

	if r.Args != nil {
		err := r.Args.One().Unmarshal(&req)
		if err != nil {
			return nil, errors.New("invalid request: " + err.Error())
		}
	}

	vhost, err := s.virtualHost(r.Username, req.VirtualHost)
	if err != nil {
		return nil, err
	}

	res := &RegisterResult{
		VirtualHost: vhost,
		Domain:      s.domain(vhost),
		Secret:      utils.RandString(32),
	}

	s.opts.Log.Debug("adding vhost=%s with secret=%s", res.VirtualHost, res.Secret)

	s.Server.AddHost(res.VirtualHost, res.Secret)

	s.Server.OnDisconnect(res.Secret, func() error {
		s.opts.Log.Debug("deleting vhost=%s and domain=%s", res.VirtualHost, res.Domain)
		s.Server.DeleteHost(res.VirtualHost)
		return nil
	})

	return res, nil
}

func (s *Server) metricsFunc() kite.HandlerFunc {
	if s.opts.Metrics == nil {
		return nil
	}
	m := s.opts.Metrics
	log := s.opts.Log
	return func(r *kite.Request) (interface{}, error) {
		// Send the metrics concurrently and don't block method handler.
		go func() {
			err := m.Count("callCount", 1, []string{"funcName:" + r.Method}, 1.0)
			if err != nil {
				log.Warning("failed to send metrics for method=%s, user=%s: %s", r.Method, r.Username, err)
			}
		}()
		return true, nil
	}
}

// NewServerKite creates a server kite for the given server.
func NewServerKite(s *Server, name, version string) (*kite.Kite, error) {
	k := kite.New(name, version)

	if s.opts.Config == nil {
		cfg, err := config.Get()
		if err != nil {
			return nil, err
		}
		s.opts.Config = cfg
	}

	if s.opts.Port != 0 {
		s.opts.Config.Port = s.opts.Port
	}
	if s.opts.Region != "" {
		s.opts.Config.Region = s.opts.Region
	}
	if s.opts.Environment != "" {
		s.opts.Config.Environment = s.opts.Environment
	}
	if s.opts.Test {
		s.opts.Config.DisableAuthentication = true
	}
	if s.opts.Debug {
		k.SetLogLevel(kite.DEBUG)
	}

	k.Log = s.opts.Log
	k.Config = s.opts.Config

	if fn := s.metricsFunc(); fn != nil {
		k.PreHandleFunc(fn)
	}

	k.HandleFunc("register", s.Register)
	k.HandleHTTPFunc("/healthCheck", s.HealthCheck(name))
	k.HandleHTTPFunc("/version", artifact.VersionHandler())
	k.HandleHTTP("/{rest:.*}", forward("/klient", s.Server))

	if s.opts.RegisterURL == nil {
		s.opts.RegisterURL = k.RegisterURL(false)
	}

	if err := k.RegisterForever(s.opts.RegisterURL); err != nil {
		return nil, err
	}

	return k, nil
}

func forward(path string, handler http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		r.URL.Path = strings.TrimPrefix(r.URL.Path, path)
		handler.ServeHTTP(w, r)
	}
}
<commit_msg>TMS-2203 tunnelserver: don't register to kontrol<commit_after>package tunnelproxy

import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"

	"koding/artifact"
	"koding/kites/common"
	"koding/kites/kloud/pkg/dnsclient"
	"koding/kites/kloud/utils"

	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/koding/ec2dynamicdata"
	"github.com/koding/kite"
	"github.com/koding/kite/config"
	"github.com/koding/logging"
	"github.com/koding/metrics"
	"github.com/koding/tunnel"
)

func publicIP() (string, error) {
	return ec2dynamicdata.GetMetadata(ec2dynamicdata.PublicIPv4)
}

type ServerOptions struct {
	// Server config.
	BaseVirtualHost string `json:"baseVirtualHost"`
	HostedZone      string `json:"hostedZone" required:"true"`
	AccessKey       string `json:"accessKey" required:"true"`
	SecretKey       string `json:"secretKey" required:"true"`

	// Server kite config.
	Port        int            `json:"port" required:"true"`
	Region      string         `json:"region" required:"true"`
	Environment string         `json:"environment" required:"true"`
	Config      *config.Config `json:"kiteConfig"`
	RegisterURL *url.URL       `json:"registerURL"`

	ServerAddr string `json:"serverAddr,omitempty"` // public IP
	Debug      bool   `json:"debug,omitempty"`
	Test       bool   `json:"test,omitempty"`

	Log     logging.Logger     `json:"-"`
	Metrics *metrics.DogStatsD `json:"-"`
}

// Server represents tunneling server that handles managing authorization
// of the tunneling sessions for the clients.
type Server struct {
	Server *tunnel.Server
	DNS    *dnsclient.Route53

	opts   *ServerOptions
	record *dnsclient.Record
}

// NewServer gives new tunneling server for the given options.
func NewServer(opts *ServerOptions) (*Server, error) {
	optsCopy := *opts

	if optsCopy.ServerAddr == "" {
		ip, err := publicIP()
		if err != nil {
			return nil, err
		}
		optsCopy.ServerAddr = ip
	}

	if optsCopy.Log == nil {
		optsCopy.Log = common.NewLogger("tunnelserver", optsCopy.Debug)
	}

	tunnelCfg := &tunnel.ServerConfig{
		Debug: optsCopy.Debug,
		Log:   optsCopy.Log,
	}
	server, err := tunnel.NewServer(tunnelCfg)
	if err != nil {
		return nil, err
	}

	dnsOpts := &dnsclient.Options{
		Creds:      credentials.NewStaticCredentials(optsCopy.AccessKey, optsCopy.SecretKey, ""),
		HostedZone: optsCopy.HostedZone,
		Log:        optsCopy.Log,
		Debug:      optsCopy.Debug,
	}
	dns, err := dnsclient.NewRoute53Client(dnsOpts)
	if err != nil {
		return nil, err
	}

	if optsCopy.BaseVirtualHost == "" {
		optsCopy.BaseVirtualHost = optsCopy.HostedZone
	}

	optsCopy.Log.Debug("Server options: %# v", &optsCopy)

	s := &Server{
		Server: server,
		DNS:    dns,
		opts:   &optsCopy,
		record: dnsclient.ParseRecord("", optsCopy.ServerAddr),
	}

	// perform the initial healthcheck during startup
	if err := s.checkDNS(); err != nil {
		s.opts.Log.Critical("%s", err)
	}

	return s, nil
}

// RegisterRequest represents request value for register method.
type RegisterRequest struct {
	// VirtualHost is a URL host requested by a client under which
	// new tunnel should be registered. The URL must be rooted
	// at <username>.<basehost> otherwise request will
	// be rejected.
	VirtualHost string `json:"virtualHost,omitempty"`
}

// RegisterResult represents response value for register method.
type RegisterResult struct {
	VirtualHost string `json:"virtualHost"`
	Secret      string `json:"identifier"`
	Domain      string `json:"domain"`
}

func (s *Server) checkDNS() error {
	domain := s.opts.BaseVirtualHost
	if host, _, err := net.SplitHostPort(domain); err == nil {
		domain = host
	}

	// check Route53 is setup correctly
	r, err := s.DNS.GetAll(domain)
	if err != nil {
		return fmt.Errorf("unable to list records for %q: %s", domain, err)
	}

	records := dnsclient.Records(r)

	serverFilter := &dnsclient.Record{
		Name: domain + ".",
	}

	rec := records.Filter(serverFilter)
	if len(rec) == 0 {
		return fmt.Errorf("no records found for %+v", serverFilter)
	}

	// Check if the tunnelserver has a wildcard domain. E.g. if base host for
	// the tunnelserver is devtunnel.koding.com, then we expect a CNAME
	// \052.devntunnel.koding.com is set to devtunnel.koding.com.
	clientsFilter := &dnsclient.Record{
		Name: "\\052." + domain + ".",
		Type: "CNAME",
	}

	rec = records.Filter(clientsFilter)
	if len(rec) == 0 {
		return fmt.Errorf("no records found for %+v", clientsFilter)
	}

	return nil
}

func (s *Server) HealthCheck(name string) http.HandlerFunc {
	return func(w http.ResponseWriter, _ *http.Request) {
		if err := s.checkDNS(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain")
		fmt.Fprintf(w, "%s is running with version: %s", name, artifact.VERSION)
	}
}

func (s *Server) virtualHost(user, virtualHost string) (string, error) {
	vhost := user + "." + s.opts.BaseVirtualHost

	if virtualHost != "" {
		if !strings.HasSuffix(virtualHost, vhost) {
			return "", fmt.Errorf("virtual host %q must be rooted at %q for user %s", virtualHost, vhost, user)
		}

		vhost = virtualHost
	}

	return vhost, nil
}

func (s *Server) domain(vhost string) string {
	if host, _, err := net.SplitHostPort(vhost); err == nil {
		return host
	}
	return vhost
}

// Register creates a virtual host and DNS record for the user.
func (s *Server) Register(r *kite.Request) (interface{}, error) {
	var req RegisterRequest

	if r.Args != nil {
		err := r.Args.One().Unmarshal(&req)
		if err != nil {
			return nil, errors.New("invalid request: " + err.Error())
		}
	}

	vhost, err := s.virtualHost(r.Username, req.VirtualHost)
	if err != nil {
		return nil, err
	}

	res := &RegisterResult{
		VirtualHost: vhost,
		Domain:      s.domain(vhost),
		Secret:      utils.RandString(32),
	}

	s.opts.Log.Debug("adding vhost=%s with secret=%s", res.VirtualHost, res.Secret)

	s.Server.AddHost(res.VirtualHost, res.Secret)

	s.Server.OnDisconnect(res.Secret, func() error {
		s.opts.Log.Debug("deleting vhost=%s and domain=%s", res.VirtualHost, res.Domain)
		s.Server.DeleteHost(res.VirtualHost)
		return nil
	})

	return res, nil
}

func (s *Server) metricsFunc() kite.HandlerFunc {
	if s.opts.Metrics == nil {
		return nil
	}
	m := s.opts.Metrics
	log := s.opts.Log
	return func(r *kite.Request) (interface{}, error) {
		// Send the metrics concurrently and don't block method handler.
		go func() {
			err := m.Count("callCount", 1, []string{"funcName:" + r.Method}, 1.0)
			if err != nil {
				log.Warning("failed to send metrics for method=%s, user=%s: %s", r.Method, r.Username, err)
			}
		}()
		return true, nil
	}
}

// NewServerKite creates a server kite for the given server.
func NewServerKite(s *Server, name, version string) (*kite.Kite, error) {
	k := kite.New(name, version)

	if s.opts.Config == nil {
		cfg, err := config.Get()
		if err != nil {
			return nil, err
		}
		s.opts.Config = cfg
	}

	if s.opts.Port != 0 {
		s.opts.Config.Port = s.opts.Port
	}
	if s.opts.Region != "" {
		s.opts.Config.Region = s.opts.Region
	}
	if s.opts.Environment != "" {
		s.opts.Config.Environment = s.opts.Environment
	}
	if s.opts.Test {
		s.opts.Config.DisableAuthentication = true
	}
	if s.opts.Debug {
		k.SetLogLevel(kite.DEBUG)
	}

	k.Log = s.opts.Log
	k.Config = s.opts.Config

	if fn := s.metricsFunc(); fn != nil {
		k.PreHandleFunc(fn)
	}

	k.HandleFunc("register", s.Register)
	k.HandleHTTPFunc("/healthCheck", s.HealthCheck(name))
	k.HandleHTTPFunc("/version", artifact.VersionHandler())
	k.HandleHTTP("/{rest:.*}", forward("/klient", s.Server))

	if s.opts.RegisterURL == nil {
		s.opts.RegisterURL = k.RegisterURL(false)
	}

	return k, nil
}

func forward(path string, handler http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		r.URL.Path = strings.TrimPrefix(r.URL.Path, path)
		handler.ServeHTTP(w, r)
	}
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// type of the message
	Type string `json:"type"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c *ChannelMessage) TableName() string {
	return "channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) Update() error {
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	interactions, err := i.List("like")
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = interactions
	// check this from database
	interactionContainer.IsInteracted = true

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}
<commit_msg>Social: add slug field into channel message struct<commit_after>package models

import (
	"errors"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// Generated Slug for body
	Slug string `json:"slug" 			           sql:"NOT NULL;UNIQUE"`

	// type of the message
	Type string `json:"type"                        sql:"NOT NULL"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"               sql:"NOT NULL"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId" sql:"NOT NULL"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c *ChannelMessage) TableName() string {
	return "channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) Update() error {
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	var err error
	c, err = Slugify(c)
	if err != nil {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	interactions, err := i.List("like")
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = interactions
	// check this from database
	interactionContainer.IsInteracted = true

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"
)

func GetComputeInterconnectAttachmentCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/regions/{{region}}/interconnectAttachments/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeInterconnectAttachmentApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/InterconnectAttachment",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "InterconnectAttachment",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeInterconnectAttachmentApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	adminEnabledProp, err := expandComputeInterconnectAttachmentAdminEnabled(d.Get("admin_enabled"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("admin_enabled"); ok || !reflect.DeepEqual(v, adminEnabledProp) {
		obj["adminEnabled"] = adminEnabledProp
	}
	interconnectProp, err := expandComputeInterconnectAttachmentInterconnect(d.Get("interconnect"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("interconnect"); !isEmptyValue(reflect.ValueOf(interconnectProp)) && (ok || !reflect.DeepEqual(v, interconnectProp)) {
		obj["interconnect"] = interconnectProp
	}
	descriptionProp, err := expandComputeInterconnectAttachmentDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	bandwidthProp, err := expandComputeInterconnectAttachmentBandwidth(d.Get("bandwidth"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("bandwidth"); !isEmptyValue(reflect.ValueOf(bandwidthProp)) && (ok || !reflect.DeepEqual(v, bandwidthProp)) {
		obj["bandwidth"] = bandwidthProp
	}
	edgeAvailabilityDomainProp, err := expandComputeInterconnectAttachmentEdgeAvailabilityDomain(d.Get("edge_availability_domain"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("edge_availability_domain"); !isEmptyValue(reflect.ValueOf(edgeAvailabilityDomainProp)) && (ok || !reflect.DeepEqual(v, edgeAvailabilityDomainProp)) {
		obj["edgeAvailabilityDomain"] = edgeAvailabilityDomainProp
	}
	typeProp, err := expandComputeInterconnectAttachmentType(d.Get("type"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("type"); !isEmptyValue(reflect.ValueOf(typeProp)) && (ok || !reflect.DeepEqual(v, typeProp)) {
		obj["type"] = typeProp
	}
	routerProp, err := expandComputeInterconnectAttachmentRouter(d.Get("router"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("router"); !isEmptyValue(reflect.ValueOf(routerProp)) && (ok || !reflect.DeepEqual(v, routerProp)) {
		obj["router"] = routerProp
	}
	nameProp, err := expandComputeInterconnectAttachmentName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	candidateSubnetsProp, err := expandComputeInterconnectAttachmentCandidateSubnets(d.Get("candidate_subnets"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("candidate_subnets"); !isEmptyValue(reflect.ValueOf(candidateSubnetsProp)) && (ok || !reflect.DeepEqual(v, candidateSubnetsProp)) {
		obj["candidateSubnets"] = candidateSubnetsProp
	}
	vlanTag8021qProp, err := expandComputeInterconnectAttachmentVlanTag8021q(d.Get("vlan_tag8021q"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("vlan_tag8021q"); !isEmptyValue(reflect.ValueOf(vlanTag8021qProp)) && (ok || !reflect.DeepEqual(v, vlanTag8021qProp)) {
		obj["vlanTag8021q"] = vlanTag8021qProp
	}
	regionProp, err := expandComputeInterconnectAttachmentRegion(d.Get("region"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
		obj["region"] = regionProp
	}

	return obj, nil
}

func expandComputeInterconnectAttachmentAdminEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentInterconnect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentBandwidth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentEdgeAvailabilityDomain(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentRouter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseRegionalFieldValue("routers", v.(string), "project", "region", "zone", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for router: %s", err)
	}
	return f.RelativeLink(), nil
}

func expandComputeInterconnectAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentCandidateSubnets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentVlanTag8021q(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for region: %s", err)
	}
	return f.RelativeLink(), nil
}
<commit_msg>Add MTU to interconnect (#4496) (#642)<commit_after>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"
)

func GetComputeInterconnectAttachmentCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/regions/{{region}}/interconnectAttachments/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeInterconnectAttachmentApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/InterconnectAttachment",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "InterconnectAttachment",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeInterconnectAttachmentApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	adminEnabledProp, err := expandComputeInterconnectAttachmentAdminEnabled(d.Get("admin_enabled"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("admin_enabled"); ok || !reflect.DeepEqual(v, adminEnabledProp) {
		obj["adminEnabled"] = adminEnabledProp
	}
	interconnectProp, err := expandComputeInterconnectAttachmentInterconnect(d.Get("interconnect"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("interconnect"); !isEmptyValue(reflect.ValueOf(interconnectProp)) && (ok || !reflect.DeepEqual(v, interconnectProp)) {
		obj["interconnect"] = interconnectProp
	}
	descriptionProp, err := expandComputeInterconnectAttachmentDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	mtuProp, err := expandComputeInterconnectAttachmentMtu(d.Get("mtu"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("mtu"); !isEmptyValue(reflect.ValueOf(mtuProp)) && (ok || !reflect.DeepEqual(v, mtuProp)) {
		obj["mtu"] = mtuProp
	}
	bandwidthProp, err := expandComputeInterconnectAttachmentBandwidth(d.Get("bandwidth"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("bandwidth"); !isEmptyValue(reflect.ValueOf(bandwidthProp)) && (ok || !reflect.DeepEqual(v, bandwidthProp)) {
		obj["bandwidth"] = bandwidthProp
	}
	edgeAvailabilityDomainProp, err := expandComputeInterconnectAttachmentEdgeAvailabilityDomain(d.Get("edge_availability_domain"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("edge_availability_domain"); !isEmptyValue(reflect.ValueOf(edgeAvailabilityDomainProp)) && (ok || !reflect.DeepEqual(v, edgeAvailabilityDomainProp)) {
		obj["edgeAvailabilityDomain"] = edgeAvailabilityDomainProp
	}
	typeProp, err := expandComputeInterconnectAttachmentType(d.Get("type"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("type"); !isEmptyValue(reflect.ValueOf(typeProp)) && (ok || !reflect.DeepEqual(v, typeProp)) {
		obj["type"] = typeProp
	}
	routerProp, err := expandComputeInterconnectAttachmentRouter(d.Get("router"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("router"); !isEmptyValue(reflect.ValueOf(routerProp)) && (ok || !reflect.DeepEqual(v, routerProp)) {
		obj["router"] = routerProp
	}
	nameProp, err := expandComputeInterconnectAttachmentName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	candidateSubnetsProp, err := expandComputeInterconnectAttachmentCandidateSubnets(d.Get("candidate_subnets"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("candidate_subnets"); !isEmptyValue(reflect.ValueOf(candidateSubnetsProp)) && (ok || !reflect.DeepEqual(v, candidateSubnetsProp)) {
		obj["candidateSubnets"] = candidateSubnetsProp
	}
	vlanTag8021qProp, err := expandComputeInterconnectAttachmentVlanTag8021q(d.Get("vlan_tag8021q"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("vlan_tag8021q"); !isEmptyValue(reflect.ValueOf(vlanTag8021qProp)) && (ok || !reflect.DeepEqual(v, vlanTag8021qProp)) {
		obj["vlanTag8021q"] = vlanTag8021qProp
	}
	regionProp, err := expandComputeInterconnectAttachmentRegion(d.Get("region"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
		obj["region"] = regionProp
	}

	return obj, nil
}

func expandComputeInterconnectAttachmentAdminEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentInterconnect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentMtu(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentBandwidth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentEdgeAvailabilityDomain(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentRouter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseRegionalFieldValue("routers", v.(string), "project", "region", "zone", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for router: %s", err)
	}
	return f.RelativeLink(), nil
}

func expandComputeInterconnectAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentCandidateSubnets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentVlanTag8021q(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeInterconnectAttachmentRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for region: %s", err)
	}
	return f.RelativeLink(), nil
}
<|endoftext|>