From 0d90451db22070eaabbe23818e5625148b1f0bf2 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Tue, 11 Dec 2018 17:55:14 +0000 Subject: [PATCH 01/14] Replaces Instance with Machine API type Signed-off-by: JoshVanL --- pkg/apis/wing/register.go | 4 +- pkg/apis/wing/types.go | 38 ++--- pkg/apis/wing/v1alpha1/constants.go | 8 +- pkg/apis/wing/v1alpha1/register.go | 4 +- pkg/apis/wing/v1alpha1/types.go | 44 ++--- .../wing/v1alpha1/zz_generated.conversion.go | 160 +++++++++--------- .../wing/v1alpha1/zz_generated.deepcopy.go | 66 ++++---- pkg/apis/wing/zz_generated.deepcopy.go | 66 ++++---- pkg/tarmak/cluster/configuration.go | 16 +- pkg/tarmak/cluster/wing.go | 70 ++++---- .../plugin/instanceinittime/admission.go | 71 -------- .../plugin/machineinittime/admission.go | 71 ++++++++ .../winginitializer/winginitializer.go | 2 +- .../winginitializer/winginitializer_test.go | 2 +- pkg/wing/apiserver/apiserver.go | 6 +- .../internalversion/fake/fake_instance.go | 123 -------------- .../wing/internalversion/fake/fake_machine.go | 123 ++++++++++++++ .../internalversion/fake/fake_wing_client.go | 4 +- .../internalversion/generated_expansion.go | 2 +- .../typed/wing/internalversion/instance.go | 157 ----------------- .../typed/wing/internalversion/machine.go | 157 +++++++++++++++++ .../typed/wing/internalversion/wing_client.go | 6 +- .../typed/wing/v1alpha1/fake/fake_instance.go | 123 -------------- .../typed/wing/v1alpha1/fake/fake_machine.go | 123 ++++++++++++++ .../wing/v1alpha1/fake/fake_wing_client.go | 4 +- .../wing/v1alpha1/generated_expansion.go | 2 +- .../versioned/typed/wing/v1alpha1/instance.go | 157 ----------------- .../versioned/typed/wing/v1alpha1/machine.go | 157 +++++++++++++++++ .../typed/wing/v1alpha1/wing_client.go | 6 +- .../informers/externalversions/factory.go | 4 +- .../informers/externalversions/generic.go | 4 +- .../wing/v1alpha1/interface.go | 10 +- .../wing/v1alpha1/{instance.go => machine.go} | 38 ++--- .../informers/internalversion/factory.go | 4 +- .../informers/internalversion/generic.go | 4 +- .../wing/internalversion/interface.go | 10 +- .../{instance.go => machine.go} | 38 ++--- .../internalversion/expansion_generated.go | 12 +- .../listers/wing/internalversion/instance.go | 80 --------- .../listers/wing/internalversion/machine.go | 80 +++++++++ .../wing/v1alpha1/expansion_generated.go | 12 +- .../client/listers/wing/v1alpha1/instance.go | 80 --------- .../client/listers/wing/v1alpha1/machine.go | 80 +++++++++ pkg/wing/controller.go | 40 ++--- pkg/wing/puppet.go | 38 ++--- pkg/wing/registry/wing/instance/strategy.go | 80 --------- .../wing/{instance => machine}/etcd.go | 10 +- pkg/wing/registry/wing/machine/strategy.go | 80 +++++++++ pkg/wing/server/server.go | 2 +- pkg/wing/wing.go | 6 +- 50 files changed, 1242 insertions(+), 1242 deletions(-) delete mode 100644 pkg/wing/admission/plugin/instanceinittime/admission.go create mode 100644 pkg/wing/admission/plugin/machineinittime/admission.go delete mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_instance.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machine.go delete mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/instance.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machine.go delete mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_instance.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machine.go delete mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/instance.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machine.go rename pkg/wing/client/informers/externalversions/wing/v1alpha1/{instance.go => machine.go} (51%) rename pkg/wing/client/informers/internalversion/wing/internalversion/{instance.go => machine.go} (51%) delete mode 100644 pkg/wing/client/listers/wing/internalversion/instance.go create mode 100644 pkg/wing/client/listers/wing/internalversion/machine.go delete mode 100644 pkg/wing/client/listers/wing/v1alpha1/instance.go create mode 100644 pkg/wing/client/listers/wing/v1alpha1/machine.go delete mode 100644 pkg/wing/registry/wing/instance/strategy.go rename pkg/wing/registry/wing/{instance => machine}/etcd.go (86%) create mode 100644 pkg/wing/registry/wing/machine/strategy.go diff --git a/pkg/apis/wing/register.go b/pkg/apis/wing/register.go index ea18a4b08c..cf063c5130 100644 --- a/pkg/apis/wing/register.go +++ b/pkg/apis/wing/register.go @@ -29,8 +29,8 @@ var ( // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &Instance{}, - &InstanceList{}, + &Machine{}, + &MachineList{}, ) return nil } diff --git a/pkg/apis/wing/types.go b/pkg/apis/wing/types.go index 4f2db40f55..224e98aa3b 100644 --- a/pkg/apis/wing/types.go +++ b/pkg/apis/wing/types.go @@ -8,40 +8,40 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type Instance struct { +type Machine struct { metav1.TypeMeta metav1.ObjectMeta - InstanceID string - InstancePool string + MachineID string + MachinePool string - Spec *InstanceSpec - Status *InstanceStatus + Spec *MachineSpec + Status *MachineStatus } -// InstanceSpec defines the desired state of Instance -type InstanceSpec struct { - Converge *InstanceSpecManifest - DryRun *InstanceSpecManifest +// MachineSpec defines the desired state of Machine +type MachineSpec struct { + Converge *MachineSpecManifest + DryRun *MachineSpecManifest } // InstaceSpecManifest defines location and hash for a specific manifest -type InstanceSpecManifest struct { +type MachineSpecManifest struct { Path string Hash string RequestTimestamp metav1.Time } -// InstanceStatus defines the observed state of Instance -type InstanceStatus struct { - Converge *InstanceStatusManifest - DryRun *InstanceStatusManifest +// MachineStatus defines the observed state of Machine +type MachineStatus struct { + Converge *MachineStatusManifest + DryRun *MachineStatusManifest } // InstaceSpecManifest defines the state and hash of a run manifest -type InstanceManifestState string -type InstanceStatusManifest struct { - State InstanceManifestState +type MachineManifestState string +type MachineStatusManifest struct { + State MachineManifestState Hash string LastUpdateTimestamp metav1.Time Messages []string @@ -50,10 +50,10 @@ type InstanceStatusManifest struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type InstanceList struct { +type MachineList struct { metav1.TypeMeta // +optional metav1.ListMeta - Items []Instance + Items []Machine } diff --git a/pkg/apis/wing/v1alpha1/constants.go b/pkg/apis/wing/v1alpha1/constants.go index 2692c97415..310b679f29 100644 --- a/pkg/apis/wing/v1alpha1/constants.go +++ b/pkg/apis/wing/v1alpha1/constants.go @@ -1,10 +1,10 @@ // Copyright Jetstack Ltd. See LICENSE for details. package v1alpha1 -type InstanceManifestState string +type MachineManifestState string const ( - InstanceManifestStateConverging = InstanceManifestState("converging") - InstanceManifestStateConverged = InstanceManifestState("converged") - InstanceManifestStateError = InstanceManifestState("error") + MachineManifestStateConverging = MachineManifestState("converging") + MachineManifestStateConverged = MachineManifestState("converged") + MachineManifestStateError = MachineManifestState("error") ) diff --git a/pkg/apis/wing/v1alpha1/register.go b/pkg/apis/wing/v1alpha1/register.go index 89e76a9336..64c6cbfd60 100644 --- a/pkg/apis/wing/v1alpha1/register.go +++ b/pkg/apis/wing/v1alpha1/register.go @@ -30,8 +30,8 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &Instance{}, - &InstanceList{}, + &Machine{}, + &MachineList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/apis/wing/v1alpha1/types.go b/pkg/apis/wing/v1alpha1/types.go index 94bab71419..9a8772b43d 100644 --- a/pkg/apis/wing/v1alpha1/types.go +++ b/pkg/apis/wing/v1alpha1/types.go @@ -8,50 +8,50 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type Instance struct { +type Machine struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - InstanceID string `json:"instanceID,omitempty"` - InstancePool string `json:"instancePool,omitempty"` + MachineID string `json:"machineID,omitempty"` + MachinePool string `json:"machinePool,omitempty"` - Spec *InstanceSpec `json:"spec,omitempty"` - Status *InstanceStatus `json:"status,omitempty"` + Spec *MachineSpec `json:"spec,omitempty"` + Status *MachineStatus `json:"status,omitempty"` } -// InstanceSpec defines the desired state of Instance -type InstanceSpec struct { - Converge *InstanceSpecManifest `json:"converge,omitempty"` - DryRun *InstanceSpecManifest `json:"dryRun,omitempty"` +// MachineSpec defines the desired state of Machine +type MachineSpec struct { + Converge *MachineSpecManifest `json:"converge,omitempty"` + DryRun *MachineSpecManifest `json:"dryRun,omitempty"` } // InstaceSpecManifest defines location and hash for a specific manifest -type InstanceSpecManifest struct { +type MachineSpecManifest struct { Path string `json:"path,omitempty"` // PATH to manifests (tar.gz) Hash string `json:"hash,omitempty"` // hash of manifests, prefixed with type (eg: sha256:xyz) RequestTimestamp metav1.Time `json:"requestTimestamp,omitempty"` // timestamp when a converge was requested } -// InstanceStatus defines the observed state of Instance -type InstanceStatus struct { - Converge *InstanceStatusManifest `json:"converge,omitempty"` - DryRun *InstanceStatusManifest `json:"dryRun,omitempty"` +// MachineStatus defines the observed state of Machine +type MachineStatus struct { + Converge *MachineStatusManifest `json:"converge,omitempty"` + DryRun *MachineStatusManifest `json:"dryRun,omitempty"` } // InstaceSpecManifest defines the state and hash of a run manifest -type InstanceStatusManifest struct { - State InstanceManifestState `json:"state,omitempty"` - Hash string `json:"hash,omitempty"` // hash of manifests, prefixed with type (eg: sha256:xyz) - LastUpdateTimestamp metav1.Time `json:"lastUpdateTimestamp,omitempty"` // timestamp when a converge was requested - Messages []string `json:"messages,omitempty"` // contains output of the retries - ExitCodes []int `json:"exitCodes,omitempty"` // return code of the retries +type MachineStatusManifest struct { + State MachineManifestState `json:"state,omitempty"` + Hash string `json:"hash,omitempty"` // hash of manifests, prefixed with type (eg: sha256:xyz) + LastUpdateTimestamp metav1.Time `json:"lastUpdateTimestamp,omitempty"` // timestamp when a converge was requested + Messages []string `json:"messages,omitempty"` // contains output of the retries + ExitCodes []int `json:"exitCodes,omitempty"` // return code of the retries } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type InstanceList struct { +type MachineList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []Instance `json:"items"` + Items []Machine `json:"items"` } diff --git a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go index 284270f80d..7a1b986d7a 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go @@ -21,141 +21,141 @@ func init() { // Public to allow building arbitrary schemes. func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( - Convert_v1alpha1_Instance_To_wing_Instance, - Convert_wing_Instance_To_v1alpha1_Instance, - Convert_v1alpha1_InstanceList_To_wing_InstanceList, - Convert_wing_InstanceList_To_v1alpha1_InstanceList, - Convert_v1alpha1_InstanceSpec_To_wing_InstanceSpec, - Convert_wing_InstanceSpec_To_v1alpha1_InstanceSpec, - Convert_v1alpha1_InstanceSpecManifest_To_wing_InstanceSpecManifest, - Convert_wing_InstanceSpecManifest_To_v1alpha1_InstanceSpecManifest, - Convert_v1alpha1_InstanceStatus_To_wing_InstanceStatus, - Convert_wing_InstanceStatus_To_v1alpha1_InstanceStatus, - Convert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest, - Convert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest, + Convert_v1alpha1_Machine_To_wing_Machine, + Convert_wing_Machine_To_v1alpha1_Machine, + Convert_v1alpha1_MachineList_To_wing_MachineList, + Convert_wing_MachineList_To_v1alpha1_MachineList, + Convert_v1alpha1_MachineSpec_To_wing_MachineSpec, + Convert_wing_MachineSpec_To_v1alpha1_MachineSpec, + Convert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest, + Convert_wing_MachineSpecManifest_To_v1alpha1_MachineSpecManifest, + Convert_v1alpha1_MachineStatus_To_wing_MachineStatus, + Convert_wing_MachineStatus_To_v1alpha1_MachineStatus, + Convert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest, + Convert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest, ) } -func autoConvert_v1alpha1_Instance_To_wing_Instance(in *Instance, out *wing.Instance, s conversion.Scope) error { +func autoConvert_v1alpha1_Machine_To_wing_Machine(in *Machine, out *wing.Machine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - out.InstanceID = in.InstanceID - out.InstancePool = in.InstancePool - out.Spec = (*wing.InstanceSpec)(unsafe.Pointer(in.Spec)) - out.Status = (*wing.InstanceStatus)(unsafe.Pointer(in.Status)) + out.MachineID = in.MachineID + out.MachinePool = in.MachinePool + out.Spec = (*wing.MachineSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*wing.MachineStatus)(unsafe.Pointer(in.Status)) return nil } -// Convert_v1alpha1_Instance_To_wing_Instance is an autogenerated conversion function. -func Convert_v1alpha1_Instance_To_wing_Instance(in *Instance, out *wing.Instance, s conversion.Scope) error { - return autoConvert_v1alpha1_Instance_To_wing_Instance(in, out, s) +// Convert_v1alpha1_Machine_To_wing_Machine is an autogenerated conversion function. +func Convert_v1alpha1_Machine_To_wing_Machine(in *Machine, out *wing.Machine, s conversion.Scope) error { + return autoConvert_v1alpha1_Machine_To_wing_Machine(in, out, s) } -func autoConvert_wing_Instance_To_v1alpha1_Instance(in *wing.Instance, out *Instance, s conversion.Scope) error { +func autoConvert_wing_Machine_To_v1alpha1_Machine(in *wing.Machine, out *Machine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - out.InstanceID = in.InstanceID - out.InstancePool = in.InstancePool - out.Spec = (*InstanceSpec)(unsafe.Pointer(in.Spec)) - out.Status = (*InstanceStatus)(unsafe.Pointer(in.Status)) + out.MachineID = in.MachineID + out.MachinePool = in.MachinePool + out.Spec = (*MachineSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*MachineStatus)(unsafe.Pointer(in.Status)) return nil } -// Convert_wing_Instance_To_v1alpha1_Instance is an autogenerated conversion function. -func Convert_wing_Instance_To_v1alpha1_Instance(in *wing.Instance, out *Instance, s conversion.Scope) error { - return autoConvert_wing_Instance_To_v1alpha1_Instance(in, out, s) +// Convert_wing_Machine_To_v1alpha1_Machine is an autogenerated conversion function. +func Convert_wing_Machine_To_v1alpha1_Machine(in *wing.Machine, out *Machine, s conversion.Scope) error { + return autoConvert_wing_Machine_To_v1alpha1_Machine(in, out, s) } -func autoConvert_v1alpha1_InstanceList_To_wing_InstanceList(in *InstanceList, out *wing.InstanceList, s conversion.Scope) error { +func autoConvert_v1alpha1_MachineList_To_wing_MachineList(in *MachineList, out *wing.MachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]wing.Instance)(unsafe.Pointer(&in.Items)) + out.Items = *(*[]wing.Machine)(unsafe.Pointer(&in.Items)) return nil } -// Convert_v1alpha1_InstanceList_To_wing_InstanceList is an autogenerated conversion function. -func Convert_v1alpha1_InstanceList_To_wing_InstanceList(in *InstanceList, out *wing.InstanceList, s conversion.Scope) error { - return autoConvert_v1alpha1_InstanceList_To_wing_InstanceList(in, out, s) +// Convert_v1alpha1_MachineList_To_wing_MachineList is an autogenerated conversion function. +func Convert_v1alpha1_MachineList_To_wing_MachineList(in *MachineList, out *wing.MachineList, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineList_To_wing_MachineList(in, out, s) } -func autoConvert_wing_InstanceList_To_v1alpha1_InstanceList(in *wing.InstanceList, out *InstanceList, s conversion.Scope) error { +func autoConvert_wing_MachineList_To_v1alpha1_MachineList(in *wing.MachineList, out *MachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]Instance)(unsafe.Pointer(&in.Items)) + out.Items = *(*[]Machine)(unsafe.Pointer(&in.Items)) return nil } -// Convert_wing_InstanceList_To_v1alpha1_InstanceList is an autogenerated conversion function. -func Convert_wing_InstanceList_To_v1alpha1_InstanceList(in *wing.InstanceList, out *InstanceList, s conversion.Scope) error { - return autoConvert_wing_InstanceList_To_v1alpha1_InstanceList(in, out, s) +// Convert_wing_MachineList_To_v1alpha1_MachineList is an autogenerated conversion function. +func Convert_wing_MachineList_To_v1alpha1_MachineList(in *wing.MachineList, out *MachineList, s conversion.Scope) error { + return autoConvert_wing_MachineList_To_v1alpha1_MachineList(in, out, s) } -func autoConvert_v1alpha1_InstanceSpec_To_wing_InstanceSpec(in *InstanceSpec, out *wing.InstanceSpec, s conversion.Scope) error { - out.Converge = (*wing.InstanceSpecManifest)(unsafe.Pointer(in.Converge)) - out.DryRun = (*wing.InstanceSpecManifest)(unsafe.Pointer(in.DryRun)) +func autoConvert_v1alpha1_MachineSpec_To_wing_MachineSpec(in *MachineSpec, out *wing.MachineSpec, s conversion.Scope) error { + out.Converge = (*wing.MachineSpecManifest)(unsafe.Pointer(in.Converge)) + out.DryRun = (*wing.MachineSpecManifest)(unsafe.Pointer(in.DryRun)) return nil } -// Convert_v1alpha1_InstanceSpec_To_wing_InstanceSpec is an autogenerated conversion function. -func Convert_v1alpha1_InstanceSpec_To_wing_InstanceSpec(in *InstanceSpec, out *wing.InstanceSpec, s conversion.Scope) error { - return autoConvert_v1alpha1_InstanceSpec_To_wing_InstanceSpec(in, out, s) +// Convert_v1alpha1_MachineSpec_To_wing_MachineSpec is an autogenerated conversion function. +func Convert_v1alpha1_MachineSpec_To_wing_MachineSpec(in *MachineSpec, out *wing.MachineSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSpec_To_wing_MachineSpec(in, out, s) } -func autoConvert_wing_InstanceSpec_To_v1alpha1_InstanceSpec(in *wing.InstanceSpec, out *InstanceSpec, s conversion.Scope) error { - out.Converge = (*InstanceSpecManifest)(unsafe.Pointer(in.Converge)) - out.DryRun = (*InstanceSpecManifest)(unsafe.Pointer(in.DryRun)) +func autoConvert_wing_MachineSpec_To_v1alpha1_MachineSpec(in *wing.MachineSpec, out *MachineSpec, s conversion.Scope) error { + out.Converge = (*MachineSpecManifest)(unsafe.Pointer(in.Converge)) + out.DryRun = (*MachineSpecManifest)(unsafe.Pointer(in.DryRun)) return nil } -// Convert_wing_InstanceSpec_To_v1alpha1_InstanceSpec is an autogenerated conversion function. -func Convert_wing_InstanceSpec_To_v1alpha1_InstanceSpec(in *wing.InstanceSpec, out *InstanceSpec, s conversion.Scope) error { - return autoConvert_wing_InstanceSpec_To_v1alpha1_InstanceSpec(in, out, s) +// Convert_wing_MachineSpec_To_v1alpha1_MachineSpec is an autogenerated conversion function. +func Convert_wing_MachineSpec_To_v1alpha1_MachineSpec(in *wing.MachineSpec, out *MachineSpec, s conversion.Scope) error { + return autoConvert_wing_MachineSpec_To_v1alpha1_MachineSpec(in, out, s) } -func autoConvert_v1alpha1_InstanceSpecManifest_To_wing_InstanceSpecManifest(in *InstanceSpecManifest, out *wing.InstanceSpecManifest, s conversion.Scope) error { +func autoConvert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest(in *MachineSpecManifest, out *wing.MachineSpecManifest, s conversion.Scope) error { out.Path = in.Path out.Hash = in.Hash out.RequestTimestamp = in.RequestTimestamp return nil } -// Convert_v1alpha1_InstanceSpecManifest_To_wing_InstanceSpecManifest is an autogenerated conversion function. -func Convert_v1alpha1_InstanceSpecManifest_To_wing_InstanceSpecManifest(in *InstanceSpecManifest, out *wing.InstanceSpecManifest, s conversion.Scope) error { - return autoConvert_v1alpha1_InstanceSpecManifest_To_wing_InstanceSpecManifest(in, out, s) +// Convert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest is an autogenerated conversion function. +func Convert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest(in *MachineSpecManifest, out *wing.MachineSpecManifest, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest(in, out, s) } -func autoConvert_wing_InstanceSpecManifest_To_v1alpha1_InstanceSpecManifest(in *wing.InstanceSpecManifest, out *InstanceSpecManifest, s conversion.Scope) error { +func autoConvert_wing_MachineSpecManifest_To_v1alpha1_MachineSpecManifest(in *wing.MachineSpecManifest, out *MachineSpecManifest, s conversion.Scope) error { out.Path = in.Path out.Hash = in.Hash out.RequestTimestamp = in.RequestTimestamp return nil } -// Convert_wing_InstanceSpecManifest_To_v1alpha1_InstanceSpecManifest is an autogenerated conversion function. -func Convert_wing_InstanceSpecManifest_To_v1alpha1_InstanceSpecManifest(in *wing.InstanceSpecManifest, out *InstanceSpecManifest, s conversion.Scope) error { - return autoConvert_wing_InstanceSpecManifest_To_v1alpha1_InstanceSpecManifest(in, out, s) +// Convert_wing_MachineSpecManifest_To_v1alpha1_MachineSpecManifest is an autogenerated conversion function. +func Convert_wing_MachineSpecManifest_To_v1alpha1_MachineSpecManifest(in *wing.MachineSpecManifest, out *MachineSpecManifest, s conversion.Scope) error { + return autoConvert_wing_MachineSpecManifest_To_v1alpha1_MachineSpecManifest(in, out, s) } -func autoConvert_v1alpha1_InstanceStatus_To_wing_InstanceStatus(in *InstanceStatus, out *wing.InstanceStatus, s conversion.Scope) error { - out.Converge = (*wing.InstanceStatusManifest)(unsafe.Pointer(in.Converge)) - out.DryRun = (*wing.InstanceStatusManifest)(unsafe.Pointer(in.DryRun)) +func autoConvert_v1alpha1_MachineStatus_To_wing_MachineStatus(in *MachineStatus, out *wing.MachineStatus, s conversion.Scope) error { + out.Converge = (*wing.MachineStatusManifest)(unsafe.Pointer(in.Converge)) + out.DryRun = (*wing.MachineStatusManifest)(unsafe.Pointer(in.DryRun)) return nil } -// Convert_v1alpha1_InstanceStatus_To_wing_InstanceStatus is an autogenerated conversion function. -func Convert_v1alpha1_InstanceStatus_To_wing_InstanceStatus(in *InstanceStatus, out *wing.InstanceStatus, s conversion.Scope) error { - return autoConvert_v1alpha1_InstanceStatus_To_wing_InstanceStatus(in, out, s) +// Convert_v1alpha1_MachineStatus_To_wing_MachineStatus is an autogenerated conversion function. +func Convert_v1alpha1_MachineStatus_To_wing_MachineStatus(in *MachineStatus, out *wing.MachineStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineStatus_To_wing_MachineStatus(in, out, s) } -func autoConvert_wing_InstanceStatus_To_v1alpha1_InstanceStatus(in *wing.InstanceStatus, out *InstanceStatus, s conversion.Scope) error { - out.Converge = (*InstanceStatusManifest)(unsafe.Pointer(in.Converge)) - out.DryRun = (*InstanceStatusManifest)(unsafe.Pointer(in.DryRun)) +func autoConvert_wing_MachineStatus_To_v1alpha1_MachineStatus(in *wing.MachineStatus, out *MachineStatus, s conversion.Scope) error { + out.Converge = (*MachineStatusManifest)(unsafe.Pointer(in.Converge)) + out.DryRun = (*MachineStatusManifest)(unsafe.Pointer(in.DryRun)) return nil } -// Convert_wing_InstanceStatus_To_v1alpha1_InstanceStatus is an autogenerated conversion function. -func Convert_wing_InstanceStatus_To_v1alpha1_InstanceStatus(in *wing.InstanceStatus, out *InstanceStatus, s conversion.Scope) error { - return autoConvert_wing_InstanceStatus_To_v1alpha1_InstanceStatus(in, out, s) +// Convert_wing_MachineStatus_To_v1alpha1_MachineStatus is an autogenerated conversion function. +func Convert_wing_MachineStatus_To_v1alpha1_MachineStatus(in *wing.MachineStatus, out *MachineStatus, s conversion.Scope) error { + return autoConvert_wing_MachineStatus_To_v1alpha1_MachineStatus(in, out, s) } -func autoConvert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest(in *InstanceStatusManifest, out *wing.InstanceStatusManifest, s conversion.Scope) error { - out.State = wing.InstanceManifestState(in.State) +func autoConvert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest(in *MachineStatusManifest, out *wing.MachineStatusManifest, s conversion.Scope) error { + out.State = wing.MachineManifestState(in.State) out.Hash = in.Hash out.LastUpdateTimestamp = in.LastUpdateTimestamp out.Messages = *(*[]string)(unsafe.Pointer(&in.Messages)) @@ -163,13 +163,13 @@ func autoConvert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest( return nil } -// Convert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest is an autogenerated conversion function. -func Convert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest(in *InstanceStatusManifest, out *wing.InstanceStatusManifest, s conversion.Scope) error { - return autoConvert_v1alpha1_InstanceStatusManifest_To_wing_InstanceStatusManifest(in, out, s) +// Convert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest is an autogenerated conversion function. +func Convert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest(in *MachineStatusManifest, out *wing.MachineStatusManifest, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest(in, out, s) } -func autoConvert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest(in *wing.InstanceStatusManifest, out *InstanceStatusManifest, s conversion.Scope) error { - out.State = InstanceManifestState(in.State) +func autoConvert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in *wing.MachineStatusManifest, out *MachineStatusManifest, s conversion.Scope) error { + out.State = MachineManifestState(in.State) out.Hash = in.Hash out.LastUpdateTimestamp = in.LastUpdateTimestamp out.Messages = *(*[]string)(unsafe.Pointer(&in.Messages)) @@ -177,7 +177,7 @@ func autoConvert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest( return nil } -// Convert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest is an autogenerated conversion function. -func Convert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest(in *wing.InstanceStatusManifest, out *InstanceStatusManifest, s conversion.Scope) error { - return autoConvert_wing_InstanceStatusManifest_To_v1alpha1_InstanceStatusManifest(in, out, s) +// Convert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest is an autogenerated conversion function. +func Convert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in *wing.MachineStatusManifest, out *MachineStatusManifest, s conversion.Scope) error { + return autoConvert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in, out, s) } diff --git a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go index 68e3769737..850bdcfd95 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go @@ -11,7 +11,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Instance) DeepCopyInto(out *Instance) { +func (in *Machine) DeepCopyInto(out *Machine) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -20,7 +20,7 @@ func (in *Instance) DeepCopyInto(out *Instance) { if *in == nil { *out = nil } else { - *out = new(InstanceSpec) + *out = new(MachineSpec) (*in).DeepCopyInto(*out) } } @@ -29,25 +29,25 @@ func (in *Instance) DeepCopyInto(out *Instance) { if *in == nil { *out = nil } else { - *out = new(InstanceStatus) + *out = new(MachineStatus) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Instance. -func (in *Instance) DeepCopy() *Instance { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Machine. +func (in *Machine) DeepCopy() *Machine { if in == nil { return nil } - out := new(Instance) + out := new(Machine) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Instance) DeepCopyObject() runtime.Object { +func (in *Machine) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } else { @@ -56,13 +56,13 @@ func (in *Instance) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceList) DeepCopyInto(out *InstanceList) { +func (in *MachineList) DeepCopyInto(out *MachineList) { *out = *in out.TypeMeta = in.TypeMeta out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]Instance, len(*in)) + *out = make([]Machine, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -70,18 +70,18 @@ func (in *InstanceList) DeepCopyInto(out *InstanceList) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceList. -func (in *InstanceList) DeepCopy() *InstanceList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineList. +func (in *MachineList) DeepCopy() *MachineList { if in == nil { return nil } - out := new(InstanceList) + out := new(MachineList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *InstanceList) DeepCopyObject() runtime.Object { +func (in *MachineList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } else { @@ -90,14 +90,14 @@ func (in *InstanceList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceSpec) DeepCopyInto(out *InstanceSpec) { +func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { *out = *in if in.Converge != nil { in, out := &in.Converge, &out.Converge if *in == nil { *out = nil } else { - *out = new(InstanceSpecManifest) + *out = new(MachineSpecManifest) (*in).DeepCopyInto(*out) } } @@ -106,49 +106,49 @@ func (in *InstanceSpec) DeepCopyInto(out *InstanceSpec) { if *in == nil { *out = nil } else { - *out = new(InstanceSpecManifest) + *out = new(MachineSpecManifest) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSpec. -func (in *InstanceSpec) DeepCopy() *InstanceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpec. +func (in *MachineSpec) DeepCopy() *MachineSpec { if in == nil { return nil } - out := new(InstanceSpec) + out := new(MachineSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceSpecManifest) DeepCopyInto(out *InstanceSpecManifest) { +func (in *MachineSpecManifest) DeepCopyInto(out *MachineSpecManifest) { *out = *in in.RequestTimestamp.DeepCopyInto(&out.RequestTimestamp) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSpecManifest. -func (in *InstanceSpecManifest) DeepCopy() *InstanceSpecManifest { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpecManifest. +func (in *MachineSpecManifest) DeepCopy() *MachineSpecManifest { if in == nil { return nil } - out := new(InstanceSpecManifest) + out := new(MachineSpecManifest) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceStatus) DeepCopyInto(out *InstanceStatus) { +func (in *MachineStatus) DeepCopyInto(out *MachineStatus) { *out = *in if in.Converge != nil { in, out := &in.Converge, &out.Converge if *in == nil { *out = nil } else { - *out = new(InstanceStatusManifest) + *out = new(MachineStatusManifest) (*in).DeepCopyInto(*out) } } @@ -157,25 +157,25 @@ func (in *InstanceStatus) DeepCopyInto(out *InstanceStatus) { if *in == nil { *out = nil } else { - *out = new(InstanceStatusManifest) + *out = new(MachineStatusManifest) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceStatus. -func (in *InstanceStatus) DeepCopy() *InstanceStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineStatus. +func (in *MachineStatus) DeepCopy() *MachineStatus { if in == nil { return nil } - out := new(InstanceStatus) + out := new(MachineStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceStatusManifest) DeepCopyInto(out *InstanceStatusManifest) { +func (in *MachineStatusManifest) DeepCopyInto(out *MachineStatusManifest) { *out = *in in.LastUpdateTimestamp.DeepCopyInto(&out.LastUpdateTimestamp) if in.Messages != nil { @@ -191,12 +191,12 @@ func (in *InstanceStatusManifest) DeepCopyInto(out *InstanceStatusManifest) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceStatusManifest. -func (in *InstanceStatusManifest) DeepCopy() *InstanceStatusManifest { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineStatusManifest. +func (in *MachineStatusManifest) DeepCopy() *MachineStatusManifest { if in == nil { return nil } - out := new(InstanceStatusManifest) + out := new(MachineStatusManifest) in.DeepCopyInto(out) return out } diff --git a/pkg/apis/wing/zz_generated.deepcopy.go b/pkg/apis/wing/zz_generated.deepcopy.go index 60477ce627..f4a486bef2 100644 --- a/pkg/apis/wing/zz_generated.deepcopy.go +++ b/pkg/apis/wing/zz_generated.deepcopy.go @@ -11,7 +11,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Instance) DeepCopyInto(out *Instance) { +func (in *Machine) DeepCopyInto(out *Machine) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -20,7 +20,7 @@ func (in *Instance) DeepCopyInto(out *Instance) { if *in == nil { *out = nil } else { - *out = new(InstanceSpec) + *out = new(MachineSpec) (*in).DeepCopyInto(*out) } } @@ -29,25 +29,25 @@ func (in *Instance) DeepCopyInto(out *Instance) { if *in == nil { *out = nil } else { - *out = new(InstanceStatus) + *out = new(MachineStatus) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Instance. -func (in *Instance) DeepCopy() *Instance { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Machine. +func (in *Machine) DeepCopy() *Machine { if in == nil { return nil } - out := new(Instance) + out := new(Machine) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Instance) DeepCopyObject() runtime.Object { +func (in *Machine) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } else { @@ -56,13 +56,13 @@ func (in *Instance) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceList) DeepCopyInto(out *InstanceList) { +func (in *MachineList) DeepCopyInto(out *MachineList) { *out = *in out.TypeMeta = in.TypeMeta out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]Instance, len(*in)) + *out = make([]Machine, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -70,18 +70,18 @@ func (in *InstanceList) DeepCopyInto(out *InstanceList) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceList. -func (in *InstanceList) DeepCopy() *InstanceList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineList. +func (in *MachineList) DeepCopy() *MachineList { if in == nil { return nil } - out := new(InstanceList) + out := new(MachineList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *InstanceList) DeepCopyObject() runtime.Object { +func (in *MachineList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } else { @@ -90,14 +90,14 @@ func (in *InstanceList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceSpec) DeepCopyInto(out *InstanceSpec) { +func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { *out = *in if in.Converge != nil { in, out := &in.Converge, &out.Converge if *in == nil { *out = nil } else { - *out = new(InstanceSpecManifest) + *out = new(MachineSpecManifest) (*in).DeepCopyInto(*out) } } @@ -106,49 +106,49 @@ func (in *InstanceSpec) DeepCopyInto(out *InstanceSpec) { if *in == nil { *out = nil } else { - *out = new(InstanceSpecManifest) + *out = new(MachineSpecManifest) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSpec. -func (in *InstanceSpec) DeepCopy() *InstanceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpec. +func (in *MachineSpec) DeepCopy() *MachineSpec { if in == nil { return nil } - out := new(InstanceSpec) + out := new(MachineSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceSpecManifest) DeepCopyInto(out *InstanceSpecManifest) { +func (in *MachineSpecManifest) DeepCopyInto(out *MachineSpecManifest) { *out = *in in.RequestTimestamp.DeepCopyInto(&out.RequestTimestamp) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSpecManifest. -func (in *InstanceSpecManifest) DeepCopy() *InstanceSpecManifest { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpecManifest. +func (in *MachineSpecManifest) DeepCopy() *MachineSpecManifest { if in == nil { return nil } - out := new(InstanceSpecManifest) + out := new(MachineSpecManifest) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceStatus) DeepCopyInto(out *InstanceStatus) { +func (in *MachineStatus) DeepCopyInto(out *MachineStatus) { *out = *in if in.Converge != nil { in, out := &in.Converge, &out.Converge if *in == nil { *out = nil } else { - *out = new(InstanceStatusManifest) + *out = new(MachineStatusManifest) (*in).DeepCopyInto(*out) } } @@ -157,25 +157,25 @@ func (in *InstanceStatus) DeepCopyInto(out *InstanceStatus) { if *in == nil { *out = nil } else { - *out = new(InstanceStatusManifest) + *out = new(MachineStatusManifest) (*in).DeepCopyInto(*out) } } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceStatus. -func (in *InstanceStatus) DeepCopy() *InstanceStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineStatus. +func (in *MachineStatus) DeepCopy() *MachineStatus { if in == nil { return nil } - out := new(InstanceStatus) + out := new(MachineStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *InstanceStatusManifest) DeepCopyInto(out *InstanceStatusManifest) { +func (in *MachineStatusManifest) DeepCopyInto(out *MachineStatusManifest) { *out = *in in.LastUpdateTimestamp.DeepCopyInto(&out.LastUpdateTimestamp) if in.Messages != nil { @@ -191,12 +191,12 @@ func (in *InstanceStatusManifest) DeepCopyInto(out *InstanceStatusManifest) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceStatusManifest. -func (in *InstanceStatusManifest) DeepCopy() *InstanceStatusManifest { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineStatusManifest. +func (in *MachineStatusManifest) DeepCopy() *MachineStatusManifest { if in == nil { return nil } - out := new(InstanceStatusManifest) + out := new(MachineStatusManifest) in.DeepCopyInto(out) return out } diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index 6460116164..b9a167b262 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -43,13 +43,13 @@ func (c *Cluster) ReapplyConfiguration() error { c.log.Infof("making sure all instances apply the latest manifest") // connect to wing - client, err := c.wingInstanceClient() + client, err := c.wingMachineClient() if err != nil { return fmt.Errorf("failed to connect to wing API on bastion: %s", err) } // list instances - instances, err := c.listInstances() + instances, err := c.listMachines() if err != nil { return fmt.Errorf("failed to list instances: %s", err) } @@ -57,9 +57,9 @@ func (c *Cluster) ReapplyConfiguration() error { for pos, _ := range instances { instance := instances[pos] if instance.Spec == nil { - instance.Spec = &wingv1alpha1.InstanceSpec{} + instance.Spec = &wingv1alpha1.MachineSpec{} } - instance.Spec.Converge = &wingv1alpha1.InstanceSpecManifest{} + instance.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} if _, err := client.Update(instance); err != nil { c.log.Warnf("error updating instance %s in wing API: %s", instance.Name, err) @@ -78,12 +78,12 @@ func (c *Cluster) WaitForConvergance() error { retries := retries for { - instances, err := c.listInstances() + instances, err := c.listMachines() if err != nil { return fmt.Errorf("failed to list instances: %s", err) } - instanceByState := make(map[wingv1alpha1.InstanceManifestState][]*wingv1alpha1.Instance) + instanceByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) for pos, _ := range instances { instance := instances[pos] @@ -95,7 +95,7 @@ func (c *Cluster) WaitForConvergance() error { state := instance.Status.Converge.State if _, ok := instanceByState[state]; !ok { - instanceByState[state] = []*wingv1alpha1.Instance{} + instanceByState[state] = []*wingv1alpha1.Machine{} } instanceByState[state] = append( @@ -104,7 +104,7 @@ func (c *Cluster) WaitForConvergance() error { ) } - err = c.checkAllInstancesConverged(instanceByState) + err = c.checkAllMachinesConverged(instanceByState) if err == nil { c.log.Info("all instances converged") return nil diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 28d26d9586..14ec366744 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -15,7 +15,7 @@ import ( wingclientv1alpha1 "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1" ) -func (c *Cluster) wingInstanceClient() (wingclientv1alpha1.InstanceInterface, error) { +func (c *Cluster) wingMachineClient() (wingclientv1alpha1.MachineInterface, error) { var err error if c.wingClientset == nil { @@ -42,75 +42,75 @@ func (c *Cluster) wingInstanceClient() (wingclientv1alpha1.InstanceInterface, er } - return c.wingClientset.WingV1alpha1().Instances(c.ClusterName()), nil + return c.wingClientset.WingV1alpha1().Machines(c.ClusterName()), nil } -func (c *Cluster) listInstances() (instances []*wingv1alpha1.Instance, err error) { +func (c *Cluster) listMachines() (machines []*wingv1alpha1.Machine, err error) { // connect to wing - client, err := c.wingInstanceClient() + client, err := c.wingMachineClient() if err != nil { - return instances, fmt.Errorf("failed to connect to wing API on bastion: %s", err) + return machines, fmt.Errorf("failed to connect to wing API on bastion: %s", err) } - // list all instances in Provider - providerInstances, err := c.ListHosts() + // list all machines in Provider + providerMachines, err := c.ListHosts() providerInstaceMap := make(map[string]interfaces.Host) if err != nil { - return instances, fmt.Errorf("failed to list provider's instances: %s", err) + return machines, fmt.Errorf("failed to list provider's machines: %s", err) } - for pos, _ := range providerInstances { - providerInstaceMap[providerInstances[pos].ID()] = providerInstances[pos] + for pos, _ := range providerMachines { + providerInstaceMap[providerMachines[pos].ID()] = providerMachines[pos] } - // list all instances in wing - wingInstances, err := client.List(metav1.ListOptions{}) + // list all machines in wing + wingMachines, err := client.List(metav1.ListOptions{}) if err != nil { - return instances, err + return machines, err } - // loop through instances - for pos, _ := range wingInstances.Items { - instance := &wingInstances.Items[pos] + // loop through machines + for pos, _ := range wingMachines.Items { + machine := &wingMachines.Items[pos] - // removes instances not in AWS - if _, ok := providerInstaceMap[instance.Name]; !ok { - c.log.Debugf("deleting unused instance %s in wing API", instance.Name) - if err := client.Delete(instance.Name, &metav1.DeleteOptions{}); err != nil { - c.log.Warnf("error deleting instance %s in wing API: %s", instance.Name, err) + // removes machines not in AWS + if _, ok := providerInstaceMap[machine.Name]; !ok { + c.log.Debugf("deleting unused machine %s in wing API", machine.Name) + if err := client.Delete(machine.Name, &metav1.DeleteOptions{}); err != nil { + c.log.Warnf("error deleting machine %s in wing API: %s", machine.Name, err) } continue } - instances = append(instances, instance) + machines = append(machines, machine) } - return instances, nil + return machines, nil } -func (c *Cluster) checkAllInstancesConverged(byState map[wingv1alpha1.InstanceManifestState][]*wingv1alpha1.Instance) error { - instancesNotConverged := []*wingv1alpha1.Instance{} - for key, instances := range byState { - if len(instances) == 0 { +func (c *Cluster) checkAllMachinesConverged(byState map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) error { + machinesNotConverged := []*wingv1alpha1.Machine{} + for key, machines := range byState { + if len(machines) == 0 { continue } - if key != wingv1alpha1.InstanceManifestStateConverged { - instancesNotConverged = append(instancesNotConverged, instances...) + if key != wingv1alpha1.MachineManifestStateConverged { + machinesNotConverged = append(machinesNotConverged, machines...) } - c.Log().Debugf("%d instances in state %s: %s", len(instances), key, outputInstances(instances)) + c.Log().Debugf("%d machines in state %s: %s", len(machines), key, outputMachines(machines)) } - if len(instancesNotConverged) > 0 { - return fmt.Errorf("not all instances have converged yet %s", outputInstances(instancesNotConverged)) + if len(machinesNotConverged) > 0 { + return fmt.Errorf("not all machines have converged yet %s", outputMachines(machinesNotConverged)) } return nil } -func outputInstances(instances []*wingv1alpha1.Instance) string { +func outputMachines(machines []*wingv1alpha1.Machine) string { var output []string - for _, instance := range instances { - output = append(output, instance.Name) + for _, machine := range machines { + output = append(output, machine.Name) } return strings.Join(output, ", ") } diff --git a/pkg/wing/admission/plugin/instanceinittime/admission.go b/pkg/wing/admission/plugin/instanceinittime/admission.go deleted file mode 100644 index 353b4cbad0..0000000000 --- a/pkg/wing/admission/plugin/instanceinittime/admission.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package instaceinittime - -import ( - "errors" - "io" - "time" - - "k8s.io/apiserver/pkg/admission" - - "github.com/jetstack/tarmak/pkg/apis/wing" -) - -const PluginName = "InstanceInitTime" - -// Register registers a plugin -func Register(plugins *admission.Plugins) { - plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { - return New() - }) -} - -type instanceInitTime struct { - *admission.Handler -} - -// Admit ensures that the object in-flight is of kind Flunder. -// In addition checks that the Name is not on the banned list. -// The list is stored in Fischers API objects. -func (d *instanceInitTime) Admit(a admission.Attributes) error { - // we are only interested in instances - if a.GetKind().GroupKind() != wing.Kind("Instance") { - return nil - } - - instance, ok := a.GetObject().(*wing.Instance) - if !ok { - return errors.New("unexpected object time") - } - - if instance.Status != nil { - if instance.Status.Converge != nil && instance.Status.Converge.LastUpdateTimestamp.IsZero() { - instance.Status.Converge.LastUpdateTimestamp.Time = time.Now() - } - if instance.Status.DryRun != nil && instance.Status.DryRun.LastUpdateTimestamp.IsZero() { - instance.Status.DryRun.LastUpdateTimestamp.Time = time.Now() - } - } - if instance.Spec != nil { - if instance.Spec.Converge != nil && instance.Spec.Converge.RequestTimestamp.IsZero() { - instance.Spec.Converge.RequestTimestamp.Time = time.Now() - } - if instance.Spec.DryRun != nil && instance.Spec.DryRun.RequestTimestamp.IsZero() { - instance.Spec.DryRun.RequestTimestamp.Time = time.Now() - } - } - - return nil -} - -// Validate checks whether the plugin was correctly initialized. -func (d *instanceInitTime) Validate() error { - return nil -} - -// New creates a new instances init time admission plugin -func New() (admission.Interface, error) { - return &instanceInitTime{ - Handler: admission.NewHandler(admission.Create, admission.Update), - }, nil -} diff --git a/pkg/wing/admission/plugin/machineinittime/admission.go b/pkg/wing/admission/plugin/machineinittime/admission.go new file mode 100644 index 0000000000..9fd3646fc7 --- /dev/null +++ b/pkg/wing/admission/plugin/machineinittime/admission.go @@ -0,0 +1,71 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package instaceinittime + +import ( + "errors" + "io" + "time" + + "k8s.io/apiserver/pkg/admission" + + "github.com/jetstack/tarmak/pkg/apis/wing" +) + +const PluginName = "MachineInitTime" + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { + return New() + }) +} + +type machineInitTime struct { + *admission.Handler +} + +// Admit ensures that the object in-flight is of kind Flunder. +// In addition checks that the Name is not on the banned list. +// The list is stored in Fischers API objects. +func (d *machineInitTime) Admit(a admission.Attributes) error { + // we are only interested in machines + if a.GetKind().GroupKind() != wing.Kind("Machine") { + return nil + } + + machine, ok := a.GetObject().(*wing.Machine) + if !ok { + return errors.New("unexpected object time") + } + + if machine.Status != nil { + if machine.Status.Converge != nil && machine.Status.Converge.LastUpdateTimestamp.IsZero() { + machine.Status.Converge.LastUpdateTimestamp.Time = time.Now() + } + if machine.Status.DryRun != nil && machine.Status.DryRun.LastUpdateTimestamp.IsZero() { + machine.Status.DryRun.LastUpdateTimestamp.Time = time.Now() + } + } + if machine.Spec != nil { + if machine.Spec.Converge != nil && machine.Spec.Converge.RequestTimestamp.IsZero() { + machine.Spec.Converge.RequestTimestamp.Time = time.Now() + } + if machine.Spec.DryRun != nil && machine.Spec.DryRun.RequestTimestamp.IsZero() { + machine.Spec.DryRun.RequestTimestamp.Time = time.Now() + } + } + + return nil +} + +// Validate checks whether the plugin was correctly initialized. +func (d *machineInitTime) Validate() error { + return nil +} + +// New creates a new machines init time admission plugin +func New() (admission.Interface, error) { + return &machineInitTime{ + Handler: admission.NewHandler(admission.Create, admission.Update), + }, nil +} diff --git a/pkg/wing/admission/winginitializer/winginitializer.go b/pkg/wing/admission/winginitializer/winginitializer.go index c432837150..80590f176c 100644 --- a/pkg/wing/admission/winginitializer/winginitializer.go +++ b/pkg/wing/admission/winginitializer/winginitializer.go @@ -13,7 +13,7 @@ type pluginInitializer struct { var _ admission.PluginInitializer = pluginInitializer{} -// New creates an instance of wing admission plugins initializer. +// New creates an machine of wing admission plugins initializer. func New(informers informers.SharedInformerFactory) (pluginInitializer, error) { return pluginInitializer{ informers: informers, diff --git a/pkg/wing/admission/winginitializer/winginitializer_test.go b/pkg/wing/admission/winginitializer/winginitializer_test.go index 4672028239..2df86e3236 100644 --- a/pkg/wing/admission/winginitializer/winginitializer_test.go +++ b/pkg/wing/admission/winginitializer/winginitializer_test.go @@ -18,7 +18,7 @@ func TestWantsInternalWingInformerFactory(t *testing.T) { sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second) target, err := winginitializer.New(sf) if err != nil { - t.Fatalf("expected to create an instance of initializer but got an error = %s", err.Error()) + t.Fatalf("expected to create an machine of initializer but got an error = %s", err.Error()) } wantWingInformerFactory := &wantInternalWingInformerFactory{} target.Initialize(wantWingInformerFactory) diff --git a/pkg/wing/apiserver/apiserver.go b/pkg/wing/apiserver/apiserver.go index 17b6754e30..f507f90ac2 100644 --- a/pkg/wing/apiserver/apiserver.go +++ b/pkg/wing/apiserver/apiserver.go @@ -17,7 +17,7 @@ import ( "github.com/jetstack/tarmak/pkg/apis/wing/install" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" wingregistry "github.com/jetstack/tarmak/pkg/wing/registry" - instancestorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/instance" + machinestorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machine" ) var ( @@ -77,7 +77,7 @@ func (cfg *Config) Complete() CompletedConfig { return CompletedConfig{&c} } -// New returns a new instance of WingServer from the given config. +// New returns a new machine of WingServer from the given config. func (c completedConfig) New() (*WingServer, error) { genericServer, err := c.GenericConfig.New("wing", genericapiserver.EmptyDelegate) if err != nil { @@ -91,7 +91,7 @@ func (c completedConfig) New() (*WingServer, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(wing.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs) apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion v1alpha1storage := map[string]rest.Storage{} - v1alpha1storage["instances"] = wingregistry.RESTInPeace(instancestorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + v1alpha1storage["machines"] = wingregistry.RESTInPeace(machinestorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_instance.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_instance.go deleted file mode 100644 index 36ead13d3f..0000000000 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_instance.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package fake - -import ( - wing "github.com/jetstack/tarmak/pkg/apis/wing" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeInstances implements InstanceInterface -type FakeInstances struct { - Fake *FakeWing - ns string -} - -var instancesResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "", Resource: "instances"} - -var instancesKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "", Kind: "Instance"} - -// Get takes name of the instance, and returns the corresponding instance object, and an error if there is any. -func (c *FakeInstances) Get(name string, options v1.GetOptions) (result *wing.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(instancesResource, c.ns, name), &wing.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*wing.Instance), err -} - -// List takes label and field selectors, and returns the list of Instances that match those selectors. -func (c *FakeInstances) List(opts v1.ListOptions) (result *wing.InstanceList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(instancesResource, instancesKind, c.ns, opts), &wing.InstanceList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &wing.InstanceList{} - for _, item := range obj.(*wing.InstanceList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested instances. -func (c *FakeInstances) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(instancesResource, c.ns, opts)) - -} - -// Create takes the representation of a instance and creates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *FakeInstances) Create(instance *wing.Instance) (result *wing.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(instancesResource, c.ns, instance), &wing.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*wing.Instance), err -} - -// Update takes the representation of a instance and updates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *FakeInstances) Update(instance *wing.Instance) (result *wing.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(instancesResource, c.ns, instance), &wing.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*wing.Instance), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeInstances) UpdateStatus(instance *wing.Instance) (*wing.Instance, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(instancesResource, "status", c.ns, instance), &wing.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*wing.Instance), err -} - -// Delete takes name of the instance and deletes it. Returns an error if one occurs. -func (c *FakeInstances) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(instancesResource, c.ns, name), &wing.Instance{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeInstances) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(instancesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &wing.InstanceList{}) - return err -} - -// Patch applies the patch and returns the patched instance. -func (c *FakeInstances) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(instancesResource, c.ns, name, data, subresources...), &wing.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*wing.Instance), err -} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machine.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machine.go new file mode 100644 index 0000000000..81a29e7396 --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machine.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachines implements MachineInterface +type FakeMachines struct { + Fake *FakeWing + ns string +} + +var machinesResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "", Resource: "machines"} + +var machinesKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "", Kind: "Machine"} + +// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any. +func (c *FakeMachines) Get(name string, options v1.GetOptions) (result *wing.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinesResource, c.ns, name), &wing.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.Machine), err +} + +// List takes label and field selectors, and returns the list of Machines that match those selectors. +func (c *FakeMachines) List(opts v1.ListOptions) (result *wing.MachineList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinesResource, machinesKind, c.ns, opts), &wing.MachineList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &wing.MachineList{} + for _, item := range obj.(*wing.MachineList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machines. +func (c *FakeMachines) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinesResource, c.ns, opts)) + +} + +// Create takes the representation of a machine and creates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *FakeMachines) Create(machine *wing.Machine) (result *wing.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinesResource, c.ns, machine), &wing.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.Machine), err +} + +// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *FakeMachines) Update(machine *wing.Machine) (result *wing.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinesResource, c.ns, machine), &wing.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.Machine), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachines) UpdateStatus(machine *wing.Machine) (*wing.Machine, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinesResource, "status", c.ns, machine), &wing.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.Machine), err +} + +// Delete takes name of the machine and deletes it. Returns an error if one occurs. +func (c *FakeMachines) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinesResource, c.ns, name), &wing.Machine{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinesResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &wing.MachineList{}) + return err +} + +// Patch applies the patch and returns the patched machine. +func (c *FakeMachines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinesResource, c.ns, name, data, subresources...), &wing.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.Machine), err +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go index 831aa39aca..592861829c 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go @@ -11,8 +11,8 @@ type FakeWing struct { *testing.Fake } -func (c *FakeWing) Instances(namespace string) internalversion.InstanceInterface { - return &FakeInstances{c, namespace} +func (c *FakeWing) Machines(namespace string) internalversion.MachineInterface { + return &FakeMachines{c, namespace} } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go index 95e2524747..f5c985ce65 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go @@ -1,4 +1,4 @@ // Copyright Jetstack Ltd. See LICENSE for details. package internalversion -type InstanceExpansion interface{} +type MachineExpansion interface{} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/instance.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/instance.go deleted file mode 100644 index f089791805..0000000000 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/instance.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package internalversion - -import ( - wing "github.com/jetstack/tarmak/pkg/apis/wing" - scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// InstancesGetter has a method to return a InstanceInterface. -// A group's client should implement this interface. -type InstancesGetter interface { - Instances(namespace string) InstanceInterface -} - -// InstanceInterface has methods to work with Instance resources. -type InstanceInterface interface { - Create(*wing.Instance) (*wing.Instance, error) - Update(*wing.Instance) (*wing.Instance, error) - UpdateStatus(*wing.Instance) (*wing.Instance, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*wing.Instance, error) - List(opts v1.ListOptions) (*wing.InstanceList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Instance, err error) - InstanceExpansion -} - -// instances implements InstanceInterface -type instances struct { - client rest.Interface - ns string -} - -// newInstances returns a Instances -func newInstances(c *WingClient, namespace string) *instances { - return &instances{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the instance, and returns the corresponding instance object, and an error if there is any. -func (c *instances) Get(name string, options v1.GetOptions) (result *wing.Instance, err error) { - result = &wing.Instance{} - err = c.client.Get(). - Namespace(c.ns). - Resource("instances"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of Instances that match those selectors. -func (c *instances) List(opts v1.ListOptions) (result *wing.InstanceList, err error) { - result = &wing.InstanceList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&opts, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested instances. -func (c *instances) Watch(opts v1.ListOptions) (watch.Interface, error) { - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&opts, scheme.ParameterCodec). - Watch() -} - -// Create takes the representation of a instance and creates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *instances) Create(instance *wing.Instance) (result *wing.Instance, err error) { - result = &wing.Instance{} - err = c.client.Post(). - Namespace(c.ns). - Resource("instances"). - Body(instance). - Do(). - Into(result) - return -} - -// Update takes the representation of a instance and updates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *instances) Update(instance *wing.Instance) (result *wing.Instance, err error) { - result = &wing.Instance{} - err = c.client.Put(). - Namespace(c.ns). - Resource("instances"). - Name(instance.Name). - Body(instance). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *instances) UpdateStatus(instance *wing.Instance) (result *wing.Instance, err error) { - result = &wing.Instance{} - err = c.client.Put(). - Namespace(c.ns). - Resource("instances"). - Name(instance.Name). - SubResource("status"). - Body(instance). - Do(). - Into(result) - return -} - -// Delete takes name of the instance and deletes it. Returns an error if one occurs. -func (c *instances) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("instances"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *instances) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched instance. -func (c *instances) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Instance, err error) { - result = &wing.Instance{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("instances"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machine.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machine.go new file mode 100644 index 0000000000..dc83a370bf --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machine.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachinesGetter has a method to return a MachineInterface. +// A group's client should implement this interface. +type MachinesGetter interface { + Machines(namespace string) MachineInterface +} + +// MachineInterface has methods to work with Machine resources. +type MachineInterface interface { + Create(*wing.Machine) (*wing.Machine, error) + Update(*wing.Machine) (*wing.Machine, error) + UpdateStatus(*wing.Machine) (*wing.Machine, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*wing.Machine, error) + List(opts v1.ListOptions) (*wing.MachineList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Machine, err error) + MachineExpansion +} + +// machines implements MachineInterface +type machines struct { + client rest.Interface + ns string +} + +// newMachines returns a Machines +func newMachines(c *WingClient, namespace string) *machines { + return &machines{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any. +func (c *machines) Get(name string, options v1.GetOptions) (result *wing.Machine, err error) { + result = &wing.Machine{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machines"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Machines that match those selectors. +func (c *machines) List(opts v1.ListOptions) (result *wing.MachineList, err error) { + result = &wing.MachineList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machines. +func (c *machines) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machine and creates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *machines) Create(machine *wing.Machine) (result *wing.Machine, err error) { + result = &wing.Machine{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machines"). + Body(machine). + Do(). + Into(result) + return +} + +// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *machines) Update(machine *wing.Machine) (result *wing.Machine, err error) { + result = &wing.Machine{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machines"). + Name(machine.Name). + Body(machine). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machines) UpdateStatus(machine *wing.Machine) (result *wing.Machine, err error) { + result = &wing.Machine{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machines"). + Name(machine.Name). + SubResource("status"). + Body(machine). + Do(). + Into(result) + return +} + +// Delete takes name of the machine and deletes it. Returns an error if one occurs. +func (c *machines) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machines"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machine. +func (c *machines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.Machine, err error) { + result = &wing.Machine{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machines"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go index abd7834ce4..ca4e3c55f6 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go @@ -8,7 +8,7 @@ import ( type WingInterface interface { RESTClient() rest.Interface - InstancesGetter + MachinesGetter } // WingClient is used to interact with features provided by the wing.tarmak.io group. @@ -16,8 +16,8 @@ type WingClient struct { restClient rest.Interface } -func (c *WingClient) Instances(namespace string) InstanceInterface { - return newInstances(c, namespace) +func (c *WingClient) Machines(namespace string) MachineInterface { + return newMachines(c, namespace) } // NewForConfig creates a new WingClient for the given config. diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_instance.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_instance.go deleted file mode 100644 index 67bd5c5f0d..0000000000 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_instance.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package fake - -import ( - v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeInstances implements InstanceInterface -type FakeInstances struct { - Fake *FakeWingV1alpha1 - ns string -} - -var instancesResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "v1alpha1", Resource: "instances"} - -var instancesKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "v1alpha1", Kind: "Instance"} - -// Get takes name of the instance, and returns the corresponding instance object, and an error if there is any. -func (c *FakeInstances) Get(name string, options v1.GetOptions) (result *v1alpha1.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(instancesResource, c.ns, name), &v1alpha1.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.Instance), err -} - -// List takes label and field selectors, and returns the list of Instances that match those selectors. -func (c *FakeInstances) List(opts v1.ListOptions) (result *v1alpha1.InstanceList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(instancesResource, instancesKind, c.ns, opts), &v1alpha1.InstanceList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.InstanceList{} - for _, item := range obj.(*v1alpha1.InstanceList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested instances. -func (c *FakeInstances) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(instancesResource, c.ns, opts)) - -} - -// Create takes the representation of a instance and creates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *FakeInstances) Create(instance *v1alpha1.Instance) (result *v1alpha1.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(instancesResource, c.ns, instance), &v1alpha1.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.Instance), err -} - -// Update takes the representation of a instance and updates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *FakeInstances) Update(instance *v1alpha1.Instance) (result *v1alpha1.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(instancesResource, c.ns, instance), &v1alpha1.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.Instance), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeInstances) UpdateStatus(instance *v1alpha1.Instance) (*v1alpha1.Instance, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(instancesResource, "status", c.ns, instance), &v1alpha1.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.Instance), err -} - -// Delete takes name of the instance and deletes it. Returns an error if one occurs. -func (c *FakeInstances) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(instancesResource, c.ns, name), &v1alpha1.Instance{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeInstances) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(instancesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &v1alpha1.InstanceList{}) - return err -} - -// Patch applies the patch and returns the patched instance. -func (c *FakeInstances) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Instance, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(instancesResource, c.ns, name, data, subresources...), &v1alpha1.Instance{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.Instance), err -} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machine.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machine.go new file mode 100644 index 0000000000..8fcdc10a40 --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machine.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachines implements MachineInterface +type FakeMachines struct { + Fake *FakeWingV1alpha1 + ns string +} + +var machinesResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "v1alpha1", Resource: "machines"} + +var machinesKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "v1alpha1", Kind: "Machine"} + +// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any. +func (c *FakeMachines) Get(name string, options v1.GetOptions) (result *v1alpha1.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinesResource, c.ns, name), &v1alpha1.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Machine), err +} + +// List takes label and field selectors, and returns the list of Machines that match those selectors. +func (c *FakeMachines) List(opts v1.ListOptions) (result *v1alpha1.MachineList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinesResource, machinesKind, c.ns, opts), &v1alpha1.MachineList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.MachineList{} + for _, item := range obj.(*v1alpha1.MachineList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machines. +func (c *FakeMachines) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinesResource, c.ns, opts)) + +} + +// Create takes the representation of a machine and creates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *FakeMachines) Create(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinesResource, c.ns, machine), &v1alpha1.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Machine), err +} + +// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *FakeMachines) Update(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinesResource, c.ns, machine), &v1alpha1.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Machine), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachines) UpdateStatus(machine *v1alpha1.Machine) (*v1alpha1.Machine, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinesResource, "status", c.ns, machine), &v1alpha1.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Machine), err +} + +// Delete takes name of the machine and deletes it. Returns an error if one occurs. +func (c *FakeMachines) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinesResource, c.ns, name), &v1alpha1.Machine{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinesResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.MachineList{}) + return err +} + +// Patch applies the patch and returns the patched machine. +func (c *FakeMachines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinesResource, c.ns, name, data, subresources...), &v1alpha1.Machine{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Machine), err +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go index 7785d8908b..3e661f5271 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go @@ -11,8 +11,8 @@ type FakeWingV1alpha1 struct { *testing.Fake } -func (c *FakeWingV1alpha1) Instances(namespace string) v1alpha1.InstanceInterface { - return &FakeInstances{c, namespace} +func (c *FakeWingV1alpha1) Machines(namespace string) v1alpha1.MachineInterface { + return &FakeMachines{c, namespace} } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go index 74e0c14501..0df983be7e 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go @@ -1,4 +1,4 @@ // Copyright Jetstack Ltd. See LICENSE for details. package v1alpha1 -type InstanceExpansion interface{} +type MachineExpansion interface{} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/instance.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/instance.go deleted file mode 100644 index f92b4aab00..0000000000 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/instance.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package v1alpha1 - -import ( - v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" - scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// InstancesGetter has a method to return a InstanceInterface. -// A group's client should implement this interface. -type InstancesGetter interface { - Instances(namespace string) InstanceInterface -} - -// InstanceInterface has methods to work with Instance resources. -type InstanceInterface interface { - Create(*v1alpha1.Instance) (*v1alpha1.Instance, error) - Update(*v1alpha1.Instance) (*v1alpha1.Instance, error) - UpdateStatus(*v1alpha1.Instance) (*v1alpha1.Instance, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*v1alpha1.Instance, error) - List(opts v1.ListOptions) (*v1alpha1.InstanceList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Instance, err error) - InstanceExpansion -} - -// instances implements InstanceInterface -type instances struct { - client rest.Interface - ns string -} - -// newInstances returns a Instances -func newInstances(c *WingV1alpha1Client, namespace string) *instances { - return &instances{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the instance, and returns the corresponding instance object, and an error if there is any. -func (c *instances) Get(name string, options v1.GetOptions) (result *v1alpha1.Instance, err error) { - result = &v1alpha1.Instance{} - err = c.client.Get(). - Namespace(c.ns). - Resource("instances"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of Instances that match those selectors. -func (c *instances) List(opts v1.ListOptions) (result *v1alpha1.InstanceList, err error) { - result = &v1alpha1.InstanceList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&opts, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested instances. -func (c *instances) Watch(opts v1.ListOptions) (watch.Interface, error) { - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&opts, scheme.ParameterCodec). - Watch() -} - -// Create takes the representation of a instance and creates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *instances) Create(instance *v1alpha1.Instance) (result *v1alpha1.Instance, err error) { - result = &v1alpha1.Instance{} - err = c.client.Post(). - Namespace(c.ns). - Resource("instances"). - Body(instance). - Do(). - Into(result) - return -} - -// Update takes the representation of a instance and updates it. Returns the server's representation of the instance, and an error, if there is any. -func (c *instances) Update(instance *v1alpha1.Instance) (result *v1alpha1.Instance, err error) { - result = &v1alpha1.Instance{} - err = c.client.Put(). - Namespace(c.ns). - Resource("instances"). - Name(instance.Name). - Body(instance). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *instances) UpdateStatus(instance *v1alpha1.Instance) (result *v1alpha1.Instance, err error) { - result = &v1alpha1.Instance{} - err = c.client.Put(). - Namespace(c.ns). - Resource("instances"). - Name(instance.Name). - SubResource("status"). - Body(instance). - Do(). - Into(result) - return -} - -// Delete takes name of the instance and deletes it. Returns an error if one occurs. -func (c *instances) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("instances"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *instances) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("instances"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched instance. -func (c *instances) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Instance, err error) { - result = &v1alpha1.Instance{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("instances"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machine.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machine.go new file mode 100644 index 0000000000..a9aa05431f --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machine.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachinesGetter has a method to return a MachineInterface. +// A group's client should implement this interface. +type MachinesGetter interface { + Machines(namespace string) MachineInterface +} + +// MachineInterface has methods to work with Machine resources. +type MachineInterface interface { + Create(*v1alpha1.Machine) (*v1alpha1.Machine, error) + Update(*v1alpha1.Machine) (*v1alpha1.Machine, error) + UpdateStatus(*v1alpha1.Machine) (*v1alpha1.Machine, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Machine, error) + List(opts v1.ListOptions) (*v1alpha1.MachineList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error) + MachineExpansion +} + +// machines implements MachineInterface +type machines struct { + client rest.Interface + ns string +} + +// newMachines returns a Machines +func newMachines(c *WingV1alpha1Client, namespace string) *machines { + return &machines{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any. +func (c *machines) Get(name string, options v1.GetOptions) (result *v1alpha1.Machine, err error) { + result = &v1alpha1.Machine{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machines"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Machines that match those selectors. +func (c *machines) List(opts v1.ListOptions) (result *v1alpha1.MachineList, err error) { + result = &v1alpha1.MachineList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machines. +func (c *machines) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machine and creates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *machines) Create(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) { + result = &v1alpha1.Machine{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machines"). + Body(machine). + Do(). + Into(result) + return +} + +// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any. +func (c *machines) Update(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) { + result = &v1alpha1.Machine{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machines"). + Name(machine.Name). + Body(machine). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machines) UpdateStatus(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) { + result = &v1alpha1.Machine{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machines"). + Name(machine.Name). + SubResource("status"). + Body(machine). + Do(). + Into(result) + return +} + +// Delete takes name of the machine and deletes it. Returns an error if one occurs. +func (c *machines) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machines"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machines"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machine. +func (c *machines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error) { + result = &v1alpha1.Machine{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machines"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go index 6debfb84db..5d1773f01b 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go @@ -10,7 +10,7 @@ import ( type WingV1alpha1Interface interface { RESTClient() rest.Interface - InstancesGetter + MachinesGetter } // WingV1alpha1Client is used to interact with features provided by the wing.tarmak.io group. @@ -18,8 +18,8 @@ type WingV1alpha1Client struct { restClient rest.Interface } -func (c *WingV1alpha1Client) Instances(namespace string) InstanceInterface { - return newInstances(c, namespace) +func (c *WingV1alpha1Client) Machines(namespace string) MachineInterface { + return newMachines(c, namespace) } // NewForConfig creates a new WingV1alpha1Client for the given config. diff --git a/pkg/wing/client/informers/externalversions/factory.go b/pkg/wing/client/informers/externalversions/factory.go index 6a5c61e2ee..1974123abf 100644 --- a/pkg/wing/client/informers/externalversions/factory.go +++ b/pkg/wing/client/informers/externalversions/factory.go @@ -30,12 +30,12 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// NewSharedInformerFactory constructs a new machine of sharedInformerFactory func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) } -// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// NewFilteredSharedInformerFactory constructs a new machine of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { diff --git a/pkg/wing/client/informers/externalversions/generic.go b/pkg/wing/client/informers/externalversions/generic.go index 42d5bf9f58..98562d275a 100644 --- a/pkg/wing/client/informers/externalversions/generic.go +++ b/pkg/wing/client/informers/externalversions/generic.go @@ -38,8 +38,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=wing.tarmak.io, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("instances"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().Instances().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("machines"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().Machines().Informer()}, nil } diff --git a/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go b/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go index 818004ff7e..3b7361d9c9 100644 --- a/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go +++ b/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go @@ -10,8 +10,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { - // Instances returns a InstanceInformer. - Instances() InstanceInformer + // Machines returns a MachineInformer. + Machines() MachineInformer } type version struct { @@ -25,7 +25,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// Instances returns a InstanceInformer. -func (v *version) Instances() InstanceInformer { - return &instanceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// Machines returns a MachineInformer. +func (v *version) Machines() MachineInformer { + return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/pkg/wing/client/informers/externalversions/wing/v1alpha1/instance.go b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machine.go similarity index 51% rename from pkg/wing/client/informers/externalversions/wing/v1alpha1/instance.go rename to pkg/wing/client/informers/externalversions/wing/v1alpha1/machine.go index 665411072b..756d5ce9e6 100644 --- a/pkg/wing/client/informers/externalversions/wing/v1alpha1/instance.go +++ b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machine.go @@ -16,59 +16,59 @@ import ( time "time" ) -// InstanceInformer provides access to a shared informer and lister for -// Instances. -type InstanceInformer interface { +// MachineInformer provides access to a shared informer and lister for +// Machines. +type MachineInformer interface { Informer() cache.SharedIndexInformer - Lister() v1alpha1.InstanceLister + Lister() v1alpha1.MachineLister } -type instanceInformer struct { +type machineInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc namespace string } -// NewInstanceInformer constructs a new informer for Instance type. +// NewMachineInformer constructs a new informer for Machine type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewInstanceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredInstanceInformer(client, namespace, resyncPeriod, indexers, nil) +func NewMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredInstanceInformer constructs a new informer for Instance type. +// NewFilteredMachineInformer constructs a new informer for Machine type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredInstanceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.WingV1alpha1().Instances(namespace).List(options) + return client.WingV1alpha1().Machines(namespace).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.WingV1alpha1().Instances(namespace).Watch(options) + return client.WingV1alpha1().Machines(namespace).Watch(options) }, }, - &wing_v1alpha1.Instance{}, + &wing_v1alpha1.Machine{}, resyncPeriod, indexers, ) } -func (f *instanceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredInstanceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *machineInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *instanceInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&wing_v1alpha1.Instance{}, f.defaultInformer) +func (f *machineInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing_v1alpha1.Machine{}, f.defaultInformer) } -func (f *instanceInformer) Lister() v1alpha1.InstanceLister { - return v1alpha1.NewInstanceLister(f.Informer().GetIndexer()) +func (f *machineInformer) Lister() v1alpha1.MachineLister { + return v1alpha1.NewMachineLister(f.Informer().GetIndexer()) } diff --git a/pkg/wing/client/informers/internalversion/factory.go b/pkg/wing/client/informers/internalversion/factory.go index f28297c844..81803a134d 100644 --- a/pkg/wing/client/informers/internalversion/factory.go +++ b/pkg/wing/client/informers/internalversion/factory.go @@ -30,12 +30,12 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory +// NewSharedInformerFactory constructs a new machine of sharedInformerFactory func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) } -// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// NewFilteredSharedInformerFactory constructs a new machine of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { diff --git a/pkg/wing/client/informers/internalversion/generic.go b/pkg/wing/client/informers/internalversion/generic.go index bc2e902c07..407a737152 100644 --- a/pkg/wing/client/informers/internalversion/generic.go +++ b/pkg/wing/client/informers/internalversion/generic.go @@ -38,8 +38,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=wing.tarmak.io, Version=internalVersion - case wing.SchemeGroupVersion.WithResource("instances"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().Instances().Informer()}, nil + case wing.SchemeGroupVersion.WithResource("machines"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().Machines().Informer()}, nil } diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go index 75bbce1341..3aaff6431c 100644 --- a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go @@ -10,8 +10,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { - // Instances returns a InstanceInformer. - Instances() InstanceInformer + // Machines returns a MachineInformer. + Machines() MachineInformer } type version struct { @@ -25,7 +25,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// Instances returns a InstanceInformer. -func (v *version) Instances() InstanceInformer { - return &instanceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// Machines returns a MachineInformer. +func (v *version) Machines() MachineInformer { + return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/instance.go b/pkg/wing/client/informers/internalversion/wing/internalversion/machine.go similarity index 51% rename from pkg/wing/client/informers/internalversion/wing/internalversion/instance.go rename to pkg/wing/client/informers/internalversion/wing/internalversion/machine.go index a239cfd789..49e82fd796 100644 --- a/pkg/wing/client/informers/internalversion/wing/internalversion/instance.go +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/machine.go @@ -16,59 +16,59 @@ import ( time "time" ) -// InstanceInformer provides access to a shared informer and lister for -// Instances. -type InstanceInformer interface { +// MachineInformer provides access to a shared informer and lister for +// Machines. +type MachineInformer interface { Informer() cache.SharedIndexInformer - Lister() internalversion.InstanceLister + Lister() internalversion.MachineLister } -type instanceInformer struct { +type machineInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc namespace string } -// NewInstanceInformer constructs a new informer for Instance type. +// NewMachineInformer constructs a new informer for Machine type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewInstanceInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredInstanceInformer(client, namespace, resyncPeriod, indexers, nil) +func NewMachineInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, namespace, resyncPeriod, indexers, nil) } -// NewFilteredInstanceInformer constructs a new informer for Instance type. +// NewFilteredMachineInformer constructs a new informer for Machine type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. -func NewFilteredInstanceInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredMachineInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.Wing().Instances(namespace).List(options) + return client.Wing().Machines(namespace).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.Wing().Instances(namespace).Watch(options) + return client.Wing().Machines(namespace).Watch(options) }, }, - &wing.Instance{}, + &wing.Machine{}, resyncPeriod, indexers, ) } -func (f *instanceInformer) defaultInformer(client clientset_internalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredInstanceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +func (f *machineInformer) defaultInformer(client clientset_internalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -func (f *instanceInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&wing.Instance{}, f.defaultInformer) +func (f *machineInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing.Machine{}, f.defaultInformer) } -func (f *instanceInformer) Lister() internalversion.InstanceLister { - return internalversion.NewInstanceLister(f.Informer().GetIndexer()) +func (f *machineInformer) Lister() internalversion.MachineLister { + return internalversion.NewMachineLister(f.Informer().GetIndexer()) } diff --git a/pkg/wing/client/listers/wing/internalversion/expansion_generated.go b/pkg/wing/client/listers/wing/internalversion/expansion_generated.go index a74252d677..454d4bcbdd 100644 --- a/pkg/wing/client/listers/wing/internalversion/expansion_generated.go +++ b/pkg/wing/client/listers/wing/internalversion/expansion_generated.go @@ -4,10 +4,10 @@ package internalversion -// InstanceListerExpansion allows custom methods to be added to -// InstanceLister. -type InstanceListerExpansion interface{} +// MachineListerExpansion allows custom methods to be added to +// MachineLister. +type MachineListerExpansion interface{} -// InstanceNamespaceListerExpansion allows custom methods to be added to -// InstanceNamespaceLister. -type InstanceNamespaceListerExpansion interface{} +// MachineNamespaceListerExpansion allows custom methods to be added to +// MachineNamespaceLister. +type MachineNamespaceListerExpansion interface{} diff --git a/pkg/wing/client/listers/wing/internalversion/instance.go b/pkg/wing/client/listers/wing/internalversion/instance.go deleted file mode 100644 index bd70666501..0000000000 --- a/pkg/wing/client/listers/wing/internalversion/instance.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. - -// This file was automatically generated by lister-gen - -package internalversion - -import ( - wing "github.com/jetstack/tarmak/pkg/apis/wing" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// InstanceLister helps list Instances. -type InstanceLister interface { - // List lists all Instances in the indexer. - List(selector labels.Selector) (ret []*wing.Instance, err error) - // Instances returns an object that can list and get Instances. - Instances(namespace string) InstanceNamespaceLister - InstanceListerExpansion -} - -// instanceLister implements the InstanceLister interface. -type instanceLister struct { - indexer cache.Indexer -} - -// NewInstanceLister returns a new InstanceLister. -func NewInstanceLister(indexer cache.Indexer) InstanceLister { - return &instanceLister{indexer: indexer} -} - -// List lists all Instances in the indexer. -func (s *instanceLister) List(selector labels.Selector) (ret []*wing.Instance, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*wing.Instance)) - }) - return ret, err -} - -// Instances returns an object that can list and get Instances. -func (s *instanceLister) Instances(namespace string) InstanceNamespaceLister { - return instanceNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// InstanceNamespaceLister helps list and get Instances. -type InstanceNamespaceLister interface { - // List lists all Instances in the indexer for a given namespace. - List(selector labels.Selector) (ret []*wing.Instance, err error) - // Get retrieves the Instance from the indexer for a given namespace and name. - Get(name string) (*wing.Instance, error) - InstanceNamespaceListerExpansion -} - -// instanceNamespaceLister implements the InstanceNamespaceLister -// interface. -type instanceNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all Instances in the indexer for a given namespace. -func (s instanceNamespaceLister) List(selector labels.Selector) (ret []*wing.Instance, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*wing.Instance)) - }) - return ret, err -} - -// Get retrieves the Instance from the indexer for a given namespace and name. -func (s instanceNamespaceLister) Get(name string) (*wing.Instance, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(wing.Resource("instance"), name) - } - return obj.(*wing.Instance), nil -} diff --git a/pkg/wing/client/listers/wing/internalversion/machine.go b/pkg/wing/client/listers/wing/internalversion/machine.go new file mode 100644 index 0000000000..d8d54ab323 --- /dev/null +++ b/pkg/wing/client/listers/wing/internalversion/machine.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineLister helps list Machines. +type MachineLister interface { + // List lists all Machines in the indexer. + List(selector labels.Selector) (ret []*wing.Machine, err error) + // Machines returns an object that can list and get Machines. + Machines(namespace string) MachineNamespaceLister + MachineListerExpansion +} + +// machineLister implements the MachineLister interface. +type machineLister struct { + indexer cache.Indexer +} + +// NewMachineLister returns a new MachineLister. +func NewMachineLister(indexer cache.Indexer) MachineLister { + return &machineLister{indexer: indexer} +} + +// List lists all Machines in the indexer. +func (s *machineLister) List(selector labels.Selector) (ret []*wing.Machine, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.Machine)) + }) + return ret, err +} + +// Machines returns an object that can list and get Machines. +func (s *machineLister) Machines(namespace string) MachineNamespaceLister { + return machineNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineNamespaceLister helps list and get Machines. +type MachineNamespaceLister interface { + // List lists all Machines in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.Machine, err error) + // Get retrieves the Machine from the indexer for a given namespace and name. + Get(name string) (*wing.Machine, error) + MachineNamespaceListerExpansion +} + +// machineNamespaceLister implements the MachineNamespaceLister +// interface. +type machineNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Machines in the indexer for a given namespace. +func (s machineNamespaceLister) List(selector labels.Selector) (ret []*wing.Machine, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.Machine)) + }) + return ret, err +} + +// Get retrieves the Machine from the indexer for a given namespace and name. +func (s machineNamespaceLister) Get(name string) (*wing.Machine, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machine"), name) + } + return obj.(*wing.Machine), nil +} diff --git a/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go b/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go index e3271e34c9..4248b6c0b1 100644 --- a/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go +++ b/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go @@ -4,10 +4,10 @@ package v1alpha1 -// InstanceListerExpansion allows custom methods to be added to -// InstanceLister. -type InstanceListerExpansion interface{} +// MachineListerExpansion allows custom methods to be added to +// MachineLister. +type MachineListerExpansion interface{} -// InstanceNamespaceListerExpansion allows custom methods to be added to -// InstanceNamespaceLister. -type InstanceNamespaceListerExpansion interface{} +// MachineNamespaceListerExpansion allows custom methods to be added to +// MachineNamespaceLister. +type MachineNamespaceListerExpansion interface{} diff --git a/pkg/wing/client/listers/wing/v1alpha1/instance.go b/pkg/wing/client/listers/wing/v1alpha1/instance.go deleted file mode 100644 index 4e6533ad87..0000000000 --- a/pkg/wing/client/listers/wing/v1alpha1/instance.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. - -// This file was automatically generated by lister-gen - -package v1alpha1 - -import ( - v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// InstanceLister helps list Instances. -type InstanceLister interface { - // List lists all Instances in the indexer. - List(selector labels.Selector) (ret []*v1alpha1.Instance, err error) - // Instances returns an object that can list and get Instances. - Instances(namespace string) InstanceNamespaceLister - InstanceListerExpansion -} - -// instanceLister implements the InstanceLister interface. -type instanceLister struct { - indexer cache.Indexer -} - -// NewInstanceLister returns a new InstanceLister. -func NewInstanceLister(indexer cache.Indexer) InstanceLister { - return &instanceLister{indexer: indexer} -} - -// List lists all Instances in the indexer. -func (s *instanceLister) List(selector labels.Selector) (ret []*v1alpha1.Instance, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.Instance)) - }) - return ret, err -} - -// Instances returns an object that can list and get Instances. -func (s *instanceLister) Instances(namespace string) InstanceNamespaceLister { - return instanceNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// InstanceNamespaceLister helps list and get Instances. -type InstanceNamespaceLister interface { - // List lists all Instances in the indexer for a given namespace. - List(selector labels.Selector) (ret []*v1alpha1.Instance, err error) - // Get retrieves the Instance from the indexer for a given namespace and name. - Get(name string) (*v1alpha1.Instance, error) - InstanceNamespaceListerExpansion -} - -// instanceNamespaceLister implements the InstanceNamespaceLister -// interface. -type instanceNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all Instances in the indexer for a given namespace. -func (s instanceNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Instance, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.Instance)) - }) - return ret, err -} - -// Get retrieves the Instance from the indexer for a given namespace and name. -func (s instanceNamespaceLister) Get(name string) (*v1alpha1.Instance, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("instance"), name) - } - return obj.(*v1alpha1.Instance), nil -} diff --git a/pkg/wing/client/listers/wing/v1alpha1/machine.go b/pkg/wing/client/listers/wing/v1alpha1/machine.go new file mode 100644 index 0000000000..6f1bea4000 --- /dev/null +++ b/pkg/wing/client/listers/wing/v1alpha1/machine.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineLister helps list Machines. +type MachineLister interface { + // List lists all Machines in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Machine, err error) + // Machines returns an object that can list and get Machines. + Machines(namespace string) MachineNamespaceLister + MachineListerExpansion +} + +// machineLister implements the MachineLister interface. +type machineLister struct { + indexer cache.Indexer +} + +// NewMachineLister returns a new MachineLister. +func NewMachineLister(indexer cache.Indexer) MachineLister { + return &machineLister{indexer: indexer} +} + +// List lists all Machines in the indexer. +func (s *machineLister) List(selector labels.Selector) (ret []*v1alpha1.Machine, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Machine)) + }) + return ret, err +} + +// Machines returns an object that can list and get Machines. +func (s *machineLister) Machines(namespace string) MachineNamespaceLister { + return machineNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineNamespaceLister helps list and get Machines. +type MachineNamespaceLister interface { + // List lists all Machines in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.Machine, err error) + // Get retrieves the Machine from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.Machine, error) + MachineNamespaceListerExpansion +} + +// machineNamespaceLister implements the MachineNamespaceLister +// interface. +type machineNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Machines in the indexer for a given namespace. +func (s machineNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Machine, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Machine)) + }) + return ret, err +} + +// Get retrieves the Machine from the indexer for a given namespace and name. +func (s machineNamespaceLister) Get(name string) (*v1alpha1.Machine, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("machine"), name) + } + return obj.(*v1alpha1.Machine), nil +} diff --git a/pkg/wing/controller.go b/pkg/wing/controller.go index cc3f19bb7d..178d42f131 100644 --- a/pkg/wing/controller.go +++ b/pkg/wing/controller.go @@ -40,7 +40,7 @@ func (c *Controller) processNextItem() bool { return false } // Tell the queue that we are done with processing this key. This unblocks the key for other workers - // This allows safe parallel processing because two instances with the same key are never processed in + // This allows safe parallel processing because two machines with the same key are never processed in // parallel. defer c.queue.Done(key) @@ -52,7 +52,7 @@ func (c *Controller) processNextItem() bool { } // syncToStdout is the business logic of the controller. In this controller it simply prints -// information about the instance to stdout. In case an error happened, it has to simply return the error. +// information about the machine to stdout. In case an error happened, it has to simply return the error. // The retry logic should not be part of the business logic. func (c *Controller) syncToStdout(key string) error { @@ -66,32 +66,32 @@ func (c *Controller) syncToStdout(key string) error { } if !exists { - // Below we will warm up our cache with a Instance, so that we will see a delete for one instance - fmt.Printf("Instance %s does not exist anymore\n", key) - instanceAPI := c.wing.clientset.WingV1alpha1().Instances(c.wing.flags.ClusterName) - instance := &v1alpha1.Instance{ + // Below we will warm up our cache with a Machine, so that we will see a delete for one machine + fmt.Printf("Machine %s does not exist anymore\n", key) + machineAPI := c.wing.clientset.WingV1alpha1().Machines(c.wing.flags.ClusterName) + machine := &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ Name: c.wing.flags.InstanceName, }, - Status: &v1alpha1.InstanceStatus{ - Converge: &v1alpha1.InstanceStatusManifest{ - State: v1alpha1.InstanceManifestStateConverging, + Status: &v1alpha1.MachineStatus{ + Converge: &v1alpha1.MachineStatusManifest{ + State: v1alpha1.MachineManifestStateConverging, }, }, } - _, err := instanceAPI.Create(instance) + _, err := machineAPI.Create(machine) if err != nil { - return fmt.Errorf("error creating instance: %s", err) + return fmt.Errorf("error creating machine: %s", err) } } else { // Note that you also have to check the uid if you have a local controlled resource, which - // is dependent on the actual instance, to detect that a Instance was recreated with the same name - instance := obj.(*v1alpha1.Instance) + // is dependent on the actual machine, to detect that a Machine was recreated with the same name + machine := obj.(*v1alpha1.Machine) // trigger converge if status time is older or not existing - if instance.Spec != nil && instance.Spec.Converge != nil && !instance.Spec.Converge.RequestTimestamp.Time.IsZero() { - if instance.Status != nil && instance.Status.Converge != nil && !instance.Status.Converge.LastUpdateTimestamp.Time.IsZero() { - if instance.Status.Converge.LastUpdateTimestamp.Time.After(instance.Spec.Converge.RequestTimestamp.Time) { + if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { + if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { + if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { c.log.Debug("no converge neccessary, last update was after request") return nil } @@ -122,7 +122,7 @@ func (c *Controller) handleErr(err error, key interface{}) { // This controller retries 5 times if something goes wrong. After that, it stops trying. if c.queue.NumRequeues(key) < 5 { - c.log.Infof("Error syncing instance %v: %v", key, err) + c.log.Infof("Error syncing machine %v: %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. @@ -133,7 +133,7 @@ func (c *Controller) handleErr(err error, key interface{}) { c.queue.Forget(key) // Report to an external entity that, even after several retries, we could not successfully process this key runtime.HandleError(err) - c.log.Infof("Dropping instance %q out of the queue: %v", key, err) + c.log.Infof("Dropping machine %q out of the queue: %v", key, err) } func (c *Controller) Run(threadiness int, stopCh chan struct{}) { @@ -141,7 +141,7 @@ func (c *Controller) Run(threadiness int, stopCh chan struct{}) { // Let the workers stop when we are done defer c.queue.ShutDown() - c.log.Info("Starting Instance controller") + c.log.Info("Starting Machine controller") go c.informer.Run(stopCh) @@ -156,7 +156,7 @@ func (c *Controller) Run(threadiness int, stopCh chan struct{}) { } <-stopCh - c.log.Info("Stopping Instance controller") + c.log.Info("Stopping Machine controller") } func (c *Controller) runWorker() { diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index dacf2fd3b2..ab9cb3fea7 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -27,11 +27,11 @@ import ( ) // This make sure puppet is converged when neccessary -func (w *Wing) runPuppet() (*v1alpha1.InstanceStatus, error) { +func (w *Wing) runPuppet() (*v1alpha1.MachineStatus, error) { // start converging mainfest - status := &v1alpha1.InstanceStatus{ - Converge: &v1alpha1.InstanceStatusManifest{ - State: v1alpha1.InstanceManifestStateConverging, + status := &v1alpha1.MachineStatus{ + Converge: &v1alpha1.MachineStatusManifest{ + State: v1alpha1.MachineManifestStateConverging, }, } @@ -103,9 +103,9 @@ func (w *Wing) runPuppet() (*v1alpha1.InstanceStatus, error) { puppetRetCodes = append(puppetRetCodes, retCode) // start converging mainfest - status = &v1alpha1.InstanceStatus{ - Converge: &v1alpha1.InstanceStatusManifest{ - State: v1alpha1.InstanceManifestStateConverging, + status = &v1alpha1.MachineStatus{ + Converge: &v1alpha1.MachineStatusManifest{ + State: v1alpha1.MachineManifestStateConverging, Messages: puppetMessages, ExitCodes: puppetRetCodes, Hash: hashString, @@ -159,11 +159,11 @@ func (w *Wing) converge() { // run puppet status, err := w.runPuppet() if err != nil { - status.Converge.State = v1alpha1.InstanceManifestStateError + status.Converge.State = v1alpha1.MachineManifestStateError status.Converge.Messages = append(status.Converge.Messages, err.Error()) w.log.Error(err) } else { - status.Converge.State = v1alpha1.InstanceManifestStateConverged + status.Converge.State = v1alpha1.MachineManifestStateConverged } // feedback puppet status to apiserver @@ -291,33 +291,33 @@ func (w *Wing) puppetApply(dir string) (output string, retCode int, err error) { } // report status to the API server -func (w *Wing) reportStatus(status *v1alpha1.InstanceStatus) error { - instanceAPI := w.clientset.WingV1alpha1().Instances(w.flags.ClusterName) - instance, err := instanceAPI.Get( +func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { + machineAPI := w.clientset.WingV1alpha1().Machines(w.flags.ClusterName) + machine, err := machineAPI.Get( w.flags.InstanceName, metav1.GetOptions{}, ) if err != nil { if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { - instance = &v1alpha1.Instance{ + machine = &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ Name: w.flags.InstanceName, }, Status: status.DeepCopy(), } - _, err := instanceAPI.Create(instance) + _, err := machineAPI.Create(machine) if err != nil { - return fmt.Errorf("error creating instance: %s", err) + return fmt.Errorf("error creating machine: %s", err) } return nil } - return fmt.Errorf("error get existing instance: %s", err) + return fmt.Errorf("error get existing machine: %s", err) } - instance.Status = status.DeepCopy() - _, err = instanceAPI.Update(instance) + machine.Status = status.DeepCopy() + _, err = machineAPI.Update(machine) if err != nil { - return fmt.Errorf("error updating existing instance: %s", err) + return fmt.Errorf("error updating existing machine: %s", err) // TODO: handle race for update } diff --git a/pkg/wing/registry/wing/instance/strategy.go b/pkg/wing/registry/wing/instance/strategy.go deleted file mode 100644 index 10154a5153..0000000000 --- a/pkg/wing/registry/wing/instance/strategy.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package instance - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/apiserver/pkg/registry/generic" - "k8s.io/apiserver/pkg/storage" - "k8s.io/apiserver/pkg/storage/names" - - "github.com/jetstack/tarmak/pkg/apis/wing" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" -) - -func NewStrategy(typer runtime.ObjectTyper) instanceStrategy { - return instanceStrategy{typer, names.SimpleNameGenerator} -} - -func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { - apiserver, ok := obj.(*wing.Instance) - if !ok { - return nil, nil, false, fmt.Errorf("given object is not a Instance.") - } - return labels.Set(apiserver.ObjectMeta.Labels), InstanceToSelectableFields(apiserver), apiserver.Initializers != nil, nil -} - -// MatchInstance is the filter used by the generic etcd backend to watch events -// from etcd to clients of the apiserver only interested in specific labels/fields. -func MatchInstance(label labels.Selector, field fields.Selector) storage.SelectionPredicate { - return storage.SelectionPredicate{ - Label: label, - Field: field, - GetAttrs: GetAttrs, - } -} - -// InstanceToSelectableFields returns a field set that represents the object. -func InstanceToSelectableFields(obj *wing.Instance) fields.Set { - return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) -} - -type instanceStrategy struct { - runtime.ObjectTyper - names.NameGenerator -} - -func (instanceStrategy) NamespaceScoped() bool { - return true -} - -func (instanceStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { - // TODO: update all none timestamp to now() -} - -func (instanceStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { - // TODO: update all none timestamp to now() -} - -func (instanceStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return field.ErrorList{} -} - -func (instanceStrategy) AllowCreateOnUpdate() bool { - return false -} - -func (instanceStrategy) AllowUnconditionalUpdate() bool { - return false -} - -func (instanceStrategy) Canonicalize(obj runtime.Object) { -} - -func (instanceStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { - return field.ErrorList{} -} diff --git a/pkg/wing/registry/wing/instance/etcd.go b/pkg/wing/registry/wing/machine/etcd.go similarity index 86% rename from pkg/wing/registry/wing/instance/etcd.go rename to pkg/wing/registry/wing/machine/etcd.go index a38b9141d9..9ec7a069d3 100644 --- a/pkg/wing/registry/wing/instance/etcd.go +++ b/pkg/wing/registry/wing/machine/etcd.go @@ -1,5 +1,5 @@ // Copyright Jetstack Ltd. See LICENSE for details. -package instance +package machine import ( "k8s.io/apimachinery/pkg/runtime" @@ -15,10 +15,10 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg strategy := NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &wing.Instance{} }, - NewListFunc: func() runtime.Object { return &wing.InstanceList{} }, - PredicateFunc: MatchInstance, - DefaultQualifiedResource: wing.Resource("instances"), + NewFunc: func() runtime.Object { return &wing.Machine{} }, + NewListFunc: func() runtime.Object { return &wing.MachineList{} }, + PredicateFunc: MatchMachine, + DefaultQualifiedResource: wing.Resource("machines"), CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/pkg/wing/registry/wing/machine/strategy.go b/pkg/wing/registry/wing/machine/strategy.go new file mode 100644 index 0000000000..8a040b869e --- /dev/null +++ b/pkg/wing/registry/wing/machine/strategy.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machine + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/names" + + "github.com/jetstack/tarmak/pkg/apis/wing" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" +) + +func NewStrategy(typer runtime.ObjectTyper) machineStrategy { + return machineStrategy{typer, names.SimpleNameGenerator} +} + +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { + apiserver, ok := obj.(*wing.Machine) + if !ok { + return nil, nil, false, fmt.Errorf("given object is not a Machine.") + } + return labels.Set(apiserver.ObjectMeta.Labels), MachineToSelectableFields(apiserver), apiserver.Initializers != nil, nil +} + +// MatchMachine is the filter used by the generic etcd backend to watch events +// from etcd to clients of the apiserver only interested in specific labels/fields. +func MatchMachine(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + } +} + +// MachineToSelectableFields returns a field set that represents the object. +func MachineToSelectableFields(obj *wing.Machine) fields.Set { + return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) +} + +type machineStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +func (machineStrategy) NamespaceScoped() bool { + return true +} + +func (machineStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machineStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machineStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { + return field.ErrorList{} +} + +func (machineStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (machineStrategy) AllowUnconditionalUpdate() bool { + return false +} + +func (machineStrategy) Canonicalize(obj runtime.Object) { +} + +func (machineStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { + return field.ErrorList{} +} diff --git a/pkg/wing/server/server.go b/pkg/wing/server/server.go index 709ad0cc3d..4c8a9293b4 100644 --- a/pkg/wing/server/server.go +++ b/pkg/wing/server/server.go @@ -13,7 +13,7 @@ import ( genericoptions "k8s.io/apiserver/pkg/server/options" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" - "github.com/jetstack/tarmak/pkg/wing/admission/plugin/instanceinittime" + "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machineinittime" "github.com/jetstack/tarmak/pkg/wing/admission/winginitializer" "github.com/jetstack/tarmak/pkg/wing/apiserver" clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" diff --git a/pkg/wing/wing.go b/pkg/wing/wing.go index 2947912baa..c2ea93ef78 100644 --- a/pkg/wing/wing.go +++ b/pkg/wing/wing.go @@ -124,8 +124,8 @@ func (w *Wing) Must(err error) *Wing { func (w *Wing) watchForNotifications() { - // create the instance watcher - instanceListWatcher := cache.NewListWatchFromClient(w.clientset.WingV1alpha1().RESTClient(), "instances", w.flags.ClusterName, fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", w.flags.InstanceName))) + // create the machine watcher + machineListWatcher := cache.NewListWatchFromClient(w.clientset.WingV1alpha1().RESTClient(), "machines", w.flags.ClusterName, fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", w.flags.InstanceName))) // create the workqueue queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) @@ -134,7 +134,7 @@ func (w *Wing) watchForNotifications() { // whenever the cache is updated, the pod key is added to the workqueue. // Note that when we finally process the item from the workqueue, we might see a newer version // of the Pod than the version which was responsible for triggering the update. - indexer, informer := cache.NewIndexerInformer(instanceListWatcher, &v1alpha1.Instance{}, 0, cache.ResourceEventHandlerFuncs{ + indexer, informer := cache.NewIndexerInformer(machineListWatcher, &v1alpha1.Machine{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) if err == nil { From 9a59bbbc6463af1ba00f0e37b1bc354c24b30d4f Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Tue, 11 Dec 2018 21:17:42 +0000 Subject: [PATCH 02/14] Adds MachineSets and MachineDeployment APIs Signed-off-by: JoshVanL --- docs/generated/cmd/wing/wing_server.rst | 2 +- pkg/apis/wing/common/consts.go | 17 + pkg/apis/wing/{types.go => machine_types.go} | 0 pkg/apis/wing/machinedeployment_types.go | 155 ++++++++ pkg/apis/wing/machineset_types.go | 112 ++++++ .../v1alpha1/{types.go => machine_types.go} | 0 .../wing/v1alpha1/machinedeployment_types.go | 155 ++++++++ pkg/apis/wing/v1alpha1/machineset_types.go | 113 ++++++ .../wing/v1alpha1/zz_generated.conversion.go | 316 +++++++++++++++ .../wing/v1alpha1/zz_generated.deepcopy.go | 367 ++++++++++++++++++ pkg/apis/wing/zz_generated.deepcopy.go | 367 ++++++++++++++++++ .../fake/fake_machinedeployment.go | 123 ++++++ .../internalversion/fake/fake_machineset.go | 123 ++++++ .../internalversion/fake/fake_wing_client.go | 8 + .../internalversion/generated_expansion.go | 4 + .../wing/internalversion/machinedeployment.go | 157 ++++++++ .../typed/wing/internalversion/machineset.go | 157 ++++++++ .../typed/wing/internalversion/wing_client.go | 10 + .../v1alpha1/fake/fake_machinedeployment.go | 123 ++++++ .../wing/v1alpha1/fake/fake_machineset.go | 123 ++++++ .../wing/v1alpha1/fake/fake_wing_client.go | 8 + .../wing/v1alpha1/generated_expansion.go | 4 + .../typed/wing/v1alpha1/machinedeployment.go | 157 ++++++++ .../typed/wing/v1alpha1/machineset.go | 157 ++++++++ .../typed/wing/v1alpha1/wing_client.go | 10 + .../externalversions/apis/interface.go | 32 ++ .../externalversions/apis/wing/interface.go | 45 +++ .../externalversions/apis/wing/machine.go | 74 ++++ .../apis/wing/machinedeployment.go | 74 ++++ .../externalversions/apis/wing/machineset.go | 74 ++++ .../informers/externalversions/factory.go | 10 +- .../informers/externalversions/generic.go | 15 +- .../wing/v1alpha1/interface.go | 14 + .../wing/v1alpha1/machinedeployment.go | 74 ++++ .../wing/v1alpha1/machineset.go | 74 ++++ .../informers/internalversion/factory.go | 4 +- .../informers/internalversion/generic.go | 2 + .../wing/internalversion/interface.go | 7 + .../wing/internalversion/machineset.go | 74 ++++ .../internalversion/expansion_generated.go | 16 + .../wing/internalversion/machinedeployment.go | 80 ++++ .../wing/internalversion/machineset.go | 80 ++++ .../wing/v1alpha1/expansion_generated.go | 16 + .../wing/v1alpha1/machinedeployment.go | 80 ++++ .../listers/wing/v1alpha1/machineset.go | 80 ++++ 45 files changed, 3687 insertions(+), 6 deletions(-) create mode 100644 pkg/apis/wing/common/consts.go rename pkg/apis/wing/{types.go => machine_types.go} (100%) create mode 100644 pkg/apis/wing/machinedeployment_types.go create mode 100644 pkg/apis/wing/machineset_types.go rename pkg/apis/wing/v1alpha1/{types.go => machine_types.go} (100%) create mode 100644 pkg/apis/wing/v1alpha1/machinedeployment_types.go create mode 100644 pkg/apis/wing/v1alpha1/machineset_types.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machinedeployment.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machineset.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machinedeployment.go create mode 100644 pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machineset.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machinedeployment.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machineset.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machinedeployment.go create mode 100644 pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machineset.go create mode 100644 pkg/wing/client/informers/externalversions/apis/interface.go create mode 100644 pkg/wing/client/informers/externalversions/apis/wing/interface.go create mode 100644 pkg/wing/client/informers/externalversions/apis/wing/machine.go create mode 100644 pkg/wing/client/informers/externalversions/apis/wing/machinedeployment.go create mode 100644 pkg/wing/client/informers/externalversions/apis/wing/machineset.go create mode 100644 pkg/wing/client/informers/externalversions/wing/v1alpha1/machinedeployment.go create mode 100644 pkg/wing/client/informers/externalversions/wing/v1alpha1/machineset.go create mode 100644 pkg/wing/client/informers/internalversion/wing/internalversion/machineset.go create mode 100644 pkg/wing/client/listers/wing/internalversion/machinedeployment.go create mode 100644 pkg/wing/client/listers/wing/internalversion/machineset.go create mode 100644 pkg/wing/client/listers/wing/v1alpha1/machinedeployment.go create mode 100644 pkg/wing/client/listers/wing/v1alpha1/machineset.go diff --git a/docs/generated/cmd/wing/wing_server.rst b/docs/generated/cmd/wing/wing_server.rst index 97a3dffbee..92edee4a11 100644 --- a/docs/generated/cmd/wing/wing_server.rst +++ b/docs/generated/cmd/wing/wing_server.rst @@ -20,7 +20,7 @@ Options :: - --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. Within each phase, the plugins will run in the order in which they are passed to this flag. Comma-delimited list of: Initializers, InstanceInitTime, MutatingAdmissionWebhook, NamespaceLifecycle, ValidatingAdmissionWebhook. (default [InstanceInitTime]) + --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. Within each phase, the plugins will run in the order in which they are passed to this flag. Comma-delimited list of: Initializers, MachineInitTime, MutatingAdmissionWebhook, NamespaceLifecycle, ValidatingAdmissionWebhook. (default [MachineInitTime]) --admission-control-config-file string File with admission control configuration. --bind-address ip The IP address on which to listen for the --secure-port port. The associated interface(s) must be reachable by the rest of the cluster, and by CLI/web clients. If blank, all interfaces will be used (0.0.0.0). (default 0.0.0.0) --cert-dir string The directory where the TLS certs are located. If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored. (default "apiserver.local.config/certificates") diff --git a/pkg/apis/wing/common/consts.go b/pkg/apis/wing/common/consts.go new file mode 100644 index 0000000000..4480164021 --- /dev/null +++ b/pkg/apis/wing/common/consts.go @@ -0,0 +1,17 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package common + +type MachineStatusError string +type MachineManifestState string + +type MachineDeploymentStrategyType string + +const ( + MachineManifestStateConverging = MachineManifestState("converging") + MachineManifestStateConverged = MachineManifestState("converged") + MachineManifestStateError = MachineManifestState("error") + + // Replace the old MachineSet by new one using rolling update + // i.e gradually scale down the old MachineSet and scale up the new one. + RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" +) diff --git a/pkg/apis/wing/types.go b/pkg/apis/wing/machine_types.go similarity index 100% rename from pkg/apis/wing/types.go rename to pkg/apis/wing/machine_types.go diff --git a/pkg/apis/wing/machinedeployment_types.go b/pkg/apis/wing/machinedeployment_types.go new file mode 100644 index 0000000000..3ede095a93 --- /dev/null +++ b/pkg/apis/wing/machinedeployment_types.go @@ -0,0 +1,155 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package wing + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" +) + +// MachineDeploymentSpec defines the desired state of MachineDeployment +type MachineDeploymentSpec struct { + // Number of desired machines. Defaults to 1. + // This is a pointer to distinguish between explicit zero and not specified. + Replicas *int32 + + // Label selector for machines. Existing MachineSets whose machines are + // selected by this will be the ones affected by this deployment. + // It must match the machine template's labels. + Selector metav1.LabelSelector + + // Template describes the machines that will be created. + Template MachineTemplateSpec + + // The deployment strategy to use to replace existing machines with + // new ones. + // +optional + Strategy *MachineDeploymentStrategy + + // Minimum number of seconds for which a newly created machine should + // be ready. + // Defaults to 0 (machine will be considered available as soon as it + // is ready) + // +optional + MinReadySeconds *int32 + + // The number of old MachineSets to retain to allow rollback. + // This is a pointer to distinguish between explicit zero and not specified. + // Defaults to 1. + // +optional + RevisionHistoryLimit *int32 + + // Indicates that the deployment is paused. + // +optional + Paused bool + + // The maximum time in seconds for a deployment to make progress before it + // is considered to be failed. The deployment controller will continue to + // process failed deployments and a condition with a ProgressDeadlineExceeded + // reason will be surfaced in the deployment status. Note that progress will + // not be estimated during the time a deployment is paused. Defaults to 600s. + ProgressDeadlineSeconds *int32 +} + +type MachineDeploymentStrategy struct { + // Type of deployment. Currently the only supported strategy is + // "RollingUpdate". + // Default is RollingUpdate. + // +optional + Type common.MachineDeploymentStrategyType + + // Rolling update config params. Present only if + // MachineDeploymentStrategyType = RollingUpdate. + // +optional + RollingUpdate *MachineRollingUpdateDeployment +} + +// Spec to control the desired behavior of rolling update. +type MachineRollingUpdateDeployment struct { + // The maximum number of machines that can be unavailable during the update. + // Value can be an absolute number (ex: 5) or a percentage of desired + // machines (ex: 10%). + // Absolute number is calculated from percentage by rounding down. + // This can not be 0 if MaxSurge is 0. + // Defaults to 0. + // Example: when this is set to 30%, the old MachineSet can be scaled + // down to 70% of desired machines immediately when the rolling update + // starts. Once new machines are ready, old MachineSet can be scaled + // down further, followed by scaling up the new MachineSet, ensuring + // that the total number of machines available at all times + // during the update is at least 70% of desired machines. + // +optional + MaxUnavailable *intstr.IntOrString + + // The maximum number of machines that can be scheduled above the + // desired number of machines. + // Value can be an absolute number (ex: 5) or a percentage of + // desired machines (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up. + // Defaults to 1. + // Example: when this is set to 30%, the new MachineSet can be scaled + // up immediately when the rolling update starts, such that the total + // number of old and new machines do not exceed 130% of desired + // machines. Once old machines have been killed, new MachineSet can + // be scaled up further, ensuring that total number of machines running + // at any time during the update is at most 130% of desired machines. + // +optional + MaxSurge *intstr.IntOrString +} + +type MachineDeploymentStatus struct { + // The generation observed by the deployment controller. + // +optional + ObservedGeneration int64 + + // Total number of non-terminated machines targeted by this deployment + // (their labels match the selector). + // +optional + Replicas int32 + + // Total number of non-terminated machines targeted by this deployment + // that have the desired template spec. + // +optional + UpdatedReplicas int32 + + // Total number of ready machines targeted by this deployment. + // +optional + ReadyReplicas int32 + + // Total number of available machines (ready for at least minReadySeconds) + // targeted by this deployment. + // +optional + AvailableReplicas int32 + + // Total number of unavailable machines targeted by this deployment. + // This is the total number of machines that are still required for + // the deployment to have 100% available capacity. They may either + // be machines that are running but not yet available or machines + // that still have not been created. + // +optional + UnavailableReplicas int32 +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineDeployment is the Schema for the machinedeployments API +// +k8s:openapi-gen=true +type MachineDeployment struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec *MachineDeploymentSpec + Status *MachineDeploymentStatus +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineDeploymentList contains a list of MachineDeployment +type MachineDeploymentList struct { + metav1.TypeMeta + metav1.ListMeta + Items []MachineDeployment +} diff --git a/pkg/apis/wing/machineset_types.go b/pkg/apis/wing/machineset_types.go new file mode 100644 index 0000000000..a424bb5725 --- /dev/null +++ b/pkg/apis/wing/machineset_types.go @@ -0,0 +1,112 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package wing + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" +) + +// MachineSetSpec defines the desired state of MachineSet +type MachineSetSpec struct { + // Replicas is the number of desired replicas. + // This is a pointer to distinguish between explicit zero and unspecified. + // Defaults to 1. + // +optional + Replicas *int32 + + // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. + // Defaults to 0 (machine will be considered available as soon as it is ready) + // +optional + MinReadySeconds int32 + + // Selector is a label query over machines that should match the replica count. + // Label keys and values that must match in order to be controlled by this MachineSet. + // It must match the machine template's labels. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + Selector metav1.LabelSelector + + // Template is the object that describes the machine that will be created if + // insufficient replicas are detected. + // +optional + Template MachineTemplateSpec +} + +// MachineTemplateSpec describes the data needed to create a Machine from a template +type MachineTemplateSpec struct { + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta + + // Specification of the desired behavior of the machine. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status + Spec MachineSpec +} + +// MachineSetStatus defines the observed state of MachineSet +type MachineSetStatus struct { + // Replicas is the most recently observed number of replicas. + Replicas int32 + + // The number of replicas that have labels matching the labels of the machine template of the MachineSet. + // +optional + FullyLabeledReplicas int32 + + // The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready". + // +optional + ReadyReplicas int32 + + // The number of available replicas (ready for at least minReadySeconds) for this MachineSet. + // +optional + AvailableReplicas int32 + + // ObservedGeneration reflects the generation of the most recently observed MachineSet. + // +optional + ObservedGeneration int64 + + // In the event that there is a terminal problem reconciling the + // replicas, both ErrorReason and ErrorMessage will be set. ErrorReason + // will be populated with a succinct value suitable for machine + // interpretation, while ErrorMessage will contain a more verbose + // string suitable for logging and human consumption. + // + // These fields should not be set for transitive errors that a + // controller faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the MachineTemplates's spec or the configuration of + // the machine controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the machine controller, or the + // responsible machine controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the MachineSet object and/or logged in the + // controller's output. + // +optional + ErrorReason common.MachineStatusError + // +optional + ErrorMessage *string +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSet is the Schema for the machinesets API +// +k8s:openapi-gen=true +type MachineSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *MachineSetSpec `json:"spec,omitempty"` + Status *MachineSetStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSetList contains a list of MachineSet +type MachineSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MachineSet `json:"items"` +} diff --git a/pkg/apis/wing/v1alpha1/types.go b/pkg/apis/wing/v1alpha1/machine_types.go similarity index 100% rename from pkg/apis/wing/v1alpha1/types.go rename to pkg/apis/wing/v1alpha1/machine_types.go diff --git a/pkg/apis/wing/v1alpha1/machinedeployment_types.go b/pkg/apis/wing/v1alpha1/machinedeployment_types.go new file mode 100644 index 0000000000..c13db04766 --- /dev/null +++ b/pkg/apis/wing/v1alpha1/machinedeployment_types.go @@ -0,0 +1,155 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" +) + +// MachineDeploymentSpec defines the desired state of MachineDeployment +type MachineDeploymentSpec struct { + // Number of desired machines. Defaults to 1. + // This is a pointer to distinguish between explicit zero and not specified. + Replicas *int32 `json:"replicas,omitempty"` + + // Label selector for machines. Existing MachineSets whose machines are + // selected by this will be the ones affected by this deployment. + // It must match the machine template's labels. + Selector metav1.LabelSelector `json:"selector"` + + // Template describes the machines that will be created. + Template MachineTemplateSpec `json:"template"` + + // The deployment strategy to use to replace existing machines with + // new ones. + // +optional + Strategy *MachineDeploymentStrategy `json:"strategy,omitempty"` + + // Minimum number of seconds for which a newly created machine should + // be ready. + // Defaults to 0 (machine will be considered available as soon as it + // is ready) + // +optional + MinReadySeconds *int32 `json:"minReadySeconds,omitempty"` + + // The number of old MachineSets to retain to allow rollback. + // This is a pointer to distinguish between explicit zero and not specified. + // Defaults to 1. + // +optional + RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"` + + // Indicates that the deployment is paused. + // +optional + Paused bool `json:"paused,omitempty"` + + // The maximum time in seconds for a deployment to make progress before it + // is considered to be failed. The deployment controller will continue to + // process failed deployments and a condition with a ProgressDeadlineExceeded + // reason will be surfaced in the deployment status. Note that progress will + // not be estimated during the time a deployment is paused. Defaults to 600s. + ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty"` +} + +type MachineDeploymentStrategy struct { + // Type of deployment. Currently the only supported strategy is + // "RollingUpdate". + // Default is RollingUpdate. + // +optional + Type common.MachineDeploymentStrategyType `json:"type,omitempty"` + + // Rolling update config params. Present only if + // MachineDeploymentStrategyType = RollingUpdate. + // +optional + RollingUpdate *MachineRollingUpdateDeployment `json:"rollingUpdate,omitempty"` +} + +// Spec to control the desired behavior of rolling update. +type MachineRollingUpdateDeployment struct { + // The maximum number of machines that can be unavailable during the update. + // Value can be an absolute number (ex: 5) or a percentage of desired + // machines (ex: 10%). + // Absolute number is calculated from percentage by rounding down. + // This can not be 0 if MaxSurge is 0. + // Defaults to 0. + // Example: when this is set to 30%, the old MachineSet can be scaled + // down to 70% of desired machines immediately when the rolling update + // starts. Once new machines are ready, old MachineSet can be scaled + // down further, followed by scaling up the new MachineSet, ensuring + // that the total number of machines available at all times + // during the update is at least 70% of desired machines. + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` + + // The maximum number of machines that can be scheduled above the + // desired number of machines. + // Value can be an absolute number (ex: 5) or a percentage of + // desired machines (ex: 10%). + // This can not be 0 if MaxUnavailable is 0. + // Absolute number is calculated from percentage by rounding up. + // Defaults to 1. + // Example: when this is set to 30%, the new MachineSet can be scaled + // up immediately when the rolling update starts, such that the total + // number of old and new machines do not exceed 130% of desired + // machines. Once old machines have been killed, new MachineSet can + // be scaled up further, ensuring that total number of machines running + // at any time during the update is at most 130% of desired machines. + // +optional + MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` +} + +type MachineDeploymentStatus struct { + // The generation observed by the deployment controller. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,1,opt,name=observedGeneration"` + + // Total number of non-terminated machines targeted by this deployment + // (their labels match the selector). + // +optional + Replicas int32 `json:"replicas,omitempty" protobuf:"varint,2,opt,name=replicas"` + + // Total number of non-terminated machines targeted by this deployment + // that have the desired template spec. + // +optional + UpdatedReplicas int32 `json:"updatedReplicas,omitempty" protobuf:"varint,3,opt,name=updatedReplicas"` + + // Total number of ready machines targeted by this deployment. + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,7,opt,name=readyReplicas"` + + // Total number of available machines (ready for at least minReadySeconds) + // targeted by this deployment. + // +optional + AvailableReplicas int32 `json:"availableReplicas,omitempty" protobuf:"varint,4,opt,name=availableReplicas"` + + // Total number of unavailable machines targeted by this deployment. + // This is the total number of machines that are still required for + // the deployment to have 100% available capacity. They may either + // be machines that are running but not yet available or machines + // that still have not been created. + // +optional + UnavailableReplicas int32 `json:"unavailableReplicas,omitempty" protobuf:"varint,5,opt,name=unavailableReplicas"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineDeployment is the Schema for the machinedeployments API +// +k8s:openapi-gen=true +type MachineDeployment struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *MachineDeploymentSpec `json:"spec,omitempty"` + Status *MachineDeploymentStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineDeploymentList contains a list of MachineDeployment +type MachineDeploymentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MachineDeployment `json:"items"` +} diff --git a/pkg/apis/wing/v1alpha1/machineset_types.go b/pkg/apis/wing/v1alpha1/machineset_types.go new file mode 100644 index 0000000000..925de5d135 --- /dev/null +++ b/pkg/apis/wing/v1alpha1/machineset_types.go @@ -0,0 +1,113 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" +) + +// MachineSetSpec defines the desired state of MachineSet +type MachineSetSpec struct { + // Replicas is the number of desired replicas. + // This is a pointer to distinguish between explicit zero and unspecified. + // Defaults to 1. + // +optional + Replicas *int32 `json:"replicas,omitempty"` + + // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. + // Defaults to 0 (machine will be considered available as soon as it is ready) + // +optional + MinReadySeconds int32 `json:"minReadySeconds,omitempty"` + + // Selector is a label query over machines that should match the replica count. + // Label keys and values that must match in order to be controlled by this MachineSet. + // It must match the machine template's labels. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + Selector metav1.LabelSelector `json:"selector"` + + // Template is the object that describes the machine that will be created if + // insufficient replicas are detected. + // +optional + Template MachineTemplateSpec `json:"template,omitempty"` +} + +// MachineTemplateSpec describes the data needed to create a Machine from a template +type MachineTemplateSpec struct { + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Specification of the desired behavior of the machine. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status + Spec MachineSpec `json:"spec,omitempty"` +} + +// MachineSetStatus defines the observed state of MachineSet +type MachineSetStatus struct { + // Replicas is the most recently observed number of replicas. + Replicas int32 `json:"replicas"` + + // The number of replicas that have labels matching the labels of the machine template of the MachineSet. + // +optional + FullyLabeledReplicas int32 `json:"fullyLabeledReplicas,omitempty"` + + // The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready". + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty"` + + // The number of available replicas (ready for at least minReadySeconds) for this MachineSet. + // +optional + AvailableReplicas int32 `json:"availableReplicas,omitempty"` + + // ObservedGeneration reflects the generation of the most recently observed MachineSet. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // In the event that there is a terminal problem reconciling the + // replicas, both ErrorReason and ErrorMessage will be set. ErrorReason + // will be populated with a succinct value suitable for machine + // interpretation, while ErrorMessage will contain a more verbose + // string suitable for logging and human consumption. + // + // These fields should not be set for transitive errors that a + // controller faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the MachineTemplates's spec or the configuration of + // the machine controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the machine controller, or the + // responsible machine controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the MachineSet object and/or logged in the + // controller's output. + // +optional + ErrorReason common.MachineStatusError `json:"errorReason,omitempty"` + //ErrorReason *string `json:"errorReason,omitempty"` + // +optional + ErrorMessage *string `json:"errorMessage,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSet is the Schema for the machinesets API +// +k8s:openapi-gen=true +type MachineSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec *MachineSetSpec `json:"spec,omitempty"` + Status *MachineSetStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSetList contains a list of MachineSet +type MachineSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MachineSet `json:"items"` +} diff --git a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go index 7a1b986d7a..3d8fb397f7 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go @@ -8,8 +8,10 @@ package v1alpha1 import ( wing "github.com/jetstack/tarmak/pkg/apis/wing" + common "github.com/jetstack/tarmak/pkg/apis/wing/common" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" unsafe "unsafe" ) @@ -23,8 +25,28 @@ func RegisterConversions(scheme *runtime.Scheme) error { return scheme.AddGeneratedConversionFuncs( Convert_v1alpha1_Machine_To_wing_Machine, Convert_wing_Machine_To_v1alpha1_Machine, + Convert_v1alpha1_MachineDeployment_To_wing_MachineDeployment, + Convert_wing_MachineDeployment_To_v1alpha1_MachineDeployment, + Convert_v1alpha1_MachineDeploymentList_To_wing_MachineDeploymentList, + Convert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList, + Convert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec, + Convert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec, + Convert_v1alpha1_MachineDeploymentStatus_To_wing_MachineDeploymentStatus, + Convert_wing_MachineDeploymentStatus_To_v1alpha1_MachineDeploymentStatus, + Convert_v1alpha1_MachineDeploymentStrategy_To_wing_MachineDeploymentStrategy, + Convert_wing_MachineDeploymentStrategy_To_v1alpha1_MachineDeploymentStrategy, Convert_v1alpha1_MachineList_To_wing_MachineList, Convert_wing_MachineList_To_v1alpha1_MachineList, + Convert_v1alpha1_MachineRollingUpdateDeployment_To_wing_MachineRollingUpdateDeployment, + Convert_wing_MachineRollingUpdateDeployment_To_v1alpha1_MachineRollingUpdateDeployment, + Convert_v1alpha1_MachineSet_To_wing_MachineSet, + Convert_wing_MachineSet_To_v1alpha1_MachineSet, + Convert_v1alpha1_MachineSetList_To_wing_MachineSetList, + Convert_wing_MachineSetList_To_v1alpha1_MachineSetList, + Convert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec, + Convert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec, + Convert_v1alpha1_MachineSetStatus_To_wing_MachineSetStatus, + Convert_wing_MachineSetStatus_To_v1alpha1_MachineSetStatus, Convert_v1alpha1_MachineSpec_To_wing_MachineSpec, Convert_wing_MachineSpec_To_v1alpha1_MachineSpec, Convert_v1alpha1_MachineSpecManifest_To_wing_MachineSpecManifest, @@ -33,6 +55,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_wing_MachineStatus_To_v1alpha1_MachineStatus, Convert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest, Convert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest, + Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec, + Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec, ) } @@ -64,6 +88,142 @@ func Convert_wing_Machine_To_v1alpha1_Machine(in *wing.Machine, out *Machine, s return autoConvert_wing_Machine_To_v1alpha1_Machine(in, out, s) } +func autoConvert_v1alpha1_MachineDeployment_To_wing_MachineDeployment(in *MachineDeployment, out *wing.MachineDeployment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Spec = (*wing.MachineDeploymentSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*wing.MachineDeploymentStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_v1alpha1_MachineDeployment_To_wing_MachineDeployment is an autogenerated conversion function. +func Convert_v1alpha1_MachineDeployment_To_wing_MachineDeployment(in *MachineDeployment, out *wing.MachineDeployment, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineDeployment_To_wing_MachineDeployment(in, out, s) +} + +func autoConvert_wing_MachineDeployment_To_v1alpha1_MachineDeployment(in *wing.MachineDeployment, out *MachineDeployment, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Spec = (*MachineDeploymentSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*MachineDeploymentStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_wing_MachineDeployment_To_v1alpha1_MachineDeployment is an autogenerated conversion function. +func Convert_wing_MachineDeployment_To_v1alpha1_MachineDeployment(in *wing.MachineDeployment, out *MachineDeployment, s conversion.Scope) error { + return autoConvert_wing_MachineDeployment_To_v1alpha1_MachineDeployment(in, out, s) +} + +func autoConvert_v1alpha1_MachineDeploymentList_To_wing_MachineDeploymentList(in *MachineDeploymentList, out *wing.MachineDeploymentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]wing.MachineDeployment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_MachineDeploymentList_To_wing_MachineDeploymentList is an autogenerated conversion function. +func Convert_v1alpha1_MachineDeploymentList_To_wing_MachineDeploymentList(in *MachineDeploymentList, out *wing.MachineDeploymentList, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineDeploymentList_To_wing_MachineDeploymentList(in, out, s) +} + +func autoConvert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList(in *wing.MachineDeploymentList, out *MachineDeploymentList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]MachineDeployment)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList is an autogenerated conversion function. +func Convert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList(in *wing.MachineDeploymentList, out *MachineDeploymentList, s conversion.Scope) error { + return autoConvert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList(in, out, s) +} + +func autoConvert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec(in *MachineDeploymentSpec, out *wing.MachineDeploymentSpec, s conversion.Scope) error { + out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.Selector = in.Selector + if err := Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { + return err + } + out.Strategy = (*wing.MachineDeploymentStrategy)(unsafe.Pointer(in.Strategy)) + out.MinReadySeconds = (*int32)(unsafe.Pointer(in.MinReadySeconds)) + out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit)) + out.Paused = in.Paused + out.ProgressDeadlineSeconds = (*int32)(unsafe.Pointer(in.ProgressDeadlineSeconds)) + return nil +} + +// Convert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec is an autogenerated conversion function. +func Convert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec(in *MachineDeploymentSpec, out *wing.MachineDeploymentSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec(in, out, s) +} + +func autoConvert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec(in *wing.MachineDeploymentSpec, out *MachineDeploymentSpec, s conversion.Scope) error { + out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.Selector = in.Selector + if err := Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { + return err + } + out.Strategy = (*MachineDeploymentStrategy)(unsafe.Pointer(in.Strategy)) + out.MinReadySeconds = (*int32)(unsafe.Pointer(in.MinReadySeconds)) + out.RevisionHistoryLimit = (*int32)(unsafe.Pointer(in.RevisionHistoryLimit)) + out.Paused = in.Paused + out.ProgressDeadlineSeconds = (*int32)(unsafe.Pointer(in.ProgressDeadlineSeconds)) + return nil +} + +// Convert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec is an autogenerated conversion function. +func Convert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec(in *wing.MachineDeploymentSpec, out *MachineDeploymentSpec, s conversion.Scope) error { + return autoConvert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec(in, out, s) +} + +func autoConvert_v1alpha1_MachineDeploymentStatus_To_wing_MachineDeploymentStatus(in *MachineDeploymentStatus, out *wing.MachineDeploymentStatus, s conversion.Scope) error { + out.ObservedGeneration = in.ObservedGeneration + out.Replicas = in.Replicas + out.UpdatedReplicas = in.UpdatedReplicas + out.ReadyReplicas = in.ReadyReplicas + out.AvailableReplicas = in.AvailableReplicas + out.UnavailableReplicas = in.UnavailableReplicas + return nil +} + +// Convert_v1alpha1_MachineDeploymentStatus_To_wing_MachineDeploymentStatus is an autogenerated conversion function. +func Convert_v1alpha1_MachineDeploymentStatus_To_wing_MachineDeploymentStatus(in *MachineDeploymentStatus, out *wing.MachineDeploymentStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineDeploymentStatus_To_wing_MachineDeploymentStatus(in, out, s) +} + +func autoConvert_wing_MachineDeploymentStatus_To_v1alpha1_MachineDeploymentStatus(in *wing.MachineDeploymentStatus, out *MachineDeploymentStatus, s conversion.Scope) error { + out.ObservedGeneration = in.ObservedGeneration + out.Replicas = in.Replicas + out.UpdatedReplicas = in.UpdatedReplicas + out.ReadyReplicas = in.ReadyReplicas + out.AvailableReplicas = in.AvailableReplicas + out.UnavailableReplicas = in.UnavailableReplicas + return nil +} + +// Convert_wing_MachineDeploymentStatus_To_v1alpha1_MachineDeploymentStatus is an autogenerated conversion function. +func Convert_wing_MachineDeploymentStatus_To_v1alpha1_MachineDeploymentStatus(in *wing.MachineDeploymentStatus, out *MachineDeploymentStatus, s conversion.Scope) error { + return autoConvert_wing_MachineDeploymentStatus_To_v1alpha1_MachineDeploymentStatus(in, out, s) +} + +func autoConvert_v1alpha1_MachineDeploymentStrategy_To_wing_MachineDeploymentStrategy(in *MachineDeploymentStrategy, out *wing.MachineDeploymentStrategy, s conversion.Scope) error { + out.Type = common.MachineDeploymentStrategyType(in.Type) + out.RollingUpdate = (*wing.MachineRollingUpdateDeployment)(unsafe.Pointer(in.RollingUpdate)) + return nil +} + +// Convert_v1alpha1_MachineDeploymentStrategy_To_wing_MachineDeploymentStrategy is an autogenerated conversion function. +func Convert_v1alpha1_MachineDeploymentStrategy_To_wing_MachineDeploymentStrategy(in *MachineDeploymentStrategy, out *wing.MachineDeploymentStrategy, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineDeploymentStrategy_To_wing_MachineDeploymentStrategy(in, out, s) +} + +func autoConvert_wing_MachineDeploymentStrategy_To_v1alpha1_MachineDeploymentStrategy(in *wing.MachineDeploymentStrategy, out *MachineDeploymentStrategy, s conversion.Scope) error { + out.Type = common.MachineDeploymentStrategyType(in.Type) + out.RollingUpdate = (*MachineRollingUpdateDeployment)(unsafe.Pointer(in.RollingUpdate)) + return nil +} + +// Convert_wing_MachineDeploymentStrategy_To_v1alpha1_MachineDeploymentStrategy is an autogenerated conversion function. +func Convert_wing_MachineDeploymentStrategy_To_v1alpha1_MachineDeploymentStrategy(in *wing.MachineDeploymentStrategy, out *MachineDeploymentStrategy, s conversion.Scope) error { + return autoConvert_wing_MachineDeploymentStrategy_To_v1alpha1_MachineDeploymentStrategy(in, out, s) +} + func autoConvert_v1alpha1_MachineList_To_wing_MachineList(in *MachineList, out *wing.MachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta out.Items = *(*[]wing.Machine)(unsafe.Pointer(&in.Items)) @@ -86,6 +246,136 @@ func Convert_wing_MachineList_To_v1alpha1_MachineList(in *wing.MachineList, out return autoConvert_wing_MachineList_To_v1alpha1_MachineList(in, out, s) } +func autoConvert_v1alpha1_MachineRollingUpdateDeployment_To_wing_MachineRollingUpdateDeployment(in *MachineRollingUpdateDeployment, out *wing.MachineRollingUpdateDeployment, s conversion.Scope) error { + out.MaxUnavailable = (*intstr.IntOrString)(unsafe.Pointer(in.MaxUnavailable)) + out.MaxSurge = (*intstr.IntOrString)(unsafe.Pointer(in.MaxSurge)) + return nil +} + +// Convert_v1alpha1_MachineRollingUpdateDeployment_To_wing_MachineRollingUpdateDeployment is an autogenerated conversion function. +func Convert_v1alpha1_MachineRollingUpdateDeployment_To_wing_MachineRollingUpdateDeployment(in *MachineRollingUpdateDeployment, out *wing.MachineRollingUpdateDeployment, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineRollingUpdateDeployment_To_wing_MachineRollingUpdateDeployment(in, out, s) +} + +func autoConvert_wing_MachineRollingUpdateDeployment_To_v1alpha1_MachineRollingUpdateDeployment(in *wing.MachineRollingUpdateDeployment, out *MachineRollingUpdateDeployment, s conversion.Scope) error { + out.MaxUnavailable = (*intstr.IntOrString)(unsafe.Pointer(in.MaxUnavailable)) + out.MaxSurge = (*intstr.IntOrString)(unsafe.Pointer(in.MaxSurge)) + return nil +} + +// Convert_wing_MachineRollingUpdateDeployment_To_v1alpha1_MachineRollingUpdateDeployment is an autogenerated conversion function. +func Convert_wing_MachineRollingUpdateDeployment_To_v1alpha1_MachineRollingUpdateDeployment(in *wing.MachineRollingUpdateDeployment, out *MachineRollingUpdateDeployment, s conversion.Scope) error { + return autoConvert_wing_MachineRollingUpdateDeployment_To_v1alpha1_MachineRollingUpdateDeployment(in, out, s) +} + +func autoConvert_v1alpha1_MachineSet_To_wing_MachineSet(in *MachineSet, out *wing.MachineSet, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Spec = (*wing.MachineSetSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*wing.MachineSetStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_v1alpha1_MachineSet_To_wing_MachineSet is an autogenerated conversion function. +func Convert_v1alpha1_MachineSet_To_wing_MachineSet(in *MachineSet, out *wing.MachineSet, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSet_To_wing_MachineSet(in, out, s) +} + +func autoConvert_wing_MachineSet_To_v1alpha1_MachineSet(in *wing.MachineSet, out *MachineSet, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.Spec = (*MachineSetSpec)(unsafe.Pointer(in.Spec)) + out.Status = (*MachineSetStatus)(unsafe.Pointer(in.Status)) + return nil +} + +// Convert_wing_MachineSet_To_v1alpha1_MachineSet is an autogenerated conversion function. +func Convert_wing_MachineSet_To_v1alpha1_MachineSet(in *wing.MachineSet, out *MachineSet, s conversion.Scope) error { + return autoConvert_wing_MachineSet_To_v1alpha1_MachineSet(in, out, s) +} + +func autoConvert_v1alpha1_MachineSetList_To_wing_MachineSetList(in *MachineSetList, out *wing.MachineSetList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]wing.MachineSet)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_MachineSetList_To_wing_MachineSetList is an autogenerated conversion function. +func Convert_v1alpha1_MachineSetList_To_wing_MachineSetList(in *MachineSetList, out *wing.MachineSetList, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSetList_To_wing_MachineSetList(in, out, s) +} + +func autoConvert_wing_MachineSetList_To_v1alpha1_MachineSetList(in *wing.MachineSetList, out *MachineSetList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]MachineSet)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_wing_MachineSetList_To_v1alpha1_MachineSetList is an autogenerated conversion function. +func Convert_wing_MachineSetList_To_v1alpha1_MachineSetList(in *wing.MachineSetList, out *MachineSetList, s conversion.Scope) error { + return autoConvert_wing_MachineSetList_To_v1alpha1_MachineSetList(in, out, s) +} + +func autoConvert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec(in *MachineSetSpec, out *wing.MachineSetSpec, s conversion.Scope) error { + out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReadySeconds = in.MinReadySeconds + out.Selector = in.Selector + if err := Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec is an autogenerated conversion function. +func Convert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec(in *MachineSetSpec, out *wing.MachineSetSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec(in, out, s) +} + +func autoConvert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec(in *wing.MachineSetSpec, out *MachineSetSpec, s conversion.Scope) error { + out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReadySeconds = in.MinReadySeconds + out.Selector = in.Selector + if err := Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { + return err + } + return nil +} + +// Convert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec is an autogenerated conversion function. +func Convert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec(in *wing.MachineSetSpec, out *MachineSetSpec, s conversion.Scope) error { + return autoConvert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec(in, out, s) +} + +func autoConvert_v1alpha1_MachineSetStatus_To_wing_MachineSetStatus(in *MachineSetStatus, out *wing.MachineSetStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.FullyLabeledReplicas = in.FullyLabeledReplicas + out.ReadyReplicas = in.ReadyReplicas + out.AvailableReplicas = in.AvailableReplicas + out.ObservedGeneration = in.ObservedGeneration + out.ErrorReason = common.MachineStatusError(in.ErrorReason) + out.ErrorMessage = (*string)(unsafe.Pointer(in.ErrorMessage)) + return nil +} + +// Convert_v1alpha1_MachineSetStatus_To_wing_MachineSetStatus is an autogenerated conversion function. +func Convert_v1alpha1_MachineSetStatus_To_wing_MachineSetStatus(in *MachineSetStatus, out *wing.MachineSetStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineSetStatus_To_wing_MachineSetStatus(in, out, s) +} + +func autoConvert_wing_MachineSetStatus_To_v1alpha1_MachineSetStatus(in *wing.MachineSetStatus, out *MachineSetStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.FullyLabeledReplicas = in.FullyLabeledReplicas + out.ReadyReplicas = in.ReadyReplicas + out.AvailableReplicas = in.AvailableReplicas + out.ObservedGeneration = in.ObservedGeneration + out.ErrorReason = common.MachineStatusError(in.ErrorReason) + out.ErrorMessage = (*string)(unsafe.Pointer(in.ErrorMessage)) + return nil +} + +// Convert_wing_MachineSetStatus_To_v1alpha1_MachineSetStatus is an autogenerated conversion function. +func Convert_wing_MachineSetStatus_To_v1alpha1_MachineSetStatus(in *wing.MachineSetStatus, out *MachineSetStatus, s conversion.Scope) error { + return autoConvert_wing_MachineSetStatus_To_v1alpha1_MachineSetStatus(in, out, s) +} + func autoConvert_v1alpha1_MachineSpec_To_wing_MachineSpec(in *MachineSpec, out *wing.MachineSpec, s conversion.Scope) error { out.Converge = (*wing.MachineSpecManifest)(unsafe.Pointer(in.Converge)) out.DryRun = (*wing.MachineSpecManifest)(unsafe.Pointer(in.DryRun)) @@ -181,3 +471,29 @@ func autoConvert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in func Convert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in *wing.MachineStatusManifest, out *MachineStatusManifest, s conversion.Scope) error { return autoConvert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in, out, s) } + +func autoConvert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(in *MachineTemplateSpec, out *wing.MachineTemplateSpec, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_MachineSpec_To_wing_MachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(in *MachineTemplateSpec, out *wing.MachineTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(in, out, s) +} + +func autoConvert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(in *wing.MachineTemplateSpec, out *MachineTemplateSpec, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_wing_MachineSpec_To_v1alpha1_MachineSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec is an autogenerated conversion function. +func Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(in *wing.MachineTemplateSpec, out *MachineTemplateSpec, s conversion.Scope) error { + return autoConvert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(in, out, s) +} diff --git a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go index 850bdcfd95..9cdf87315b 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go @@ -8,6 +8,7 @@ package v1alpha1 import ( runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -55,6 +56,189 @@ func (in *Machine) DeepCopyObject() runtime.Object { } } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeployment) DeepCopyInto(out *MachineDeployment) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentSpec) + (*in).DeepCopyInto(*out) + } + } + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentStatus) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeployment. +func (in *MachineDeployment) DeepCopy() *MachineDeployment { + if in == nil { + return nil + } + out := new(MachineDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineDeployment) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentList) DeepCopyInto(out *MachineDeploymentList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineDeployment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentList. +func (in *MachineDeploymentList) DeepCopy() *MachineDeploymentList { + if in == nil { + return nil + } + out := new(MachineDeploymentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineDeploymentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentSpec) DeepCopyInto(out *MachineDeploymentSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + if in.Strategy != nil { + in, out := &in.Strategy, &out.Strategy + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentStrategy) + (*in).DeepCopyInto(*out) + } + } + if in.MinReadySeconds != nil { + in, out := &in.MinReadySeconds, &out.MinReadySeconds + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.RevisionHistoryLimit != nil { + in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.ProgressDeadlineSeconds != nil { + in, out := &in.ProgressDeadlineSeconds, &out.ProgressDeadlineSeconds + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentSpec. +func (in *MachineDeploymentSpec) DeepCopy() *MachineDeploymentSpec { + if in == nil { + return nil + } + out := new(MachineDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentStatus) DeepCopyInto(out *MachineDeploymentStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentStatus. +func (in *MachineDeploymentStatus) DeepCopy() *MachineDeploymentStatus { + if in == nil { + return nil + } + out := new(MachineDeploymentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentStrategy) DeepCopyInto(out *MachineDeploymentStrategy) { + *out = *in + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + if *in == nil { + *out = nil + } else { + *out = new(MachineRollingUpdateDeployment) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentStrategy. +func (in *MachineDeploymentStrategy) DeepCopy() *MachineDeploymentStrategy { + if in == nil { + return nil + } + out := new(MachineDeploymentStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineList) DeepCopyInto(out *MachineList) { *out = *in @@ -89,6 +273,171 @@ func (in *MachineList) DeepCopyObject() runtime.Object { } } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineRollingUpdateDeployment) DeepCopyInto(out *MachineRollingUpdateDeployment) { + *out = *in + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + if *in == nil { + *out = nil + } else { + *out = new(intstr.IntOrString) + **out = **in + } + } + if in.MaxSurge != nil { + in, out := &in.MaxSurge, &out.MaxSurge + if *in == nil { + *out = nil + } else { + *out = new(intstr.IntOrString) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineRollingUpdateDeployment. +func (in *MachineRollingUpdateDeployment) DeepCopy() *MachineRollingUpdateDeployment { + if in == nil { + return nil + } + out := new(MachineRollingUpdateDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSet) DeepCopyInto(out *MachineSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + if *in == nil { + *out = nil + } else { + *out = new(MachineSetSpec) + (*in).DeepCopyInto(*out) + } + } + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(MachineSetStatus) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSet. +func (in *MachineSet) DeepCopy() *MachineSet { + if in == nil { + return nil + } + out := new(MachineSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetList) DeepCopyInto(out *MachineSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetList. +func (in *MachineSetList) DeepCopy() *MachineSetList { + if in == nil { + return nil + } + out := new(MachineSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetSpec) DeepCopyInto(out *MachineSetSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetSpec. +func (in *MachineSetSpec) DeepCopy() *MachineSetSpec { + if in == nil { + return nil + } + out := new(MachineSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetStatus) DeepCopyInto(out *MachineSetStatus) { + *out = *in + if in.ErrorMessage != nil { + in, out := &in.ErrorMessage, &out.ErrorMessage + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetStatus. +func (in *MachineSetStatus) DeepCopy() *MachineSetStatus { + if in == nil { + return nil + } + out := new(MachineSetStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { *out = *in @@ -200,3 +549,21 @@ func (in *MachineStatusManifest) DeepCopy() *MachineStatusManifest { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineTemplateSpec) DeepCopyInto(out *MachineTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineTemplateSpec. +func (in *MachineTemplateSpec) DeepCopy() *MachineTemplateSpec { + if in == nil { + return nil + } + out := new(MachineTemplateSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/wing/zz_generated.deepcopy.go b/pkg/apis/wing/zz_generated.deepcopy.go index f4a486bef2..90618733a5 100644 --- a/pkg/apis/wing/zz_generated.deepcopy.go +++ b/pkg/apis/wing/zz_generated.deepcopy.go @@ -8,6 +8,7 @@ package wing import ( runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -55,6 +56,189 @@ func (in *Machine) DeepCopyObject() runtime.Object { } } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeployment) DeepCopyInto(out *MachineDeployment) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentSpec) + (*in).DeepCopyInto(*out) + } + } + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentStatus) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeployment. +func (in *MachineDeployment) DeepCopy() *MachineDeployment { + if in == nil { + return nil + } + out := new(MachineDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineDeployment) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentList) DeepCopyInto(out *MachineDeploymentList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineDeployment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentList. +func (in *MachineDeploymentList) DeepCopy() *MachineDeploymentList { + if in == nil { + return nil + } + out := new(MachineDeploymentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineDeploymentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentSpec) DeepCopyInto(out *MachineDeploymentSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + if in.Strategy != nil { + in, out := &in.Strategy, &out.Strategy + if *in == nil { + *out = nil + } else { + *out = new(MachineDeploymentStrategy) + (*in).DeepCopyInto(*out) + } + } + if in.MinReadySeconds != nil { + in, out := &in.MinReadySeconds, &out.MinReadySeconds + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.RevisionHistoryLimit != nil { + in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.ProgressDeadlineSeconds != nil { + in, out := &in.ProgressDeadlineSeconds, &out.ProgressDeadlineSeconds + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentSpec. +func (in *MachineDeploymentSpec) DeepCopy() *MachineDeploymentSpec { + if in == nil { + return nil + } + out := new(MachineDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentStatus) DeepCopyInto(out *MachineDeploymentStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentStatus. +func (in *MachineDeploymentStatus) DeepCopy() *MachineDeploymentStatus { + if in == nil { + return nil + } + out := new(MachineDeploymentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentStrategy) DeepCopyInto(out *MachineDeploymentStrategy) { + *out = *in + if in.RollingUpdate != nil { + in, out := &in.RollingUpdate, &out.RollingUpdate + if *in == nil { + *out = nil + } else { + *out = new(MachineRollingUpdateDeployment) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentStrategy. +func (in *MachineDeploymentStrategy) DeepCopy() *MachineDeploymentStrategy { + if in == nil { + return nil + } + out := new(MachineDeploymentStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineList) DeepCopyInto(out *MachineList) { *out = *in @@ -89,6 +273,171 @@ func (in *MachineList) DeepCopyObject() runtime.Object { } } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineRollingUpdateDeployment) DeepCopyInto(out *MachineRollingUpdateDeployment) { + *out = *in + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + if *in == nil { + *out = nil + } else { + *out = new(intstr.IntOrString) + **out = **in + } + } + if in.MaxSurge != nil { + in, out := &in.MaxSurge, &out.MaxSurge + if *in == nil { + *out = nil + } else { + *out = new(intstr.IntOrString) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineRollingUpdateDeployment. +func (in *MachineRollingUpdateDeployment) DeepCopy() *MachineRollingUpdateDeployment { + if in == nil { + return nil + } + out := new(MachineRollingUpdateDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSet) DeepCopyInto(out *MachineSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + if *in == nil { + *out = nil + } else { + *out = new(MachineSetSpec) + (*in).DeepCopyInto(*out) + } + } + if in.Status != nil { + in, out := &in.Status, &out.Status + if *in == nil { + *out = nil + } else { + *out = new(MachineSetStatus) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSet. +func (in *MachineSet) DeepCopy() *MachineSet { + if in == nil { + return nil + } + out := new(MachineSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetList) DeepCopyInto(out *MachineSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetList. +func (in *MachineSetList) DeepCopy() *MachineSetList { + if in == nil { + return nil + } + out := new(MachineSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } else { + return nil + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetSpec) DeepCopyInto(out *MachineSetSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetSpec. +func (in *MachineSetSpec) DeepCopy() *MachineSetSpec { + if in == nil { + return nil + } + out := new(MachineSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetStatus) DeepCopyInto(out *MachineSetStatus) { + *out = *in + if in.ErrorMessage != nil { + in, out := &in.ErrorMessage, &out.ErrorMessage + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetStatus. +func (in *MachineSetStatus) DeepCopy() *MachineSetStatus { + if in == nil { + return nil + } + out := new(MachineSetStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { *out = *in @@ -200,3 +549,21 @@ func (in *MachineStatusManifest) DeepCopy() *MachineStatusManifest { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineTemplateSpec) DeepCopyInto(out *MachineTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineTemplateSpec. +func (in *MachineTemplateSpec) DeepCopy() *MachineTemplateSpec { + if in == nil { + return nil + } + out := new(MachineTemplateSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machinedeployment.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machinedeployment.go new file mode 100644 index 0000000000..c969515857 --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machinedeployment.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachineDeployments implements MachineDeploymentInterface +type FakeMachineDeployments struct { + Fake *FakeWing + ns string +} + +var machinedeploymentsResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "", Resource: "machinedeployments"} + +var machinedeploymentsKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "", Kind: "MachineDeployment"} + +// Get takes name of the machineDeployment, and returns the corresponding machineDeployment object, and an error if there is any. +func (c *FakeMachineDeployments) Get(name string, options v1.GetOptions) (result *wing.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinedeploymentsResource, c.ns, name), &wing.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineDeployment), err +} + +// List takes label and field selectors, and returns the list of MachineDeployments that match those selectors. +func (c *FakeMachineDeployments) List(opts v1.ListOptions) (result *wing.MachineDeploymentList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinedeploymentsResource, machinedeploymentsKind, c.ns, opts), &wing.MachineDeploymentList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &wing.MachineDeploymentList{} + for _, item := range obj.(*wing.MachineDeploymentList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machineDeployments. +func (c *FakeMachineDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinedeploymentsResource, c.ns, opts)) + +} + +// Create takes the representation of a machineDeployment and creates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *FakeMachineDeployments) Create(machineDeployment *wing.MachineDeployment) (result *wing.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinedeploymentsResource, c.ns, machineDeployment), &wing.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineDeployment), err +} + +// Update takes the representation of a machineDeployment and updates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *FakeMachineDeployments) Update(machineDeployment *wing.MachineDeployment) (result *wing.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinedeploymentsResource, c.ns, machineDeployment), &wing.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineDeployment), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachineDeployments) UpdateStatus(machineDeployment *wing.MachineDeployment) (*wing.MachineDeployment, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinedeploymentsResource, "status", c.ns, machineDeployment), &wing.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineDeployment), err +} + +// Delete takes name of the machineDeployment and deletes it. Returns an error if one occurs. +func (c *FakeMachineDeployments) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinedeploymentsResource, c.ns, name), &wing.MachineDeployment{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachineDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinedeploymentsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &wing.MachineDeploymentList{}) + return err +} + +// Patch applies the patch and returns the patched machineDeployment. +func (c *FakeMachineDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinedeploymentsResource, c.ns, name, data, subresources...), &wing.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineDeployment), err +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machineset.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machineset.go new file mode 100644 index 0000000000..cf93ebbd4c --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_machineset.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachineSets implements MachineSetInterface +type FakeMachineSets struct { + Fake *FakeWing + ns string +} + +var machinesetsResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "", Resource: "machinesets"} + +var machinesetsKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "", Kind: "MachineSet"} + +// Get takes name of the machineSet, and returns the corresponding machineSet object, and an error if there is any. +func (c *FakeMachineSets) Get(name string, options v1.GetOptions) (result *wing.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinesetsResource, c.ns, name), &wing.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineSet), err +} + +// List takes label and field selectors, and returns the list of MachineSets that match those selectors. +func (c *FakeMachineSets) List(opts v1.ListOptions) (result *wing.MachineSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinesetsResource, machinesetsKind, c.ns, opts), &wing.MachineSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &wing.MachineSetList{} + for _, item := range obj.(*wing.MachineSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machineSets. +func (c *FakeMachineSets) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinesetsResource, c.ns, opts)) + +} + +// Create takes the representation of a machineSet and creates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *FakeMachineSets) Create(machineSet *wing.MachineSet) (result *wing.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinesetsResource, c.ns, machineSet), &wing.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineSet), err +} + +// Update takes the representation of a machineSet and updates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *FakeMachineSets) Update(machineSet *wing.MachineSet) (result *wing.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinesetsResource, c.ns, machineSet), &wing.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachineSets) UpdateStatus(machineSet *wing.MachineSet) (*wing.MachineSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinesetsResource, "status", c.ns, machineSet), &wing.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineSet), err +} + +// Delete takes name of the machineSet and deletes it. Returns an error if one occurs. +func (c *FakeMachineSets) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinesetsResource, c.ns, name), &wing.MachineSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachineSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinesetsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &wing.MachineSetList{}) + return err +} + +// Patch applies the patch and returns the patched machineSet. +func (c *FakeMachineSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinesetsResource, c.ns, name, data, subresources...), &wing.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*wing.MachineSet), err +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go index 592861829c..103879c1e7 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/fake/fake_wing_client.go @@ -15,6 +15,14 @@ func (c *FakeWing) Machines(namespace string) internalversion.MachineInterface { return &FakeMachines{c, namespace} } +func (c *FakeWing) MachineDeployments(namespace string) internalversion.MachineDeploymentInterface { + return &FakeMachineDeployments{c, namespace} +} + +func (c *FakeWing) MachineSets(namespace string) internalversion.MachineSetInterface { + return &FakeMachineSets{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeWing) RESTClient() rest.Interface { diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go index f5c985ce65..b0cff6f03a 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/generated_expansion.go @@ -2,3 +2,7 @@ package internalversion type MachineExpansion interface{} + +type MachineDeploymentExpansion interface{} + +type MachineSetExpansion interface{} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machinedeployment.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machinedeployment.go new file mode 100644 index 0000000000..7d4bf2c44c --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machinedeployment.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachineDeploymentsGetter has a method to return a MachineDeploymentInterface. +// A group's client should implement this interface. +type MachineDeploymentsGetter interface { + MachineDeployments(namespace string) MachineDeploymentInterface +} + +// MachineDeploymentInterface has methods to work with MachineDeployment resources. +type MachineDeploymentInterface interface { + Create(*wing.MachineDeployment) (*wing.MachineDeployment, error) + Update(*wing.MachineDeployment) (*wing.MachineDeployment, error) + UpdateStatus(*wing.MachineDeployment) (*wing.MachineDeployment, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*wing.MachineDeployment, error) + List(opts v1.ListOptions) (*wing.MachineDeploymentList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineDeployment, err error) + MachineDeploymentExpansion +} + +// machineDeployments implements MachineDeploymentInterface +type machineDeployments struct { + client rest.Interface + ns string +} + +// newMachineDeployments returns a MachineDeployments +func newMachineDeployments(c *WingClient, namespace string) *machineDeployments { + return &machineDeployments{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machineDeployment, and returns the corresponding machineDeployment object, and an error if there is any. +func (c *machineDeployments) Get(name string, options v1.GetOptions) (result *wing.MachineDeployment, err error) { + result = &wing.MachineDeployment{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of MachineDeployments that match those selectors. +func (c *machineDeployments) List(opts v1.ListOptions) (result *wing.MachineDeploymentList, err error) { + result = &wing.MachineDeploymentList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machineDeployments. +func (c *machineDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machineDeployment and creates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *machineDeployments) Create(machineDeployment *wing.MachineDeployment) (result *wing.MachineDeployment, err error) { + result = &wing.MachineDeployment{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machinedeployments"). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// Update takes the representation of a machineDeployment and updates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *machineDeployments) Update(machineDeployment *wing.MachineDeployment) (result *wing.MachineDeployment, err error) { + result = &wing.MachineDeployment{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(machineDeployment.Name). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machineDeployments) UpdateStatus(machineDeployment *wing.MachineDeployment) (result *wing.MachineDeployment, err error) { + result = &wing.MachineDeployment{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(machineDeployment.Name). + SubResource("status"). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// Delete takes name of the machineDeployment and deletes it. Returns an error if one occurs. +func (c *machineDeployments) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machineDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machineDeployment. +func (c *machineDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineDeployment, err error) { + result = &wing.MachineDeployment{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machinedeployments"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machineset.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machineset.go new file mode 100644 index 0000000000..f014a04e52 --- /dev/null +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/machineset.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachineSetsGetter has a method to return a MachineSetInterface. +// A group's client should implement this interface. +type MachineSetsGetter interface { + MachineSets(namespace string) MachineSetInterface +} + +// MachineSetInterface has methods to work with MachineSet resources. +type MachineSetInterface interface { + Create(*wing.MachineSet) (*wing.MachineSet, error) + Update(*wing.MachineSet) (*wing.MachineSet, error) + UpdateStatus(*wing.MachineSet) (*wing.MachineSet, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*wing.MachineSet, error) + List(opts v1.ListOptions) (*wing.MachineSetList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineSet, err error) + MachineSetExpansion +} + +// machineSets implements MachineSetInterface +type machineSets struct { + client rest.Interface + ns string +} + +// newMachineSets returns a MachineSets +func newMachineSets(c *WingClient, namespace string) *machineSets { + return &machineSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machineSet, and returns the corresponding machineSet object, and an error if there is any. +func (c *machineSets) Get(name string, options v1.GetOptions) (result *wing.MachineSet, err error) { + result = &wing.MachineSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of MachineSets that match those selectors. +func (c *machineSets) List(opts v1.ListOptions) (result *wing.MachineSetList, err error) { + result = &wing.MachineSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machineSets. +func (c *machineSets) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machineSet and creates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *machineSets) Create(machineSet *wing.MachineSet) (result *wing.MachineSet, err error) { + result = &wing.MachineSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machinesets"). + Body(machineSet). + Do(). + Into(result) + return +} + +// Update takes the representation of a machineSet and updates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *machineSets) Update(machineSet *wing.MachineSet) (result *wing.MachineSet, err error) { + result = &wing.MachineSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinesets"). + Name(machineSet.Name). + Body(machineSet). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machineSets) UpdateStatus(machineSet *wing.MachineSet) (result *wing.MachineSet, err error) { + result = &wing.MachineSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinesets"). + Name(machineSet.Name). + SubResource("status"). + Body(machineSet). + Do(). + Into(result) + return +} + +// Delete takes name of the machineSet and deletes it. Returns an error if one occurs. +func (c *machineSets) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinesets"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machineSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machineSet. +func (c *machineSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wing.MachineSet, err error) { + result = &wing.MachineSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machinesets"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go index ca4e3c55f6..00e7093577 100644 --- a/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go +++ b/pkg/wing/client/clientset/internalversion/typed/wing/internalversion/wing_client.go @@ -9,6 +9,8 @@ import ( type WingInterface interface { RESTClient() rest.Interface MachinesGetter + MachineDeploymentsGetter + MachineSetsGetter } // WingClient is used to interact with features provided by the wing.tarmak.io group. @@ -20,6 +22,14 @@ func (c *WingClient) Machines(namespace string) MachineInterface { return newMachines(c, namespace) } +func (c *WingClient) MachineDeployments(namespace string) MachineDeploymentInterface { + return newMachineDeployments(c, namespace) +} + +func (c *WingClient) MachineSets(namespace string) MachineSetInterface { + return newMachineSets(c, namespace) +} + // NewForConfig creates a new WingClient for the given config. func NewForConfig(c *rest.Config) (*WingClient, error) { config := *c diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machinedeployment.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machinedeployment.go new file mode 100644 index 0000000000..d48ff60dc3 --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machinedeployment.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachineDeployments implements MachineDeploymentInterface +type FakeMachineDeployments struct { + Fake *FakeWingV1alpha1 + ns string +} + +var machinedeploymentsResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "v1alpha1", Resource: "machinedeployments"} + +var machinedeploymentsKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "v1alpha1", Kind: "MachineDeployment"} + +// Get takes name of the machineDeployment, and returns the corresponding machineDeployment object, and an error if there is any. +func (c *FakeMachineDeployments) Get(name string, options v1.GetOptions) (result *v1alpha1.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinedeploymentsResource, c.ns, name), &v1alpha1.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineDeployment), err +} + +// List takes label and field selectors, and returns the list of MachineDeployments that match those selectors. +func (c *FakeMachineDeployments) List(opts v1.ListOptions) (result *v1alpha1.MachineDeploymentList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinedeploymentsResource, machinedeploymentsKind, c.ns, opts), &v1alpha1.MachineDeploymentList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.MachineDeploymentList{} + for _, item := range obj.(*v1alpha1.MachineDeploymentList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machineDeployments. +func (c *FakeMachineDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinedeploymentsResource, c.ns, opts)) + +} + +// Create takes the representation of a machineDeployment and creates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *FakeMachineDeployments) Create(machineDeployment *v1alpha1.MachineDeployment) (result *v1alpha1.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinedeploymentsResource, c.ns, machineDeployment), &v1alpha1.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineDeployment), err +} + +// Update takes the representation of a machineDeployment and updates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *FakeMachineDeployments) Update(machineDeployment *v1alpha1.MachineDeployment) (result *v1alpha1.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinedeploymentsResource, c.ns, machineDeployment), &v1alpha1.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineDeployment), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachineDeployments) UpdateStatus(machineDeployment *v1alpha1.MachineDeployment) (*v1alpha1.MachineDeployment, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinedeploymentsResource, "status", c.ns, machineDeployment), &v1alpha1.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineDeployment), err +} + +// Delete takes name of the machineDeployment and deletes it. Returns an error if one occurs. +func (c *FakeMachineDeployments) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinedeploymentsResource, c.ns, name), &v1alpha1.MachineDeployment{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachineDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinedeploymentsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.MachineDeploymentList{}) + return err +} + +// Patch applies the patch and returns the patched machineDeployment. +func (c *FakeMachineDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineDeployment, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinedeploymentsResource, c.ns, name, data, subresources...), &v1alpha1.MachineDeployment{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineDeployment), err +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machineset.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machineset.go new file mode 100644 index 0000000000..4f11c21bc4 --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_machineset.go @@ -0,0 +1,123 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package fake + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMachineSets implements MachineSetInterface +type FakeMachineSets struct { + Fake *FakeWingV1alpha1 + ns string +} + +var machinesetsResource = schema.GroupVersionResource{Group: "wing.tarmak.io", Version: "v1alpha1", Resource: "machinesets"} + +var machinesetsKind = schema.GroupVersionKind{Group: "wing.tarmak.io", Version: "v1alpha1", Kind: "MachineSet"} + +// Get takes name of the machineSet, and returns the corresponding machineSet object, and an error if there is any. +func (c *FakeMachineSets) Get(name string, options v1.GetOptions) (result *v1alpha1.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(machinesetsResource, c.ns, name), &v1alpha1.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineSet), err +} + +// List takes label and field selectors, and returns the list of MachineSets that match those selectors. +func (c *FakeMachineSets) List(opts v1.ListOptions) (result *v1alpha1.MachineSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(machinesetsResource, machinesetsKind, c.ns, opts), &v1alpha1.MachineSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.MachineSetList{} + for _, item := range obj.(*v1alpha1.MachineSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested machineSets. +func (c *FakeMachineSets) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(machinesetsResource, c.ns, opts)) + +} + +// Create takes the representation of a machineSet and creates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *FakeMachineSets) Create(machineSet *v1alpha1.MachineSet) (result *v1alpha1.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(machinesetsResource, c.ns, machineSet), &v1alpha1.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineSet), err +} + +// Update takes the representation of a machineSet and updates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *FakeMachineSets) Update(machineSet *v1alpha1.MachineSet) (result *v1alpha1.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(machinesetsResource, c.ns, machineSet), &v1alpha1.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeMachineSets) UpdateStatus(machineSet *v1alpha1.MachineSet) (*v1alpha1.MachineSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(machinesetsResource, "status", c.ns, machineSet), &v1alpha1.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineSet), err +} + +// Delete takes name of the machineSet and deletes it. Returns an error if one occurs. +func (c *FakeMachineSets) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(machinesetsResource, c.ns, name), &v1alpha1.MachineSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMachineSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(machinesetsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.MachineSetList{}) + return err +} + +// Patch applies the patch and returns the patched machineSet. +func (c *FakeMachineSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(machinesetsResource, c.ns, name, data, subresources...), &v1alpha1.MachineSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MachineSet), err +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go index 3e661f5271..fbb5605244 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/fake/fake_wing_client.go @@ -15,6 +15,14 @@ func (c *FakeWingV1alpha1) Machines(namespace string) v1alpha1.MachineInterface return &FakeMachines{c, namespace} } +func (c *FakeWingV1alpha1) MachineDeployments(namespace string) v1alpha1.MachineDeploymentInterface { + return &FakeMachineDeployments{c, namespace} +} + +func (c *FakeWingV1alpha1) MachineSets(namespace string) v1alpha1.MachineSetInterface { + return &FakeMachineSets{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeWingV1alpha1) RESTClient() rest.Interface { diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go index 0df983be7e..afcc92ee13 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/generated_expansion.go @@ -2,3 +2,7 @@ package v1alpha1 type MachineExpansion interface{} + +type MachineDeploymentExpansion interface{} + +type MachineSetExpansion interface{} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machinedeployment.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machinedeployment.go new file mode 100644 index 0000000000..c659b2460c --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machinedeployment.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachineDeploymentsGetter has a method to return a MachineDeploymentInterface. +// A group's client should implement this interface. +type MachineDeploymentsGetter interface { + MachineDeployments(namespace string) MachineDeploymentInterface +} + +// MachineDeploymentInterface has methods to work with MachineDeployment resources. +type MachineDeploymentInterface interface { + Create(*v1alpha1.MachineDeployment) (*v1alpha1.MachineDeployment, error) + Update(*v1alpha1.MachineDeployment) (*v1alpha1.MachineDeployment, error) + UpdateStatus(*v1alpha1.MachineDeployment) (*v1alpha1.MachineDeployment, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.MachineDeployment, error) + List(opts v1.ListOptions) (*v1alpha1.MachineDeploymentList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineDeployment, err error) + MachineDeploymentExpansion +} + +// machineDeployments implements MachineDeploymentInterface +type machineDeployments struct { + client rest.Interface + ns string +} + +// newMachineDeployments returns a MachineDeployments +func newMachineDeployments(c *WingV1alpha1Client, namespace string) *machineDeployments { + return &machineDeployments{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machineDeployment, and returns the corresponding machineDeployment object, and an error if there is any. +func (c *machineDeployments) Get(name string, options v1.GetOptions) (result *v1alpha1.MachineDeployment, err error) { + result = &v1alpha1.MachineDeployment{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of MachineDeployments that match those selectors. +func (c *machineDeployments) List(opts v1.ListOptions) (result *v1alpha1.MachineDeploymentList, err error) { + result = &v1alpha1.MachineDeploymentList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machineDeployments. +func (c *machineDeployments) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machineDeployment and creates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *machineDeployments) Create(machineDeployment *v1alpha1.MachineDeployment) (result *v1alpha1.MachineDeployment, err error) { + result = &v1alpha1.MachineDeployment{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machinedeployments"). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// Update takes the representation of a machineDeployment and updates it. Returns the server's representation of the machineDeployment, and an error, if there is any. +func (c *machineDeployments) Update(machineDeployment *v1alpha1.MachineDeployment) (result *v1alpha1.MachineDeployment, err error) { + result = &v1alpha1.MachineDeployment{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(machineDeployment.Name). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machineDeployments) UpdateStatus(machineDeployment *v1alpha1.MachineDeployment) (result *v1alpha1.MachineDeployment, err error) { + result = &v1alpha1.MachineDeployment{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(machineDeployment.Name). + SubResource("status"). + Body(machineDeployment). + Do(). + Into(result) + return +} + +// Delete takes name of the machineDeployment and deletes it. Returns an error if one occurs. +func (c *machineDeployments) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinedeployments"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machineDeployments) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinedeployments"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machineDeployment. +func (c *machineDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineDeployment, err error) { + result = &v1alpha1.MachineDeployment{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machinedeployments"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machineset.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machineset.go new file mode 100644 index 0000000000..9b86627633 --- /dev/null +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/machineset.go @@ -0,0 +1,157 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + scheme "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MachineSetsGetter has a method to return a MachineSetInterface. +// A group's client should implement this interface. +type MachineSetsGetter interface { + MachineSets(namespace string) MachineSetInterface +} + +// MachineSetInterface has methods to work with MachineSet resources. +type MachineSetInterface interface { + Create(*v1alpha1.MachineSet) (*v1alpha1.MachineSet, error) + Update(*v1alpha1.MachineSet) (*v1alpha1.MachineSet, error) + UpdateStatus(*v1alpha1.MachineSet) (*v1alpha1.MachineSet, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.MachineSet, error) + List(opts v1.ListOptions) (*v1alpha1.MachineSetList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineSet, err error) + MachineSetExpansion +} + +// machineSets implements MachineSetInterface +type machineSets struct { + client rest.Interface + ns string +} + +// newMachineSets returns a MachineSets +func newMachineSets(c *WingV1alpha1Client, namespace string) *machineSets { + return &machineSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the machineSet, and returns the corresponding machineSet object, and an error if there is any. +func (c *machineSets) Get(name string, options v1.GetOptions) (result *v1alpha1.MachineSet, err error) { + result = &v1alpha1.MachineSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of MachineSets that match those selectors. +func (c *machineSets) List(opts v1.ListOptions) (result *v1alpha1.MachineSetList, err error) { + result = &v1alpha1.MachineSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested machineSets. +func (c *machineSets) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a machineSet and creates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *machineSets) Create(machineSet *v1alpha1.MachineSet) (result *v1alpha1.MachineSet, err error) { + result = &v1alpha1.MachineSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("machinesets"). + Body(machineSet). + Do(). + Into(result) + return +} + +// Update takes the representation of a machineSet and updates it. Returns the server's representation of the machineSet, and an error, if there is any. +func (c *machineSets) Update(machineSet *v1alpha1.MachineSet) (result *v1alpha1.MachineSet, err error) { + result = &v1alpha1.MachineSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinesets"). + Name(machineSet.Name). + Body(machineSet). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *machineSets) UpdateStatus(machineSet *v1alpha1.MachineSet) (result *v1alpha1.MachineSet, err error) { + result = &v1alpha1.MachineSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("machinesets"). + Name(machineSet.Name). + SubResource("status"). + Body(machineSet). + Do(). + Into(result) + return +} + +// Delete takes name of the machineSet and deletes it. Returns an error if one occurs. +func (c *machineSets) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinesets"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *machineSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("machinesets"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched machineSet. +func (c *machineSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.MachineSet, err error) { + result = &v1alpha1.MachineSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("machinesets"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go index 5d1773f01b..f713067f54 100644 --- a/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go +++ b/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1/wing_client.go @@ -11,6 +11,8 @@ import ( type WingV1alpha1Interface interface { RESTClient() rest.Interface MachinesGetter + MachineDeploymentsGetter + MachineSetsGetter } // WingV1alpha1Client is used to interact with features provided by the wing.tarmak.io group. @@ -22,6 +24,14 @@ func (c *WingV1alpha1Client) Machines(namespace string) MachineInterface { return newMachines(c, namespace) } +func (c *WingV1alpha1Client) MachineDeployments(namespace string) MachineDeploymentInterface { + return newMachineDeployments(c, namespace) +} + +func (c *WingV1alpha1Client) MachineSets(namespace string) MachineSetInterface { + return newMachineSets(c, namespace) +} + // NewForConfig creates a new WingV1alpha1Client for the given config. func NewForConfig(c *rest.Config) (*WingV1alpha1Client, error) { config := *c diff --git a/pkg/wing/client/informers/externalversions/apis/interface.go b/pkg/wing/client/informers/externalversions/apis/interface.go new file mode 100644 index 0000000000..bae0632a80 --- /dev/null +++ b/pkg/wing/client/informers/externalversions/apis/interface.go @@ -0,0 +1,32 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package wing + +import ( + wing "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/apis/wing" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // Wing provides access to shared informers for resources in Wing. + Wing() wing.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Wing returns a new wing.Interface. +func (g *group) Wing() wing.Interface { + return wing.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/wing/client/informers/externalversions/apis/wing/interface.go b/pkg/wing/client/informers/externalversions/apis/wing/interface.go new file mode 100644 index 0000000000..3af0ab9d4e --- /dev/null +++ b/pkg/wing/client/informers/externalversions/apis/wing/interface.go @@ -0,0 +1,45 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package wing + +import ( + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Machines returns a MachineInformer. + Machines() MachineInformer + // MachineDeployments returns a MachineDeploymentInformer. + MachineDeployments() MachineDeploymentInformer + // MachineSets returns a MachineSetInformer. + MachineSets() MachineSetInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Machines returns a MachineInformer. +func (v *version) Machines() MachineInformer { + return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// MachineDeployments returns a MachineDeploymentInformer. +func (v *version) MachineDeployments() MachineDeploymentInformer { + return &machineDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// MachineSets returns a MachineSetInformer. +func (v *version) MachineSets() MachineSetInformer { + return &machineSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/wing/client/informers/externalversions/apis/wing/machine.go b/pkg/wing/client/informers/externalversions/apis/wing/machine.go new file mode 100644 index 0000000000..2e1f30fb57 --- /dev/null +++ b/pkg/wing/client/informers/externalversions/apis/wing/machine.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package wing + +import ( + apis_wing "github.com/jetstack/tarmak/pkg/apis/wing" + versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" + wing "github.com/jetstack/tarmak/pkg/wing/client/listers/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineInformer provides access to a shared informer and lister for +// Machines. +type MachineInformer interface { + Informer() cache.SharedIndexInformer + Lister() wing.MachineLister +} + +type machineInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineInformer constructs a new informer for Machine type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineInformer constructs a new informer for Machine type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().Machines(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().Machines(namespace).Watch(options) + }, + }, + &apis_wing.Machine{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apis_wing.Machine{}, f.defaultInformer) +} + +func (f *machineInformer) Lister() wing.MachineLister { + return wing.NewMachineLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/informers/externalversions/apis/wing/machinedeployment.go b/pkg/wing/client/informers/externalversions/apis/wing/machinedeployment.go new file mode 100644 index 0000000000..3a0ded6f18 --- /dev/null +++ b/pkg/wing/client/informers/externalversions/apis/wing/machinedeployment.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package wing + +import ( + apis_wing "github.com/jetstack/tarmak/pkg/apis/wing" + versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" + wing "github.com/jetstack/tarmak/pkg/wing/client/listers/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineDeploymentInformer provides access to a shared informer and lister for +// MachineDeployments. +type MachineDeploymentInformer interface { + Informer() cache.SharedIndexInformer + Lister() wing.MachineDeploymentLister +} + +type machineDeploymentInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineDeploymentInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineDeploymentInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().MachineDeployments(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().MachineDeployments(namespace).Watch(options) + }, + }, + &apis_wing.MachineDeployment{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineDeploymentInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineDeploymentInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apis_wing.MachineDeployment{}, f.defaultInformer) +} + +func (f *machineDeploymentInformer) Lister() wing.MachineDeploymentLister { + return wing.NewMachineDeploymentLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/informers/externalversions/apis/wing/machineset.go b/pkg/wing/client/informers/externalversions/apis/wing/machineset.go new file mode 100644 index 0000000000..293c21c29c --- /dev/null +++ b/pkg/wing/client/informers/externalversions/apis/wing/machineset.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package wing + +import ( + apis_wing "github.com/jetstack/tarmak/pkg/apis/wing" + versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" + wing "github.com/jetstack/tarmak/pkg/wing/client/listers/apis/wing" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineSetInformer provides access to a shared informer and lister for +// MachineSets. +type MachineSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() wing.MachineSetLister +} + +type machineSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().MachineSets(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingWing().MachineSets(namespace).Watch(options) + }, + }, + &apis_wing.MachineSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apis_wing.MachineSet{}, f.defaultInformer) +} + +func (f *machineSetInformer) Lister() wing.MachineSetLister { + return wing.NewMachineSetLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/informers/externalversions/factory.go b/pkg/wing/client/informers/externalversions/factory.go index 1974123abf..a2e14e26b4 100644 --- a/pkg/wing/client/informers/externalversions/factory.go +++ b/pkg/wing/client/informers/externalversions/factory.go @@ -6,6 +6,7 @@ package externalversions import ( versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + apis "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/apis" internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" wing "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/wing" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,12 +31,12 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new machine of sharedInformerFactory +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) } -// NewFilteredSharedInformerFactory constructs a new machine of sharedInformerFactory. +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { @@ -108,9 +109,14 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + Wing() apis.Interface Wing() wing.Interface } +func (f *sharedInformerFactory) Wing() apis.Interface { + return apis.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Wing() wing.Interface { return wing.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/wing/client/informers/externalversions/generic.go b/pkg/wing/client/informers/externalversions/generic.go index 98562d275a..1091331bde 100644 --- a/pkg/wing/client/informers/externalversions/generic.go +++ b/pkg/wing/client/informers/externalversions/generic.go @@ -6,6 +6,7 @@ package externalversions import ( "fmt" + wing "github.com/jetstack/tarmak/pkg/apis/wing" v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" @@ -37,9 +38,21 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=wing.tarmak.io, Version=v1alpha1 + // Group=wing.tarmak.io, Version=wing + case wing.SchemeGroupVersion.WithResource("machines"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().Machines().Informer()}, nil + case wing.SchemeGroupVersion.WithResource("machinedeployments"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().MachineDeployments().Informer()}, nil + case wing.SchemeGroupVersion.WithResource("machinesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().MachineSets().Informer()}, nil + + // Group=wing.tarmak.io, Version=v1alpha1 case v1alpha1.SchemeGroupVersion.WithResource("machines"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().Machines().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("machinedeployments"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().MachineDeployments().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("machinesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().MachineSets().Informer()}, nil } diff --git a/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go b/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go index 3b7361d9c9..f4914be766 100644 --- a/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go +++ b/pkg/wing/client/informers/externalversions/wing/v1alpha1/interface.go @@ -12,6 +12,10 @@ import ( type Interface interface { // Machines returns a MachineInformer. Machines() MachineInformer + // MachineDeployments returns a MachineDeploymentInformer. + MachineDeployments() MachineDeploymentInformer + // MachineSets returns a MachineSetInformer. + MachineSets() MachineSetInformer } type version struct { @@ -29,3 +33,13 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (v *version) Machines() MachineInformer { return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// MachineDeployments returns a MachineDeploymentInformer. +func (v *version) MachineDeployments() MachineDeploymentInformer { + return &machineDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// MachineSets returns a MachineSetInformer. +func (v *version) MachineSets() MachineSetInformer { + return &machineSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/wing/client/informers/externalversions/wing/v1alpha1/machinedeployment.go b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machinedeployment.go new file mode 100644 index 0000000000..abd9881207 --- /dev/null +++ b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machinedeployment.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package v1alpha1 + +import ( + wing_v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/jetstack/tarmak/pkg/wing/client/listers/wing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineDeploymentInformer provides access to a shared informer and lister for +// MachineDeployments. +type MachineDeploymentInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.MachineDeploymentLister +} + +type machineDeploymentInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineDeploymentInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineDeploymentInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingV1alpha1().MachineDeployments(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingV1alpha1().MachineDeployments(namespace).Watch(options) + }, + }, + &wing_v1alpha1.MachineDeployment{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineDeploymentInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineDeploymentInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing_v1alpha1.MachineDeployment{}, f.defaultInformer) +} + +func (f *machineDeploymentInformer) Lister() v1alpha1.MachineDeploymentLister { + return v1alpha1.NewMachineDeploymentLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/informers/externalversions/wing/v1alpha1/machineset.go b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machineset.go new file mode 100644 index 0000000000..a35656cf25 --- /dev/null +++ b/pkg/wing/client/informers/externalversions/wing/v1alpha1/machineset.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package v1alpha1 + +import ( + wing_v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/jetstack/tarmak/pkg/wing/client/listers/wing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineSetInformer provides access to a shared informer and lister for +// MachineSets. +type MachineSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.MachineSetLister +} + +type machineSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingV1alpha1().MachineSets(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WingV1alpha1().MachineSets(namespace).Watch(options) + }, + }, + &wing_v1alpha1.MachineSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing_v1alpha1.MachineSet{}, f.defaultInformer) +} + +func (f *machineSetInformer) Lister() v1alpha1.MachineSetLister { + return v1alpha1.NewMachineSetLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/informers/internalversion/factory.go b/pkg/wing/client/informers/internalversion/factory.go index 81803a134d..f28297c844 100644 --- a/pkg/wing/client/informers/internalversion/factory.go +++ b/pkg/wing/client/informers/internalversion/factory.go @@ -30,12 +30,12 @@ type sharedInformerFactory struct { startedInformers map[reflect.Type]bool } -// NewSharedInformerFactory constructs a new machine of sharedInformerFactory +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { return NewFilteredSharedInformerFactory(client, defaultResync, v1.NamespaceAll, nil) } -// NewFilteredSharedInformerFactory constructs a new machine of sharedInformerFactory. +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { diff --git a/pkg/wing/client/informers/internalversion/generic.go b/pkg/wing/client/informers/internalversion/generic.go index 407a737152..2a78cc7067 100644 --- a/pkg/wing/client/informers/internalversion/generic.go +++ b/pkg/wing/client/informers/internalversion/generic.go @@ -40,6 +40,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=wing.tarmak.io, Version=internalVersion case wing.SchemeGroupVersion.WithResource("machines"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().Machines().Informer()}, nil + case wing.SchemeGroupVersion.WithResource("machinesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().MachineSets().Informer()}, nil } diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go index 3aaff6431c..35e2d742db 100644 --- a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go @@ -12,6 +12,8 @@ import ( type Interface interface { // Machines returns a MachineInformer. Machines() MachineInformer + // MachineSets returns a MachineSetInformer. + MachineSets() MachineSetInformer } type version struct { @@ -29,3 +31,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (v *version) Machines() MachineInformer { return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// MachineSets returns a MachineSetInformer. +func (v *version) MachineSets() MachineSetInformer { + return &machineSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/machineset.go b/pkg/wing/client/informers/internalversion/wing/internalversion/machineset.go new file mode 100644 index 0000000000..6c2d7b48ce --- /dev/null +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/machineset.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + clientset_internalversion "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/internalversion/internalinterfaces" + internalversion "github.com/jetstack/tarmak/pkg/wing/client/listers/wing/internalversion" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineSetInformer provides access to a shared informer and lister for +// MachineSets. +type MachineSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() internalversion.MachineSetLister +} + +type machineSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineSetInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineSetInformer constructs a new informer for MachineSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineSetInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Wing().MachineSets(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Wing().MachineSets(namespace).Watch(options) + }, + }, + &wing.MachineSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineSetInformer) defaultInformer(client clientset_internalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing.MachineSet{}, f.defaultInformer) +} + +func (f *machineSetInformer) Lister() internalversion.MachineSetLister { + return internalversion.NewMachineSetLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/listers/wing/internalversion/expansion_generated.go b/pkg/wing/client/listers/wing/internalversion/expansion_generated.go index 454d4bcbdd..c598d24db3 100644 --- a/pkg/wing/client/listers/wing/internalversion/expansion_generated.go +++ b/pkg/wing/client/listers/wing/internalversion/expansion_generated.go @@ -11,3 +11,19 @@ type MachineListerExpansion interface{} // MachineNamespaceListerExpansion allows custom methods to be added to // MachineNamespaceLister. type MachineNamespaceListerExpansion interface{} + +// MachineDeploymentListerExpansion allows custom methods to be added to +// MachineDeploymentLister. +type MachineDeploymentListerExpansion interface{} + +// MachineDeploymentNamespaceListerExpansion allows custom methods to be added to +// MachineDeploymentNamespaceLister. +type MachineDeploymentNamespaceListerExpansion interface{} + +// MachineSetListerExpansion allows custom methods to be added to +// MachineSetLister. +type MachineSetListerExpansion interface{} + +// MachineSetNamespaceListerExpansion allows custom methods to be added to +// MachineSetNamespaceLister. +type MachineSetNamespaceListerExpansion interface{} diff --git a/pkg/wing/client/listers/wing/internalversion/machinedeployment.go b/pkg/wing/client/listers/wing/internalversion/machinedeployment.go new file mode 100644 index 0000000000..ca327abfdb --- /dev/null +++ b/pkg/wing/client/listers/wing/internalversion/machinedeployment.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineDeploymentLister helps list MachineDeployments. +type MachineDeploymentLister interface { + // List lists all MachineDeployments in the indexer. + List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) + // MachineDeployments returns an object that can list and get MachineDeployments. + MachineDeployments(namespace string) MachineDeploymentNamespaceLister + MachineDeploymentListerExpansion +} + +// machineDeploymentLister implements the MachineDeploymentLister interface. +type machineDeploymentLister struct { + indexer cache.Indexer +} + +// NewMachineDeploymentLister returns a new MachineDeploymentLister. +func NewMachineDeploymentLister(indexer cache.Indexer) MachineDeploymentLister { + return &machineDeploymentLister{indexer: indexer} +} + +// List lists all MachineDeployments in the indexer. +func (s *machineDeploymentLister) List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineDeployment)) + }) + return ret, err +} + +// MachineDeployments returns an object that can list and get MachineDeployments. +func (s *machineDeploymentLister) MachineDeployments(namespace string) MachineDeploymentNamespaceLister { + return machineDeploymentNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineDeploymentNamespaceLister helps list and get MachineDeployments. +type MachineDeploymentNamespaceLister interface { + // List lists all MachineDeployments in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) + // Get retrieves the MachineDeployment from the indexer for a given namespace and name. + Get(name string) (*wing.MachineDeployment, error) + MachineDeploymentNamespaceListerExpansion +} + +// machineDeploymentNamespaceLister implements the MachineDeploymentNamespaceLister +// interface. +type machineDeploymentNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineDeployments in the indexer for a given namespace. +func (s machineDeploymentNamespaceLister) List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineDeployment)) + }) + return ret, err +} + +// Get retrieves the MachineDeployment from the indexer for a given namespace and name. +func (s machineDeploymentNamespaceLister) Get(name string) (*wing.MachineDeployment, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machinedeployment"), name) + } + return obj.(*wing.MachineDeployment), nil +} diff --git a/pkg/wing/client/listers/wing/internalversion/machineset.go b/pkg/wing/client/listers/wing/internalversion/machineset.go new file mode 100644 index 0000000000..d2b81fbc46 --- /dev/null +++ b/pkg/wing/client/listers/wing/internalversion/machineset.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineSetLister helps list MachineSets. +type MachineSetLister interface { + // List lists all MachineSets in the indexer. + List(selector labels.Selector) (ret []*wing.MachineSet, err error) + // MachineSets returns an object that can list and get MachineSets. + MachineSets(namespace string) MachineSetNamespaceLister + MachineSetListerExpansion +} + +// machineSetLister implements the MachineSetLister interface. +type machineSetLister struct { + indexer cache.Indexer +} + +// NewMachineSetLister returns a new MachineSetLister. +func NewMachineSetLister(indexer cache.Indexer) MachineSetLister { + return &machineSetLister{indexer: indexer} +} + +// List lists all MachineSets in the indexer. +func (s *machineSetLister) List(selector labels.Selector) (ret []*wing.MachineSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineSet)) + }) + return ret, err +} + +// MachineSets returns an object that can list and get MachineSets. +func (s *machineSetLister) MachineSets(namespace string) MachineSetNamespaceLister { + return machineSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineSetNamespaceLister helps list and get MachineSets. +type MachineSetNamespaceLister interface { + // List lists all MachineSets in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.MachineSet, err error) + // Get retrieves the MachineSet from the indexer for a given namespace and name. + Get(name string) (*wing.MachineSet, error) + MachineSetNamespaceListerExpansion +} + +// machineSetNamespaceLister implements the MachineSetNamespaceLister +// interface. +type machineSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineSets in the indexer for a given namespace. +func (s machineSetNamespaceLister) List(selector labels.Selector) (ret []*wing.MachineSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineSet)) + }) + return ret, err +} + +// Get retrieves the MachineSet from the indexer for a given namespace and name. +func (s machineSetNamespaceLister) Get(name string) (*wing.MachineSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machineset"), name) + } + return obj.(*wing.MachineSet), nil +} diff --git a/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go b/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go index 4248b6c0b1..ff2f536863 100644 --- a/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go +++ b/pkg/wing/client/listers/wing/v1alpha1/expansion_generated.go @@ -11,3 +11,19 @@ type MachineListerExpansion interface{} // MachineNamespaceListerExpansion allows custom methods to be added to // MachineNamespaceLister. type MachineNamespaceListerExpansion interface{} + +// MachineDeploymentListerExpansion allows custom methods to be added to +// MachineDeploymentLister. +type MachineDeploymentListerExpansion interface{} + +// MachineDeploymentNamespaceListerExpansion allows custom methods to be added to +// MachineDeploymentNamespaceLister. +type MachineDeploymentNamespaceListerExpansion interface{} + +// MachineSetListerExpansion allows custom methods to be added to +// MachineSetLister. +type MachineSetListerExpansion interface{} + +// MachineSetNamespaceListerExpansion allows custom methods to be added to +// MachineSetNamespaceLister. +type MachineSetNamespaceListerExpansion interface{} diff --git a/pkg/wing/client/listers/wing/v1alpha1/machinedeployment.go b/pkg/wing/client/listers/wing/v1alpha1/machinedeployment.go new file mode 100644 index 0000000000..f28a244a78 --- /dev/null +++ b/pkg/wing/client/listers/wing/v1alpha1/machinedeployment.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineDeploymentLister helps list MachineDeployments. +type MachineDeploymentLister interface { + // List lists all MachineDeployments in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.MachineDeployment, err error) + // MachineDeployments returns an object that can list and get MachineDeployments. + MachineDeployments(namespace string) MachineDeploymentNamespaceLister + MachineDeploymentListerExpansion +} + +// machineDeploymentLister implements the MachineDeploymentLister interface. +type machineDeploymentLister struct { + indexer cache.Indexer +} + +// NewMachineDeploymentLister returns a new MachineDeploymentLister. +func NewMachineDeploymentLister(indexer cache.Indexer) MachineDeploymentLister { + return &machineDeploymentLister{indexer: indexer} +} + +// List lists all MachineDeployments in the indexer. +func (s *machineDeploymentLister) List(selector labels.Selector) (ret []*v1alpha1.MachineDeployment, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MachineDeployment)) + }) + return ret, err +} + +// MachineDeployments returns an object that can list and get MachineDeployments. +func (s *machineDeploymentLister) MachineDeployments(namespace string) MachineDeploymentNamespaceLister { + return machineDeploymentNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineDeploymentNamespaceLister helps list and get MachineDeployments. +type MachineDeploymentNamespaceLister interface { + // List lists all MachineDeployments in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.MachineDeployment, err error) + // Get retrieves the MachineDeployment from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.MachineDeployment, error) + MachineDeploymentNamespaceListerExpansion +} + +// machineDeploymentNamespaceLister implements the MachineDeploymentNamespaceLister +// interface. +type machineDeploymentNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineDeployments in the indexer for a given namespace. +func (s machineDeploymentNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.MachineDeployment, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MachineDeployment)) + }) + return ret, err +} + +// Get retrieves the MachineDeployment from the indexer for a given namespace and name. +func (s machineDeploymentNamespaceLister) Get(name string) (*v1alpha1.MachineDeployment, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("machinedeployment"), name) + } + return obj.(*v1alpha1.MachineDeployment), nil +} diff --git a/pkg/wing/client/listers/wing/v1alpha1/machineset.go b/pkg/wing/client/listers/wing/v1alpha1/machineset.go new file mode 100644 index 0000000000..6f43194960 --- /dev/null +++ b/pkg/wing/client/listers/wing/v1alpha1/machineset.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package v1alpha1 + +import ( + v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineSetLister helps list MachineSets. +type MachineSetLister interface { + // List lists all MachineSets in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.MachineSet, err error) + // MachineSets returns an object that can list and get MachineSets. + MachineSets(namespace string) MachineSetNamespaceLister + MachineSetListerExpansion +} + +// machineSetLister implements the MachineSetLister interface. +type machineSetLister struct { + indexer cache.Indexer +} + +// NewMachineSetLister returns a new MachineSetLister. +func NewMachineSetLister(indexer cache.Indexer) MachineSetLister { + return &machineSetLister{indexer: indexer} +} + +// List lists all MachineSets in the indexer. +func (s *machineSetLister) List(selector labels.Selector) (ret []*v1alpha1.MachineSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MachineSet)) + }) + return ret, err +} + +// MachineSets returns an object that can list and get MachineSets. +func (s *machineSetLister) MachineSets(namespace string) MachineSetNamespaceLister { + return machineSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineSetNamespaceLister helps list and get MachineSets. +type MachineSetNamespaceLister interface { + // List lists all MachineSets in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.MachineSet, err error) + // Get retrieves the MachineSet from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.MachineSet, error) + MachineSetNamespaceListerExpansion +} + +// machineSetNamespaceLister implements the MachineSetNamespaceLister +// interface. +type machineSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineSets in the indexer for a given namespace. +func (s machineSetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.MachineSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MachineSet)) + }) + return ret, err +} + +// Get retrieves the MachineSet from the indexer for a given namespace and name. +func (s machineSetNamespaceLister) Get(name string) (*v1alpha1.MachineSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("machineset"), name) + } + return obj.(*v1alpha1.MachineSet), nil +} From b4fbb19d409bab70993f8858067ad5c3bb44de79 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Wed, 12 Dec 2018 09:55:59 +0000 Subject: [PATCH 03/14] Adds wing dev mode to bastion instance Signed-off-by: JoshVanL --- pkg/terraform/templating.go | 4 ++++ terraform/amazon/modules/bastion/bastion.tf | 3 +++ .../amazon/modules/bastion/bastion_iam.tf | 20 +++++++++++++++++++ terraform/amazon/modules/bastion/inputs.tf | 2 ++ .../bastion/templates/wing_binary_read.json | 15 ++++++++++++++ .../bastion_user_data.yaml.template} | 13 ++++++++---- .../amazon/templates/modules.tf.template | 7 +++++-- 7 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 terraform/amazon/modules/bastion/templates/wing_binary_read.json rename terraform/amazon/{modules/bastion/templates/bastion_user_data.yaml => templates/bastion_user_data.yaml.template} (94%) diff --git a/pkg/terraform/templating.go b/pkg/terraform/templating.go index f50c02ce43..9e3e11fbb8 100644 --- a/pkg/terraform/templating.go +++ b/pkg/terraform/templating.go @@ -141,6 +141,7 @@ func (t *terraformTemplate) Generate() error { {"outputs", "outputs"}, {"providers", "providers"}, {"jenkins_elb", "modules/jenkins/jenkins_elb"}, + {"wing_s3", "modules/bastion/wing_s3"}, {"wing_s3", "modules/kubernetes/wing_s3"}, {"vault_instances", "modules/vault/vault_instances"}, } { @@ -152,6 +153,9 @@ func (t *terraformTemplate) Generate() error { if err := t.generateTemplate("puppet_agent_user_data", "modules/kubernetes/templates/puppet_agent_user_data", "yaml"); err != nil { result = multierror.Append(result, err) } + if err := t.generateTemplate("bastion_user_data", "modules/bastion/templates/bastion_user_data", "yaml"); err != nil { + result = multierror.Append(result, err) + } if err := t.generateTerraformVariables(); err != nil { result = multierror.Append(result, err) } diff --git a/terraform/amazon/modules/bastion/bastion.tf b/terraform/amazon/modules/bastion/bastion.tf index 5ea49128be..4fb7cf323d 100644 --- a/terraform/amazon/modules/bastion/bastion.tf +++ b/terraform/amazon/modules/bastion/bastion.tf @@ -3,6 +3,9 @@ data "template_file" "bastion_user_data" { vars { fqdn = "bastion.${var.public_zone}" + + wing_binary_path = "${var.secrets_bucket}/${data.template_file.stack_name.rendered}/${var.wing_binary_path}" + wing_version = "${var.wing_version}" } } diff --git a/terraform/amazon/modules/bastion/bastion_iam.tf b/terraform/amazon/modules/bastion/bastion_iam.tf index f622907eab..068b328802 100644 --- a/terraform/amazon/modules/bastion/bastion_iam.tf +++ b/terraform/amazon/modules/bastion/bastion_iam.tf @@ -17,3 +17,23 @@ resource "aws_iam_policy_attachment" "bastion_additional_policy" { count = "${length(var.bastion_iam_additional_policy_arns)}" policy_arn = "${element(var.bastion_iam_additional_policy_arns, count.index)}" } + +data "template_file" "wing_binary_read" { + template = "${file("${path.module}/templates/wing_binary_read.json")}" + + vars { + wing_binary_path = "${var.secrets_bucket}/${data.template_file.stack_name.rendered}/wing-*" + } +} + +resource "aws_iam_policy" "wing_binary_read" { + name = "bastion.${data.template_file.stack_name.rendered}.wing_binary_read" + path = "/" + policy = "${data.template_file.wing_binary_read.rendered}" +} + +resource "aws_iam_policy_attachment" "wing_binary_read" { + name = "${data.template_file.stack_name.rendered}-wing-binary" + roles = ["${aws_iam_role.bastion.name}"] + policy_arn = "${aws_iam_policy.wing_binary_read.arn}" +} diff --git a/terraform/amazon/modules/bastion/inputs.tf b/terraform/amazon/modules/bastion/inputs.tf index 43ec1d79ec..96c8897621 100644 --- a/terraform/amazon/modules/bastion/inputs.tf +++ b/terraform/amazon/modules/bastion/inputs.tf @@ -36,3 +36,5 @@ variable "private_zone_id" {} variable "bastion_iam_additional_policy_arns" { type = "list" } + +variable "secrets_bucket" {} diff --git a/terraform/amazon/modules/bastion/templates/wing_binary_read.json b/terraform/amazon/modules/bastion/templates/wing_binary_read.json new file mode 100644 index 0000000000..20dc764ac8 --- /dev/null +++ b/terraform/amazon/modules/bastion/templates/wing_binary_read.json @@ -0,0 +1,15 @@ +{ + "Statement": [ + { + "Action": [ + "s3:GetObject", + "s3:HeadObjectAcl" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::${wing_binary_path}" + ] + } + ], + "Version": "2012-10-17" +} diff --git a/terraform/amazon/modules/bastion/templates/bastion_user_data.yaml b/terraform/amazon/templates/bastion_user_data.yaml.template similarity index 94% rename from terraform/amazon/modules/bastion/templates/bastion_user_data.yaml rename to terraform/amazon/templates/bastion_user_data.yaml.template index 1885692c94..c8fa042abf 100644 --- a/terraform/amazon/modules/bastion/templates/bastion_user_data.yaml +++ b/terraform/amazon/templates/bastion_user_data.yaml.template @@ -56,13 +56,17 @@ write_files: Requires=etcd.service [Service] - Environment=AIRWORTHY_VERSION=0.2.0 - Environment=AIRWORTHY_HASH=2d69cfe0b92f86481805c28d0b8ae47a8ffa6bb2373217e7c5215d61fc9efa1d - Environment=WING_VERSION=0.5.3 - Environment=WING_DATA_DIR=/var/lib/wing PermissionsStartOnly=true Restart=on-failure RestartSec=10 + Environment=WING_DATA_DIR=/var/lib/wing +{{- if .WingDevMode }} + Environment=WING_VERSION="${wing_version}" + ExecStartPre=/bin/sh -c 'aws s3 cp "s3://${wing_binary_path}" /opt/wing-$${WING_VERSION}/wing; chmod 0755 /opt/wing-$${WING_VERSION}/wing' +{{- else }} + Environment=AIRWORTHY_VERSION=0.2.0 + Environment=AIRWORTHY_HASH=2d69cfe0b92f86481805c28d0b8ae47a8ffa6bb2373217e7c5215d61fc9efa1d + Environment=WING_VERSION=0.5.3 ExecStartPre=/bin/sh -c '\ set -e ;\ test -x /opt/wing-$${WING_VERSION}/wing && exit 0 ;\ @@ -73,6 +77,7 @@ write_files: chmod 755 /opt/airworthy-$${AIRWORTHY_VERSION}/airworthy ;\ fi ;\ /opt/airworthy-$${AIRWORTHY_VERSION}/airworthy download --output /opt/wing-$${WING_VERSION}/wing --sha256sums https://github.com/jetstack/tarmak/releases/download/$${WING_VERSION}/tarmak_$${WING_VERSION}_checksums.txt --signature-armored https://github.com/jetstack/tarmak/releases/download/$${WING_VERSION}/tarmak_$${WING_VERSION}_checksums.txt.asc https://github.com/jetstack/tarmak/releases/download/$${WING_VERSION}/wing_$${WING_VERSION}_linux_amd64' +{{- end }} ExecStartPre=/bin/sh -c '\ set -e ;\ test -d $${WING_DATA_DIR} && exit 0 ;\ diff --git a/terraform/amazon/templates/modules.tf.template b/terraform/amazon/templates/modules.tf.template index 91acbfd66d..e422d653b9 100644 --- a/terraform/amazon/templates/modules.tf.template +++ b/terraform/amazon/templates/modules.tf.template @@ -68,6 +68,7 @@ module "bastion" { bastion_admin_cidrs = ["${var.bastion_admin_cidrs}"] public_zone_id = "${module.state.public_zone_id}" private_zone_id = "${module.network.private_zone_id[0]}" + secrets_bucket = "${module.state.secrets_bucket[0]}" bastion_min_instance_count = "${var.bastion_min_instance_count}" bastion_iam_additional_policy_arns = ["${var.bastion_iam_additional_policy_arns}"] @@ -183,7 +184,6 @@ module "kubernetes" { public_zone_id = "${module.state.public_zone_id}" vault_security_group_id = "${module.vault.vault_security_group_id}" bastion_security_group_id = "${module.bastion.bastion_security_group_id}" - backups_bucket = "${module.state.backups_bucket[0]}" elb_access_logs_public_enabled = "${var.elb_access_logs_public_enabled}" elb_access_logs_public_bucket = "${var.elb_access_logs_public_bucket}" @@ -193,6 +193,8 @@ module "kubernetes" { elb_access_logs_internal_bucket = "${var.elb_access_logs_internal_bucket}" elb_access_logs_internal_bucket_prefix = "${var.elb_access_logs_internal_bucket_prefix}" elb_access_logs_internal_bucket_interval = "${var.elb_access_logs_internal_bucket_interval}" + + backups_bucket = "${module.state.backups_bucket[0]}" } {{- end -}} @@ -249,7 +251,6 @@ module "kubernetes" { vault_ca = "${data.terraform_remote_state.hub_state.vault_vault_ca}" vault_url = "${data.terraform_remote_state.hub_state.vault_vault_url}" vault_security_group_id = "${data.terraform_remote_state.hub_state.vault_vault_security_group_id}" - backups_bucket = "${data.terraform_remote_state.hub_state.state_backups_bucket[0]}" elb_access_logs_public_enabled = "${var.elb_access_logs_public_enabled}" elb_access_logs_public_bucket = "${var.elb_access_logs_public_bucket}" @@ -259,5 +260,7 @@ module "kubernetes" { elb_access_logs_internal_bucket = "${var.elb_access_logs_internal_bucket}" elb_access_logs_internal_bucket_prefix = "${var.elb_access_logs_internal_bucket_prefix}" elb_access_logs_internal_bucket_interval = "${var.elb_access_logs_internal_bucket_interval}" + + backups_bucket = "${data.terraform_remote_state.hub_state.state_backups_bucket[0]}" } {{- end }} From 370fd8760244e25ad188c9c32dad7dbcb720e902 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Wed, 12 Dec 2018 12:37:22 +0000 Subject: [PATCH 04/14] Adds machine{set,deployment} to server and labels on machines Signed-off-by: JoshVanL --- cmd/wing/cmd/agent.go | 3 +- pkg/apis/wing/machine_types.go | 3 - pkg/apis/wing/machinedeployment_types.go | 3 +- pkg/apis/wing/machineset_types.go | 5 +- pkg/apis/wing/register.go | 4 + pkg/apis/wing/v1alpha1/machine_types.go | 3 - .../wing/v1alpha1/machinedeployment_types.go | 3 +- pkg/apis/wing/v1alpha1/machineset_types.go | 3 +- pkg/apis/wing/v1alpha1/register.go | 4 + .../wing/v1alpha1/zz_generated.conversion.go | 16 ++-- .../wing/v1alpha1/zz_generated.deepcopy.go | 26 +++++- pkg/apis/wing/zz_generated.deepcopy.go | 26 +++++- pkg/tarmak/cluster/cluster.go | 2 + pkg/tarmak/cluster/configuration.go | 66 ++++++++------- pkg/tarmak/cluster/wing.go | 1 - .../machinedeploymentinittime/admission.go | 65 +++++++++++++++ .../plugin/machineinittime/admission.go | 2 +- .../plugin/machinesetinittime/admission.go | 65 +++++++++++++++ pkg/wing/apiserver/apiserver.go | 4 + .../informers/externalversions/factory.go | 6 -- .../informers/externalversions/generic.go | 11 +-- .../informers/internalversion/generic.go | 2 + .../wing/internalversion/interface.go | 7 ++ .../wing/internalversion/machinedeployment.go | 74 +++++++++++++++++ .../listers/apis/wing/expansion_generated.go | 29 +++++++ pkg/wing/client/listers/apis/wing/machine.go | 80 +++++++++++++++++++ .../listers/apis/wing/machinedeployment.go | 80 +++++++++++++++++++ .../client/listers/apis/wing/machineset.go | 80 +++++++++++++++++++ pkg/wing/controller.go | 8 +- pkg/wing/puppet.go | 11 ++- .../registry/wing/machinedeployment/etcd.go | 34 ++++++++ .../wing/machinedeployment/strategy.go | 80 +++++++++++++++++++ pkg/wing/registry/wing/machineset/etcd.go | 34 ++++++++ pkg/wing/registry/wing/machineset/strategy.go | 80 +++++++++++++++++++ pkg/wing/server/server.go | 6 +- pkg/wing/wing.go | 23 +++--- .../puppet_agent_user_data.yaml.template | 2 +- 37 files changed, 855 insertions(+), 96 deletions(-) create mode 100644 pkg/wing/admission/plugin/machinedeploymentinittime/admission.go create mode 100644 pkg/wing/admission/plugin/machinesetinittime/admission.go create mode 100644 pkg/wing/client/informers/internalversion/wing/internalversion/machinedeployment.go create mode 100644 pkg/wing/client/listers/apis/wing/expansion_generated.go create mode 100644 pkg/wing/client/listers/apis/wing/machine.go create mode 100644 pkg/wing/client/listers/apis/wing/machinedeployment.go create mode 100644 pkg/wing/client/listers/apis/wing/machineset.go create mode 100644 pkg/wing/registry/wing/machinedeployment/etcd.go create mode 100644 pkg/wing/registry/wing/machinedeployment/strategy.go create mode 100644 pkg/wing/registry/wing/machineset/etcd.go create mode 100644 pkg/wing/registry/wing/machineset/strategy.go diff --git a/cmd/wing/cmd/agent.go b/cmd/wing/cmd/agent.go index b5d7fc3a4b..9231455e86 100644 --- a/cmd/wing/cmd/agent.go +++ b/cmd/wing/cmd/agent.go @@ -21,7 +21,8 @@ func init() { agentCmd.Flags().StringVar(&agentFlags.ClusterName, "cluster-name", "myenv-mycluster", "this specifies the cluster name [environment]-[cluster]") agentCmd.Flags().StringVar(&agentFlags.ServerURL, "server-url", "https://localhost:9443", "this specifies the URL to the wing server") agentCmd.Flags().StringVar(&agentFlags.ManifestURL, "manifest-url", "", "this specifies the URL where the puppet.tar.gz can be found") - agentCmd.Flags().StringVar(&agentFlags.InstanceName, "instance-name", wing.DefaultInstanceName, "this specifies the instance's name") + agentCmd.Flags().StringVar(&agentFlags.MachineName, "instance-name", wing.DefaultMachineName, "this specifies the instance's name") + agentCmd.Flags().StringVar(&agentFlags.Role, "role", "", "this specifies the machines role, used as a label selector for machinesets") RootCmd.AddCommand(agentCmd) } diff --git a/pkg/apis/wing/machine_types.go b/pkg/apis/wing/machine_types.go index 224e98aa3b..970885e084 100644 --- a/pkg/apis/wing/machine_types.go +++ b/pkg/apis/wing/machine_types.go @@ -12,9 +12,6 @@ type Machine struct { metav1.TypeMeta metav1.ObjectMeta - MachineID string - MachinePool string - Spec *MachineSpec Status *MachineStatus } diff --git a/pkg/apis/wing/machinedeployment_types.go b/pkg/apis/wing/machinedeployment_types.go index 3ede095a93..f956ec60a3 100644 --- a/pkg/apis/wing/machinedeployment_types.go +++ b/pkg/apis/wing/machinedeployment_types.go @@ -12,7 +12,8 @@ import ( type MachineDeploymentSpec struct { // Number of desired machines. Defaults to 1. // This is a pointer to distinguish between explicit zero and not specified. - Replicas *int32 + MinReplicas *int32 + MaxReplicas *int32 // Label selector for machines. Existing MachineSets whose machines are // selected by this will be the ones affected by this deployment. diff --git a/pkg/apis/wing/machineset_types.go b/pkg/apis/wing/machineset_types.go index a424bb5725..6adf2b9556 100644 --- a/pkg/apis/wing/machineset_types.go +++ b/pkg/apis/wing/machineset_types.go @@ -9,11 +9,12 @@ import ( // MachineSetSpec defines the desired state of MachineSet type MachineSetSpec struct { - // Replicas is the number of desired replicas. + // Replicas is the number of desired minimum and maximum replicas. // This is a pointer to distinguish between explicit zero and unspecified. // Defaults to 1. // +optional - Replicas *int32 + MinReplicas *int32 + MaxReplicas *int32 // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. // Defaults to 0 (machine will be considered available as soon as it is ready) diff --git a/pkg/apis/wing/register.go b/pkg/apis/wing/register.go index cf063c5130..fa71bc7217 100644 --- a/pkg/apis/wing/register.go +++ b/pkg/apis/wing/register.go @@ -31,6 +31,10 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Machine{}, &MachineList{}, + &MachineSet{}, + &MachineSetList{}, + &MachineDeployment{}, + &MachineDeploymentList{}, ) return nil } diff --git a/pkg/apis/wing/v1alpha1/machine_types.go b/pkg/apis/wing/v1alpha1/machine_types.go index 9a8772b43d..007c81e744 100644 --- a/pkg/apis/wing/v1alpha1/machine_types.go +++ b/pkg/apis/wing/v1alpha1/machine_types.go @@ -12,9 +12,6 @@ type Machine struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - MachineID string `json:"machineID,omitempty"` - MachinePool string `json:"machinePool,omitempty"` - Spec *MachineSpec `json:"spec,omitempty"` Status *MachineStatus `json:"status,omitempty"` } diff --git a/pkg/apis/wing/v1alpha1/machinedeployment_types.go b/pkg/apis/wing/v1alpha1/machinedeployment_types.go index c13db04766..2bf9be276b 100644 --- a/pkg/apis/wing/v1alpha1/machinedeployment_types.go +++ b/pkg/apis/wing/v1alpha1/machinedeployment_types.go @@ -12,7 +12,8 @@ import ( type MachineDeploymentSpec struct { // Number of desired machines. Defaults to 1. // This is a pointer to distinguish between explicit zero and not specified. - Replicas *int32 `json:"replicas,omitempty"` + MinReplicas *int32 `json:"minReplicas,omitempty"` + MaxReplicas *int32 `json:"minReplicas,omitempty"` // Label selector for machines. Existing MachineSets whose machines are // selected by this will be the ones affected by this deployment. diff --git a/pkg/apis/wing/v1alpha1/machineset_types.go b/pkg/apis/wing/v1alpha1/machineset_types.go index 925de5d135..8cd8386ea6 100644 --- a/pkg/apis/wing/v1alpha1/machineset_types.go +++ b/pkg/apis/wing/v1alpha1/machineset_types.go @@ -13,7 +13,8 @@ type MachineSetSpec struct { // This is a pointer to distinguish between explicit zero and unspecified. // Defaults to 1. // +optional - Replicas *int32 `json:"replicas,omitempty"` + MinReplicas *int32 `json:"minReplicas,omitempty"` + MaxReplicas *int32 `json:"minReplicas,omitempty"` // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. // Defaults to 0 (machine will be considered available as soon as it is ready) diff --git a/pkg/apis/wing/v1alpha1/register.go b/pkg/apis/wing/v1alpha1/register.go index 64c6cbfd60..1b0731348d 100644 --- a/pkg/apis/wing/v1alpha1/register.go +++ b/pkg/apis/wing/v1alpha1/register.go @@ -32,6 +32,10 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Machine{}, &MachineList{}, + &MachineSet{}, + &MachineSetList{}, + &MachineDeployment{}, + &MachineDeploymentList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go index 3d8fb397f7..2ba04e83f5 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go @@ -62,8 +62,6 @@ func RegisterConversions(scheme *runtime.Scheme) error { func autoConvert_v1alpha1_Machine_To_wing_Machine(in *Machine, out *wing.Machine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - out.MachineID = in.MachineID - out.MachinePool = in.MachinePool out.Spec = (*wing.MachineSpec)(unsafe.Pointer(in.Spec)) out.Status = (*wing.MachineStatus)(unsafe.Pointer(in.Status)) return nil @@ -76,8 +74,6 @@ func Convert_v1alpha1_Machine_To_wing_Machine(in *Machine, out *wing.Machine, s func autoConvert_wing_Machine_To_v1alpha1_Machine(in *wing.Machine, out *Machine, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta - out.MachineID = in.MachineID - out.MachinePool = in.MachinePool out.Spec = (*MachineSpec)(unsafe.Pointer(in.Spec)) out.Status = (*MachineStatus)(unsafe.Pointer(in.Status)) return nil @@ -135,7 +131,8 @@ func Convert_wing_MachineDeploymentList_To_v1alpha1_MachineDeploymentList(in *wi } func autoConvert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec(in *MachineDeploymentSpec, out *wing.MachineDeploymentSpec, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas)) + out.MaxReplicas = (*int32)(unsafe.Pointer(in.MaxReplicas)) out.Selector = in.Selector if err := Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { return err @@ -154,7 +151,8 @@ func Convert_v1alpha1_MachineDeploymentSpec_To_wing_MachineDeploymentSpec(in *Ma } func autoConvert_wing_MachineDeploymentSpec_To_v1alpha1_MachineDeploymentSpec(in *wing.MachineDeploymentSpec, out *MachineDeploymentSpec, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas)) + out.MaxReplicas = (*int32)(unsafe.Pointer(in.MaxReplicas)) out.Selector = in.Selector if err := Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { return err @@ -315,7 +313,8 @@ func Convert_wing_MachineSetList_To_v1alpha1_MachineSetList(in *wing.MachineSetL } func autoConvert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec(in *MachineSetSpec, out *wing.MachineSetSpec, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas)) + out.MaxReplicas = (*int32)(unsafe.Pointer(in.MaxReplicas)) out.MinReadySeconds = in.MinReadySeconds out.Selector = in.Selector if err := Convert_v1alpha1_MachineTemplateSpec_To_wing_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { @@ -330,7 +329,8 @@ func Convert_v1alpha1_MachineSetSpec_To_wing_MachineSetSpec(in *MachineSetSpec, } func autoConvert_wing_MachineSetSpec_To_v1alpha1_MachineSetSpec(in *wing.MachineSetSpec, out *MachineSetSpec, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas)) + out.MaxReplicas = (*int32)(unsafe.Pointer(in.MaxReplicas)) out.MinReadySeconds = in.MinReadySeconds out.Selector = in.Selector if err := Convert_wing_MachineTemplateSpec_To_v1alpha1_MachineTemplateSpec(&in.Template, &out.Template, s); err != nil { diff --git a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go index 9cdf87315b..74664716d9 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.deepcopy.go @@ -138,8 +138,17 @@ func (in *MachineDeploymentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineDeploymentSpec) DeepCopyInto(out *MachineDeploymentSpec) { *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas if *in == nil { *out = nil } else { @@ -389,8 +398,17 @@ func (in *MachineSetList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineSetSpec) DeepCopyInto(out *MachineSetSpec) { *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas if *in == nil { *out = nil } else { diff --git a/pkg/apis/wing/zz_generated.deepcopy.go b/pkg/apis/wing/zz_generated.deepcopy.go index 90618733a5..d82943944e 100644 --- a/pkg/apis/wing/zz_generated.deepcopy.go +++ b/pkg/apis/wing/zz_generated.deepcopy.go @@ -138,8 +138,17 @@ func (in *MachineDeploymentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineDeploymentSpec) DeepCopyInto(out *MachineDeploymentSpec) { *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas if *in == nil { *out = nil } else { @@ -389,8 +398,17 @@ func (in *MachineSetList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineSetSpec) DeepCopyInto(out *MachineSetSpec) { *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + if *in == nil { + *out = nil + } else { + *out = new(int32) + **out = **in + } + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas if *in == nil { *out = nil } else { diff --git a/pkg/tarmak/cluster/cluster.go b/pkg/tarmak/cluster/cluster.go index c66347e32d..45c46135db 100644 --- a/pkg/tarmak/cluster/cluster.go +++ b/pkg/tarmak/cluster/cluster.go @@ -31,6 +31,7 @@ const ( // returns a server type Cluster struct { conf *clusterv1alpha1.Cluster + ctx interfaces.CancellationContext environment interfaces.Environment networkCIDR *net.IPNet @@ -53,6 +54,7 @@ var _ interfaces.Cluster = &Cluster{} func NewFromConfig(environment interfaces.Environment, conf *clusterv1alpha1.Cluster) (*Cluster, error) { cluster := &Cluster{ conf: conf, + ctx: environment.Tarmak().CancellationContext(), environment: environment, log: environment.Log().WithField("cluster", conf.Name), } diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index b9a167b262..9f9b0a13ff 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -38,9 +38,9 @@ func (c *Cluster) UploadConfiguration() error { ) } -// This enforces a reapply of the puppet.tar.gz on every instance in the cluster +// This enforces a reapply of the puppet.tar.gz on every machine in the cluster func (c *Cluster) ReapplyConfiguration() error { - c.log.Infof("making sure all instances apply the latest manifest") + c.log.Infof("making sure all machines apply the latest manifest") // connect to wing client, err := c.wingMachineClient() @@ -48,21 +48,21 @@ func (c *Cluster) ReapplyConfiguration() error { return fmt.Errorf("failed to connect to wing API on bastion: %s", err) } - // list instances - instances, err := c.listMachines() + // list machines + machines, err := c.listMachines() if err != nil { - return fmt.Errorf("failed to list instances: %s", err) + return fmt.Errorf("failed to list machines: %s", err) } - for pos, _ := range instances { - instance := instances[pos] - if instance.Spec == nil { - instance.Spec = &wingv1alpha1.MachineSpec{} + for pos, _ := range machines { + machine := machines[pos] + if machine.Spec == nil { + machine.Spec = &wingv1alpha1.MachineSpec{} } - instance.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} + machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} - if _, err := client.Update(instance); err != nil { - c.log.Warnf("error updating instance %s in wing API: %s", instance.Name, err) + if _, err := client.Update(machine); err != nil { + c.log.Warnf("error updating machine %s in wing API: %s", machine.Name, err) } } @@ -72,46 +72,52 @@ func (c *Cluster) ReapplyConfiguration() error { return nil } -// This waits until all instances have congverged successfully +// This waits until all machines have congverged successfully func (c *Cluster) WaitForConvergance() error { - c.log.Debugf("making sure all instances have converged using puppet") + c.log.Debugf("making sure all machine have converged using puppet") retries := retries for { - instances, err := c.listMachines() + machines, err := c.listMachines() if err != nil { - return fmt.Errorf("failed to list instances: %s", err) + return fmt.Errorf("failed to list machines: %s", err) } - instanceByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) + machineByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) - for pos, _ := range instances { - instance := instances[pos] + for pos, _ := range machines { + machine := machines[pos] - // index by instance convergance state - if instance.Status == nil || instance.Status.Converge == nil || instance.Status.Converge.State == "" { + // index by machine convergance state + if machine.Status == nil || machine.Status.Converge == nil || machine.Status.Converge.State == "" { continue } - state := instance.Status.Converge.State - if _, ok := instanceByState[state]; !ok { - instanceByState[state] = []*wingv1alpha1.Machine{} + state := machine.Status.Converge.State + if _, ok := machineByState[state]; !ok { + machineByState[state] = []*wingv1alpha1.Machine{} } - instanceByState[state] = append( - instanceByState[state], - instance, + machineByState[state] = append( + machineByState[state], + machine, ) } - err = c.checkAllMachinesConverged(instanceByState) + err = c.checkAllMachinesConverged(machineByState) if err == nil { - c.log.Info("all instances converged") + c.log.Info("all machines converged") return nil } else { c.log.Debug(err) } + select { + case <-c.ctx.Done(): + return c.ctx.Err() + default: + } + retries-- if retries == 0 { break @@ -120,5 +126,5 @@ func (c *Cluster) WaitForConvergance() error { } - return fmt.Errorf("instances failed to converge in time") + return fmt.Errorf("machines failed to converge in time") } diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 14ec366744..80eb972ac4 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -85,7 +85,6 @@ func (c *Cluster) listMachines() (machines []*wingv1alpha1.Machine, err error) { } return machines, nil - } func (c *Cluster) checkAllMachinesConverged(byState map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) error { diff --git a/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go new file mode 100644 index 0000000000..b2e3cd641f --- /dev/null +++ b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go @@ -0,0 +1,65 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machinedeploymentinittime + +import ( + "errors" + "fmt" + "io" + + "k8s.io/apiserver/pkg/admission" + + "github.com/jetstack/tarmak/pkg/apis/wing" +) + +const PluginName = "MachineDeploymentInitTime" + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { + return New() + }) +} + +type machinedeploymentInitTime struct { + *admission.Handler +} + +// Admit ensures that the object in-flight is of kind Flunder. +// In addition checks that the Name is not on the banned list. +// The list is stored in Fischers API objects. +func (d *machinedeploymentInitTime) Admit(a admission.Attributes) error { + // we are only interested in machinedeploymentss + if a.GetKind().GroupKind() != wing.Kind("MachineDeployment") { + return nil + } + + machinedeployment, ok := a.GetObject().(*wing.MachineDeployment) + if !ok { + return errors.New("unexpected object time") + } + + if machinedeployment.Spec == nil { + return fmt.Errorf("expected machinedeployment replicas to be set, got=%v", machinedeployment.Spec) + } + + if machinedeployment.Spec.MinReplicas == nil { + return fmt.Errorf("expected machinedeployment min replicas to be set, got=%v", machinedeployment.Spec.MinReplicas) + } + if machinedeployment.Spec.MaxReplicas == nil { + return fmt.Errorf("expected machinedeployment max replicas to be set, got=%v", machinedeployment.Spec.MaxReplicas) + } + + return nil +} + +// Validate checks whether the plugin was correctly initialized. +func (d *machinedeploymentInitTime) Validate() error { + return nil +} + +// New creates a new machines init time admission plugin +func New() (admission.Interface, error) { + return &machinedeploymentInitTime{ + Handler: admission.NewHandler(admission.Create, admission.Update), + }, nil +} diff --git a/pkg/wing/admission/plugin/machineinittime/admission.go b/pkg/wing/admission/plugin/machineinittime/admission.go index 9fd3646fc7..bf23fb2f9e 100644 --- a/pkg/wing/admission/plugin/machineinittime/admission.go +++ b/pkg/wing/admission/plugin/machineinittime/admission.go @@ -1,5 +1,5 @@ // Copyright Jetstack Ltd. See LICENSE for details. -package instaceinittime +package machineinittime import ( "errors" diff --git a/pkg/wing/admission/plugin/machinesetinittime/admission.go b/pkg/wing/admission/plugin/machinesetinittime/admission.go new file mode 100644 index 0000000000..3b7408e097 --- /dev/null +++ b/pkg/wing/admission/plugin/machinesetinittime/admission.go @@ -0,0 +1,65 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machinesetinittime + +import ( + "errors" + "fmt" + "io" + + "k8s.io/apiserver/pkg/admission" + + "github.com/jetstack/tarmak/pkg/apis/wing" +) + +const PluginName = "MachineSetInitTime" + +// Register registers a plugin +func Register(plugins *admission.Plugins) { + plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { + return New() + }) +} + +type machinesetInitTime struct { + *admission.Handler +} + +// Admit ensures that the object in-flight is of kind Flunder. +// In addition checks that the Name is not on the banned list. +// The list is stored in Fischers API objects. +func (d *machinesetInitTime) Admit(a admission.Attributes) error { + // we are only interested in machinesetss + if a.GetKind().GroupKind() != wing.Kind("MachineSet") { + return nil + } + + machineset, ok := a.GetObject().(*wing.MachineSet) + if !ok { + return errors.New("unexpected object time") + } + + if machineset.Spec == nil { + return fmt.Errorf("expected machineset replicas to be set, got=%v", machineset.Spec) + } + + if machineset.Spec.MinReplicas == nil { + return fmt.Errorf("expected machineset min replicas to be set, got=%v", machineset.Spec.MinReplicas) + } + if machineset.Spec.MaxReplicas == nil { + return fmt.Errorf("expected machineset max replicas to be set, got=%v", machineset.Spec.MaxReplicas) + } + + return nil +} + +// Validate checks whether the plugin was correctly initialized. +func (d *machinesetInitTime) Validate() error { + return nil +} + +// New creates a new machines init time admission plugin +func New() (admission.Interface, error) { + return &machinesetInitTime{ + Handler: admission.NewHandler(admission.Create, admission.Update), + }, nil +} diff --git a/pkg/wing/apiserver/apiserver.go b/pkg/wing/apiserver/apiserver.go index f507f90ac2..68f0808bab 100644 --- a/pkg/wing/apiserver/apiserver.go +++ b/pkg/wing/apiserver/apiserver.go @@ -18,6 +18,8 @@ import ( "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" wingregistry "github.com/jetstack/tarmak/pkg/wing/registry" machinestorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machine" + machinedeploymentstorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machinedeployment" + machinesetsstorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machineset" ) var ( @@ -92,6 +94,8 @@ func (c completedConfig) New() (*WingServer, error) { apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion v1alpha1storage := map[string]rest.Storage{} v1alpha1storage["machines"] = wingregistry.RESTInPeace(machinestorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + v1alpha1storage["machinesets"] = wingregistry.RESTInPeace(machinesetsstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + v1alpha1storage["machinedeployments"] = wingregistry.RESTInPeace(machinedeploymentstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { diff --git a/pkg/wing/client/informers/externalversions/factory.go b/pkg/wing/client/informers/externalversions/factory.go index a2e14e26b4..6a5c61e2ee 100644 --- a/pkg/wing/client/informers/externalversions/factory.go +++ b/pkg/wing/client/informers/externalversions/factory.go @@ -6,7 +6,6 @@ package externalversions import ( versioned "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" - apis "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/apis" internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/internalinterfaces" wing "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions/wing" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -109,14 +108,9 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - Wing() apis.Interface Wing() wing.Interface } -func (f *sharedInformerFactory) Wing() apis.Interface { - return apis.New(f, f.namespace, f.tweakListOptions) -} - func (f *sharedInformerFactory) Wing() wing.Interface { return wing.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/wing/client/informers/externalversions/generic.go b/pkg/wing/client/informers/externalversions/generic.go index 1091331bde..d8127fd480 100644 --- a/pkg/wing/client/informers/externalversions/generic.go +++ b/pkg/wing/client/informers/externalversions/generic.go @@ -6,7 +6,6 @@ package externalversions import ( "fmt" - wing "github.com/jetstack/tarmak/pkg/apis/wing" v1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" @@ -38,15 +37,7 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=wing.tarmak.io, Version=wing - case wing.SchemeGroupVersion.WithResource("machines"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().Machines().Informer()}, nil - case wing.SchemeGroupVersion.WithResource("machinedeployments"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().MachineDeployments().Informer()}, nil - case wing.SchemeGroupVersion.WithResource("machinesets"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().Wing().MachineSets().Informer()}, nil - - // Group=wing.tarmak.io, Version=v1alpha1 + // Group=wing.tarmak.io, Version=v1alpha1 case v1alpha1.SchemeGroupVersion.WithResource("machines"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().V1alpha1().Machines().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("machinedeployments"): diff --git a/pkg/wing/client/informers/internalversion/generic.go b/pkg/wing/client/informers/internalversion/generic.go index 2a78cc7067..f8149b568a 100644 --- a/pkg/wing/client/informers/internalversion/generic.go +++ b/pkg/wing/client/informers/internalversion/generic.go @@ -40,6 +40,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=wing.tarmak.io, Version=internalVersion case wing.SchemeGroupVersion.WithResource("machines"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().Machines().Informer()}, nil + case wing.SchemeGroupVersion.WithResource("machinedeployments"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().MachineDeployments().Informer()}, nil case wing.SchemeGroupVersion.WithResource("machinesets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Wing().InternalVersion().MachineSets().Informer()}, nil diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go index 35e2d742db..adfc6e264f 100644 --- a/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/interface.go @@ -12,6 +12,8 @@ import ( type Interface interface { // Machines returns a MachineInformer. Machines() MachineInformer + // MachineDeployments returns a MachineDeploymentInformer. + MachineDeployments() MachineDeploymentInformer // MachineSets returns a MachineSetInformer. MachineSets() MachineSetInformer } @@ -32,6 +34,11 @@ func (v *version) Machines() MachineInformer { return &machineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// MachineDeployments returns a MachineDeploymentInformer. +func (v *version) MachineDeployments() MachineDeploymentInformer { + return &machineDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // MachineSets returns a MachineSetInformer. func (v *version) MachineSets() MachineSetInformer { return &machineSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/wing/client/informers/internalversion/wing/internalversion/machinedeployment.go b/pkg/wing/client/informers/internalversion/wing/internalversion/machinedeployment.go new file mode 100644 index 0000000000..ed8e002ca6 --- /dev/null +++ b/pkg/wing/client/informers/internalversion/wing/internalversion/machinedeployment.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by informer-gen + +package internalversion + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + clientset_internalversion "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" + internalinterfaces "github.com/jetstack/tarmak/pkg/wing/client/informers/internalversion/internalinterfaces" + internalversion "github.com/jetstack/tarmak/pkg/wing/client/listers/wing/internalversion" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + time "time" +) + +// MachineDeploymentInformer provides access to a shared informer and lister for +// MachineDeployments. +type MachineDeploymentInformer interface { + Informer() cache.SharedIndexInformer + Lister() internalversion.MachineDeploymentLister +} + +type machineDeploymentInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMachineDeploymentInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMachineDeploymentInformer constructs a new informer for MachineDeployment type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMachineDeploymentInformer(client clientset_internalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Wing().MachineDeployments(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Wing().MachineDeployments(namespace).Watch(options) + }, + }, + &wing.MachineDeployment{}, + resyncPeriod, + indexers, + ) +} + +func (f *machineDeploymentInformer) defaultInformer(client clientset_internalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMachineDeploymentInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *machineDeploymentInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&wing.MachineDeployment{}, f.defaultInformer) +} + +func (f *machineDeploymentInformer) Lister() internalversion.MachineDeploymentLister { + return internalversion.NewMachineDeploymentLister(f.Informer().GetIndexer()) +} diff --git a/pkg/wing/client/listers/apis/wing/expansion_generated.go b/pkg/wing/client/listers/apis/wing/expansion_generated.go new file mode 100644 index 0000000000..f1bb16114e --- /dev/null +++ b/pkg/wing/client/listers/apis/wing/expansion_generated.go @@ -0,0 +1,29 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package wing + +// MachineListerExpansion allows custom methods to be added to +// MachineLister. +type MachineListerExpansion interface{} + +// MachineNamespaceListerExpansion allows custom methods to be added to +// MachineNamespaceLister. +type MachineNamespaceListerExpansion interface{} + +// MachineDeploymentListerExpansion allows custom methods to be added to +// MachineDeploymentLister. +type MachineDeploymentListerExpansion interface{} + +// MachineDeploymentNamespaceListerExpansion allows custom methods to be added to +// MachineDeploymentNamespaceLister. +type MachineDeploymentNamespaceListerExpansion interface{} + +// MachineSetListerExpansion allows custom methods to be added to +// MachineSetLister. +type MachineSetListerExpansion interface{} + +// MachineSetNamespaceListerExpansion allows custom methods to be added to +// MachineSetNamespaceLister. +type MachineSetNamespaceListerExpansion interface{} diff --git a/pkg/wing/client/listers/apis/wing/machine.go b/pkg/wing/client/listers/apis/wing/machine.go new file mode 100644 index 0000000000..c3d88be0b0 --- /dev/null +++ b/pkg/wing/client/listers/apis/wing/machine.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package wing + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineLister helps list Machines. +type MachineLister interface { + // List lists all Machines in the indexer. + List(selector labels.Selector) (ret []*wing.Machine, err error) + // Machines returns an object that can list and get Machines. + Machines(namespace string) MachineNamespaceLister + MachineListerExpansion +} + +// machineLister implements the MachineLister interface. +type machineLister struct { + indexer cache.Indexer +} + +// NewMachineLister returns a new MachineLister. +func NewMachineLister(indexer cache.Indexer) MachineLister { + return &machineLister{indexer: indexer} +} + +// List lists all Machines in the indexer. +func (s *machineLister) List(selector labels.Selector) (ret []*wing.Machine, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.Machine)) + }) + return ret, err +} + +// Machines returns an object that can list and get Machines. +func (s *machineLister) Machines(namespace string) MachineNamespaceLister { + return machineNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineNamespaceLister helps list and get Machines. +type MachineNamespaceLister interface { + // List lists all Machines in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.Machine, err error) + // Get retrieves the Machine from the indexer for a given namespace and name. + Get(name string) (*wing.Machine, error) + MachineNamespaceListerExpansion +} + +// machineNamespaceLister implements the MachineNamespaceLister +// interface. +type machineNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Machines in the indexer for a given namespace. +func (s machineNamespaceLister) List(selector labels.Selector) (ret []*wing.Machine, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.Machine)) + }) + return ret, err +} + +// Get retrieves the Machine from the indexer for a given namespace and name. +func (s machineNamespaceLister) Get(name string) (*wing.Machine, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machine"), name) + } + return obj.(*wing.Machine), nil +} diff --git a/pkg/wing/client/listers/apis/wing/machinedeployment.go b/pkg/wing/client/listers/apis/wing/machinedeployment.go new file mode 100644 index 0000000000..a704216892 --- /dev/null +++ b/pkg/wing/client/listers/apis/wing/machinedeployment.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package wing + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineDeploymentLister helps list MachineDeployments. +type MachineDeploymentLister interface { + // List lists all MachineDeployments in the indexer. + List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) + // MachineDeployments returns an object that can list and get MachineDeployments. + MachineDeployments(namespace string) MachineDeploymentNamespaceLister + MachineDeploymentListerExpansion +} + +// machineDeploymentLister implements the MachineDeploymentLister interface. +type machineDeploymentLister struct { + indexer cache.Indexer +} + +// NewMachineDeploymentLister returns a new MachineDeploymentLister. +func NewMachineDeploymentLister(indexer cache.Indexer) MachineDeploymentLister { + return &machineDeploymentLister{indexer: indexer} +} + +// List lists all MachineDeployments in the indexer. +func (s *machineDeploymentLister) List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineDeployment)) + }) + return ret, err +} + +// MachineDeployments returns an object that can list and get MachineDeployments. +func (s *machineDeploymentLister) MachineDeployments(namespace string) MachineDeploymentNamespaceLister { + return machineDeploymentNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineDeploymentNamespaceLister helps list and get MachineDeployments. +type MachineDeploymentNamespaceLister interface { + // List lists all MachineDeployments in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) + // Get retrieves the MachineDeployment from the indexer for a given namespace and name. + Get(name string) (*wing.MachineDeployment, error) + MachineDeploymentNamespaceListerExpansion +} + +// machineDeploymentNamespaceLister implements the MachineDeploymentNamespaceLister +// interface. +type machineDeploymentNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineDeployments in the indexer for a given namespace. +func (s machineDeploymentNamespaceLister) List(selector labels.Selector) (ret []*wing.MachineDeployment, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineDeployment)) + }) + return ret, err +} + +// Get retrieves the MachineDeployment from the indexer for a given namespace and name. +func (s machineDeploymentNamespaceLister) Get(name string) (*wing.MachineDeployment, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machinedeployment"), name) + } + return obj.(*wing.MachineDeployment), nil +} diff --git a/pkg/wing/client/listers/apis/wing/machineset.go b/pkg/wing/client/listers/apis/wing/machineset.go new file mode 100644 index 0000000000..800e5e3a5c --- /dev/null +++ b/pkg/wing/client/listers/apis/wing/machineset.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. + +// This file was automatically generated by lister-gen + +package wing + +import ( + wing "github.com/jetstack/tarmak/pkg/apis/wing" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MachineSetLister helps list MachineSets. +type MachineSetLister interface { + // List lists all MachineSets in the indexer. + List(selector labels.Selector) (ret []*wing.MachineSet, err error) + // MachineSets returns an object that can list and get MachineSets. + MachineSets(namespace string) MachineSetNamespaceLister + MachineSetListerExpansion +} + +// machineSetLister implements the MachineSetLister interface. +type machineSetLister struct { + indexer cache.Indexer +} + +// NewMachineSetLister returns a new MachineSetLister. +func NewMachineSetLister(indexer cache.Indexer) MachineSetLister { + return &machineSetLister{indexer: indexer} +} + +// List lists all MachineSets in the indexer. +func (s *machineSetLister) List(selector labels.Selector) (ret []*wing.MachineSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineSet)) + }) + return ret, err +} + +// MachineSets returns an object that can list and get MachineSets. +func (s *machineSetLister) MachineSets(namespace string) MachineSetNamespaceLister { + return machineSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MachineSetNamespaceLister helps list and get MachineSets. +type MachineSetNamespaceLister interface { + // List lists all MachineSets in the indexer for a given namespace. + List(selector labels.Selector) (ret []*wing.MachineSet, err error) + // Get retrieves the MachineSet from the indexer for a given namespace and name. + Get(name string) (*wing.MachineSet, error) + MachineSetNamespaceListerExpansion +} + +// machineSetNamespaceLister implements the MachineSetNamespaceLister +// interface. +type machineSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MachineSets in the indexer for a given namespace. +func (s machineSetNamespaceLister) List(selector labels.Selector) (ret []*wing.MachineSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*wing.MachineSet)) + }) + return ret, err +} + +// Get retrieves the MachineSet from the indexer for a given namespace and name. +func (s machineSetNamespaceLister) Get(name string) (*wing.MachineSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(wing.Resource("machineset"), name) + } + return obj.(*wing.MachineSet), nil +} diff --git a/pkg/wing/controller.go b/pkg/wing/controller.go index 178d42f131..8449593bef 100644 --- a/pkg/wing/controller.go +++ b/pkg/wing/controller.go @@ -2,6 +2,7 @@ package wing import ( + "errors" "fmt" "time" @@ -71,7 +72,7 @@ func (c *Controller) syncToStdout(key string) error { machineAPI := c.wing.clientset.WingV1alpha1().Machines(c.wing.flags.ClusterName) machine := &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ - Name: c.wing.flags.InstanceName, + Name: c.wing.flags.MachineName, }, Status: &v1alpha1.MachineStatus{ Converge: &v1alpha1.MachineStatusManifest{ @@ -86,7 +87,10 @@ func (c *Controller) syncToStdout(key string) error { } else { // Note that you also have to check the uid if you have a local controlled resource, which // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machine := obj.(*v1alpha1.Machine) + machine, ok := obj.(*v1alpha1.Machine) + if !ok { + return errors.New("failed to process next item, not a machine") + } // trigger converge if status time is older or not existing if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index ab9cb3fea7..28a430739b 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -120,8 +120,8 @@ func (w *Wing) runPuppet() (*v1alpha1.MachineStatus, error) { } expBackoff := backoff.NewExponentialBackOff() - expBackoff.InitialInterval = time.Second * 30 - expBackoff.MaxElapsedTime = time.Minute * 30 + expBackoff.InitialInterval = time.Second * 10 + expBackoff.MaxElapsedTime = time.Minute * 20 // add context to backoff ctx, cancelRetries := context.WithCancel(context.Background()) @@ -294,14 +294,17 @@ func (w *Wing) puppetApply(dir string) (output string, retCode int, err error) { func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { machineAPI := w.clientset.WingV1alpha1().Machines(w.flags.ClusterName) machine, err := machineAPI.Get( - w.flags.InstanceName, + w.flags.MachineName, metav1.GetOptions{}, ) if err != nil { if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { machine = &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ - Name: w.flags.InstanceName, + Name: w.flags.MachineName, + Labels: map[string]string{ + "role": w.flags.Role, + }, }, Status: status.DeepCopy(), } diff --git a/pkg/wing/registry/wing/machinedeployment/etcd.go b/pkg/wing/registry/wing/machinedeployment/etcd.go new file mode 100644 index 0000000000..6a12df1ddd --- /dev/null +++ b/pkg/wing/registry/wing/machinedeployment/etcd.go @@ -0,0 +1,34 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machinedeployment + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + + "github.com/jetstack/tarmak/pkg/apis/wing" + "github.com/jetstack/tarmak/pkg/wing/registry" +) + +// NewREST returns a RESTStorage object that will work against API services. +func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*registry.REST, error) { + strategy := NewStrategy(scheme) + + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &wing.MachineDeployment{} }, + NewListFunc: func() runtime.Object { return &wing.MachineDeploymentList{} }, + PredicateFunc: MatchMachineDeployment, + DefaultQualifiedResource: wing.Resource("machinedeploymentss"), + + CreateStrategy: strategy, + UpdateStrategy: strategy, + DeleteStrategy: strategy, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + return nil, err + } + return ®istry.REST{ + Store: store, + }, nil +} diff --git a/pkg/wing/registry/wing/machinedeployment/strategy.go b/pkg/wing/registry/wing/machinedeployment/strategy.go new file mode 100644 index 0000000000..3535f0915b --- /dev/null +++ b/pkg/wing/registry/wing/machinedeployment/strategy.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machinedeployment + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/names" + + "github.com/jetstack/tarmak/pkg/apis/wing" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" +) + +func NewStrategy(typer runtime.ObjectTyper) machinedeploymentStrategy { + return machinedeploymentStrategy{typer, names.SimpleNameGenerator} +} + +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { + apiserver, ok := obj.(*wing.Machine) + if !ok { + return nil, nil, false, fmt.Errorf("given object is not a Machine.") + } + return labels.Set(apiserver.ObjectMeta.Labels), MachineToSelectableFields(apiserver), apiserver.Initializers != nil, nil +} + +// MatchMachineDeployment is the filter used by the generic etcd backend to watch events +// from etcd to clients of the apiserver only interested in specific labels/fields. +func MatchMachineDeployment(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + } +} + +// MachineToSelectableFields returns a field set that represents the object. +func MachineToSelectableFields(obj *wing.Machine) fields.Set { + return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) +} + +type machinedeploymentStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +func (machinedeploymentStrategy) NamespaceScoped() bool { + return true +} + +func (machinedeploymentStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machinedeploymentStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machinedeploymentStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { + return field.ErrorList{} +} + +func (machinedeploymentStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (machinedeploymentStrategy) AllowUnconditionalUpdate() bool { + return false +} + +func (machinedeploymentStrategy) Canonicalize(obj runtime.Object) { +} + +func (machinedeploymentStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { + return field.ErrorList{} +} diff --git a/pkg/wing/registry/wing/machineset/etcd.go b/pkg/wing/registry/wing/machineset/etcd.go new file mode 100644 index 0000000000..01b02b46fc --- /dev/null +++ b/pkg/wing/registry/wing/machineset/etcd.go @@ -0,0 +1,34 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machineset + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + + "github.com/jetstack/tarmak/pkg/apis/wing" + "github.com/jetstack/tarmak/pkg/wing/registry" +) + +// NewREST returns a RESTStorage object that will work against API services. +func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*registry.REST, error) { + strategy := NewStrategy(scheme) + + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &wing.MachineSet{} }, + NewListFunc: func() runtime.Object { return &wing.MachineSetList{} }, + PredicateFunc: MatchMachineSet, + DefaultQualifiedResource: wing.Resource("machinesetss"), + + CreateStrategy: strategy, + UpdateStrategy: strategy, + DeleteStrategy: strategy, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + return nil, err + } + return ®istry.REST{ + Store: store, + }, nil +} diff --git a/pkg/wing/registry/wing/machineset/strategy.go b/pkg/wing/registry/wing/machineset/strategy.go new file mode 100644 index 0000000000..f22e417c62 --- /dev/null +++ b/pkg/wing/registry/wing/machineset/strategy.go @@ -0,0 +1,80 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machineset + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/names" + + "github.com/jetstack/tarmak/pkg/apis/wing" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" +) + +func NewStrategy(typer runtime.ObjectTyper) machinesetStrategy { + return machinesetStrategy{typer, names.SimpleNameGenerator} +} + +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { + apiserver, ok := obj.(*wing.Machine) + if !ok { + return nil, nil, false, fmt.Errorf("given object is not a Machine.") + } + return labels.Set(apiserver.ObjectMeta.Labels), MachineToSelectableFields(apiserver), apiserver.Initializers != nil, nil +} + +// MatchMachineSet is the filter used by the generic etcd backend to watch events +// from etcd to clients of the apiserver only interested in specific labels/fields. +func MatchMachineSet(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + } +} + +// MachineToSelectableFields returns a field set that represents the object. +func MachineToSelectableFields(obj *wing.Machine) fields.Set { + return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) +} + +type machinesetStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +func (machinesetStrategy) NamespaceScoped() bool { + return true +} + +func (machinesetStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machinesetStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) { + // TODO: update all none timestamp to now() +} + +func (machinesetStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { + return field.ErrorList{} +} + +func (machinesetStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (machinesetStrategy) AllowUnconditionalUpdate() bool { + return false +} + +func (machinesetStrategy) Canonicalize(obj runtime.Object) { +} + +func (machinesetStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { + return field.ErrorList{} +} diff --git a/pkg/wing/server/server.go b/pkg/wing/server/server.go index 4c8a9293b4..e368c55007 100644 --- a/pkg/wing/server/server.go +++ b/pkg/wing/server/server.go @@ -14,6 +14,7 @@ import ( "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machineinittime" + "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machinesetinittime" "github.com/jetstack/tarmak/pkg/wing/admission/winginitializer" "github.com/jetstack/tarmak/pkg/wing/apiserver" clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" @@ -30,7 +31,7 @@ type WingServerOptions struct { StdErr io.Writer } -var defaultAdmissionControllers = []string{instaceinittime.PluginName} +var defaultAdmissionControllers = []string{machineinittime.PluginName, machinesetinittime.PluginName} func NewWingServerOptions(out, errOut io.Writer) *WingServerOptions { o := &WingServerOptions{ @@ -47,7 +48,8 @@ func NewWingServerOptions(out, errOut io.Writer) *WingServerOptions { // NewCommandStartMaster provides a CLI handler for 'start master' command func NewCommandStartWingServer(out, errOut io.Writer, stopCh <-chan struct{}) *cobra.Command { o := NewWingServerOptions(out, errOut) - instaceinittime.Register(o.Admission.Plugins) + machineinittime.Register(o.Admission.Plugins) + machinesetinittime.Register(o.Admission.Plugins) o.Admission.PluginNames = defaultAdmissionControllers cmd := &cobra.Command{ diff --git a/pkg/wing/wing.go b/pkg/wing/wing.go index c2ea93ef78..b9f8884d5b 100644 --- a/pkg/wing/wing.go +++ b/pkg/wing/wing.go @@ -21,7 +21,7 @@ import ( ) const ( - DefaultInstanceName = "$(hostname)" + DefaultMachineName = "$(hostname)" ) type Wing struct { @@ -43,10 +43,11 @@ type Wing struct { } type Flags struct { - ManifestURL string - ServerURL string - ClusterName string - InstanceName string + ManifestURL string + ServerURL string + ClusterName string + MachineName string + Role string } func New(flags *Flags) *Wing { @@ -65,17 +66,17 @@ func New(flags *Flags) *Wing { func (w *Wing) Run(args []string) error { var errors []error - if w.flags.InstanceName == DefaultInstanceName { - instanceName, err := os.Hostname() + if w.flags.MachineName == DefaultMachineName { + machineName, err := os.Hostname() if err != nil { return err } - w.flags.InstanceName = instanceName + w.flags.MachineName = machineName } - if w.flags.InstanceName == "" { - errors = append(errors, fmt.Errorf("--instance-name flag cannot be empty")) + if w.flags.MachineName == "" { + errors = append(errors, fmt.Errorf("--machine-name flag cannot be empty")) } if w.flags.ManifestURL == "" { errors = append(errors, fmt.Errorf("--manifest-url flag cannot be empty")) @@ -125,7 +126,7 @@ func (w *Wing) Must(err error) *Wing { func (w *Wing) watchForNotifications() { // create the machine watcher - machineListWatcher := cache.NewListWatchFromClient(w.clientset.WingV1alpha1().RESTClient(), "machines", w.flags.ClusterName, fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", w.flags.InstanceName))) + machineListWatcher := cache.NewListWatchFromClient(w.clientset.WingV1alpha1().RESTClient(), "machines", w.flags.ClusterName, fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", w.flags.MachineName))) // create the workqueue queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) diff --git a/terraform/amazon/templates/puppet_agent_user_data.yaml.template b/terraform/amazon/templates/puppet_agent_user_data.yaml.template index 36452555bd..4823516acb 100644 --- a/terraform/amazon/templates/puppet_agent_user_data.yaml.template +++ b/terraform/amazon/templates/puppet_agent_user_data.yaml.template @@ -38,7 +38,7 @@ write_files: {{- end }} ExecStart=/bin/sh -c '\ set -e ;\ - exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443"' + exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443"' --role "${tarmak_role}" [Install] WantedBy=multi-user.target From ad78527745e5f1c75ac46dc4f18fc7cc6450e2fc Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Wed, 12 Dec 2018 17:54:21 +0000 Subject: [PATCH 05/14] Adds MachineSet and MachineDeployment controllers Signed-off-by: JoshVanL --- cmd/wing/cmd/agent.go | 3 +- pkg/apis/wing/common/consts.go | 17 +- pkg/tarmak/utils/maps.go | 8 + .../{ => controller/machine}/controller.go | 21 +- .../machinedeployment/controller.go | 217 ++++++++++++++++++ pkg/wing/controller/machineset/controller.go | 207 +++++++++++++++++ pkg/wing/interfaces/interfaces.go | 17 ++ pkg/wing/puppet.go | 5 +- pkg/wing/server/controller.go | 74 ++++++ pkg/wing/server/server.go | 14 +- pkg/wing/wing.go | 41 ++-- 11 files changed, 593 insertions(+), 31 deletions(-) rename pkg/wing/{ => controller/machine}/controller.go (90%) create mode 100644 pkg/wing/controller/machinedeployment/controller.go create mode 100644 pkg/wing/controller/machineset/controller.go create mode 100644 pkg/wing/interfaces/interfaces.go create mode 100644 pkg/wing/server/controller.go diff --git a/cmd/wing/cmd/agent.go b/cmd/wing/cmd/agent.go index 9231455e86..c2cd8c234d 100644 --- a/cmd/wing/cmd/agent.go +++ b/cmd/wing/cmd/agent.go @@ -4,10 +4,11 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/jetstack/tarmak/pkg/apis/wing/common" "github.com/jetstack/tarmak/pkg/wing" ) -var agentFlags = &wing.Flags{} +var agentFlags = &common.Flags{} var agentCmd = &cobra.Command{ Use: "agent", diff --git a/pkg/apis/wing/common/consts.go b/pkg/apis/wing/common/consts.go index 4480164021..e1a2b0de2b 100644 --- a/pkg/apis/wing/common/consts.go +++ b/pkg/apis/wing/common/consts.go @@ -1,11 +1,6 @@ // Copyright Jetstack Ltd. See LICENSE for details. package common -type MachineStatusError string -type MachineManifestState string - -type MachineDeploymentStrategyType string - const ( MachineManifestStateConverging = MachineManifestState("converging") MachineManifestStateConverged = MachineManifestState("converged") @@ -15,3 +10,15 @@ const ( // i.e gradually scale down the old MachineSet and scale up the new one. RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" ) + +type MachineStatusError string +type MachineManifestState string +type MachineDeploymentStrategyType string + +type Flags struct { + ManifestURL string + ServerURL string + ClusterName string + MachineName string + Role string +} diff --git a/pkg/tarmak/utils/maps.go b/pkg/tarmak/utils/maps.go index bd46968445..c99a585cfb 100644 --- a/pkg/tarmak/utils/maps.go +++ b/pkg/tarmak/utils/maps.go @@ -26,3 +26,11 @@ func DuplicateMapBool(base map[string]bool) map[string]bool { } return newMap } + +func DuplicateMapString(base map[string]string) map[string]string { + newMap := make(map[string]string) + for key, value := range base { + newMap[key] = value + } + return newMap +} diff --git a/pkg/wing/controller.go b/pkg/wing/controller/machine/controller.go similarity index 90% rename from pkg/wing/controller.go rename to pkg/wing/controller/machine/controller.go index 8449593bef..5468dbbc2a 100644 --- a/pkg/wing/controller.go +++ b/pkg/wing/controller/machine/controller.go @@ -1,5 +1,5 @@ // Copyright Jetstack Ltd. See LICENSE for details. -package wing +package machine import ( "errors" @@ -14,6 +14,7 @@ import ( "k8s.io/client-go/util/workqueue" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "github.com/jetstack/tarmak/pkg/wing/interfaces" ) type Controller struct { @@ -21,15 +22,15 @@ type Controller struct { queue workqueue.RateLimitingInterface informer cache.Controller log *logrus.Entry - wing *Wing + wing interfaces.Wing } -func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller, wing *Wing) *Controller { +func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller, wing interfaces.Wing) *Controller { return &Controller{ informer: informer, indexer: indexer, queue: queue, - log: wing.log.WithField("tier", "controller"), + log: wing.Log().WithField("tier", "controller"), wing: wing, } } @@ -58,7 +59,7 @@ func (c *Controller) processNextItem() bool { func (c *Controller) syncToStdout(key string) error { // ensure only one converge at a time - c.wing.convergeWG.Wait() + c.wing.ConvergeWGWait() obj, exists, err := c.indexer.GetByKey(key) if err != nil { @@ -69,10 +70,14 @@ func (c *Controller) syncToStdout(key string) error { if !exists { // Below we will warm up our cache with a Machine, so that we will see a delete for one machine fmt.Printf("Machine %s does not exist anymore\n", key) - machineAPI := c.wing.clientset.WingV1alpha1().Machines(c.wing.flags.ClusterName) + machineAPI := c.wing.Clientset().WingV1alpha1().Machines(c.wing.Flags().ClusterName) machine := &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ - Name: c.wing.flags.MachineName, + Name: c.wing.Flags().MachineName, + Labels: map[string]string{ + "role": c.wing.Flags().Role, + "cluster": c.wing.Flags().ClusterName, + }, }, Status: &v1alpha1.MachineStatus{ Converge: &v1alpha1.MachineStatusManifest{ @@ -109,7 +114,7 @@ func (c *Controller) syncToStdout(key string) error { } c.log.Infof("running converge") - c.wing.converge() + c.wing.Converge() } return nil } diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go new file mode 100644 index 0000000000..d3b7f89379 --- /dev/null +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -0,0 +1,217 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machinedeployment + +import ( + "errors" + "fmt" + "time" + + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "github.com/jetstack/tarmak/pkg/apis/wing" + "github.com/jetstack/tarmak/pkg/tarmak/utils" + clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" +) + +type Controller struct { + indexer cache.Indexer + queue workqueue.RateLimitingInterface + informer cache.Controller + log *logrus.Entry + client *clientset.Clientset +} + +func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller, client *clientset.Clientset) *Controller { + return &Controller{ + informer: informer, + indexer: indexer, + queue: queue, + log: logrus.NewEntry(logrus.New()).WithField("tier", "controller"), + client: client, + } +} + +func (c *Controller) processNextItem() bool { + // Wait until there is a new item in the working queue + key, quit := c.queue.Get() + if quit { + return false + } + // Tell the queue that we are done with processing this key. This unblocks the key for other workers + // This allows safe parallel processing because two machinedeployments with the same key are never processed in + // parallel. + defer c.queue.Done(key) + + // Invoke the method containing the business logic + err := c.syncToStdout(key.(string)) + // Handle the error if something went wrong during the execution of the business logic + c.handleErr(err, key) + return true +} + +// syncToStdout is the business logic of the controller. In this controller it simply prints +// information about the machine to stdout. In case an error happened, it has to simply return the error. +// The retry logic should not be part of the business logic. +func (c *Controller) syncToStdout(key string) error { + + obj, exists, err := c.indexer.GetByKey(key) + if err != nil { + c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) + return err + } + + if !exists { + fmt.Printf("Machine %s does not exist anymore\n", key) + return nil + } + + // Note that you also have to check the uid if you have a local controlled resource, which + // is dependent on the actual machine, to detect that a Machine was recreated with the same name + machinedeployment, ok := obj.(*wing.MachineDeployment) + if !ok { + return errors.New("failed to process next item, not a machinedeployment") + } + machinedeployment = machinedeployment.DeepCopy() + + machinesetAPI := c.client.Wing().MachineSets(machinedeployment.Namespace) + machinesetList, err := machinesetAPI.List(metav1.ListOptions{ + FieldSelector: machinedeployment.Spec.Selector.String(), + }) + if err != nil { + return err + } + machinesetList = machinesetList.DeepCopy() + + if len(machinesetList.Items) > 1 { + return fmt.Errorf("there can only be a maximum of one MachineSet per MachineDeployment, got=%d", len(machinesetList.Items)) + } + + // we need to create the machine set for this deployment + if len(machinesetList.Items) == 0 { + fmt.Printf("Creating MachineSet for MachineDeployment %s\n", key) + machineset := &wing.MachineSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: machinedeployment.Name, + Labels: utils.DuplicateMapString(machinedeployment.Labels), + }, + Spec: &wing.MachineSetSpec{ + MaxReplicas: machinedeployment.Spec.MaxReplicas, + MinReadySeconds: *machinedeployment.Spec.MinReadySeconds, + MinReplicas: machinedeployment.Spec.MinReplicas, + Selector: machinedeployment.Spec.Selector, + }, + } + + _, err := machinesetAPI.Create(machineset) + if err != nil { + return fmt.Errorf("error creating machine: %s", err) + } + + return nil + } + + machineset := machinesetList.Items[0] + status := &wing.MachineDeploymentStatus{ + Replicas: machineset.Status.Replicas, + ObservedGeneration: machinedeployment.Status.ObservedGeneration + 1, + ReadyReplicas: machineset.Status.ReadyReplicas, + // we may want to do something with available replicas + AvailableReplicas: machineset.Status.ReadyReplicas, + UnavailableReplicas: machineset.Status.Replicas - machineset.Status.ReadyReplicas, + } + + machineDeploymentAPI := c.client.Wing().MachineDeployments(machinedeployment.Namespace) + machinedeployment.Status = status.DeepCopy() + _, err = machineDeploymentAPI.Update(machinedeployment) + if err != nil { + return fmt.Errorf("failed to update machinedeployment: %s", err) + } + + return nil +} + +// handleErr checks if an error happened and makes sure we will retry later. +func (c *Controller) handleErr(err error, key interface{}) { + if err == nil { + // Forget about the #AddRateLimited history of the key on every successful synchronization. + // This ensures that future processing of updates for this key is not delayed because of + // an outdated error history. + c.queue.Forget(key) + return + } + + // This controller retries 5 times if something goes wrong. After that, it stops trying. + if c.queue.NumRequeues(key) < 5 { + c.log.Infof("Error syncing machine %v: %v", key, err) + + // Re-enqueue the key rate limited. Based on the rate limiter on the + // queue and the re-enqueue history, the key will be processed later again. + c.queue.AddRateLimited(key) + return + } + + c.queue.Forget(key) + // Report to an external entity that, even after several retries, we could not successfully process this key + runtime.HandleError(err) + c.log.Infof("Dropping machine %q out of the queue: %v", key, err) +} + +func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { + defer runtime.HandleCrash() + + // Let the workers stop when we are done + defer c.queue.ShutDown() + c.log.Info("Starting MachineDeployment controller") + + go c.informer.Run(stopCh) + + // Wait for all involved caches to be synced, before processing items from the queue is started + if !cache.WaitForCacheSync(stopCh, c.informer.HasSynced) { + runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync")) + return + } + + for i := 0; i < threadiness; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + <-stopCh + c.log.Info("Stopping Machine controller") +} + +func (c *Controller) runWorker() { + for c.processNextItem() { + } +} + +func (c *Controller) machineConverged(machine wing.Machine) bool { + if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { + if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { + if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { + return true + } + } else { + return true + } + } else { + return true + } + + return false +} + +func (c *Controller) fullyLabeledMachine(set *wing.MachineSet, machine wing.Machine) bool { + for k, v := range set.Spec.Selector.MatchLabels { + a, ok := machine.Labels[k] + if !ok || a != v { + return false + } + } + + return true +} diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go new file mode 100644 index 0000000000..77c47bd035 --- /dev/null +++ b/pkg/wing/controller/machineset/controller.go @@ -0,0 +1,207 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package machineset + +import ( + "errors" + "fmt" + "time" + + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "github.com/jetstack/tarmak/pkg/apis/wing" + clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" +) + +type Controller struct { + indexer cache.Indexer + queue workqueue.RateLimitingInterface + informer cache.Controller + log *logrus.Entry + client *clientset.Clientset +} + +func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller, client *clientset.Clientset) *Controller { + return &Controller{ + informer: informer, + indexer: indexer, + queue: queue, + log: logrus.NewEntry(logrus.New()).WithField("tier", "controller"), + client: client, + } +} + +func (c *Controller) processNextItem() bool { + // Wait until there is a new item in the working queue + key, quit := c.queue.Get() + if quit { + return false + } + // Tell the queue that we are done with processing this key. This unblocks the key for other workers + // This allows safe parallel processing because two machinesets with the same key are never processed in + // parallel. + defer c.queue.Done(key) + + // Invoke the method containing the business logic + err := c.syncToStdout(key.(string)) + // Handle the error if something went wrong during the execution of the business logic + c.handleErr(err, key) + return true +} + +// syncToStdout is the business logic of the controller. In this controller it simply prints +// information about the machine to stdout. In case an error happened, it has to simply return the error. +// The retry logic should not be part of the business logic. +func (c *Controller) syncToStdout(key string) error { + + obj, exists, err := c.indexer.GetByKey(key) + if err != nil { + c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) + return err + } + + if !exists { + c.log.Infof("MachineSet %s does not exist anymore\n", key) + return nil + } + + // Note that you also have to check the uid if you have a local controlled resource, which + // is dependent on the actual machine, to detect that a Machine was recreated with the same name + machineset, ok := obj.(*wing.MachineSet) + if !ok { + return errors.New("failed to process next item, not a machineset") + } + machineset = machineset.DeepCopy() + + machineAPI := c.client.Wing().Machines(machineset.Namespace) + machineList, err := machineAPI.List(metav1.ListOptions{ + FieldSelector: machineset.Spec.Selector.String(), + }) + if err != nil { + return err + } + machineList = machineList.DeepCopy() + + if int32(len(machineList.Items)) > *machineset.Spec.MaxReplicas { + c.log.Warnf("more machines exist then the maximum, max=%v curr=%v", *machineset.Spec.MaxReplicas, len(machineList.Items)) + } + + //if int32(len(machineList.Items)) < *machineset.Spec.MinReplicas { + // c.log.Warnf("less machines exist then the minimum, min=%v curr=%v", *machineset.Spec.MinReplicas, len(machineList.Items)) + //} + + var readyMachines int32 + var fullyLabeledMachines int32 + for _, i := range machineList.Items { + if c.machineConverged(i) { + readyMachines++ + } + + if c.fullyLabeledMachine(machineset, i) { + fullyLabeledMachines++ + } + } + + status := &wing.MachineSetStatus{ + Replicas: int32(len(machineList.Items)), + ObservedGeneration: machineset.Status.ObservedGeneration + 1, + ReadyReplicas: readyMachines, + FullyLabeledReplicas: fullyLabeledMachines, + // we may want to do something with available replicas + AvailableReplicas: readyMachines, + } + + machineSetAPI := c.client.Wing().MachineSets(machineset.Namespace) + machineset.Status = status.DeepCopy() + _, err = machineSetAPI.Update(machineset) + if err != nil { + return fmt.Errorf("failed to update machineset: %s", err) + } + + return nil +} + +// handleErr checks if an error happened and makes sure we will retry later. +func (c *Controller) handleErr(err error, key interface{}) { + if err == nil { + // Forget about the #AddRateLimited history of the key on every successful synchronization. + // This ensures that future processing of updates for this key is not delayed because of + // an outdated error history. + c.queue.Forget(key) + return + } + + // This controller retries 5 times if something goes wrong. After that, it stops trying. + if c.queue.NumRequeues(key) < 5 { + c.log.Infof("Error syncing machine %v: %v", key, err) + + // Re-enqueue the key rate limited. Based on the rate limiter on the + // queue and the re-enqueue history, the key will be processed later again. + c.queue.AddRateLimited(key) + return + } + + c.queue.Forget(key) + // Report to an external entity that, even after several retries, we could not successfully process this key + runtime.HandleError(err) + c.log.Infof("Dropping machine %q out of the queue: %v", key, err) +} + +func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { + defer runtime.HandleCrash() + + // Let the workers stop when we are done + defer c.queue.ShutDown() + c.log.Info("Starting MachineSet controller") + + go c.informer.Run(stopCh) + + // Wait for all involved caches to be synced, before processing items from the queue is started + if !cache.WaitForCacheSync(stopCh, c.informer.HasSynced) { + runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync")) + return + } + + for i := 0; i < threadiness; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + <-stopCh + c.log.Info("Stopping Machine controller") +} + +func (c *Controller) runWorker() { + for c.processNextItem() { + } +} + +func (c *Controller) machineConverged(machine wing.Machine) bool { + if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { + if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { + if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { + return true + } + } else { + return true + } + } else { + return true + } + + return false +} + +func (c *Controller) fullyLabeledMachine(set *wing.MachineSet, machine wing.Machine) bool { + for k, v := range set.Spec.Selector.MatchLabels { + a, ok := machine.Labels[k] + if !ok || a != v { + return false + } + } + + return true +} diff --git a/pkg/wing/interfaces/interfaces.go b/pkg/wing/interfaces/interfaces.go new file mode 100644 index 0000000000..73bf6fa12b --- /dev/null +++ b/pkg/wing/interfaces/interfaces.go @@ -0,0 +1,17 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package interfaces + +import ( + "github.com/sirupsen/logrus" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" + client "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" +) + +type Wing interface { + Log() *logrus.Entry + Converge() + ConvergeWGWait() + Clientset() *client.Clientset + Flags() common.Flags +} diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index 28a430739b..e1e9f62042 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -152,7 +152,7 @@ func (w *Wing) runPuppet() (*v1alpha1.MachineStatus, error) { return status, nil } -func (w *Wing) converge() { +func (w *Wing) Converge() { w.convergeWG.Add(1) defer w.convergeWG.Done() @@ -303,7 +303,8 @@ func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { ObjectMeta: metav1.ObjectMeta{ Name: w.flags.MachineName, Labels: map[string]string{ - "role": w.flags.Role, + "role": w.flags.Role, + "cluster": w.flags.ClusterName, }, }, Status: status.DeepCopy(), diff --git a/pkg/wing/server/controller.go b/pkg/wing/server/controller.go new file mode 100644 index 0000000000..514317850b --- /dev/null +++ b/pkg/wing/server/controller.go @@ -0,0 +1,74 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package server + +import ( + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "github.com/jetstack/tarmak/pkg/wing/controller/machinedeployment" + "github.com/jetstack/tarmak/pkg/wing/controller/machineset" +) + +func (o WingServerOptions) StartMachineControllers() error { + machinesetListWatcher := cache.NewListWatchFromClient(o.client.Wing().RESTClient(), "machinesets", metav1.NamespaceAll, fields.Everything()) + queueSet := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + indexerSet, informerSet := cache.NewIndexerInformer(machinesetListWatcher, &v1alpha1.MachineSet{}, 0, cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + key, err := cache.MetaNamespaceKeyFunc(obj) + if err == nil { + queueSet.AddAfter(key, 2*time.Second) + } + }, + UpdateFunc: func(old interface{}, new interface{}) { + key, err := cache.MetaNamespaceKeyFunc(new) + if err == nil { + queueSet.AddAfter(key, 2*time.Second) + } + }, + DeleteFunc: func(obj interface{}) { + // IndexerInformer uses a delta queue, therefore for deletes we have to use this + // key function. + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err == nil { + queueSet.AddAfter(key, 2*time.Second) + } + }, + }, cache.Indexers{}) + machinesetController := machineset.NewController(queueSet, indexerSet, informerSet, o.client) + + machinedeploymentListWatcher := cache.NewListWatchFromClient(o.client.Wing().RESTClient(), "machinedeployments", metav1.NamespaceAll, fields.Everything()) + queueDeployment := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + indexerDeployment, informerDeployment := cache.NewIndexerInformer(machinedeploymentListWatcher, &v1alpha1.MachineDeployment{}, 0, cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + key, err := cache.MetaNamespaceKeyFunc(obj) + if err == nil { + queueDeployment.AddAfter(key, 2*time.Second) + } + }, + UpdateFunc: func(old interface{}, new interface{}) { + key, err := cache.MetaNamespaceKeyFunc(new) + if err == nil { + queueDeployment.AddAfter(key, 2*time.Second) + } + }, + DeleteFunc: func(obj interface{}) { + // IndexerInformer uses a delta queue, therefore for deletes we have to use this + // key function. + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err == nil { + queueDeployment.AddAfter(key, 2*time.Second) + } + }, + }, cache.Indexers{}) + machinedeploymentController := machinedeployment.NewController(queueDeployment, indexerDeployment, informerDeployment, o.client) + + //// Now let's start the controllers + go machinesetController.Run(1, o.stopCh) + go machinedeploymentController.Run(1, o.stopCh) + return nil +} diff --git a/pkg/wing/server/server.go b/pkg/wing/server/server.go index e368c55007..aa33faf06d 100644 --- a/pkg/wing/server/server.go +++ b/pkg/wing/server/server.go @@ -1,5 +1,4 @@ // Copyright Jetstack Ltd. See LICENSE for details. - package server import ( @@ -26,9 +25,13 @@ const defaultEtcdPathPrefix = "/registry/wing.tarmak.io" type WingServerOptions struct { RecommendedOptions *genericoptions.RecommendedOptions Admission *genericoptions.AdmissionOptions + informerFactory informers.SharedInformerFactory StdOut io.Writer StdErr io.Writer + + stopCh <-chan struct{} + client *clientset.Clientset } var defaultAdmissionControllers = []string{machineinittime.PluginName, machinesetinittime.PluginName} @@ -106,7 +109,11 @@ func (o WingServerOptions) Config() (*apiserver.Config, error) { if err != nil { return nil, err } + client.Wing() + o.client = client + informerFactory := informers.NewSharedInformerFactory(client, serverConfig.LoopbackClientConfig.Timeout) + o.informerFactory = informerFactory admissionInitializer, err := winginitializer.New(informerFactory) if err != nil { return nil, err @@ -116,6 +123,11 @@ func (o WingServerOptions) Config() (*apiserver.Config, error) { return nil, err } + err = o.StartMachineControllers() + if err != nil { + return nil, err + } + config := &apiserver.Config{ GenericConfig: serverConfig, } diff --git a/pkg/wing/wing.go b/pkg/wing/wing.go index b9f8884d5b..7bb5f24b54 100644 --- a/pkg/wing/wing.go +++ b/pkg/wing/wing.go @@ -16,8 +16,10 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" + "github.com/jetstack/tarmak/pkg/apis/wing/common" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" client "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + "github.com/jetstack/tarmak/pkg/wing/controller/machine" ) const ( @@ -26,7 +28,7 @@ const ( type Wing struct { log *logrus.Entry - flags *Flags + flags *common.Flags clientset *client.Clientset // stop channel, signals termination to all goroutines @@ -36,21 +38,13 @@ type Wing struct { convergeWG sync.WaitGroup // wait group for converge runs // controller loop - controller *Controller + controller *machine.Controller // allows overriding puppet command for testing puppetCommandOverride Command } -type Flags struct { - ManifestURL string - ServerURL string - ClusterName string - MachineName string - Role string -} - -func New(flags *Flags) *Wing { +func New(flags *common.Flags) *Wing { logger := logrus.New() logger.Level = logrus.DebugLevel @@ -104,7 +98,7 @@ func (w *Wing) Run(args []string) error { w.signalHandler(signalCh) // run converge loop after first start - go w.converge() + go w.Converge() // start watching for API server events that trigger applies w.watchForNotifications() @@ -158,7 +152,7 @@ func (w *Wing) watchForNotifications() { }, }, cache.Indexers{}) - w.controller = NewController(queue, indexer, informer, w) + w.controller = machine.NewController(queue, indexer, informer, w) // Now let's start the controller go w.controller.Run(1, w.stopCh) @@ -182,7 +176,7 @@ func (w *Wing) signalHandler(ch chan os.Signal) { // create new converge stop channel and run converge w.convergeStopCh = make(chan struct{}) - w.converge() + w.Converge() case syscall.SIGINT: w.log.Infof("wing received SIGINT") @@ -197,3 +191,22 @@ func (w *Wing) signalHandler(ch chan os.Signal) { } }() } + +func (w *Wing) Log() *logrus.Entry { + return w.log +} + +func (w *Wing) ConvergeWGWait() { + w.convergeWG.Wait() +} + +func (w *Wing) Clientset() *client.Clientset { + return w.clientset +} + +func (w *Wing) Flags() common.Flags { + if w.flags != nil { + return *w.flags + } + return common.Flags{} +} From 7bdd5c22af57901d6d1da9db49e27fc8c6aa10f5 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Wed, 12 Dec 2018 23:49:23 +0000 Subject: [PATCH 06/14] Tarmak sets up deployments of instance pools Signed-off-by: JoshVanL --- pkg/tarmak/cluster/configuration.go | 104 +++++++---- pkg/tarmak/cluster/wing.go | 167 +++++++++++++++--- pkg/tarmak/environment/environment.go | 9 +- pkg/tarmak/utils/pointer.go | 7 + .../machinedeploymentinittime/admission.go | 16 +- .../plugin/machineinittime/admission.go | 3 +- .../plugin/machinesetinittime/admission.go | 16 +- .../admission/winginitializer/interfaces.go | 2 +- .../winginitializer/winginitializer.go | 2 +- pkg/wing/apiserver/apiserver.go | 4 +- pkg/wing/controller/machine/controller.go | 4 +- .../machinedeployment/controller.go | 59 ++----- pkg/wing/controller/machineset/controller.go | 41 +++-- .../registry/wing/machinedeployment/etcd.go | 2 +- .../wing/machinedeployment/strategy.go | 6 +- pkg/wing/registry/wing/machineset/strategy.go | 6 +- pkg/wing/server/controller.go | 2 +- pkg/wing/server/server.go | 9 +- .../puppet_agent_user_data.yaml.template | 2 +- 19 files changed, 295 insertions(+), 166 deletions(-) create mode 100644 pkg/tarmak/utils/pointer.go diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index 9f9b0a13ff..84900adefb 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -43,28 +43,38 @@ func (c *Cluster) ReapplyConfiguration() error { c.log.Infof("making sure all machines apply the latest manifest") // connect to wing - client, err := c.wingMachineClient() - if err != nil { - return fmt.Errorf("failed to connect to wing API on bastion: %s", err) - } + //client, err := c.wingMachineDeploymentClient() + //if err != nil { + // return fmt.Errorf("failed to connect to wing API on bastion: %s", err) + //} - // list machines - machines, err := c.listMachines() - if err != nil { - return fmt.Errorf("failed to list machines: %s", err) + //if err := c.deleteUnusedMachines(); err != nil { + // return err + //} + + if err := c.updateMachineDeployments(); err != nil { + return err } - for pos, _ := range machines { - machine := machines[pos] - if machine.Spec == nil { - machine.Spec = &wingv1alpha1.MachineSpec{} - } - machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} + //// list machine deployments + //deployments, err := c.listMachineDeployments() + //if err != nil { + // return fmt.Errorf("failed to list machines: %s", err) + //} - if _, err := client.Update(machine); err != nil { - c.log.Warnf("error updating machine %s in wing API: %s", machine.Name, err) - } - } + //for pos, _ := range deployments { + // deployment := deployments[pos] + // if deployment.Spec == nil { + // //machine.Spec = &wingv1alpha1.MachineSpec{} + // } + // //machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} + + // if _, err := client.Update(deployment); err != nil { + // c.log.Warnf("error updating machine deployment %s in wing API: %s", deployment.Name, err) + // } + //} + + //fmt.Printf("%+#v\n", deployments) // TODO: solve this on the API server side time.Sleep(time.Second * 5) @@ -78,40 +88,60 @@ func (c *Cluster) WaitForConvergance() error { retries := retries for { - machines, err := c.listMachines() + deployments, err := c.listMachineDeployments() if err != nil { return fmt.Errorf("failed to list machines: %s", err) } - machineByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) + //machineByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) - for pos, _ := range machines { - machine := machines[pos] - - // index by machine convergance state - if machine.Status == nil || machine.Status.Converge == nil || machine.Status.Converge.State == "" { + var converged []*wingv1alpha1.MachineDeployment + var converging []*wingv1alpha1.MachineDeployment + for pos, _ := range deployments { + deployment := deployments[pos] + if deployment.Status == nil || deployment.Spec == nil || deployment.Spec.MinReplicas == nil { + converging = append(converging, deployment) continue } - state := machine.Status.Converge.State - if _, ok := machineByState[state]; !ok { - machineByState[state] = []*wingv1alpha1.Machine{} + if deployment.Status.ReadyReplicas >= deployment.Status.Replicas && + deployment.Status.Replicas >= *deployment.Spec.MinReplicas { + converged = append(converged, deployment) + continue } - machineByState[state] = append( - machineByState[state], - machine, - ) + converging = append(converging, deployment) } - err = c.checkAllMachinesConverged(machineByState) - if err == nil { - c.log.Info("all machines converged") + if len(converging) == 0 { + c.log.Info("all deployments converged") return nil - } else { - c.log.Debug(err) } + var convergingStr string + var convergedStr string + for _, c := range converging { + convergingStr = fmt.Sprintf("%s %s", convergingStr, c.Name) + } + for _, c := range converged { + convergedStr = fmt.Sprintf("%s %s", convergedStr, c.Name) + } + + if convergedStr != "" { + c.log.Debugf("converged deployments [%s]", convergedStr) + } + c.log.Debugf("converging deployments [%s]", convergingStr) + + //c.log. + + //err = c.checkAllMachinesConverged(machineByState) + //if err == nil { + // c.log.Info("all machines converged") + // return nil + //} else { + // c.log.Debug(err) + //} + select { case <-c.ctx.Done(): return c.ctx.Err() diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 80eb972ac4..42aaaa95be 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -12,51 +12,125 @@ import ( wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/tarmak/interfaces" + "github.com/jetstack/tarmak/pkg/tarmak/utils" + wingclient "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" wingclientv1alpha1 "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned/typed/wing/v1alpha1" ) -func (c *Cluster) wingMachineClient() (wingclientv1alpha1.MachineInterface, error) { - var err error +func (c *Cluster) listMachineDeployments() ([]*wingv1alpha1.MachineDeployment, error) { - if c.wingClientset == nil { - // connect to wing + client, err := c.wingMachineDeploymentClient() + if err != nil { + return nil, fmt.Errorf("failed to connect to wing API on bastion: %s", err) + } - wingClientsetTry := func() error { - c.wingClientset, c.wingTunnel, err = c.Environment().WingClientset() - if err != nil { - return fmt.Errorf("failed to connect to wing API on bastion: %s", err) - } + machineDeploymentsList, err := client.List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + + var deployments []*wingv1alpha1.MachineDeployment + for _, d := range machineDeploymentsList.DeepCopy().Items { + deployments = append(deployments, &d) + } + + return deployments, nil +} + +func (c *Cluster) updateMachineDeployments() error { + client, err := c.wingMachineDeploymentClient() + if err != nil { + return fmt.Errorf("failed to connect to wing API on bastion: %s", err) + } - return nil + // list all deployments in wing + deployments, err := client.List(metav1.ListOptions{}) + if err != nil { + return err + } + + deploymentsMap := make(map[string]*wingv1alpha1.MachineDeployment) + if err != nil { + return fmt.Errorf("failed to list provider's machines: %s", err) + } + + for _, d := range deployments.DeepCopy().Items { + deploymentsMap[d.Name] = &d + } + + for _, i := range c.InstancePools() { + if i.Role().Name() == "bastion" { + continue } - expBackoff := backoff.NewExponentialBackOff() - expBackoff.InitialInterval = time.Second - expBackoff.MaxElapsedTime = time.Minute * 2 + spec := c.deploymentSpec(i) + d, ok := deploymentsMap[i.Role().Name()] + if !ok { + + dep := &wingv1alpha1.MachineDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: i.Role().Name(), + Namespace: i.Config().ClusterName, + Labels: map[string]string{ + "role": i.Role().Name(), + "cluster": c.ClusterName(), + }, + }, + Spec: c.deploymentSpec(i), + } + _, err := client.Create(dep) + if err != nil { + return fmt.Errorf("failed to create new deployment %s: %s", i.Role().Name(), err) + } - b := backoff.WithContext(expBackoff, context.Background()) + c.log.Infof("created new machine deployment %s", i.Role().Name()) - if err := backoff.Retry(wingClientsetTry, b); err != nil { - return nil, err + continue } + d = d.DeepCopy() + d.Spec = spec + + _, err := client.Update(d) + if err != nil { + return fmt.Errorf("failed to update deployment sepc %s: %s", i.Role().Name(), err) + } } - return c.wingClientset.WingV1alpha1().Machines(c.ClusterName()), nil + return nil +} + +func (c *Cluster) deploymentSpec(instancePool interfaces.InstancePool) *wingv1alpha1.MachineDeploymentSpec { + a := int32(instancePool.Config().MaxCount) + b := int32(instancePool.Config().MinCount) + return &wingv1alpha1.MachineDeploymentSpec{ + //MaxReplicas: utils.PointerInt32(instancePool.Config().MaxCount), + //MinReplicas: utils.PointerInt32(instancePool.Config().MinCount), + MaxReplicas: &a, + MinReplicas: &b, + MinReadySeconds: utils.PointerInt32(1000), + Paused: false, + Selector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "role": instancePool.Role().Name(), + "cluster": c.ClusterName(), + }, + }, + } } -func (c *Cluster) listMachines() (machines []*wingv1alpha1.Machine, err error) { +func (c *Cluster) deleteUnusedMachines() error { // connect to wing client, err := c.wingMachineClient() if err != nil { - return machines, fmt.Errorf("failed to connect to wing API on bastion: %s", err) + return fmt.Errorf("failed to connect to wing API on bastion: %s", err) } // list all machines in Provider providerMachines, err := c.ListHosts() providerInstaceMap := make(map[string]interfaces.Host) if err != nil { - return machines, fmt.Errorf("failed to list provider's machines: %s", err) + return fmt.Errorf("failed to list provider's machines: %s", err) } for pos, _ := range providerMachines { @@ -66,12 +140,13 @@ func (c *Cluster) listMachines() (machines []*wingv1alpha1.Machine, err error) { // list all machines in wing wingMachines, err := client.List(metav1.ListOptions{}) if err != nil { - return machines, err + return err } // loop through machines for pos, _ := range wingMachines.Items { machine := &wingMachines.Items[pos] + fmt.Printf("%+#v\n", machine) // removes machines not in AWS if _, ok := providerInstaceMap[machine.Name]; !ok { @@ -81,10 +156,9 @@ func (c *Cluster) listMachines() (machines []*wingv1alpha1.Machine, err error) { } continue } - machines = append(machines, machine) } - return machines, nil + return nil } func (c *Cluster) checkAllMachinesConverged(byState map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) error { @@ -113,3 +187,50 @@ func outputMachines(machines []*wingv1alpha1.Machine) string { } return strings.Join(output, ", ") } + +func (c *Cluster) wingClient() (*wingclient.Clientset, error) { + if c.wingClientset != nil { + return c.wingClientset, nil + } + + // connect to wing + var err error + wingClientsetTry := func() error { + c.wingClientset, c.wingTunnel, err = c.Environment().WingClientset() + if err != nil { + return fmt.Errorf("failed to connect to wing API on bastion: %s", err) + } + + return nil + } + + expBackoff := backoff.NewExponentialBackOff() + expBackoff.InitialInterval = time.Second + expBackoff.MaxElapsedTime = time.Minute * 2 + + b := backoff.WithContext(expBackoff, context.Background()) + + if err := backoff.Retry(wingClientsetTry, b); err != nil { + return nil, err + } + + return c.wingClientset, nil +} + +func (c *Cluster) wingMachineClient() (wingclientv1alpha1.MachineInterface, error) { + client, err := c.wingClient() + if err != nil { + return nil, err + } + + return client.WingV1alpha1().Machines(c.ClusterName()), nil +} + +func (c *Cluster) wingMachineDeploymentClient() (wingclientv1alpha1.MachineDeploymentInterface, error) { + client, err := c.wingClient() + if err != nil { + return nil, err + } + + return client.WingV1alpha1().MachineDeployments(c.ClusterName()), nil +} diff --git a/pkg/tarmak/environment/environment.go b/pkg/tarmak/environment/environment.go index 3e07a56010..5abfbc1f42 100644 --- a/pkg/tarmak/environment/environment.go +++ b/pkg/tarmak/environment/environment.go @@ -305,13 +305,14 @@ func (e *Environment) WingTunnel() interfaces.Tunnel { func (e *Environment) WingClientset() (*wingclient.Clientset, interfaces.Tunnel, error) { tunnel := e.WingTunnel() - if err := tunnel.Start(); err != nil { - return nil, nil, err - } + //if err := tunnel.Start(); err != nil { + // return nil, nil, err + //} // TODO: Do proper TLS here restConfig := &rest.Config{ - Host: fmt.Sprintf("https://127.0.0.1:%d", tunnel.Port()), + //Host: fmt.Sprintf("https://127.0.0.1:%d", tunnel.Port()), + Host: fmt.Sprintf("https://127.0.0.1:%d", 9443), TLSClientConfig: rest.TLSClientConfig{ Insecure: true, }, diff --git a/pkg/tarmak/utils/pointer.go b/pkg/tarmak/utils/pointer.go new file mode 100644 index 0000000000..ea0c1f1c9a --- /dev/null +++ b/pkg/tarmak/utils/pointer.go @@ -0,0 +1,7 @@ +// Copyright Jetstack Ltd. See LICENSE for details. +package utils + +func PointerInt32(i int) *int32 { + j := int32(i) + return &j +} diff --git a/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go index b2e3cd641f..19af3f5c06 100644 --- a/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go +++ b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go @@ -3,7 +3,6 @@ package machinedeploymentinittime import ( "errors" - "fmt" "io" "k8s.io/apiserver/pkg/admission" @@ -28,27 +27,16 @@ type machinedeploymentInitTime struct { // In addition checks that the Name is not on the banned list. // The list is stored in Fischers API objects. func (d *machinedeploymentInitTime) Admit(a admission.Attributes) error { - // we are only interested in machinedeploymentss + // we are only interested in machinedeployments if a.GetKind().GroupKind() != wing.Kind("MachineDeployment") { return nil } - machinedeployment, ok := a.GetObject().(*wing.MachineDeployment) + _, ok := a.GetObject().(*wing.MachineDeployment) if !ok { return errors.New("unexpected object time") } - if machinedeployment.Spec == nil { - return fmt.Errorf("expected machinedeployment replicas to be set, got=%v", machinedeployment.Spec) - } - - if machinedeployment.Spec.MinReplicas == nil { - return fmt.Errorf("expected machinedeployment min replicas to be set, got=%v", machinedeployment.Spec.MinReplicas) - } - if machinedeployment.Spec.MaxReplicas == nil { - return fmt.Errorf("expected machinedeployment max replicas to be set, got=%v", machinedeployment.Spec.MaxReplicas) - } - return nil } diff --git a/pkg/wing/admission/plugin/machineinittime/admission.go b/pkg/wing/admission/plugin/machineinittime/admission.go index bf23fb2f9e..70a24ea9a1 100644 --- a/pkg/wing/admission/plugin/machineinittime/admission.go +++ b/pkg/wing/admission/plugin/machineinittime/admission.go @@ -35,8 +35,9 @@ func (d *machineInitTime) Admit(a admission.Attributes) error { machine, ok := a.GetObject().(*wing.Machine) if !ok { - return errors.New("unexpected object time") + return errors.New("unexpected object type") } + machine = machine.DeepCopy() if machine.Status != nil { if machine.Status.Converge != nil && machine.Status.Converge.LastUpdateTimestamp.IsZero() { diff --git a/pkg/wing/admission/plugin/machinesetinittime/admission.go b/pkg/wing/admission/plugin/machinesetinittime/admission.go index 3b7408e097..4aebbd2e76 100644 --- a/pkg/wing/admission/plugin/machinesetinittime/admission.go +++ b/pkg/wing/admission/plugin/machinesetinittime/admission.go @@ -3,7 +3,6 @@ package machinesetinittime import ( "errors" - "fmt" "io" "k8s.io/apiserver/pkg/admission" @@ -33,20 +32,9 @@ func (d *machinesetInitTime) Admit(a admission.Attributes) error { return nil } - machineset, ok := a.GetObject().(*wing.MachineSet) + _, ok := a.GetObject().(*wing.MachineSet) if !ok { - return errors.New("unexpected object time") - } - - if machineset.Spec == nil { - return fmt.Errorf("expected machineset replicas to be set, got=%v", machineset.Spec) - } - - if machineset.Spec.MinReplicas == nil { - return fmt.Errorf("expected machineset min replicas to be set, got=%v", machineset.Spec.MinReplicas) - } - if machineset.Spec.MaxReplicas == nil { - return fmt.Errorf("expected machineset max replicas to be set, got=%v", machineset.Spec.MaxReplicas) + return errors.New("unexpected object type") } return nil diff --git a/pkg/wing/admission/winginitializer/interfaces.go b/pkg/wing/admission/winginitializer/interfaces.go index c2766db0af..6391ec5b58 100644 --- a/pkg/wing/admission/winginitializer/interfaces.go +++ b/pkg/wing/admission/winginitializer/interfaces.go @@ -3,7 +3,7 @@ package winginitializer import ( - informers "github.com/jetstack/tarmak/pkg/wing/client/informers/internalversion" + informers "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions" "k8s.io/apiserver/pkg/admission" ) diff --git a/pkg/wing/admission/winginitializer/winginitializer.go b/pkg/wing/admission/winginitializer/winginitializer.go index 80590f176c..4da088cda0 100644 --- a/pkg/wing/admission/winginitializer/winginitializer.go +++ b/pkg/wing/admission/winginitializer/winginitializer.go @@ -3,7 +3,7 @@ package winginitializer import ( - informers "github.com/jetstack/tarmak/pkg/wing/client/informers/internalversion" + informers "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions" "k8s.io/apiserver/pkg/admission" ) diff --git a/pkg/wing/apiserver/apiserver.go b/pkg/wing/apiserver/apiserver.go index 68f0808bab..7c3433929e 100644 --- a/pkg/wing/apiserver/apiserver.go +++ b/pkg/wing/apiserver/apiserver.go @@ -19,7 +19,7 @@ import ( wingregistry "github.com/jetstack/tarmak/pkg/wing/registry" machinestorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machine" machinedeploymentstorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machinedeployment" - machinesetsstorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machineset" + machinesetstorage "github.com/jetstack/tarmak/pkg/wing/registry/wing/machineset" ) var ( @@ -94,7 +94,7 @@ func (c completedConfig) New() (*WingServer, error) { apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion v1alpha1storage := map[string]rest.Storage{} v1alpha1storage["machines"] = wingregistry.RESTInPeace(machinestorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) - v1alpha1storage["machinesets"] = wingregistry.RESTInPeace(machinesetsstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + v1alpha1storage["machinesets"] = wingregistry.RESTInPeace(machinesetstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) v1alpha1storage["machinedeployments"] = wingregistry.RESTInPeace(machinedeploymentstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage diff --git a/pkg/wing/controller/machine/controller.go b/pkg/wing/controller/machine/controller.go index 5468dbbc2a..05946984c2 100644 --- a/pkg/wing/controller/machine/controller.go +++ b/pkg/wing/controller/machine/controller.go @@ -131,7 +131,7 @@ func (c *Controller) handleErr(err error, key interface{}) { // This controller retries 5 times if something goes wrong. After that, it stops trying. if c.queue.NumRequeues(key) < 5 { - c.log.Infof("Error syncing machine %v: %v", key, err) + c.log.Errorf("Error syncing machine %v: %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. @@ -142,7 +142,7 @@ func (c *Controller) handleErr(err error, key interface{}) { c.queue.Forget(key) // Report to an external entity that, even after several retries, we could not successfully process this key runtime.HandleError(err) - c.log.Infof("Dropping machine %q out of the queue: %v", key, err) + c.log.Errorf("Dropping machine %q out of the queue: %v", key, err) } func (c *Controller) Run(threadiness int, stopCh chan struct{}) { diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index d3b7f89379..f9fe9670e0 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -4,6 +4,7 @@ package machinedeployment import ( "errors" "fmt" + "strings" "time" "github.com/sirupsen/logrus" @@ -13,9 +14,9 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - "github.com/jetstack/tarmak/pkg/apis/wing" + "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/tarmak/utils" - clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" + clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" ) type Controller struct { @@ -66,21 +67,26 @@ func (c *Controller) syncToStdout(key string) error { } if !exists { - fmt.Printf("Machine %s does not exist anymore\n", key) + fmt.Printf("MachineDeployment %s does not exist anymore\n", key) return nil } // Note that you also have to check the uid if you have a local controlled resource, which // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machinedeployment, ok := obj.(*wing.MachineDeployment) + machinedeployment, ok := obj.(*v1alpha1.MachineDeployment) if !ok { return errors.New("failed to process next item, not a machinedeployment") } machinedeployment = machinedeployment.DeepCopy() - machinesetAPI := c.client.Wing().MachineSets(machinedeployment.Namespace) + var selectors []string + for k, v := range machinedeployment.Spec.Selector.MatchLabels { + selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) + } + + machinesetAPI := c.client.WingV1alpha1().MachineSets(machinedeployment.Namespace) machinesetList, err := machinesetAPI.List(metav1.ListOptions{ - FieldSelector: machinedeployment.Spec.Selector.String(), + LabelSelector: strings.Join(selectors, ","), }) if err != nil { return err @@ -94,12 +100,12 @@ func (c *Controller) syncToStdout(key string) error { // we need to create the machine set for this deployment if len(machinesetList.Items) == 0 { fmt.Printf("Creating MachineSet for MachineDeployment %s\n", key) - machineset := &wing.MachineSet{ + machineset := &v1alpha1.MachineSet{ ObjectMeta: metav1.ObjectMeta{ Name: machinedeployment.Name, Labels: utils.DuplicateMapString(machinedeployment.Labels), }, - Spec: &wing.MachineSetSpec{ + Spec: &v1alpha1.MachineSetSpec{ MaxReplicas: machinedeployment.Spec.MaxReplicas, MinReadySeconds: *machinedeployment.Spec.MinReadySeconds, MinReplicas: machinedeployment.Spec.MinReplicas, @@ -116,7 +122,7 @@ func (c *Controller) syncToStdout(key string) error { } machineset := machinesetList.Items[0] - status := &wing.MachineDeploymentStatus{ + status := &v1alpha1.MachineDeploymentStatus{ Replicas: machineset.Status.Replicas, ObservedGeneration: machinedeployment.Status.ObservedGeneration + 1, ReadyReplicas: machineset.Status.ReadyReplicas, @@ -125,7 +131,7 @@ func (c *Controller) syncToStdout(key string) error { UnavailableReplicas: machineset.Status.Replicas - machineset.Status.ReadyReplicas, } - machineDeploymentAPI := c.client.Wing().MachineDeployments(machinedeployment.Namespace) + machineDeploymentAPI := c.client.WingV1alpha1().MachineDeployments(machinedeployment.Namespace) machinedeployment.Status = status.DeepCopy() _, err = machineDeploymentAPI.Update(machinedeployment) if err != nil { @@ -147,7 +153,7 @@ func (c *Controller) handleErr(err error, key interface{}) { // This controller retries 5 times if something goes wrong. After that, it stops trying. if c.queue.NumRequeues(key) < 5 { - c.log.Infof("Error syncing machine %v: %v", key, err) + c.log.Errorf("Error syncing machine deployment %v: %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. @@ -158,7 +164,7 @@ func (c *Controller) handleErr(err error, key interface{}) { c.queue.Forget(key) // Report to an external entity that, even after several retries, we could not successfully process this key runtime.HandleError(err) - c.log.Infof("Dropping machine %q out of the queue: %v", key, err) + c.log.Errorf("Dropping machine deployment %q out of the queue: %v", key, err) } func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { @@ -181,37 +187,10 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { } <-stopCh - c.log.Info("Stopping Machine controller") + c.log.Info("Stopping MachineDeployment controller") } func (c *Controller) runWorker() { for c.processNextItem() { } } - -func (c *Controller) machineConverged(machine wing.Machine) bool { - if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { - if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { - if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { - return true - } - } else { - return true - } - } else { - return true - } - - return false -} - -func (c *Controller) fullyLabeledMachine(set *wing.MachineSet, machine wing.Machine) bool { - for k, v := range set.Spec.Selector.MatchLabels { - a, ok := machine.Labels[k] - if !ok || a != v { - return false - } - } - - return true -} diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index 77c47bd035..2701507592 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -4,6 +4,7 @@ package machineset import ( "errors" "fmt" + "strings" "time" "github.com/sirupsen/logrus" @@ -13,8 +14,8 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - "github.com/jetstack/tarmak/pkg/apis/wing" - clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" + "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" ) type Controller struct { @@ -71,20 +72,32 @@ func (c *Controller) syncToStdout(key string) error { // Note that you also have to check the uid if you have a local controlled resource, which // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machineset, ok := obj.(*wing.MachineSet) + machineset, ok := obj.(*v1alpha1.MachineSet) if !ok { return errors.New("failed to process next item, not a machineset") } - machineset = machineset.DeepCopy() - machineAPI := c.client.Wing().Machines(machineset.Namespace) + if machineset.Spec == nil { + return fmt.Errorf("machineset spec is nil: %v", machineset.Spec) + } + + if machineset.Spec.MaxReplicas == nil || machineset.Spec.MinReplicas == nil { + return fmt.Errorf("expected machineset min and max replicas to not be nil: min=%v max=%v", + machineset.Spec.MaxReplicas, machineset.Spec.MinReplicas) + } + + var selectors []string + for k, v := range machineset.Spec.Selector.MatchLabels { + selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) + } + + machineAPI := c.client.WingV1alpha1().Machines(machineset.Namespace) machineList, err := machineAPI.List(metav1.ListOptions{ - FieldSelector: machineset.Spec.Selector.String(), + LabelSelector: strings.Join(selectors, ","), }) if err != nil { return err } - machineList = machineList.DeepCopy() if int32(len(machineList.Items)) > *machineset.Spec.MaxReplicas { c.log.Warnf("more machines exist then the maximum, max=%v curr=%v", *machineset.Spec.MaxReplicas, len(machineList.Items)) @@ -106,7 +119,7 @@ func (c *Controller) syncToStdout(key string) error { } } - status := &wing.MachineSetStatus{ + status := &v1alpha1.MachineSetStatus{ Replicas: int32(len(machineList.Items)), ObservedGeneration: machineset.Status.ObservedGeneration + 1, ReadyReplicas: readyMachines, @@ -115,7 +128,7 @@ func (c *Controller) syncToStdout(key string) error { AvailableReplicas: readyMachines, } - machineSetAPI := c.client.Wing().MachineSets(machineset.Namespace) + machineSetAPI := c.client.WingV1alpha1().MachineSets(machineset.Namespace) machineset.Status = status.DeepCopy() _, err = machineSetAPI.Update(machineset) if err != nil { @@ -137,7 +150,7 @@ func (c *Controller) handleErr(err error, key interface{}) { // This controller retries 5 times if something goes wrong. After that, it stops trying. if c.queue.NumRequeues(key) < 5 { - c.log.Infof("Error syncing machine %v: %v", key, err) + c.log.Errorf("Error syncing machineset %v: %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. @@ -148,7 +161,7 @@ func (c *Controller) handleErr(err error, key interface{}) { c.queue.Forget(key) // Report to an external entity that, even after several retries, we could not successfully process this key runtime.HandleError(err) - c.log.Infof("Dropping machine %q out of the queue: %v", key, err) + c.log.Errorf("Dropping machineset %q out of the queue: %v", key, err) } func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { @@ -171,7 +184,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { } <-stopCh - c.log.Info("Stopping Machine controller") + c.log.Info("Stopping MachineSet controller") } func (c *Controller) runWorker() { @@ -179,7 +192,7 @@ func (c *Controller) runWorker() { } } -func (c *Controller) machineConverged(machine wing.Machine) bool { +func (c *Controller) machineConverged(machine v1alpha1.Machine) bool { if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { @@ -195,7 +208,7 @@ func (c *Controller) machineConverged(machine wing.Machine) bool { return false } -func (c *Controller) fullyLabeledMachine(set *wing.MachineSet, machine wing.Machine) bool { +func (c *Controller) fullyLabeledMachine(set *v1alpha1.MachineSet, machine v1alpha1.Machine) bool { for k, v := range set.Spec.Selector.MatchLabels { a, ok := machine.Labels[k] if !ok || a != v { diff --git a/pkg/wing/registry/wing/machinedeployment/etcd.go b/pkg/wing/registry/wing/machinedeployment/etcd.go index 6a12df1ddd..ffa01710bd 100644 --- a/pkg/wing/registry/wing/machinedeployment/etcd.go +++ b/pkg/wing/registry/wing/machinedeployment/etcd.go @@ -18,7 +18,7 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*reg NewFunc: func() runtime.Object { return &wing.MachineDeployment{} }, NewListFunc: func() runtime.Object { return &wing.MachineDeploymentList{} }, PredicateFunc: MatchMachineDeployment, - DefaultQualifiedResource: wing.Resource("machinedeploymentss"), + DefaultQualifiedResource: wing.Resource("machinedeployments"), CreateStrategy: strategy, UpdateStrategy: strategy, diff --git a/pkg/wing/registry/wing/machinedeployment/strategy.go b/pkg/wing/registry/wing/machinedeployment/strategy.go index 3535f0915b..0af4f46117 100644 --- a/pkg/wing/registry/wing/machinedeployment/strategy.go +++ b/pkg/wing/registry/wing/machinedeployment/strategy.go @@ -21,9 +21,9 @@ func NewStrategy(typer runtime.ObjectTyper) machinedeploymentStrategy { } func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { - apiserver, ok := obj.(*wing.Machine) + apiserver, ok := obj.(*wing.MachineDeployment) if !ok { - return nil, nil, false, fmt.Errorf("given object is not a Machine.") + return nil, nil, false, fmt.Errorf("given object is not a MachineDeployment.") } return labels.Set(apiserver.ObjectMeta.Labels), MachineToSelectableFields(apiserver), apiserver.Initializers != nil, nil } @@ -39,7 +39,7 @@ func MatchMachineDeployment(label labels.Selector, field fields.Selector) storag } // MachineToSelectableFields returns a field set that represents the object. -func MachineToSelectableFields(obj *wing.Machine) fields.Set { +func MachineToSelectableFields(obj *wing.MachineDeployment) fields.Set { return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) } diff --git a/pkg/wing/registry/wing/machineset/strategy.go b/pkg/wing/registry/wing/machineset/strategy.go index f22e417c62..89bdf01329 100644 --- a/pkg/wing/registry/wing/machineset/strategy.go +++ b/pkg/wing/registry/wing/machineset/strategy.go @@ -21,9 +21,9 @@ func NewStrategy(typer runtime.ObjectTyper) machinesetStrategy { } func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { - apiserver, ok := obj.(*wing.Machine) + apiserver, ok := obj.(*wing.MachineSet) if !ok { - return nil, nil, false, fmt.Errorf("given object is not a Machine.") + return nil, nil, false, fmt.Errorf("given object is not a MachineSet.") } return labels.Set(apiserver.ObjectMeta.Labels), MachineToSelectableFields(apiserver), apiserver.Initializers != nil, nil } @@ -39,7 +39,7 @@ func MatchMachineSet(label labels.Selector, field fields.Selector) storage.Selec } // MachineToSelectableFields returns a field set that represents the object. -func MachineToSelectableFields(obj *wing.Machine) fields.Set { +func MachineToSelectableFields(obj *wing.MachineSet) fields.Set { return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) } diff --git a/pkg/wing/server/controller.go b/pkg/wing/server/controller.go index 514317850b..84c2dc1ca2 100644 --- a/pkg/wing/server/controller.go +++ b/pkg/wing/server/controller.go @@ -15,7 +15,7 @@ import ( ) func (o WingServerOptions) StartMachineControllers() error { - machinesetListWatcher := cache.NewListWatchFromClient(o.client.Wing().RESTClient(), "machinesets", metav1.NamespaceAll, fields.Everything()) + machinesetListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machinesets", metav1.NamespaceAll, fields.Everything()) queueSet := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) indexerSet, informerSet := cache.NewIndexerInformer(machinesetListWatcher, &v1alpha1.MachineSet{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/pkg/wing/server/server.go b/pkg/wing/server/server.go index aa33faf06d..a161c181ad 100644 --- a/pkg/wing/server/server.go +++ b/pkg/wing/server/server.go @@ -12,12 +12,13 @@ import ( genericoptions "k8s.io/apiserver/pkg/server/options" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" + "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machinedeploymentinittime" "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machineinittime" "github.com/jetstack/tarmak/pkg/wing/admission/plugin/machinesetinittime" "github.com/jetstack/tarmak/pkg/wing/admission/winginitializer" "github.com/jetstack/tarmak/pkg/wing/apiserver" - clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/internalversion" - informers "github.com/jetstack/tarmak/pkg/wing/client/informers/internalversion" + clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" + informers "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions" ) const defaultEtcdPathPrefix = "/registry/wing.tarmak.io" @@ -34,7 +35,7 @@ type WingServerOptions struct { client *clientset.Clientset } -var defaultAdmissionControllers = []string{machineinittime.PluginName, machinesetinittime.PluginName} +var defaultAdmissionControllers = []string{machineinittime.PluginName, machinesetinittime.PluginName, machinedeploymentinittime.PluginName} func NewWingServerOptions(out, errOut io.Writer) *WingServerOptions { o := &WingServerOptions{ @@ -53,6 +54,7 @@ func NewCommandStartWingServer(out, errOut io.Writer, stopCh <-chan struct{}) *c o := NewWingServerOptions(out, errOut) machineinittime.Register(o.Admission.Plugins) machinesetinittime.Register(o.Admission.Plugins) + machinedeploymentinittime.Register(o.Admission.Plugins) o.Admission.PluginNames = defaultAdmissionControllers cmd := &cobra.Command{ @@ -109,7 +111,6 @@ func (o WingServerOptions) Config() (*apiserver.Config, error) { if err != nil { return nil, err } - client.Wing() o.client = client informerFactory := informers.NewSharedInformerFactory(client, serverConfig.LoopbackClientConfig.Timeout) diff --git a/terraform/amazon/templates/puppet_agent_user_data.yaml.template b/terraform/amazon/templates/puppet_agent_user_data.yaml.template index 4823516acb..927a608dfe 100644 --- a/terraform/amazon/templates/puppet_agent_user_data.yaml.template +++ b/terraform/amazon/templates/puppet_agent_user_data.yaml.template @@ -38,7 +38,7 @@ write_files: {{- end }} ExecStart=/bin/sh -c '\ set -e ;\ - exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443"' --role "${tarmak_role}" + exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443" --role "${tarmak_role}"' [Install] WantedBy=multi-user.target From 19735f9af780026be931e8d98b9369fa065c1a0a Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Thu, 13 Dec 2018 20:25:35 +0000 Subject: [PATCH 07/14] MachineDeployment controller syncs by watch of MachineSet Signed-off-by: JoshVanL --- pkg/apis/wing/machinedeployment_types.go | 4 + .../wing/v1alpha1/machinedeployment_types.go | 6 +- pkg/apis/wing/v1alpha1/machineset_types.go | 2 +- pkg/tarmak/cluster/configuration.go | 58 ++++----- pkg/tarmak/cluster/wing.go | 33 +++-- pkg/tarmak/environment/environment.go | 9 +- .../machinedeploymentinittime/admission.go | 35 ++++- .../plugin/machinesetinittime/admission.go | 12 +- pkg/wing/controller/machine/controller.go | 6 +- .../machinedeployment/controller.go | 123 +++++++++++------- pkg/wing/controller/machineset/controller.go | 22 ++-- .../wing/machinedeployment/strategy.go | 1 + pkg/wing/server/controller.go | 6 +- 13 files changed, 188 insertions(+), 129 deletions(-) diff --git a/pkg/apis/wing/machinedeployment_types.go b/pkg/apis/wing/machinedeployment_types.go index f956ec60a3..0ef3b305ea 100644 --- a/pkg/apis/wing/machinedeployment_types.go +++ b/pkg/apis/wing/machinedeployment_types.go @@ -10,9 +10,13 @@ import ( // MachineDeploymentSpec defines the desired state of MachineDeployment type MachineDeploymentSpec struct { + // Number of desired machines. Defaults to 1. // This is a pointer to distinguish between explicit zero and not specified. + // +optional MinReplicas *int32 + + // +optional MaxReplicas *int32 // Label selector for machines. Existing MachineSets whose machines are diff --git a/pkg/apis/wing/v1alpha1/machinedeployment_types.go b/pkg/apis/wing/v1alpha1/machinedeployment_types.go index 2bf9be276b..97c7516a54 100644 --- a/pkg/apis/wing/v1alpha1/machinedeployment_types.go +++ b/pkg/apis/wing/v1alpha1/machinedeployment_types.go @@ -10,10 +10,14 @@ import ( // MachineDeploymentSpec defines the desired state of MachineDeployment type MachineDeploymentSpec struct { + // Number of desired machines. Defaults to 1. // This is a pointer to distinguish between explicit zero and not specified. + // +optional MinReplicas *int32 `json:"minReplicas,omitempty"` - MaxReplicas *int32 `json:"minReplicas,omitempty"` + + // +optional + MaxReplicas *int32 `json:"manReplicas,omitempty"` // Label selector for machines. Existing MachineSets whose machines are // selected by this will be the ones affected by this deployment. diff --git a/pkg/apis/wing/v1alpha1/machineset_types.go b/pkg/apis/wing/v1alpha1/machineset_types.go index 8cd8386ea6..bf5cefe933 100644 --- a/pkg/apis/wing/v1alpha1/machineset_types.go +++ b/pkg/apis/wing/v1alpha1/machineset_types.go @@ -14,7 +14,7 @@ type MachineSetSpec struct { // Defaults to 1. // +optional MinReplicas *int32 `json:"minReplicas,omitempty"` - MaxReplicas *int32 `json:"minReplicas,omitempty"` + MaxReplicas *int32 `json:"maxReplicas,omitempty"` // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. // Defaults to 0 (machine will be considered available as soon as it is ready) diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index 84900adefb..bcc4569e61 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -48,19 +48,19 @@ func (c *Cluster) ReapplyConfiguration() error { // return fmt.Errorf("failed to connect to wing API on bastion: %s", err) //} - //if err := c.deleteUnusedMachines(); err != nil { - // return err - //} + if err := c.deleteUnusedMachines(); err != nil { + return err + } if err := c.updateMachineDeployments(); err != nil { return err } //// list machine deployments - //deployments, err := c.listMachineDeployments() - //if err != nil { - // return fmt.Errorf("failed to list machines: %s", err) - //} + _, err := c.listMachineDeployments() + if err != nil { + return fmt.Errorf("failed to list machines: %s", err) + } //for pos, _ := range deployments { // deployment := deployments[pos] @@ -93,13 +93,12 @@ func (c *Cluster) WaitForConvergance() error { return fmt.Errorf("failed to list machines: %s", err) } - //machineByState := make(map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) - var converged []*wingv1alpha1.MachineDeployment var converging []*wingv1alpha1.MachineDeployment for pos, _ := range deployments { deployment := deployments[pos] - if deployment.Status == nil || deployment.Spec == nil || deployment.Spec.MinReplicas == nil { + + if deployment.Status == nil { converging = append(converging, deployment) continue } @@ -118,42 +117,35 @@ func (c *Cluster) WaitForConvergance() error { return nil } - var convergingStr string + c.log.Debug("--------") var convergedStr string - for _, c := range converging { - convergingStr = fmt.Sprintf("%s %s", convergingStr, c.Name) + for _, d := range converged { + convergedStr = fmt.Sprintf("%s %s", convergedStr, d.Name) } - for _, c := range converged { - convergedStr = fmt.Sprintf("%s %s", convergedStr, c.Name) - } - if convergedStr != "" { c.log.Debugf("converged deployments [%s]", convergedStr) } - c.log.Debugf("converging deployments [%s]", convergingStr) - //c.log. - - //err = c.checkAllMachinesConverged(machineByState) - //if err == nil { - // c.log.Info("all machines converged") - // return nil - //} else { - // c.log.Debug(err) - //} - - select { - case <-c.ctx.Done(): - return c.ctx.Err() - default: + for _, d := range converging { + var readyReplicas int32 + if d.Status != nil { + readyReplicas = d.Status.Replicas + } + c.log.Debugf("converging %s [%v/%v]", d.Name, readyReplicas, *d.Spec.MinReplicas) } retries-- if retries == 0 { break } - time.Sleep(time.Second * 5) + tok := time.Tick(time.Second * 5) + + select { + case <-c.ctx.Done(): + return c.ctx.Err() + case <-tok: + } } return fmt.Errorf("machines failed to converge in time") diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 42aaaa95be..ba3e2ea2b9 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -30,8 +30,8 @@ func (c *Cluster) listMachineDeployments() ([]*wingv1alpha1.MachineDeployment, e } var deployments []*wingv1alpha1.MachineDeployment - for _, d := range machineDeploymentsList.DeepCopy().Items { - deployments = append(deployments, &d) + for i := range machineDeploymentsList.Items { + deployments = append(deployments, &machineDeploymentsList.Items[i]) } return deployments, nil @@ -54,16 +54,15 @@ func (c *Cluster) updateMachineDeployments() error { return fmt.Errorf("failed to list provider's machines: %s", err) } - for _, d := range deployments.DeepCopy().Items { - deploymentsMap[d.Name] = &d + for i := range deployments.Items { + deploymentsMap[deployments.Items[i].Name] = &deployments.Items[i] } for _, i := range c.InstancePools() { - if i.Role().Name() == "bastion" { + if i.Role().Name() == "bastion" || i.Role().Name() == "vault" { continue } - spec := c.deploymentSpec(i) d, ok := deploymentsMap[i.Role().Name()] if !ok { @@ -78,20 +77,21 @@ func (c *Cluster) updateMachineDeployments() error { }, Spec: c.deploymentSpec(i), } + _, err := client.Create(dep) if err != nil { return fmt.Errorf("failed to create new deployment %s: %s", i.Role().Name(), err) } - c.log.Infof("created new machine deployment %s", i.Role().Name()) + c.log.Debugf("created new machine deployment %s", i.Role().Name()) continue } d = d.DeepCopy() - d.Spec = spec + d.Spec = c.deploymentSpec(i) - _, err := client.Update(d) + _, err = client.Update(d) if err != nil { return fmt.Errorf("failed to update deployment sepc %s: %s", i.Role().Name(), err) } @@ -101,15 +101,13 @@ func (c *Cluster) updateMachineDeployments() error { } func (c *Cluster) deploymentSpec(instancePool interfaces.InstancePool) *wingv1alpha1.MachineDeploymentSpec { - a := int32(instancePool.Config().MaxCount) - b := int32(instancePool.Config().MinCount) return &wingv1alpha1.MachineDeploymentSpec{ - //MaxReplicas: utils.PointerInt32(instancePool.Config().MaxCount), - //MinReplicas: utils.PointerInt32(instancePool.Config().MinCount), - MaxReplicas: &a, - MinReplicas: &b, - MinReadySeconds: utils.PointerInt32(1000), - Paused: false, + MaxReplicas: utils.PointerInt32(instancePool.Config().MaxCount), + MinReplicas: utils.PointerInt32(instancePool.Config().MinCount), + ProgressDeadlineSeconds: new(int32), + RevisionHistoryLimit: new(int32), + Strategy: &wingv1alpha1.MachineDeploymentStrategy{}, + Paused: false, Selector: metav1.LabelSelector{ MatchLabels: map[string]string{ "role": instancePool.Role().Name(), @@ -146,7 +144,6 @@ func (c *Cluster) deleteUnusedMachines() error { // loop through machines for pos, _ := range wingMachines.Items { machine := &wingMachines.Items[pos] - fmt.Printf("%+#v\n", machine) // removes machines not in AWS if _, ok := providerInstaceMap[machine.Name]; !ok { diff --git a/pkg/tarmak/environment/environment.go b/pkg/tarmak/environment/environment.go index 5abfbc1f42..3e07a56010 100644 --- a/pkg/tarmak/environment/environment.go +++ b/pkg/tarmak/environment/environment.go @@ -305,14 +305,13 @@ func (e *Environment) WingTunnel() interfaces.Tunnel { func (e *Environment) WingClientset() (*wingclient.Clientset, interfaces.Tunnel, error) { tunnel := e.WingTunnel() - //if err := tunnel.Start(); err != nil { - // return nil, nil, err - //} + if err := tunnel.Start(); err != nil { + return nil, nil, err + } // TODO: Do proper TLS here restConfig := &rest.Config{ - //Host: fmt.Sprintf("https://127.0.0.1:%d", tunnel.Port()), - Host: fmt.Sprintf("https://127.0.0.1:%d", 9443), + Host: fmt.Sprintf("https://127.0.0.1:%d", tunnel.Port()), TLSClientConfig: rest.TLSClientConfig{ Insecure: true, }, diff --git a/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go index 19af3f5c06..928071d0c5 100644 --- a/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go +++ b/pkg/wing/admission/plugin/machinedeploymentinittime/admission.go @@ -3,15 +3,23 @@ package machinedeploymentinittime import ( "errors" + "fmt" "io" "k8s.io/apiserver/pkg/admission" "github.com/jetstack/tarmak/pkg/apis/wing" + informers "github.com/jetstack/tarmak/pkg/wing/client/informers/externalversions" + listers "github.com/jetstack/tarmak/pkg/wing/client/listers/wing/v1alpha1" ) const PluginName = "MachineDeploymentInitTime" +type machinedeploymentInitTime struct { + *admission.Handler + lister listers.MachineDeploymentLister +} + // Register registers a plugin func Register(plugins *admission.Plugins) { plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) { @@ -19,10 +27,6 @@ func Register(plugins *admission.Plugins) { }) } -type machinedeploymentInitTime struct { - *admission.Handler -} - // Admit ensures that the object in-flight is of kind Flunder. // In addition checks that the Name is not on the banned list. // The list is stored in Fischers API objects. @@ -32,19 +36,36 @@ func (d *machinedeploymentInitTime) Admit(a admission.Attributes) error { return nil } - _, ok := a.GetObject().(*wing.MachineDeployment) + if !d.WaitForReady() { + return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request")) + } + + deployment, ok := a.GetObject().(*wing.MachineDeployment) if !ok { - return errors.New("unexpected object time") + return errors.New("failed to converte obj to Machien Deployment type") + } + + if deployment.Spec == nil { + return errors.New("machine deployment spec cannot be nil") + } + + if deployment.Spec.MinReplicas == nil || deployment.Spec.MaxReplicas == nil { + return fmt.Errorf("machine deployment min or max replicas cannot be nil: nil: min=%v max=%v", + deployment.Spec.MinReplicas, deployment.Spec.MaxReplicas) } return nil } // Validate checks whether the plugin was correctly initialized. -func (d *machinedeploymentInitTime) Validate() error { +func (d *machinedeploymentInitTime) ValidateInitialization() error { return nil } +func (d *machinedeploymentInitTime) SetInternalWingInformerFactory(f informers.SharedInformerFactory) { + d.lister = f.Wing().V1alpha1().MachineDeployments().Lister() +} + // New creates a new machines init time admission plugin func New() (admission.Interface, error) { return &machinedeploymentInitTime{ diff --git a/pkg/wing/admission/plugin/machinesetinittime/admission.go b/pkg/wing/admission/plugin/machinesetinittime/admission.go index 4aebbd2e76..e8efcc3756 100644 --- a/pkg/wing/admission/plugin/machinesetinittime/admission.go +++ b/pkg/wing/admission/plugin/machinesetinittime/admission.go @@ -3,6 +3,7 @@ package machinesetinittime import ( "errors" + "fmt" "io" "k8s.io/apiserver/pkg/admission" @@ -32,11 +33,20 @@ func (d *machinesetInitTime) Admit(a admission.Attributes) error { return nil } - _, ok := a.GetObject().(*wing.MachineSet) + machineset, ok := a.GetObject().(*wing.MachineSet) if !ok { return errors.New("unexpected object type") } + if machineset.Spec == nil { + return errors.New("machineset spec cannot be nil") + } + + if machineset.Spec.MinReplicas == nil || machineset.Spec.MaxReplicas == nil { + return fmt.Errorf("machineset min or max replicas cannot be nil: nil: min=%v max=%v", + machineset.Spec.MinReplicas, machineset.Spec.MaxReplicas) + } + return nil } diff --git a/pkg/wing/controller/machine/controller.go b/pkg/wing/controller/machine/controller.go index 05946984c2..aab6def5a7 100644 --- a/pkg/wing/controller/machine/controller.go +++ b/pkg/wing/controller/machine/controller.go @@ -30,7 +30,7 @@ func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer: informer, indexer: indexer, queue: queue, - log: wing.Log().WithField("tier", "controller"), + log: wing.Log().WithField("tier", "Machine-controller"), wing: wing, } } @@ -69,7 +69,7 @@ func (c *Controller) syncToStdout(key string) error { if !exists { // Below we will warm up our cache with a Machine, so that we will see a delete for one machine - fmt.Printf("Machine %s does not exist anymore\n", key) + c.log.Infof("Machine %s does not exist anymore\n", key) machineAPI := c.wing.Clientset().WingV1alpha1().Machines(c.wing.Flags().ClusterName) machine := &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ @@ -89,6 +89,8 @@ func (c *Controller) syncToStdout(key string) error { if err != nil { return fmt.Errorf("error creating machine: %s", err) } + + c.log.Infof("Machine created %v", key) } else { // Note that you also have to check the uid if you have a local controlled resource, which // is dependent on the actual machine, to detect that a Machine was recreated with the same name diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index f9fe9670e0..a3226d1b8c 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -4,10 +4,10 @@ package machinedeployment import ( "errors" "fmt" - "strings" "time" "github.com/sirupsen/logrus" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" @@ -32,7 +32,7 @@ func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer: informer, indexer: indexer, queue: queue, - log: logrus.NewEntry(logrus.New()).WithField("tier", "controller"), + log: logrus.NewEntry(logrus.New()).WithField("tier", "MachineDeployment-controller"), client: client, } } @@ -49,16 +49,13 @@ func (c *Controller) processNextItem() bool { defer c.queue.Done(key) // Invoke the method containing the business logic - err := c.syncToStdout(key.(string)) + err := c.sync(key.(string)) // Handle the error if something went wrong during the execution of the business logic c.handleErr(err, key) return true } -// syncToStdout is the business logic of the controller. In this controller it simply prints -// information about the machine to stdout. In case an error happened, it has to simply return the error. -// The retry logic should not be part of the business logic. -func (c *Controller) syncToStdout(key string) error { +func (c *Controller) sync(key string) error { obj, exists, err := c.indexer.GetByKey(key) if err != nil { @@ -67,7 +64,7 @@ func (c *Controller) syncToStdout(key string) error { } if !exists { - fmt.Printf("MachineDeployment %s does not exist anymore\n", key) + c.log.Infof("object %s does not exist anymore\n", key) return nil } @@ -75,65 +72,93 @@ func (c *Controller) syncToStdout(key string) error { // is dependent on the actual machine, to detect that a Machine was recreated with the same name machinedeployment, ok := obj.(*v1alpha1.MachineDeployment) if !ok { - return errors.New("failed to process next item, not a machinedeployment") + machineset, ok := obj.(*v1alpha1.MachineSet) + if !ok { + return errors.New("failed to process next item, not a machinedeployment or machineset") + } + md, err := c.getMachineDeployment(machineset) + if err != nil { + return err + } + + return c.syncFromMachineSet(md, machineset) } - machinedeployment = machinedeployment.DeepCopy() var selectors []string for k, v := range machinedeployment.Spec.Selector.MatchLabels { selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) } + var minReplicas int32 = 1 + var maxReplicas int32 = 1 + if machinedeployment.Spec.MinReplicas != nil { + minReplicas = *machinedeployment.Spec.MinReplicas + } + if machinedeployment.Spec.MaxReplicas != nil { + maxReplicas = *machinedeployment.Spec.MaxReplicas + } + machinesetAPI := c.client.WingV1alpha1().MachineSets(machinedeployment.Namespace) - machinesetList, err := machinesetAPI.List(metav1.ListOptions{ - LabelSelector: strings.Join(selectors, ","), - }) + machineset, err := machinesetAPI.Get(machinedeployment.Name, metav1.GetOptions{}) + if err != nil { + if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { + c.log.Infof("Creating MachineSet for MachineDeployment %s\n", key) + machineset := &v1alpha1.MachineSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: machinedeployment.Name, + Labels: utils.DuplicateMapString(machinedeployment.Labels), + }, + Spec: &v1alpha1.MachineSetSpec{ + MaxReplicas: &minReplicas, + MinReplicas: &maxReplicas, + Selector: machinedeployment.Spec.Selector, + }, + Status: &v1alpha1.MachineSetStatus{}, + } + + machineset, err = machinesetAPI.Create(machineset) + if err != nil { + return fmt.Errorf("error creating machineset: %s", err) + } + + } else { + return fmt.Errorf("error get existing machineset: %s", err) + } + } + + err = c.syncFromMachineSet(machinedeployment, machineset) if err != nil { return err } - machinesetList = machinesetList.DeepCopy() - - if len(machinesetList.Items) > 1 { - return fmt.Errorf("there can only be a maximum of one MachineSet per MachineDeployment, got=%d", len(machinesetList.Items)) - } - - // we need to create the machine set for this deployment - if len(machinesetList.Items) == 0 { - fmt.Printf("Creating MachineSet for MachineDeployment %s\n", key) - machineset := &v1alpha1.MachineSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: machinedeployment.Name, - Labels: utils.DuplicateMapString(machinedeployment.Labels), - }, - Spec: &v1alpha1.MachineSetSpec{ - MaxReplicas: machinedeployment.Spec.MaxReplicas, - MinReadySeconds: *machinedeployment.Spec.MinReadySeconds, - MinReplicas: machinedeployment.Spec.MinReplicas, - Selector: machinedeployment.Spec.Selector, - }, - } - _, err := machinesetAPI.Create(machineset) - if err != nil { - return fmt.Errorf("error creating machine: %s", err) - } + return nil +} - return nil +func (c *Controller) getMachineDeployment(machineset *v1alpha1.MachineSet) (*v1alpha1.MachineDeployment, error) { + machinedeploymentAPI := c.client.WingV1alpha1().MachineDeployments(machineset.Namespace) + machinedeployment, err := machinedeploymentAPI.Get(machineset.Name, metav1.GetOptions{}) + if err != nil { + return nil, err } - machineset := machinesetList.Items[0] - status := &v1alpha1.MachineDeploymentStatus{ - Replicas: machineset.Status.Replicas, - ObservedGeneration: machinedeployment.Status.ObservedGeneration + 1, - ReadyReplicas: machineset.Status.ReadyReplicas, - // we may want to do something with available replicas - AvailableReplicas: machineset.Status.ReadyReplicas, - UnavailableReplicas: machineset.Status.Replicas - machineset.Status.ReadyReplicas, + return machinedeployment, nil +} + +func (c *Controller) syncFromMachineSet(machinedeployment *v1alpha1.MachineDeployment, machineset *v1alpha1.MachineSet) error { + c.log.Infof("deployment set status: %+v", machinedeployment.Status) + status := &v1alpha1.MachineDeploymentStatus{} + if machineset.Status != nil { + status.Replicas = machineset.Status.Replicas + status.ObservedGeneration = machineset.Status.ObservedGeneration + 1 + status.ReadyReplicas = machineset.Status.ReadyReplicas + // TODO: we may want to do something with available replicas + status.AvailableReplicas = machineset.Status.ReadyReplicas + status.UnavailableReplicas = machineset.Status.Replicas - machineset.Status.ReadyReplicas } machineDeploymentAPI := c.client.WingV1alpha1().MachineDeployments(machinedeployment.Namespace) - machinedeployment.Status = status.DeepCopy() - _, err = machineDeploymentAPI.Update(machinedeployment) + machinedeployment.Status = status + _, err := machineDeploymentAPI.Update(machinedeployment) if err != nil { return fmt.Errorf("failed to update machinedeployment: %s", err) } diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index 2701507592..1c49313e3b 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -110,6 +110,10 @@ func (c *Controller) syncToStdout(key string) error { var readyMachines int32 var fullyLabeledMachines int32 for _, i := range machineList.Items { + //c.log.Infof("status: %+v", i.Status) + //if i.Status.Converge != nil { + // c.log.Infof("status: %+v", i.Status.Converge.State) + //} if c.machineConverged(i) { readyMachines++ } @@ -119,9 +123,14 @@ func (c *Controller) syncToStdout(key string) error { } } + var observedGeneration int64 = 0 + if machineset.Status != nil { + observedGeneration = machineset.Status.ObservedGeneration + } + status := &v1alpha1.MachineSetStatus{ Replicas: int32(len(machineList.Items)), - ObservedGeneration: machineset.Status.ObservedGeneration + 1, + ObservedGeneration: observedGeneration + 1, ReadyReplicas: readyMachines, FullyLabeledReplicas: fullyLabeledMachines, // we may want to do something with available replicas @@ -130,6 +139,7 @@ func (c *Controller) syncToStdout(key string) error { machineSetAPI := c.client.WingV1alpha1().MachineSets(machineset.Namespace) machineset.Status = status.DeepCopy() + c.log.Infof("set status: %+v\n", machineset.Status) _, err = machineSetAPI.Update(machineset) if err != nil { return fmt.Errorf("failed to update machineset: %s", err) @@ -193,15 +203,7 @@ func (c *Controller) runWorker() { } func (c *Controller) machineConverged(machine v1alpha1.Machine) bool { - if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { - if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { - if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { - return true - } - } else { - return true - } - } else { + if machine.Status != nil && machine.Status.Converge != nil && machine.Status.Converge.State == v1alpha1.MachineManifestStateConverged { return true } diff --git a/pkg/wing/registry/wing/machinedeployment/strategy.go b/pkg/wing/registry/wing/machinedeployment/strategy.go index 0af4f46117..09ecbce785 100644 --- a/pkg/wing/registry/wing/machinedeployment/strategy.go +++ b/pkg/wing/registry/wing/machinedeployment/strategy.go @@ -13,6 +13,7 @@ import ( "k8s.io/apiserver/pkg/storage/names" "github.com/jetstack/tarmak/pkg/apis/wing" + //"github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) diff --git a/pkg/wing/server/controller.go b/pkg/wing/server/controller.go index 84c2dc1ca2..0e28639508 100644 --- a/pkg/wing/server/controller.go +++ b/pkg/wing/server/controller.go @@ -16,7 +16,10 @@ import ( func (o WingServerOptions) StartMachineControllers() error { machinesetListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machinesets", metav1.NamespaceAll, fields.Everything()) + machinedeploymentListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machinedeployments", metav1.NamespaceAll, fields.Everything()) queueSet := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + queueDeployment := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + indexerSet, informerSet := cache.NewIndexerInformer(machinesetListWatcher, &v1alpha1.MachineSet{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) @@ -28,6 +31,7 @@ func (o WingServerOptions) StartMachineControllers() error { key, err := cache.MetaNamespaceKeyFunc(new) if err == nil { queueSet.AddAfter(key, 2*time.Second) + queueDeployment.AddAfter(key, 2*time.Second) } }, DeleteFunc: func(obj interface{}) { @@ -41,8 +45,6 @@ func (o WingServerOptions) StartMachineControllers() error { }, cache.Indexers{}) machinesetController := machineset.NewController(queueSet, indexerSet, informerSet, o.client) - machinedeploymentListWatcher := cache.NewListWatchFromClient(o.client.Wing().RESTClient(), "machinedeployments", metav1.NamespaceAll, fields.Everything()) - queueDeployment := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) indexerDeployment, informerDeployment := cache.NewIndexerInformer(machinedeploymentListWatcher, &v1alpha1.MachineDeployment{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) From df9806e842a89e1f74ac22a8497375c9bcbea2c9 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Fri, 14 Dec 2018 09:29:52 +0000 Subject: [PATCH 08/14] Fix error formatting Signed-off-by: JoshVanL --- pkg/wing/admission/plugin/machinesetinittime/admission.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/wing/admission/plugin/machinesetinittime/admission.go b/pkg/wing/admission/plugin/machinesetinittime/admission.go index e8efcc3756..94830a374d 100644 --- a/pkg/wing/admission/plugin/machinesetinittime/admission.go +++ b/pkg/wing/admission/plugin/machinesetinittime/admission.go @@ -43,7 +43,7 @@ func (d *machinesetInitTime) Admit(a admission.Attributes) error { } if machineset.Spec.MinReplicas == nil || machineset.Spec.MaxReplicas == nil { - return fmt.Errorf("machineset min or max replicas cannot be nil: nil: min=%v max=%v", + return fmt.Errorf("machineset min or max replicas cannot be nil: min=%v max=%v", machineset.Spec.MinReplicas, machineset.Spec.MaxReplicas) } From fa215550dbbf919b0a7916636d7db7806f544469 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Fri, 14 Dec 2018 18:53:58 +0000 Subject: [PATCH 09/14] Enforce controller hierarchy and correctly watch resources Signed-off-by: JoshVanL --- cmd/wing/cmd/agent.go | 2 +- pkg/apis/wing/common/consts.go | 2 +- pkg/tarmak/cluster/configuration.go | 56 +++--- pkg/tarmak/cluster/wing.go | 74 ++++---- pkg/wing/controller/machine/controller.go | 2 +- .../machinedeployment/controller.go | 174 ++++++++++-------- pkg/wing/controller/machineset/controller.go | 90 +++++---- pkg/wing/puppet.go | 2 +- pkg/wing/server/controller.go | 59 +++--- .../puppet_agent_user_data.yaml.template | 2 +- 10 files changed, 243 insertions(+), 220 deletions(-) diff --git a/cmd/wing/cmd/agent.go b/cmd/wing/cmd/agent.go index c2cd8c234d..9df3dbfefc 100644 --- a/cmd/wing/cmd/agent.go +++ b/cmd/wing/cmd/agent.go @@ -23,7 +23,7 @@ func init() { agentCmd.Flags().StringVar(&agentFlags.ServerURL, "server-url", "https://localhost:9443", "this specifies the URL to the wing server") agentCmd.Flags().StringVar(&agentFlags.ManifestURL, "manifest-url", "", "this specifies the URL where the puppet.tar.gz can be found") agentCmd.Flags().StringVar(&agentFlags.MachineName, "instance-name", wing.DefaultMachineName, "this specifies the instance's name") - agentCmd.Flags().StringVar(&agentFlags.Role, "role", "", "this specifies the machines role, used as a label selector for machinesets") + agentCmd.Flags().StringVar(&agentFlags.Pool, "pool", "", "this specifies the instance pool the machine resides in, used as a label selector") RootCmd.AddCommand(agentCmd) } diff --git a/pkg/apis/wing/common/consts.go b/pkg/apis/wing/common/consts.go index e1a2b0de2b..34917f09fd 100644 --- a/pkg/apis/wing/common/consts.go +++ b/pkg/apis/wing/common/consts.go @@ -20,5 +20,5 @@ type Flags struct { ServerURL string ClusterName string MachineName string - Role string + Pool string } diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index bcc4569e61..67887c6cc4 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -42,12 +42,6 @@ func (c *Cluster) UploadConfiguration() error { func (c *Cluster) ReapplyConfiguration() error { c.log.Infof("making sure all machines apply the latest manifest") - // connect to wing - //client, err := c.wingMachineDeploymentClient() - //if err != nil { - // return fmt.Errorf("failed to connect to wing API on bastion: %s", err) - //} - if err := c.deleteUnusedMachines(); err != nil { return err } @@ -56,25 +50,28 @@ func (c *Cluster) ReapplyConfiguration() error { return err } - //// list machine deployments - _, err := c.listMachineDeployments() + client, err := c.wingMachineClient() if err != nil { - return fmt.Errorf("failed to list machines: %s", err) + return err } - //for pos, _ := range deployments { - // deployment := deployments[pos] - // if deployment.Spec == nil { - // //machine.Spec = &wingv1alpha1.MachineSpec{} - // } - // //machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} + // here we need to start the mechanism to trigger a re-converge + machines, err := c.listMachines() + if err != nil { + return fmt.Errorf("failed to list machines: %s", err) + } - // if _, err := client.Update(deployment); err != nil { - // c.log.Warnf("error updating machine deployment %s in wing API: %s", deployment.Name, err) - // } - //} + for pos, _ := range machines { + machine := machines[pos] + if machine.Spec == nil { + machine.Spec = &wingv1alpha1.MachineSpec{} + } + machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} - //fmt.Printf("%+#v\n", deployments) + if _, err := client.Update(machine); err != nil { + c.log.Warnf("error updating machine %s in wing API: %s", machine.Name, err) + } + } // TODO: solve this on the API server side time.Sleep(time.Second * 5) @@ -104,7 +101,7 @@ func (c *Cluster) WaitForConvergance() error { } if deployment.Status.ReadyReplicas >= deployment.Status.Replicas && - deployment.Status.Replicas >= *deployment.Spec.MinReplicas { + deployment.Status.ReadyReplicas >= *deployment.Spec.MinReplicas { converged = append(converged, deployment) continue } @@ -112,18 +109,21 @@ func (c *Cluster) WaitForConvergance() error { converging = append(converging, deployment) } + var convergedStr string + for _, d := range converged { + convergedStr = fmt.Sprintf("%s %s", convergedStr, d.Name) + } + convergedStr = fmt.Sprintf("converged deployments [%s]", convergedStr) + if len(converging) == 0 { c.log.Info("all deployments converged") + c.log.Info(convergedStr) return nil } c.log.Debug("--------") - var convergedStr string - for _, d := range converged { - convergedStr = fmt.Sprintf("%s %s", convergedStr, d.Name) - } - if convergedStr != "" { - c.log.Debugf("converged deployments [%s]", convergedStr) + if len(converged) > 0 { + c.log.Debug(convergedStr) } for _, d := range converging { @@ -131,7 +131,7 @@ func (c *Cluster) WaitForConvergance() error { if d.Status != nil { readyReplicas = d.Status.Replicas } - c.log.Debugf("converging %s [%v/%v]", d.Name, readyReplicas, *d.Spec.MinReplicas) + c.log.Debugf("converging %s [%v/%v]", d.Name, readyReplicas, d.Status.Replicas) } retries-- diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index ba3e2ea2b9..50e899825e 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -3,7 +3,6 @@ package cluster import ( "fmt" - "strings" "time" "github.com/cenkalti/backoff" @@ -37,6 +36,26 @@ func (c *Cluster) listMachineDeployments() ([]*wingv1alpha1.MachineDeployment, e return deployments, nil } +func (c *Cluster) listMachines() ([]*wingv1alpha1.Machine, error) { + + client, err := c.wingMachineClient() + if err != nil { + return nil, fmt.Errorf("failed to connect to wing API on bastion: %s", err) + } + + mList, err := client.List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + + var machines []*wingv1alpha1.Machine + for i := range mList.Items { + machines = append(machines, &mList.Items[i]) + } + + return machines, nil +} + func (c *Cluster) updateMachineDeployments() error { client, err := c.wingMachineDeploymentClient() if err != nil { @@ -63,27 +82,27 @@ func (c *Cluster) updateMachineDeployments() error { continue } - d, ok := deploymentsMap[i.Role().Name()] + d, ok := deploymentsMap[i.Name()] if !ok { - dep := &wingv1alpha1.MachineDeployment{ + md := &wingv1alpha1.MachineDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: i.Role().Name(), Namespace: i.Config().ClusterName, Labels: map[string]string{ - "role": i.Role().Name(), + "pool": i.Name(), "cluster": c.ClusterName(), }, }, Spec: c.deploymentSpec(i), } - _, err := client.Create(dep) + _, err := client.Create(md) if err != nil { - return fmt.Errorf("failed to create new deployment %s: %s", i.Role().Name(), err) + return fmt.Errorf("failed to create new deployment %s: %s", i.Name(), err) } - c.log.Debugf("created new machine deployment %s", i.Role().Name()) + c.log.Debugf("created new machine deployment %s", i.Name()) continue } @@ -93,7 +112,7 @@ func (c *Cluster) updateMachineDeployments() error { _, err = client.Update(d) if err != nil { - return fmt.Errorf("failed to update deployment sepc %s: %s", i.Role().Name(), err) + return fmt.Errorf("failed to update deployment sepc %s: %s", i.Name(), err) } } @@ -110,7 +129,7 @@ func (c *Cluster) deploymentSpec(instancePool interfaces.InstancePool) *wingv1al Paused: false, Selector: metav1.LabelSelector{ MatchLabels: map[string]string{ - "role": instancePool.Role().Name(), + "pool": instancePool.Name(), "cluster": c.ClusterName(), }, }, @@ -143,13 +162,13 @@ func (c *Cluster) deleteUnusedMachines() error { // loop through machines for pos, _ := range wingMachines.Items { - machine := &wingMachines.Items[pos] + m := &wingMachines.Items[pos] // removes machines not in AWS - if _, ok := providerInstaceMap[machine.Name]; !ok { - c.log.Debugf("deleting unused machine %s in wing API", machine.Name) - if err := client.Delete(machine.Name, &metav1.DeleteOptions{}); err != nil { - c.log.Warnf("error deleting machine %s in wing API: %s", machine.Name, err) + if _, ok := providerInstaceMap[m.Name]; !ok { + c.log.Debugf("deleting unused machine %s in wing API", m.Name) + if err := client.Delete(m.Name, &metav1.DeleteOptions{}); err != nil { + c.log.Warnf("error deleting machine %s in wing API: %s", m.Name, err) } continue } @@ -158,33 +177,6 @@ func (c *Cluster) deleteUnusedMachines() error { return nil } -func (c *Cluster) checkAllMachinesConverged(byState map[wingv1alpha1.MachineManifestState][]*wingv1alpha1.Machine) error { - machinesNotConverged := []*wingv1alpha1.Machine{} - for key, machines := range byState { - if len(machines) == 0 { - continue - } - if key != wingv1alpha1.MachineManifestStateConverged { - machinesNotConverged = append(machinesNotConverged, machines...) - } - c.Log().Debugf("%d machines in state %s: %s", len(machines), key, outputMachines(machines)) - } - - if len(machinesNotConverged) > 0 { - return fmt.Errorf("not all machines have converged yet %s", outputMachines(machinesNotConverged)) - } - - return nil -} - -func outputMachines(machines []*wingv1alpha1.Machine) string { - var output []string - for _, machine := range machines { - output = append(output, machine.Name) - } - return strings.Join(output, ", ") -} - func (c *Cluster) wingClient() (*wingclient.Clientset, error) { if c.wingClientset != nil { return c.wingClientset, nil diff --git a/pkg/wing/controller/machine/controller.go b/pkg/wing/controller/machine/controller.go index aab6def5a7..e2a6bebde5 100644 --- a/pkg/wing/controller/machine/controller.go +++ b/pkg/wing/controller/machine/controller.go @@ -75,7 +75,7 @@ func (c *Controller) syncToStdout(key string) error { ObjectMeta: metav1.ObjectMeta{ Name: c.wing.Flags().MachineName, Labels: map[string]string{ - "role": c.wing.Flags().Role, + "pool": c.wing.Flags().Pool, "cluster": c.wing.Flags().ClusterName, }, }, diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index a3226d1b8c..ceb291be20 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -20,20 +20,25 @@ import ( ) type Controller struct { - indexer cache.Indexer - queue workqueue.RateLimitingInterface - informer cache.Controller - log *logrus.Entry - client *clientset.Clientset + queue workqueue.RateLimitingInterface + depInformer cache.Controller + setInformer cache.Controller + depIndexer cache.Indexer + setIndexer cache.Indexer + log *logrus.Entry + client *clientset.Clientset } -func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller, client *clientset.Clientset) *Controller { +func NewController(queue workqueue.RateLimitingInterface, depIndexer cache.Indexer, + setIndexer cache.Indexer, depInformer cache.Controller, setInformer cache.Controller, client *clientset.Clientset) *Controller { return &Controller{ - informer: informer, - indexer: indexer, - queue: queue, - log: logrus.NewEntry(logrus.New()).WithField("tier", "MachineDeployment-controller"), - client: client, + depInformer: depInformer, + setInformer: setInformer, + depIndexer: depIndexer, + setIndexer: setIndexer, + queue: queue, + log: logrus.NewEntry(logrus.New()).WithField("tier", "MachineDeployment-controller"), + client: client, } } @@ -57,76 +62,58 @@ func (c *Controller) processNextItem() bool { func (c *Controller) sync(key string) error { - obj, exists, err := c.indexer.GetByKey(key) - if err != nil { - c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) - return err - } - - if !exists { - c.log.Infof("object %s does not exist anymore\n", key) - return nil - } + // see whether we have a deployment or set + obj, exist, err := c.depIndexer.GetByKey(key) + if err != nil || !exist { + // we should have a set + obj, exists, err := c.setIndexer.GetByKey(key) + if err != nil { + c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) + return err + } + if !exists { + return nil + } - // Note that you also have to check the uid if you have a local controlled resource, which - // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machinedeployment, ok := obj.(*v1alpha1.MachineDeployment) - if !ok { - machineset, ok := obj.(*v1alpha1.MachineSet) + ms, ok := obj.(*v1alpha1.MachineSet) if !ok { return errors.New("failed to process next item, not a machinedeployment or machineset") } - md, err := c.getMachineDeployment(machineset) + + // get our deployment controlling this set + md, err := c.getMachineDeployment(ms) if err != nil { return err } - return c.syncFromMachineSet(md, machineset) + // sync deployment from the set + return c.syncFromMachineSet(md, ms) } - var selectors []string - for k, v := range machinedeployment.Spec.Selector.MatchLabels { - selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) + md, ok := obj.(*v1alpha1.MachineDeployment) + if !ok { + return errors.New("failed to process next item, not a machinedeployment") } - var minReplicas int32 = 1 - var maxReplicas int32 = 1 - if machinedeployment.Spec.MinReplicas != nil { - minReplicas = *machinedeployment.Spec.MinReplicas - } - if machinedeployment.Spec.MaxReplicas != nil { - maxReplicas = *machinedeployment.Spec.MaxReplicas + var selectors []string + for k, v := range md.Spec.Selector.MatchLabels { + selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) } - machinesetAPI := c.client.WingV1alpha1().MachineSets(machinedeployment.Namespace) - machineset, err := machinesetAPI.Get(machinedeployment.Name, metav1.GetOptions{}) + // get controlled set from our deployment + msAPI := c.client.WingV1alpha1().MachineSets(md.Namespace) + ms, err := msAPI.Get(md.Name, metav1.GetOptions{}) if err != nil { + // the set doesn't exist so we need to create it if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { - c.log.Infof("Creating MachineSet for MachineDeployment %s\n", key) - machineset := &v1alpha1.MachineSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: machinedeployment.Name, - Labels: utils.DuplicateMapString(machinedeployment.Labels), - }, - Spec: &v1alpha1.MachineSetSpec{ - MaxReplicas: &minReplicas, - MinReplicas: &maxReplicas, - Selector: machinedeployment.Spec.Selector, - }, - Status: &v1alpha1.MachineSetStatus{}, - } - - machineset, err = machinesetAPI.Create(machineset) - if err != nil { - return fmt.Errorf("error creating machineset: %s", err) - } - + return c.createControlledMachineSet(md) } else { return fmt.Errorf("error get existing machineset: %s", err) } } - err = c.syncFromMachineSet(machinedeployment, machineset) + // sync deployment from the set + err = c.syncFromMachineSet(md, ms) if err != nil { return err } @@ -134,31 +121,63 @@ func (c *Controller) sync(key string) error { return nil } -func (c *Controller) getMachineDeployment(machineset *v1alpha1.MachineSet) (*v1alpha1.MachineDeployment, error) { - machinedeploymentAPI := c.client.WingV1alpha1().MachineDeployments(machineset.Namespace) - machinedeployment, err := machinedeploymentAPI.Get(machineset.Name, metav1.GetOptions{}) +func (c *Controller) createControlledMachineSet(md *v1alpha1.MachineDeployment) error { + var minReplicas int32 = 1 + var maxReplicas int32 = 1 + if md.Spec.MinReplicas != nil { + minReplicas = *md.Spec.MinReplicas + } + if md.Spec.MaxReplicas != nil { + maxReplicas = *md.Spec.MaxReplicas + } + + c.log.Infof("Creating MachineSet for MachineDeployment %s\n", md.Name) + ms := &v1alpha1.MachineSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: md.Name, + Labels: utils.DuplicateMapString(md.Labels), + }, + Spec: &v1alpha1.MachineSetSpec{ + MaxReplicas: &minReplicas, + MinReplicas: &maxReplicas, + Selector: md.Spec.Selector, + }, + Status: &v1alpha1.MachineSetStatus{}, + } + + msAPI := c.client.WingV1alpha1().MachineSets(md.Namespace) + _, err := msAPI.Create(ms) + if err != nil { + return fmt.Errorf("error creating machineset: %s", err) + } + + return nil +} + +func (c *Controller) getMachineDeployment(ms *v1alpha1.MachineSet) (*v1alpha1.MachineDeployment, error) { + mdAPI := c.client.WingV1alpha1().MachineDeployments(ms.Namespace) + md, err := mdAPI.Get(ms.Name, metav1.GetOptions{}) if err != nil { return nil, err } - return machinedeployment, nil + return md, nil } -func (c *Controller) syncFromMachineSet(machinedeployment *v1alpha1.MachineDeployment, machineset *v1alpha1.MachineSet) error { - c.log.Infof("deployment set status: %+v", machinedeployment.Status) +func (c *Controller) syncFromMachineSet(md *v1alpha1.MachineDeployment, ms *v1alpha1.MachineSet) error { status := &v1alpha1.MachineDeploymentStatus{} - if machineset.Status != nil { - status.Replicas = machineset.Status.Replicas - status.ObservedGeneration = machineset.Status.ObservedGeneration + 1 - status.ReadyReplicas = machineset.Status.ReadyReplicas + if ms.Status != nil { + status.Replicas = ms.Status.Replicas + status.ObservedGeneration = ms.Status.ObservedGeneration + 1 + status.ReadyReplicas = ms.Status.ReadyReplicas // TODO: we may want to do something with available replicas - status.AvailableReplicas = machineset.Status.ReadyReplicas - status.UnavailableReplicas = machineset.Status.Replicas - machineset.Status.ReadyReplicas + status.AvailableReplicas = ms.Status.ReadyReplicas + status.UnavailableReplicas = ms.Status.Replicas - ms.Status.ReadyReplicas } - machineDeploymentAPI := c.client.WingV1alpha1().MachineDeployments(machinedeployment.Namespace) - machinedeployment.Status = status - _, err := machineDeploymentAPI.Update(machinedeployment) + mdAPI := c.client.WingV1alpha1().MachineDeployments(md.Namespace) + md.Status = status + _, err := mdAPI.Update(md) if err != nil { return fmt.Errorf("failed to update machinedeployment: %s", err) } @@ -199,10 +218,11 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { defer c.queue.ShutDown() c.log.Info("Starting MachineDeployment controller") - go c.informer.Run(stopCh) + go c.depInformer.Run(stopCh) + go c.setInformer.Run(stopCh) // Wait for all involved caches to be synced, before processing items from the queue is started - if !cache.WaitForCacheSync(stopCh, c.informer.HasSynced) { + if !cache.WaitForCacheSync(stopCh, c.depInformer.HasSynced) || !cache.WaitForCacheSync(stopCh, c.setInformer.HasSynced) { runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync")) return } diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index 1c49313e3b..0a178365da 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -8,6 +8,7 @@ import ( "time" "github.com/sirupsen/logrus" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" @@ -54,11 +55,7 @@ func (c *Controller) processNextItem() bool { return true } -// syncToStdout is the business logic of the controller. In this controller it simply prints -// information about the machine to stdout. In case an error happened, it has to simply return the error. -// The retry logic should not be part of the business logic. func (c *Controller) syncToStdout(key string) error { - obj, exists, err := c.indexer.GetByKey(key) if err != nil { c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) @@ -66,70 +63,76 @@ func (c *Controller) syncToStdout(key string) error { } if !exists { - c.log.Infof("MachineSet %s does not exist anymore\n", key) + c.log.Infof("Machine %s does not exist anymore\n", key) return nil } - // Note that you also have to check the uid if you have a local controlled resource, which - // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machineset, ok := obj.(*v1alpha1.MachineSet) + m, ok := obj.(*v1alpha1.Machine) if !ok { return errors.New("failed to process next item, not a machineset") } - if machineset.Spec == nil { - return fmt.Errorf("machineset spec is nil: %v", machineset.Spec) + ms, found, err := c.getMachineSet(m) + if err != nil { + return err + } + + // machineset doesn't exist for this machine + if !found { + c.log.Warnf("did not find machineset for machine %s", m.Name) + return nil + } + + if ms.Spec == nil { + return fmt.Errorf("machineset spec is nil: %v", ms.Spec) } - if machineset.Spec.MaxReplicas == nil || machineset.Spec.MinReplicas == nil { + if ms.Spec.MaxReplicas == nil || ms.Spec.MinReplicas == nil { return fmt.Errorf("expected machineset min and max replicas to not be nil: min=%v max=%v", - machineset.Spec.MaxReplicas, machineset.Spec.MinReplicas) + ms.Spec.MaxReplicas, ms.Spec.MinReplicas) } var selectors []string - for k, v := range machineset.Spec.Selector.MatchLabels { + for k, v := range ms.Spec.Selector.MatchLabels { selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) } - machineAPI := c.client.WingV1alpha1().Machines(machineset.Namespace) - machineList, err := machineAPI.List(metav1.ListOptions{ + // find all the machines coverged by this machien set and update status accordingly + mAPI := c.client.WingV1alpha1().Machines(ms.Namespace) + mList, err := mAPI.List(metav1.ListOptions{ LabelSelector: strings.Join(selectors, ","), }) if err != nil { return err } - if int32(len(machineList.Items)) > *machineset.Spec.MaxReplicas { - c.log.Warnf("more machines exist then the maximum, max=%v curr=%v", *machineset.Spec.MaxReplicas, len(machineList.Items)) + if int32(len(mList.Items)) > *ms.Spec.MaxReplicas { + c.log.Warnf("more machines exist then the maximum, max=%v curr=%v", *ms.Spec.MaxReplicas, len(mList.Items)) } - //if int32(len(machineList.Items)) < *machineset.Spec.MinReplicas { - // c.log.Warnf("less machines exist then the minimum, min=%v curr=%v", *machineset.Spec.MinReplicas, len(machineList.Items)) + //if int32(len(mList.Items)) < *ms.Spec.MinReplicas { + // c.log.Warnf("less machines exist then the minimum, min=%v curr=%v", *ms.Spec.MinReplicas, len(m.Items)) //} var readyMachines int32 var fullyLabeledMachines int32 - for _, i := range machineList.Items { - //c.log.Infof("status: %+v", i.Status) - //if i.Status.Converge != nil { - // c.log.Infof("status: %+v", i.Status.Converge.State) - //} + for _, i := range mList.Items { if c.machineConverged(i) { readyMachines++ } - if c.fullyLabeledMachine(machineset, i) { + if c.fullyLabeledMachine(ms, i) { fullyLabeledMachines++ } } var observedGeneration int64 = 0 - if machineset.Status != nil { - observedGeneration = machineset.Status.ObservedGeneration + if ms.Status != nil { + observedGeneration = ms.Status.ObservedGeneration } status := &v1alpha1.MachineSetStatus{ - Replicas: int32(len(machineList.Items)), + Replicas: int32(len(mList.Items)), ObservedGeneration: observedGeneration + 1, ReadyReplicas: readyMachines, FullyLabeledReplicas: fullyLabeledMachines, @@ -137,10 +140,9 @@ func (c *Controller) syncToStdout(key string) error { AvailableReplicas: readyMachines, } - machineSetAPI := c.client.WingV1alpha1().MachineSets(machineset.Namespace) - machineset.Status = status.DeepCopy() - c.log.Infof("set status: %+v\n", machineset.Status) - _, err = machineSetAPI.Update(machineset) + msAPI := c.client.WingV1alpha1().MachineSets(ms.Namespace) + ms.Status = status.DeepCopy() + _, err = msAPI.Update(ms) if err != nil { return fmt.Errorf("failed to update machineset: %s", err) } @@ -148,6 +150,30 @@ func (c *Controller) syncToStdout(key string) error { return nil } +func (c *Controller) getMachineSet(m *v1alpha1.Machine) (*v1alpha1.MachineSet, bool, error) { + pool, ok := m.Labels["pool"] + if !ok { + return nil, false, fmt.Errorf("found machine without a pool label: %s", m.Name) + } + + cluster, ok := m.Labels["cluster"] + if !ok { + return nil, false, fmt.Errorf("found machine without a cluster label: %s", m.Name) + } + + msAPI := c.client.WingV1alpha1().MachineSets(cluster) + ms, err := msAPI.Get(pool, metav1.GetOptions{}) + if err != nil { + if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { + return nil, false, nil + } else { + return nil, false, err + } + } + + return ms, true, nil +} + // handleErr checks if an error happened and makes sure we will retry later. func (c *Controller) handleErr(err error, key interface{}) { if err == nil { diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index e1e9f62042..69b272556e 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -303,7 +303,7 @@ func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { ObjectMeta: metav1.ObjectMeta{ Name: w.flags.MachineName, Labels: map[string]string{ - "role": w.flags.Role, + "pool": w.flags.Pool, "cluster": w.flags.ClusterName, }, }, diff --git a/pkg/wing/server/controller.go b/pkg/wing/server/controller.go index 0e28639508..be9a1d9dee 100644 --- a/pkg/wing/server/controller.go +++ b/pkg/wing/server/controller.go @@ -6,6 +6,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -15,62 +16,46 @@ import ( ) func (o WingServerOptions) StartMachineControllers() error { + + // machineset controller needs to watch for changes to machines + machineListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machines", metav1.NamespaceAll, fields.Everything()) + queueSet := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + indexerMachine, informerMachine := o.newIndexInfomer(machineListWatcher, &v1alpha1.Machine{}, queueSet) + machinesetController := machineset.NewController(queueSet, indexerMachine, informerMachine, o.client) + + // machindeployment controller needs to watch for changes to machinedeployments and machinesets machinesetListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machinesets", metav1.NamespaceAll, fields.Everything()) machinedeploymentListWatcher := cache.NewListWatchFromClient(o.client.WingV1alpha1().RESTClient(), "machinedeployments", metav1.NamespaceAll, fields.Everything()) - queueSet := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) queueDeployment := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + indexerSet, informerSet := o.newIndexInfomer(machinesetListWatcher, &v1alpha1.MachineSet{}, queueDeployment) + indexerDeployment, informerDeployment := o.newIndexInfomer(machinedeploymentListWatcher, &v1alpha1.MachineDeployment{}, queueDeployment) + machinedeploymentController := machinedeployment.NewController(queueDeployment, indexerDeployment, indexerSet, informerDeployment, informerSet, o.client) - indexerSet, informerSet := cache.NewIndexerInformer(machinesetListWatcher, &v1alpha1.MachineSet{}, 0, cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - key, err := cache.MetaNamespaceKeyFunc(obj) - if err == nil { - queueSet.AddAfter(key, 2*time.Second) - } - }, - UpdateFunc: func(old interface{}, new interface{}) { - key, err := cache.MetaNamespaceKeyFunc(new) - if err == nil { - queueSet.AddAfter(key, 2*time.Second) - queueDeployment.AddAfter(key, 2*time.Second) - } - }, - DeleteFunc: func(obj interface{}) { - // IndexerInformer uses a delta queue, therefore for deletes we have to use this - // key function. - key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) - if err == nil { - queueSet.AddAfter(key, 2*time.Second) - } - }, - }, cache.Indexers{}) - machinesetController := machineset.NewController(queueSet, indexerSet, informerSet, o.client) + //// Now let's start the controllers + go machinesetController.Run(1, o.stopCh) + go machinedeploymentController.Run(1, o.stopCh) + return nil +} - indexerDeployment, informerDeployment := cache.NewIndexerInformer(machinedeploymentListWatcher, &v1alpha1.MachineDeployment{}, 0, cache.ResourceEventHandlerFuncs{ +func (o WingServerOptions) newIndexInfomer(listWatcher cache.ListerWatcher, objType runtime.Object, queue workqueue.RateLimitingInterface) (cache.Indexer, cache.Controller) { + return cache.NewIndexerInformer(listWatcher, objType, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) if err == nil { - queueDeployment.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 2*time.Second) } }, UpdateFunc: func(old interface{}, new interface{}) { key, err := cache.MetaNamespaceKeyFunc(new) if err == nil { - queueDeployment.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 2*time.Second) } }, DeleteFunc: func(obj interface{}) { - // IndexerInformer uses a delta queue, therefore for deletes we have to use this - // key function. key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) if err == nil { - queueDeployment.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 2*time.Second) } }, }, cache.Indexers{}) - machinedeploymentController := machinedeployment.NewController(queueDeployment, indexerDeployment, informerDeployment, o.client) - - //// Now let's start the controllers - go machinesetController.Run(1, o.stopCh) - go machinedeploymentController.Run(1, o.stopCh) - return nil } diff --git a/terraform/amazon/templates/puppet_agent_user_data.yaml.template b/terraform/amazon/templates/puppet_agent_user_data.yaml.template index 927a608dfe..a65e540e30 100644 --- a/terraform/amazon/templates/puppet_agent_user_data.yaml.template +++ b/terraform/amazon/templates/puppet_agent_user_data.yaml.template @@ -38,7 +38,7 @@ write_files: {{- end }} ExecStart=/bin/sh -c '\ set -e ;\ - exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443" --role "${tarmak_role}"' + exec /opt/wing-$${WING_VERSION}/wing agent --manifest-url "s3://${legacy_puppet_manifest}" --cluster-name "${tarmak_cluster}" --instance-name "$$(curl --silent --retry 5 http://169.254.169.254/latest/meta-data/instance-id || echo "unknown")" --server-url "https://bastion.${tarmak_environment}.${tarmak_dns_root}:9443" --pool "${tarmak_instance_pool}"' [Install] WantedBy=multi-user.target From 64e9bd347c62c2fd37beb4dc8fcbaa62584d8ec6 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Mon, 17 Dec 2018 11:33:43 +0000 Subject: [PATCH 10/14] Ensure machines exist to converge Signed-off-by: JoshVanL --- pkg/tarmak/cluster/configuration.go | 17 ++++++----- pkg/tarmak/cluster/wing.go | 30 +++++++++++++++++-- .../machinedeployment/controller.go | 7 +++++ pkg/wing/controller/machineset/controller.go | 12 ++++++-- pkg/wing/puppet.go | 15 ++++++---- 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index 67887c6cc4..fe5d31510e 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -6,6 +6,7 @@ import ( "crypto/md5" "encoding/hex" "fmt" + "strings" "time" wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" @@ -96,6 +97,7 @@ func (c *Cluster) WaitForConvergance() error { deployment := deployments[pos] if deployment.Status == nil { + deployment.Status = &wingv1alpha1.MachineDeploymentStatus{} converging = append(converging, deployment) continue } @@ -109,11 +111,11 @@ func (c *Cluster) WaitForConvergance() error { converging = append(converging, deployment) } - var convergedStr string + var convergedSlice []string for _, d := range converged { - convergedStr = fmt.Sprintf("%s %s", convergedStr, d.Name) + convergedSlice = append(convergedSlice, d.Name) } - convergedStr = fmt.Sprintf("converged deployments [%s]", convergedStr) + convergedStr := fmt.Sprintf("converged deployments [%s]", strings.Join(convergedSlice, " ")) if len(converging) == 0 { c.log.Info("all deployments converged") @@ -127,11 +129,12 @@ func (c *Cluster) WaitForConvergance() error { } for _, d := range converging { - var readyReplicas int32 - if d.Status != nil { - readyReplicas = d.Status.Replicas + reps := d.Status.Replicas + if d.Spec != nil && d.Spec.MinReplicas != nil && reps < *d.Spec.MinReplicas { + reps = *d.Spec.MinReplicas } - c.log.Debugf("converging %s [%v/%v]", d.Name, readyReplicas, d.Status.Replicas) + + c.log.Debugf("converging %s [%v/%v]", d.Name, d.Status.ReadyReplicas, reps) } retries-- diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 50e899825e..4c3a00b8cd 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -7,6 +7,7 @@ import ( "github.com/cenkalti/backoff" "golang.org/x/net/context" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" @@ -43,14 +44,37 @@ func (c *Cluster) listMachines() ([]*wingv1alpha1.Machine, error) { return nil, fmt.Errorf("failed to connect to wing API on bastion: %s", err) } - mList, err := client.List(metav1.ListOptions{}) + hosts, err := c.ListHosts() if err != nil { return nil, err } var machines []*wingv1alpha1.Machine - for i := range mList.Items { - machines = append(machines, &mList.Items[i]) + for _, h := range hosts { + m, err := client.Get(h.ID(), metav1.GetOptions{}) + if err != nil { + if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { + machine := &wingv1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Name: h.ID(), + }, + Status: &wingv1alpha1.MachineStatus{ + Converge: &wingv1alpha1.MachineStatusManifest{ + State: wingv1alpha1.MachineManifestStateConverging, + }, + }, + } + + m, err = client.Create(machine) + if err != nil { + return nil, fmt.Errorf("error creating machine: %s", err) + } + } else { + return nil, fmt.Errorf("failed to get machine resource %s: %s", h.ID(), err) + } + } + + machines = append(machines, m) } return machines, nil diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index ceb291be20..0d92a2cb17 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -71,6 +71,9 @@ func (c *Controller) sync(key string) error { c.log.Errorf("Fetching object with key %s from store failed with %v", key, err) return err } + + c.log.Debugf("machine deployment controller did not get deployment or set") + if !exists { return nil } @@ -80,12 +83,16 @@ func (c *Controller) sync(key string) error { return errors.New("failed to process next item, not a machinedeployment or machineset") } + c.log.Debugf("machine deployment controller got machineset: %s", ms.Name) + // get our deployment controlling this set md, err := c.getMachineDeployment(ms) if err != nil { return err } + c.log.Debugf("machine deployment controller got matching matchine deployment: %s", md.Name) + // sync deployment from the set return c.syncFromMachineSet(md, ms) } diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index 0a178365da..08548885cc 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -69,9 +69,11 @@ func (c *Controller) syncToStdout(key string) error { m, ok := obj.(*v1alpha1.Machine) if !ok { - return errors.New("failed to process next item, not a machineset") + return errors.New("failed to process next item, not a machine") } + c.log.Debugf("machineset controller got a mahcine: %s", m.Name) + ms, found, err := c.getMachineSet(m) if err != nil { return err @@ -83,6 +85,8 @@ func (c *Controller) syncToStdout(key string) error { return nil } + c.log.Debugf("machineset controller got matching machineset: %s", ms.Name) + if ms.Spec == nil { return fmt.Errorf("machineset spec is nil: %v", ms.Spec) } @@ -140,6 +144,8 @@ func (c *Controller) syncToStdout(key string) error { AvailableReplicas: readyMachines, } + c.log.Debugf("updating machine set status: %+v", status) + msAPI := c.client.WingV1alpha1().MachineSets(ms.Namespace) ms.Status = status.DeepCopy() _, err = msAPI.Update(ms) @@ -153,12 +159,12 @@ func (c *Controller) syncToStdout(key string) error { func (c *Controller) getMachineSet(m *v1alpha1.Machine) (*v1alpha1.MachineSet, bool, error) { pool, ok := m.Labels["pool"] if !ok { - return nil, false, fmt.Errorf("found machine without a pool label: %s", m.Name) + return nil, false, nil } cluster, ok := m.Labels["cluster"] if !ok { - return nil, false, fmt.Errorf("found machine without a cluster label: %s", m.Name) + return nil, false, nil } msAPI := c.client.WingV1alpha1().MachineSets(cluster) diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index 69b272556e..526eb80569 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -292,6 +292,11 @@ func (w *Wing) puppetApply(dir string) (output string, retCode int, err error) { // report status to the API server func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { + labels := map[string]string{ + "pool": w.flags.Pool, + "cluster": w.flags.ClusterName, + } + machineAPI := w.clientset.WingV1alpha1().Machines(w.flags.ClusterName) machine, err := machineAPI.Get( w.flags.MachineName, @@ -301,11 +306,8 @@ func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { if kerr, ok := err.(*apierrors.StatusError); ok && kerr.ErrStatus.Reason == metav1.StatusReasonNotFound { machine = &v1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ - Name: w.flags.MachineName, - Labels: map[string]string{ - "pool": w.flags.Pool, - "cluster": w.flags.ClusterName, - }, + Name: w.flags.MachineName, + Labels: labels, }, Status: status.DeepCopy(), } @@ -313,11 +315,14 @@ func (w *Wing) reportStatus(status *v1alpha1.MachineStatus) error { if err != nil { return fmt.Errorf("error creating machine: %s", err) } + return nil } + return fmt.Errorf("error get existing machine: %s", err) } + machine.ObjectMeta.Labels = labels machine.Status = status.DeepCopy() _, err = machineAPI.Update(machine) if err != nil { From 42a29a537822334cc613b74dfdcf7c5173b29557 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Mon, 17 Dec 2018 14:28:40 +0000 Subject: [PATCH 11/14] Improve responsiveness and display machine id of converging Signed-off-by: JoshVanL --- pkg/apis/wing/machine_types.go | 5 ++- pkg/apis/wing/v1alpha1/constants.go | 10 ----- pkg/apis/wing/v1alpha1/machine_types.go | 12 +++--- .../wing/v1alpha1/zz_generated.conversion.go | 4 +- pkg/tarmak/cluster/configuration.go | 30 +++++++++++--- pkg/tarmak/cluster/wing.go | 5 +-- pkg/wing/controller/machine/controller.go | 40 ++++++++++--------- .../machinedeployment/controller.go | 6 --- pkg/wing/controller/machineset/controller.go | 7 +--- pkg/wing/puppet.go | 9 +++-- pkg/wing/server/controller.go | 6 +-- pkg/wing/wing.go | 6 +-- 12 files changed, 74 insertions(+), 66 deletions(-) delete mode 100644 pkg/apis/wing/v1alpha1/constants.go diff --git a/pkg/apis/wing/machine_types.go b/pkg/apis/wing/machine_types.go index 970885e084..6da7f3a8c1 100644 --- a/pkg/apis/wing/machine_types.go +++ b/pkg/apis/wing/machine_types.go @@ -3,6 +3,8 @@ package wing import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" ) // +genclient @@ -36,9 +38,8 @@ type MachineStatus struct { } // InstaceSpecManifest defines the state and hash of a run manifest -type MachineManifestState string type MachineStatusManifest struct { - State MachineManifestState + State common.MachineManifestState Hash string LastUpdateTimestamp metav1.Time Messages []string diff --git a/pkg/apis/wing/v1alpha1/constants.go b/pkg/apis/wing/v1alpha1/constants.go deleted file mode 100644 index 310b679f29..0000000000 --- a/pkg/apis/wing/v1alpha1/constants.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright Jetstack Ltd. See LICENSE for details. -package v1alpha1 - -type MachineManifestState string - -const ( - MachineManifestStateConverging = MachineManifestState("converging") - MachineManifestStateConverged = MachineManifestState("converged") - MachineManifestStateError = MachineManifestState("error") -) diff --git a/pkg/apis/wing/v1alpha1/machine_types.go b/pkg/apis/wing/v1alpha1/machine_types.go index 007c81e744..602dba61c2 100644 --- a/pkg/apis/wing/v1alpha1/machine_types.go +++ b/pkg/apis/wing/v1alpha1/machine_types.go @@ -3,6 +3,8 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/jetstack/tarmak/pkg/apis/wing/common" ) // +genclient @@ -37,11 +39,11 @@ type MachineStatus struct { // InstaceSpecManifest defines the state and hash of a run manifest type MachineStatusManifest struct { - State MachineManifestState `json:"state,omitempty"` - Hash string `json:"hash,omitempty"` // hash of manifests, prefixed with type (eg: sha256:xyz) - LastUpdateTimestamp metav1.Time `json:"lastUpdateTimestamp,omitempty"` // timestamp when a converge was requested - Messages []string `json:"messages,omitempty"` // contains output of the retries - ExitCodes []int `json:"exitCodes,omitempty"` // return code of the retries + State common.MachineManifestState `json:"state,omitempty"` + Hash string `json:"hash,omitempty"` // hash of manifests, prefixed with type (eg: sha256:xyz) + LastUpdateTimestamp metav1.Time `json:"lastUpdateTimestamp,omitempty"` // timestamp when a converge was requested + Messages []string `json:"messages,omitempty"` // contains output of the retries + ExitCodes []int `json:"exitCodes,omitempty"` // return code of the retries } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go index 2ba04e83f5..e2b34a793f 100644 --- a/pkg/apis/wing/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/wing/v1alpha1/zz_generated.conversion.go @@ -445,7 +445,7 @@ func Convert_wing_MachineStatus_To_v1alpha1_MachineStatus(in *wing.MachineStatus } func autoConvert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest(in *MachineStatusManifest, out *wing.MachineStatusManifest, s conversion.Scope) error { - out.State = wing.MachineManifestState(in.State) + out.State = common.MachineManifestState(in.State) out.Hash = in.Hash out.LastUpdateTimestamp = in.LastUpdateTimestamp out.Messages = *(*[]string)(unsafe.Pointer(&in.Messages)) @@ -459,7 +459,7 @@ func Convert_v1alpha1_MachineStatusManifest_To_wing_MachineStatusManifest(in *Ma } func autoConvert_wing_MachineStatusManifest_To_v1alpha1_MachineStatusManifest(in *wing.MachineStatusManifest, out *MachineStatusManifest, s conversion.Scope) error { - out.State = MachineManifestState(in.State) + out.State = common.MachineManifestState(in.State) out.Hash = in.Hash out.LastUpdateTimestamp = in.LastUpdateTimestamp out.Messages = *(*[]string)(unsafe.Pointer(&in.Messages)) diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index fe5d31510e..f5a73921d6 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -9,6 +9,8 @@ import ( "strings" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" ) @@ -64,10 +66,8 @@ func (c *Cluster) ReapplyConfiguration() error { for pos, _ := range machines { machine := machines[pos] - if machine.Spec == nil { - machine.Spec = &wingv1alpha1.MachineSpec{} - } - machine.Spec.Converge = &wingv1alpha1.MachineSpecManifest{} + machine.Status = &wingv1alpha1.MachineStatus{} + machine.Status.Converge = &wingv1alpha1.MachineStatusManifest{} if _, err := client.Update(machine); err != nil { c.log.Warnf("error updating machine %s in wing API: %s", machine.Name, err) @@ -128,13 +128,33 @@ func (c *Cluster) WaitForConvergance() error { c.log.Debug(convergedStr) } + client, err := c.wingMachineClient() + if err != nil { + return err + } + for _, d := range converging { + + mList, err := client.List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("pool=%s,cluster=%s", + d.Labels["pool"], d.Labels["cluster"]), + }) + if err != nil { + return err + } + + var convergingMachines []string + for _, m := range mList.Items { + convergingMachines = append(convergingMachines, m.Name) + } + reps := d.Status.Replicas if d.Spec != nil && d.Spec.MinReplicas != nil && reps < *d.Spec.MinReplicas { reps = *d.Spec.MinReplicas } - c.log.Debugf("converging %s [%v/%v]", d.Name, d.Status.ReadyReplicas, reps) + c.log.Debugf("converging %s [%v/%v] (%s)", + d.Name, d.Status.ReadyReplicas, reps, strings.Join(convergingMachines, ", ")) } retries-- diff --git a/pkg/tarmak/cluster/wing.go b/pkg/tarmak/cluster/wing.go index 4c3a00b8cd..e62db2b0a3 100644 --- a/pkg/tarmak/cluster/wing.go +++ b/pkg/tarmak/cluster/wing.go @@ -10,6 +10,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/jetstack/tarmak/pkg/apis/wing/common" wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/tarmak/interfaces" "github.com/jetstack/tarmak/pkg/tarmak/utils" @@ -60,7 +61,7 @@ func (c *Cluster) listMachines() ([]*wingv1alpha1.Machine, error) { }, Status: &wingv1alpha1.MachineStatus{ Converge: &wingv1alpha1.MachineStatusManifest{ - State: wingv1alpha1.MachineManifestStateConverging, + State: common.MachineManifestStateConverging, }, }, } @@ -131,9 +132,7 @@ func (c *Cluster) updateMachineDeployments() error { continue } - d = d.DeepCopy() d.Spec = c.deploymentSpec(i) - _, err = client.Update(d) if err != nil { return fmt.Errorf("failed to update deployment sepc %s: %s", i.Name(), err) diff --git a/pkg/wing/controller/machine/controller.go b/pkg/wing/controller/machine/controller.go index e2a6bebde5..fd376a2d5c 100644 --- a/pkg/wing/controller/machine/controller.go +++ b/pkg/wing/controller/machine/controller.go @@ -13,6 +13,7 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" + "github.com/jetstack/tarmak/pkg/apis/wing/common" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/wing/interfaces" ) @@ -81,7 +82,7 @@ func (c *Controller) syncToStdout(key string) error { }, Status: &v1alpha1.MachineStatus{ Converge: &v1alpha1.MachineStatusManifest{ - State: v1alpha1.MachineManifestStateConverging, + State: common.MachineManifestStateConverging, }, }, } @@ -91,33 +92,36 @@ func (c *Controller) syncToStdout(key string) error { } c.log.Infof("Machine created %v", key) - } else { - // Note that you also have to check the uid if you have a local controlled resource, which - // is dependent on the actual machine, to detect that a Machine was recreated with the same name - machine, ok := obj.(*v1alpha1.Machine) - if !ok { - return errors.New("failed to process next item, not a machine") - } + return nil + } + + // Note that you also have to check the uid if you have a local controlled resource, which + // is dependent on the actual machine, to detect that a Machine was recreated with the same name + machine, ok := obj.(*v1alpha1.Machine) + if !ok { + return errors.New("failed to process next item, not a machine") + } - // trigger converge if status time is older or not existing - if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { - if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { - if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { - c.log.Debug("no converge neccessary, last update was after request") - return nil - } - } else { - c.log.Debug("no converge neccessary, no status section found or update timestamp zero") + // trigger converge if status time is older or not existing + if machine.Spec != nil && machine.Spec.Converge != nil && !machine.Spec.Converge.RequestTimestamp.Time.IsZero() { + if machine.Status != nil && machine.Status.Converge != nil && !machine.Status.Converge.LastUpdateTimestamp.Time.IsZero() { + if machine.Status.Converge.LastUpdateTimestamp.Time.After(machine.Spec.Converge.RequestTimestamp.Time) { + c.log.Debug("no converge neccessary, last update was after request") return nil } } else { - c.log.Debug("no converge neccessary, no spec section found or request timestamp zero") + c.log.Debug("no converge neccessary, no status section found or update timestamp zero") return nil } + } + if machine.Status != nil && machine.Status.Converge != nil && + machine.Status.Converge.State != common.MachineManifestStateConverging && + machine.Status.Converge.State != common.MachineManifestStateConverged { c.log.Infof("running converge") c.wing.Converge() } + return nil } diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index 0d92a2cb17..b10a82654a 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -72,8 +72,6 @@ func (c *Controller) sync(key string) error { return err } - c.log.Debugf("machine deployment controller did not get deployment or set") - if !exists { return nil } @@ -83,16 +81,12 @@ func (c *Controller) sync(key string) error { return errors.New("failed to process next item, not a machinedeployment or machineset") } - c.log.Debugf("machine deployment controller got machineset: %s", ms.Name) - // get our deployment controlling this set md, err := c.getMachineDeployment(ms) if err != nil { return err } - c.log.Debugf("machine deployment controller got matching matchine deployment: %s", md.Name) - // sync deployment from the set return c.syncFromMachineSet(md, ms) } diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index 08548885cc..e0e257726e 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -15,6 +15,7 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" + "github.com/jetstack/tarmak/pkg/apis/wing/common" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" clientset "github.com/jetstack/tarmak/pkg/wing/client/clientset/versioned" ) @@ -72,8 +73,6 @@ func (c *Controller) syncToStdout(key string) error { return errors.New("failed to process next item, not a machine") } - c.log.Debugf("machineset controller got a mahcine: %s", m.Name) - ms, found, err := c.getMachineSet(m) if err != nil { return err @@ -85,8 +84,6 @@ func (c *Controller) syncToStdout(key string) error { return nil } - c.log.Debugf("machineset controller got matching machineset: %s", ms.Name) - if ms.Spec == nil { return fmt.Errorf("machineset spec is nil: %v", ms.Spec) } @@ -235,7 +232,7 @@ func (c *Controller) runWorker() { } func (c *Controller) machineConverged(machine v1alpha1.Machine) bool { - if machine.Status != nil && machine.Status.Converge != nil && machine.Status.Converge.State == v1alpha1.MachineManifestStateConverged { + if machine.Status != nil && machine.Status.Converge != nil && machine.Status.Converge.State == common.MachineManifestStateConverged { return true } diff --git a/pkg/wing/puppet.go b/pkg/wing/puppet.go index 526eb80569..4d84252583 100644 --- a/pkg/wing/puppet.go +++ b/pkg/wing/puppet.go @@ -22,6 +22,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/jetstack/tarmak/pkg/apis/wing/common" "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" "github.com/jetstack/tarmak/pkg/wing/provider" ) @@ -31,7 +32,7 @@ func (w *Wing) runPuppet() (*v1alpha1.MachineStatus, error) { // start converging mainfest status := &v1alpha1.MachineStatus{ Converge: &v1alpha1.MachineStatusManifest{ - State: v1alpha1.MachineManifestStateConverging, + State: common.MachineManifestStateConverging, }, } @@ -105,7 +106,7 @@ func (w *Wing) runPuppet() (*v1alpha1.MachineStatus, error) { // start converging mainfest status = &v1alpha1.MachineStatus{ Converge: &v1alpha1.MachineStatusManifest{ - State: v1alpha1.MachineManifestStateConverging, + State: common.MachineManifestStateConverging, Messages: puppetMessages, ExitCodes: puppetRetCodes, Hash: hashString, @@ -159,11 +160,11 @@ func (w *Wing) Converge() { // run puppet status, err := w.runPuppet() if err != nil { - status.Converge.State = v1alpha1.MachineManifestStateError + status.Converge.State = common.MachineManifestStateError status.Converge.Messages = append(status.Converge.Messages, err.Error()) w.log.Error(err) } else { - status.Converge.State = v1alpha1.MachineManifestStateConverged + status.Converge.State = common.MachineManifestStateConverged } // feedback puppet status to apiserver diff --git a/pkg/wing/server/controller.go b/pkg/wing/server/controller.go index be9a1d9dee..7cc48707a8 100644 --- a/pkg/wing/server/controller.go +++ b/pkg/wing/server/controller.go @@ -42,19 +42,19 @@ func (o WingServerOptions) newIndexInfomer(listWatcher cache.ListerWatcher, objT AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, UpdateFunc: func(old interface{}, new interface{}) { key, err := cache.MetaNamespaceKeyFunc(new) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, DeleteFunc: func(obj interface{}) { key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, }, cache.Indexers{}) diff --git a/pkg/wing/wing.go b/pkg/wing/wing.go index 7bb5f24b54..aa433cdf03 100644 --- a/pkg/wing/wing.go +++ b/pkg/wing/wing.go @@ -133,13 +133,13 @@ func (w *Wing) watchForNotifications() { AddFunc: func(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, UpdateFunc: func(old interface{}, new interface{}) { key, err := cache.MetaNamespaceKeyFunc(new) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, DeleteFunc: func(obj interface{}) { @@ -147,7 +147,7 @@ func (w *Wing) watchForNotifications() { // key function. key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) if err == nil { - queue.AddAfter(key, 2*time.Second) + queue.AddAfter(key, 1*time.Second) } }, }, cache.Indexers{}) From a2dd649d269de5cc43413504533b6479976515f3 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Mon, 17 Dec 2018 14:52:14 +0000 Subject: [PATCH 12/14] Output converging machine names Signed-off-by: JoshVanL --- pkg/tarmak/cluster/configuration.go | 6 +++++- pkg/wing/controller/machinedeployment/controller.go | 2 +- pkg/wing/controller/machineset/controller.go | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/tarmak/cluster/configuration.go b/pkg/tarmak/cluster/configuration.go index f5a73921d6..aac7736059 100644 --- a/pkg/tarmak/cluster/configuration.go +++ b/pkg/tarmak/cluster/configuration.go @@ -11,6 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/jetstack/tarmak/pkg/apis/wing/common" wingv1alpha1 "github.com/jetstack/tarmak/pkg/apis/wing/v1alpha1" ) @@ -145,7 +146,10 @@ func (c *Cluster) WaitForConvergance() error { var convergingMachines []string for _, m := range mList.Items { - convergingMachines = append(convergingMachines, m.Name) + if m.Status == nil || m.Status.Converge == nil || + m.Status.Converge.State != common.MachineManifestStateConverged { + convergingMachines = append(convergingMachines, m.Name) + } } reps := d.Status.Replicas diff --git a/pkg/wing/controller/machinedeployment/controller.go b/pkg/wing/controller/machinedeployment/controller.go index b10a82654a..9d6d6e47cb 100644 --- a/pkg/wing/controller/machinedeployment/controller.go +++ b/pkg/wing/controller/machinedeployment/controller.go @@ -132,7 +132,7 @@ func (c *Controller) createControlledMachineSet(md *v1alpha1.MachineDeployment) maxReplicas = *md.Spec.MaxReplicas } - c.log.Infof("Creating MachineSet for MachineDeployment %s\n", md.Name) + c.log.Infof("Creating MachineSet from MachineDeployment %s\n", md.Name) ms := &v1alpha1.MachineSet{ ObjectMeta: metav1.ObjectMeta{ Name: md.Name, diff --git a/pkg/wing/controller/machineset/controller.go b/pkg/wing/controller/machineset/controller.go index e0e257726e..0802879849 100644 --- a/pkg/wing/controller/machineset/controller.go +++ b/pkg/wing/controller/machineset/controller.go @@ -33,7 +33,7 @@ func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer: informer, indexer: indexer, queue: queue, - log: logrus.NewEntry(logrus.New()).WithField("tier", "controller"), + log: logrus.NewEntry(logrus.New()).WithField("tier", "MachineSet-controller"), client: client, } } @@ -80,7 +80,6 @@ func (c *Controller) syncToStdout(key string) error { // machineset doesn't exist for this machine if !found { - c.log.Warnf("did not find machineset for machine %s", m.Name) return nil } From c50c71be740a3e517ebaa3e95ade64ad8479dea9 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Mon, 17 Dec 2018 15:45:48 +0000 Subject: [PATCH 13/14] Updates tests, docs and vendor Signed-off-by: JoshVanL --- Gopkg.lock | 1 + docs/generated/cmd/wing/wing_agent.rst | 1 + docs/generated/cmd/wing/wing_server.rst | 2 +- docs/generated/reference/config.yaml | 8 +- docs/generated/reference/output/api-docs.html | 568 ++++++++-- docs/generated/reference/output/navData.js | 2 +- .../node_modules/bootstrap/Gruntfile.js | 273 ++--- .../output/node_modules/bootstrap/LICENSE | 42 +- .../bootstrap/dist/css/bootstrap-theme.css | 200 ++-- .../dist/css/bootstrap-theme.css.map | 2 +- .../dist/css/bootstrap-theme.min.css | 6 +- .../dist/css/bootstrap-theme.min.css.map | 2 +- .../bootstrap/dist/css/bootstrap.css | 985 ++++++++++-------- .../bootstrap/dist/css/bootstrap.css.map | 2 +- .../bootstrap/dist/css/bootstrap.min.css | 6 +- .../bootstrap/dist/css/bootstrap.min.css.map | 2 +- .../bootstrap/dist/js/bootstrap.js | 209 ++-- .../bootstrap/dist/js/bootstrap.min.js | 7 +- .../node_modules/bootstrap/grunt/.jshintrc | 14 +- .../node_modules/bootstrap/grunt/.stylelintrc | 289 +++++ .../node_modules/bootstrap/grunt/browsers.js | 86 ++ .../bootstrap/grunt/bs-commonjs-generator.js | 6 +- .../grunt/bs-glyphicons-data-generator.js | 4 +- .../bootstrap/grunt/bs-lessdoc-parser.js | 4 +- .../bootstrap/grunt/bs-raw-files-generator.js | 4 +- .../bootstrap/grunt/change-version.js | 2 +- .../bootstrap/grunt/generate-sri.js | 62 ++ .../bootstrap/grunt/karma.conf.js | 79 ++ .../bootstrap/grunt/sauce_browsers.yml | 82 -- .../output/node_modules/bootstrap/js/affix.js | 12 +- .../output/node_modules/bootstrap/js/alert.js | 11 +- .../node_modules/bootstrap/js/button.js | 8 +- .../node_modules/bootstrap/js/carousel.js | 23 +- .../node_modules/bootstrap/js/collapse.js | 12 +- .../node_modules/bootstrap/js/dropdown.js | 10 +- .../output/node_modules/bootstrap/js/modal.js | 67 +- .../node_modules/bootstrap/js/popover.js | 12 +- .../node_modules/bootstrap/js/scrollspy.js | 8 +- .../output/node_modules/bootstrap/js/tab.js | 20 +- .../node_modules/bootstrap/js/tooltip.js | 12 +- .../node_modules/bootstrap/js/transition.js | 10 +- .../node_modules/bootstrap/less/alerts.less | 6 +- .../node_modules/bootstrap/less/badges.less | 6 +- .../bootstrap/less/bootstrap.less | 4 +- .../bootstrap/less/breadcrumbs.less | 2 +- .../bootstrap/less/button-groups.less | 12 +- .../node_modules/bootstrap/less/buttons.less | 10 +- .../node_modules/bootstrap/less/carousel.less | 57 +- .../node_modules/bootstrap/less/close.less | 3 + .../node_modules/bootstrap/less/code.less | 6 +- .../bootstrap/less/component-animations.less | 3 + .../bootstrap/less/dropdowns.less | 43 +- .../node_modules/bootstrap/less/forms.less | 106 +- .../bootstrap/less/glyphicons.less | 20 +- .../node_modules/bootstrap/less/grid.less | 10 + .../bootstrap/less/input-groups.less | 6 +- .../bootstrap/less/jumbotron.less | 10 +- .../node_modules/bootstrap/less/labels.less | 2 +- .../bootstrap/less/list-group.less | 64 +- .../node_modules/bootstrap/less/media.less | 2 +- .../bootstrap/less/mixins/alerts.less | 3 +- .../bootstrap/less/mixins/border-radius.less | 8 +- .../bootstrap/less/mixins/buttons.less | 16 +- .../bootstrap/less/mixins/center-block.less | 2 +- .../bootstrap/less/mixins/clearfix.less | 2 +- .../bootstrap/less/mixins/forms.less | 8 +- .../bootstrap/less/mixins/gradients.less | 14 +- .../bootstrap/less/mixins/grid-framework.less | 2 +- .../bootstrap/less/mixins/grid.less | 14 +- .../bootstrap/less/mixins/hide-text.less | 2 + .../bootstrap/less/mixins/image.less | 15 +- .../bootstrap/less/mixins/opacity.less | 5 +- .../bootstrap/less/mixins/reset-text.less | 8 +- .../bootstrap/less/mixins/resize.less | 2 +- .../less/mixins/responsive-visibility.less | 4 +- .../less/mixins/vendor-prefixes.less | 4 +- .../node_modules/bootstrap/less/modals.less | 12 +- .../node_modules/bootstrap/less/navbar.less | 158 ++- .../node_modules/bootstrap/less/navs.less | 10 +- .../bootstrap/less/normalize.less | 9 +- .../node_modules/bootstrap/less/pager.less | 4 +- .../bootstrap/less/pagination.less | 27 +- .../node_modules/bootstrap/less/panels.less | 10 +- .../node_modules/bootstrap/less/popovers.less | 99 +- .../node_modules/bootstrap/less/print.less | 184 ++-- .../bootstrap/less/progress-bars.less | 8 +- .../bootstrap/less/responsive-embed.less | 4 +- .../bootstrap/less/responsive-utilities.less | 8 +- .../bootstrap/less/scaffolding.less | 14 +- .../node_modules/bootstrap/less/tables.less | 48 +- .../node_modules/bootstrap/less/theme.less | 40 +- .../bootstrap/less/thumbnails.less | 4 +- .../node_modules/bootstrap/less/tooltip.less | 65 +- .../node_modules/bootstrap/less/type.less | 22 +- .../bootstrap/less/utilities.less | 2 + .../bootstrap/less/variables.less | 14 +- .../node_modules/bootstrap/less/wells.less | 4 +- .../node_modules/colors/lib/.colors.js.swp | Bin 16384 -> 0 bytes .../output/node_modules/colors/lib/colors.js | 2 +- .../node_modules/colors/lib/custom/trap.js | 4 +- .../node_modules/colors/lib/custom/zalgo.js | 30 +- .../colors/lib/extendStringPrototype.js | 24 +- .../node_modules/colors/lib/maps/random.js | 2 +- hack/update-cmd-docs.sh | 6 +- pkg/apis/wing/v1alpha1/machine_types.go | 2 + .../wing/v1alpha1/machinedeployment_types.go | 4 +- pkg/apis/wing/v1alpha1/machineset_types.go | 2 + pkg/tarmak/cluster/cluster_test.go | 3 + .../winginitializer/winginitializer_test.go | 6 +- .../externalversions/apis/wing/machine.go | 4 +- .../apis/wing/machinedeployment.go | 4 +- .../externalversions/apis/wing/machineset.go | 4 +- pkg/wing/wing_test.go | 23 +- 113 files changed, 2720 insertions(+), 1782 deletions(-) create mode 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/.stylelintrc create mode 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/browsers.js mode change 100755 => 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/change-version.js create mode 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/generate-sri.js create mode 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/karma.conf.js delete mode 100644 docs/generated/reference/output/node_modules/bootstrap/grunt/sauce_browsers.yml delete mode 100644 docs/generated/reference/output/node_modules/colors/lib/.colors.js.swp diff --git a/Gopkg.lock b/Gopkg.lock index bb895973e0..d4eae57abf 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2707,6 +2707,7 @@ "k8s.io/apimachinery/pkg/runtime/serializer/json", "k8s.io/apimachinery/pkg/types", "k8s.io/apimachinery/pkg/util/errors", + "k8s.io/apimachinery/pkg/util/intstr", "k8s.io/apimachinery/pkg/util/runtime", "k8s.io/apimachinery/pkg/util/sets", "k8s.io/apimachinery/pkg/util/validation/field", diff --git a/docs/generated/cmd/wing/wing_agent.rst b/docs/generated/cmd/wing/wing_agent.rst index 80c7ebc1a4..cd4482b761 100644 --- a/docs/generated/cmd/wing/wing_agent.rst +++ b/docs/generated/cmd/wing/wing_agent.rst @@ -24,6 +24,7 @@ Options -h, --help help for agent --instance-name string this specifies the instance's name (default "$(hostname)") --manifest-url string this specifies the URL where the puppet.tar.gz can be found + --pool string this specifies the instance pool the machine resides in, used as a label selector --server-url string this specifies the URL to the wing server (default "https://localhost:9443") Options inherited from parent commands diff --git a/docs/generated/cmd/wing/wing_server.rst b/docs/generated/cmd/wing/wing_server.rst index 92edee4a11..9e72885204 100644 --- a/docs/generated/cmd/wing/wing_server.rst +++ b/docs/generated/cmd/wing/wing_server.rst @@ -20,7 +20,7 @@ Options :: - --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. Within each phase, the plugins will run in the order in which they are passed to this flag. Comma-delimited list of: Initializers, MachineInitTime, MutatingAdmissionWebhook, NamespaceLifecycle, ValidatingAdmissionWebhook. (default [MachineInitTime]) + --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. Within each phase, the plugins will run in the order in which they are passed to this flag. Comma-delimited list of: Initializers, MachineDeploymentInitTime, MachineInitTime, MachineSetInitTime, MutatingAdmissionWebhook, NamespaceLifecycle, ValidatingAdmissionWebhook. (default [MachineInitTime,MachineSetInitTime,MachineDeploymentInitTime]) --admission-control-config-file string File with admission control configuration. --bind-address ip The IP address on which to listen for the --secure-port port. The associated interface(s) must be reachable by the rest of the cluster, and by CLI/web clients. If blank, all interfaces will be used (0.0.0.0). (default 0.0.0.0) --cert-dir string The directory where the TLS certs are located. If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored. (default "apiserver.local.config/certificates") diff --git a/docs/generated/reference/config.yaml b/docs/generated/reference/config.yaml index 0af8ec74a2..7fbcc8344a 100644 --- a/docs/generated/reference/config.yaml +++ b/docs/generated/reference/config.yaml @@ -19,6 +19,12 @@ resource_categories: - name: "Cluster" version: "v1alpha1" group: "cluster" - - name: "Instance" + - name: "Machine" + version: "v1alpha1" + group: "wing" + - name: "MachineSet" + version: "v1alpha1" + group: "wing" + - name: "MachineDeployment" version: "v1alpha1" group: "wing" diff --git a/docs/generated/reference/output/api-docs.html b/docs/generated/reference/output/api-docs.html index 05ffa87c76..0c9f934acf 100644 --- a/docs/generated/reference/output/api-docs.html +++ b/docs/generated/reference/output/api-docs.html @@ -11,7 +11,7 @@ - +

    Tarmak

    @@ -297,7 +297,7 @@

    Cluster v1alpha1


    -

    Instance v1alpha1

    +

    Machine v1alpha1

    @@ -310,7 +310,7 @@

    Instance v1alpha1

    - +
    wing v1alpha1InstanceMachine
    @@ -327,14 +327,108 @@

    Instance v1alpha1

    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources -instanceID
    string +kind
    string +Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + + +metadata
    ObjectMeta + + + +spec
    MachineSpec + + + +status
    MachineStatus + + +

    MachineSpec v1alpha1

    + + + + + + + + + + - + + + + + +
    FieldDescription
    instancePool
    string
    converge
    MachineSpecManifest
    dryRun
    MachineSpecManifest
    +

    MachineStatus v1alpha1

    + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    converge
    MachineStatusManifest
    dryRun
    MachineStatusManifest
    +
    +

    MachineSet v1alpha1

    + + + + + + + + + + + + + + + +
    GroupVersionKind
    wingv1alpha1MachineSet
    +

    MachineSet is the Schema for the machinesets API

    + + + + + + + + + + + + + @@ -343,21 +437,21 @@

    Instance v1alpha1

    - + - +
    FieldDescription
    apiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
    kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
    spec
    InstanceSpec
    spec
    MachineSetSpec
    status
    InstanceStatus
    status
    MachineSetStatus
    -

    InstanceSpec v1alpha1

    +

    MachineSetSpec v1alpha1

    @@ -369,21 +463,33 @@

    InstanceSpec v1alpha1

    - + - - + + + + + + + + + + + + + +
    converge
    InstanceSpecManifest
    maxReplicas
    integer
    dryRun
    InstanceSpecManifest
    minReadySeconds
    integer
    MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready. Defaults to 0 (machine will be considered available as soon as it is ready)
    minReplicas
    integer
    Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1.
    selector
    LabelSelector
    Selector is a label query over machines that should match the replica count. Label keys and values that must match in order to be controlled by this MachineSet. It must match the machine template's labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
    template
    MachineTemplateSpec
    Template is the object that describes the machine that will be created if insufficient replicas are detected.
    -

    InstanceStatus v1alpha1

    +

    MachineSetStatus v1alpha1

    @@ -395,15 +501,206 @@

    InstanceStatus v1alpha1

    - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    converge
    InstanceStatusManifest
    availableReplicas
    integer
    The number of available replicas (ready for at least minReadySeconds) for this MachineSet.
    errorMessage
    string
    ErrorReason *string json:&#34;errorReason,omitempty&#34;
    errorReason
    string
    In the event that there is a terminal problem reconciling the replicas, both ErrorReason and ErrorMessage will be set. ErrorReason will be populated with a succinct value suitable for machine interpretation, while ErrorMessage will contain a more verbose string suitable for logging and human consumption. These fields should not be set for transitive errors that a controller faces that are expected to be fixed automatically over time (like service outages), but instead indicate that something is fundamentally wrong with the MachineTemplates's spec or the configuration of the machine controller, and that manual intervention is required. Examples of terminal errors would be invalid combinations of settings in the spec, values that are unsupported by the machine controller, or the responsible machine controller itself being critically misconfigured. Any transient errors that occur during the reconciliation of Machines can be added as events to the MachineSet object and/or logged in the controller's output.
    fullyLabeledReplicas
    integer
    The number of replicas that have labels matching the labels of the machine template of the MachineSet.
    observedGeneration
    integer
    ObservedGeneration reflects the generation of the most recently observed MachineSet.
    readyReplicas
    integer
    The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready".
    replicas
    integer
    Replicas is the most recently observed number of replicas.
    +
    +

    MachineDeployment v1alpha1

    + + + + + + + + + + + + + + + +
    GroupVersionKind
    wingv1alpha1MachineDeployment
    +

    MachineDeployment is the Schema for the machinedeployments API

    + + + + + + + + + + + + + + + + + + + + + + - +
    FieldDescription
    apiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
    kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
    metadata
    ObjectMeta
    spec
    MachineDeploymentSpec
    dryRun
    InstanceStatusManifest
    status
    MachineDeploymentStatus
    +

    MachineDeploymentSpec v1alpha1

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    maxReplicas
    integer
    minReadySeconds
    integer
    Minimum number of seconds for which a newly created machine should be ready. Defaults to 0 (machine will be considered available as soon as it is ready)
    minReplicas
    integer
    Number of desired machines. Defaults to 1. This is a pointer to distinguish between explicit zero and not specified.
    paused
    boolean
    Indicates that the deployment is paused.
    progressDeadlineSeconds
    integer
    The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.
    revisionHistoryLimit
    integer
    The number of old MachineSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.
    selector
    LabelSelector
    Label selector for machines. Existing MachineSets whose machines are selected by this will be the ones affected by this deployment. It must match the machine template's labels.
    strategy
    MachineDeploymentStrategy
    The deployment strategy to use to replace existing machines with new ones.
    template
    MachineTemplateSpec
    Template describes the machines that will be created.
    +

    MachineDeploymentStatus v1alpha1

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    availableReplicas
    integer
    Total number of available machines (ready for at least minReadySeconds) targeted by this deployment.
    observedGeneration
    integer
    The generation observed by the deployment controller.
    readyReplicas
    integer
    Total number of ready machines targeted by this deployment.
    replicas
    integer
    Total number of non-terminated machines targeted by this deployment (their labels match the selector).
    unavailableReplicas
    integer
    Total number of unavailable machines targeted by this deployment. This is the total number of machines that are still required for the deployment to have 100% available capacity. They may either be machines that are running but not yet available or machines that still have not been created.
    updatedReplicas
    integer
    Total number of non-terminated machines targeted by this deployment that have the desired template spec.
    +

    MachineDeploymentStrategy v1alpha1

    + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    rollingUpdate
    MachineRollingUpdateDeployment
    Rolling update config params. Present only if MachineDeploymentStrategyType = RollingUpdate.
    type
    string
    Type of deployment. Currently the only supported strategy is "RollingUpdate". Default is RollingUpdate.

    Old API Versions


    Field Definitions

    @@ -2087,7 +2384,7 @@

    InstancePoolKubernetes v1alpha1

    -

    InstanceSpecManifest v1alpha1

    +

    InternetGW v1alpha1

    @@ -2098,18 +2395,17 @@

    InstanceSpecManifest v1alpha1

    - + - +
    wingcluster v1alpha1InstanceSpecManifestInternetGW
    -

    InstaceSpecManifest defines location and hash for a specific manifest

    @@ -2121,20 +2417,24 @@

    InstanceSpecManifest v1alpha1

    - - + + - + - - + + + + + +
    hash
    string
    PATH to manifests (tar.gz)apiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
    path
    string
    identifier
    string
    requestTimestamp
    Time
    hash of manifests, prefixed with type (eg: sha256:xyz)kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
    metadata
    ObjectMeta
    -

    InstanceStatusManifest v1alpha1

    +

    KubernetesAPI v1alpha1

    @@ -2145,18 +2445,17 @@

    InstanceStatusManifest v1alpha1

    - + - +
    wingcluster v1alpha1InstanceStatusManifestKubernetesAPI
    -

    InstaceSpecManifest defines the state and hash of a run manifest

    @@ -2168,28 +2467,28 @@

    InstanceStatusManifest v1alpha1

    - - + + - + - - + + - - + + - +
    exitCodes
    integer array
    contains output of the retriesapiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
    hash
    string
    endpoint
    string
    lastUpdateTimestamp
    Time
    hash of manifests, prefixed with type (eg: sha256:xyz)kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
    messages
    string array
    timestamp when a converge was requestedmetadata
    ObjectMeta
    state
    string
    port
    string
    -

    InternetGW v1alpha1

    +

    Label v1alpha1

    @@ -2202,15 +2501,16 @@

    InternetGW v1alpha1

    - +
    cluster v1alpha1InternetGWLabel
    +

    Label structure for instancepool node labels

    @@ -2222,24 +2522,58 @@

    InternetGW v1alpha1

    - - + + - + + +
    apiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resourceskey
    string
    identifier
    string
    value
    string
    +

    LoggingSink v1alpha1

    + + - - + + + + + - + + + + + +
    kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kindsGroupVersionKind
    metadata
    ObjectMeta
    clusterv1alpha1LoggingSink
    + + + + + + + + + + + + + + + +
    FieldDescription
    elasticsearch
    LoggingSinkElasticsearch
    types
    string array
    -

    KubernetesAPI v1alpha1

    +

    LoggingSinkElasticsearch v1alpha1

    @@ -2252,7 +2586,7 @@

    KubernetesAPI v1alpha1

    - +
    cluster v1alpha1KubernetesAPILoggingSinkElasticsearch
    @@ -2260,7 +2594,7 @@

    KubernetesAPI v1alpha1

    Appears In: @@ -2272,28 +2606,40 @@

    KubernetesAPI v1alpha1

    - - + + - + + + + + - - + + - + - + + + + + + + + +
    apiVersion
    string
    APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resourcesamazonESProxy
    AmazonESProxy
    endpoint
    string
    host
    string
    https://fluentbit.io/documentation/0.12/output/elasticsearch.html
    httpBasicAuth
    HTTPBasicAuth
    kind
    string
    Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kindslogstashPrefix
    string
    metadata
    ObjectMeta
    port
    integer
    port
    string
    tls
    boolean
    tlsCA
    string
    tlsVerify
    boolean
    -

    Label v1alpha1

    +

    MachineRollingUpdateDeployment v1alpha1

    @@ -2304,18 +2650,18 @@

    Label v1alpha1

    - + - +
    clusterwing v1alpha1LabelMachineRollingUpdateDeployment
    -

    Label structure for instancepool node labels

    +

    Spec to control the desired behavior of rolling update.

    @@ -2327,16 +2673,16 @@

    Label v1alpha1

    - - + + - - + +
    key
    string
    maxSurge
    IntOrString
    The maximum number of machines that can be scheduled above the desired number of machines. Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 1. Example: when this is set to 30%, the new MachineSet can be scaled up immediately when the rolling update starts, such that the total number of old and new machines do not exceed 130% of desired machines. Once old machines have been killed, new MachineSet can be scaled up further, ensuring that total number of machines running at any time during the update is at most 130% of desired machines.
    value
    string
    maxUnavailable
    IntOrString
    The maximum number of machines that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 0. Example: when this is set to 30%, the old MachineSet can be scaled down to 70% of desired machines immediately when the rolling update starts. Once new machines are ready, old MachineSet can be scaled down further, followed by scaling up the new MachineSet, ensuring that the total number of machines available at all times during the update is at least 70% of desired machines.
    -

    LoggingSink v1alpha1

    +

    MachineSpecManifest v1alpha1

    @@ -2347,17 +2693,18 @@

    LoggingSink v1alpha1

    - + - +
    clusterwing v1alpha1LoggingSinkMachineSpecManifest
    +

    InstaceSpecManifest defines location and hash for a specific manifest

    @@ -2369,16 +2716,20 @@

    LoggingSink v1alpha1

    - - + + - + + + + +
    elasticsearch
    LoggingSinkElasticsearch
    hash
    string
    PATH to manifests (tar.gz)
    types
    string array
    path
    string
    requestTimestamp
    Time
    hash of manifests, prefixed with type (eg: sha256:xyz)
    -

    LoggingSinkElasticsearch v1alpha1

    +

    MachineStatusManifest v1alpha1

    @@ -2389,17 +2740,18 @@

    LoggingSinkElasticsearch v1alpha1

    - + - +
    clusterwing v1alpha1LoggingSinkElasticsearchMachineStatusManifest
    +

    InstaceSpecManifest defines the state and hash of a run manifest

    @@ -2411,36 +2763,68 @@

    LoggingSinkElasticsearch v1alpha1

    - + + + + + - - + + - - + + - + + +
    amazonESProxy
    AmazonESProxy
    exitCodes
    integer array
    contains output of the retries
    hash
    string
    host
    string
    https://fluentbit.io/documentation/0.12/output/elasticsearch.htmllastUpdateTimestamp
    Time
    hash of manifests, prefixed with type (eg: sha256:xyz)
    httpBasicAuth
    HTTPBasicAuth
    messages
    string array
    timestamp when a converge was requested
    logstashPrefix
    string
    state
    string
    +

    MachineTemplateSpec v1alpha1

    + + - - + + + + + - - + + + + +
    port
    integer
    GroupVersionKind
    tls
    boolean
    wingv1alpha1MachineTemplateSpec
    +

    MachineTemplateSpec describes the data needed to create a Machine from a template

    + + + + - - + + + + - - + + + + + +
    tlsCA
    string
    FieldDescription
    tlsVerify
    boolean
    metadata
    ObjectMeta
    Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
    spec
    MachineSpec
    Specification of the desired behavior of the machine. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
    diff --git a/docs/generated/reference/output/navData.js b/docs/generated/reference/output/navData.js index 4a6a007661..77112e2b93 100644 --- a/docs/generated/reference/output/navData.js +++ b/docs/generated/reference/output/navData.js @@ -1 +1 @@ -(function(){navData = {"toc":[{"section":"-strong-field-definitions-strong-","subsections":[{"section":"volume-v1alpha1"},{"section":"values-v1alpha1"},{"section":"taint-v1alpha1"},{"section":"subnet-v1alpha1"},{"section":"ssh-v1alpha1"},{"section":"providergcp-v1alpha1"},{"section":"providerazure-v1alpha1"},{"section":"provideramazon-v1alpha1"},{"section":"provider-v1alpha1"},{"section":"network-v1alpha1"},{"section":"loggingsinkelasticsearch-v1alpha1"},{"section":"loggingsink-v1alpha1"},{"section":"label-v1alpha1"},{"section":"kubernetesapi-v1alpha1"},{"section":"internetgw-v1alpha1"},{"section":"instancestatusmanifest-v1alpha1"},{"section":"instancespecmanifest-v1alpha1"},{"section":"instancepoolkubernetes-v1alpha1"},{"section":"instancepoolamazon-v1alpha1"},{"section":"instancepool-v1alpha1"},{"section":"ingressrule-v1alpha1"},{"section":"httpbasicauth-v1alpha1"},{"section":"firewall-v1alpha1"},{"section":"environment-v1alpha1"},{"section":"egressrule-v1alpha1"},{"section":"clustervaulthelper-v1alpha1"},{"section":"clusterpodsecuritypolicy-v1alpha1"},{"section":"clusterplanflags-v1alpha1"},{"section":"clusterkubernetestiller-v1alpha1"},{"section":"clusterkubernetesscheduler-v1alpha1"},{"section":"clusterkubernetesproxy-v1alpha1"},{"section":"clusterkubernetesprometheus-v1alpha1"},{"section":"clusterkuberneteskubelet-v1alpha1"},{"section":"clusterkubernetesdashboard-v1alpha1"},{"section":"clusterkubernetescontrollermanager-v1alpha1"},{"section":"clusterkubernetesclusterautoscaleroverprovisioning-v1alpha1"},{"section":"clusterkubernetesclusterautoscaler-v1alpha1"},{"section":"clusterkubernetesapiserveroidc-v1alpha1"},{"section":"clusterkubernetesapiserveramazonaccesslogs-v1alpha1"},{"section":"clusterkubernetesapiserveramazon-v1alpha1"},{"section":"clusterkubernetesapiserver-v1alpha1"},{"section":"clusterkubernetes-v1alpha1"},{"section":"clusterkubeconfigflags-v1alpha1"},{"section":"clusterimagesflags-v1alpha1"},{"section":"clusterimagesbuildflags-v1alpha1"},{"section":"clusterflags-v1alpha1"},{"section":"clusterdestroyflags-v1alpha1"},{"section":"clusterapplyflags-v1alpha1"},{"section":"clusteramazon-v1alpha1"},{"section":"amazonesproxy-v1alpha1"}]},{"section":"-strong-old-api-versions-strong-","subsections":[]},{"section":"instance-v1alpha1","subsections":[]},{"section":"cluster-v1alpha1","subsections":[]},{"section":"flags-v1alpha1","subsections":[]},{"section":"image-v1alpha1","subsections":[]},{"section":"config-v1alpha1","subsections":[]},{"section":"-strong-tarmak-strong-","subsections":[]}],"flatToc":["volume-v1alpha1","values-v1alpha1","taint-v1alpha1","subnet-v1alpha1","ssh-v1alpha1","providergcp-v1alpha1","providerazure-v1alpha1","provideramazon-v1alpha1","provider-v1alpha1","network-v1alpha1","loggingsinkelasticsearch-v1alpha1","loggingsink-v1alpha1","label-v1alpha1","kubernetesapi-v1alpha1","internetgw-v1alpha1","instancestatusmanifest-v1alpha1","instancespecmanifest-v1alpha1","instancepoolkubernetes-v1alpha1","instancepoolamazon-v1alpha1","instancepool-v1alpha1","ingressrule-v1alpha1","httpbasicauth-v1alpha1","firewall-v1alpha1","environment-v1alpha1","egressrule-v1alpha1","clustervaulthelper-v1alpha1","clusterpodsecuritypolicy-v1alpha1","clusterplanflags-v1alpha1","clusterkubernetestiller-v1alpha1","clusterkubernetesscheduler-v1alpha1","clusterkubernetesproxy-v1alpha1","clusterkubernetesprometheus-v1alpha1","clusterkuberneteskubelet-v1alpha1","clusterkubernetesdashboard-v1alpha1","clusterkubernetescontrollermanager-v1alpha1","clusterkubernetesclusterautoscaleroverprovisioning-v1alpha1","clusterkubernetesclusterautoscaler-v1alpha1","clusterkubernetesapiserveroidc-v1alpha1","clusterkubernetesapiserveramazonaccesslogs-v1alpha1","clusterkubernetesapiserveramazon-v1alpha1","clusterkubernetesapiserver-v1alpha1","clusterkubernetes-v1alpha1","clusterkubeconfigflags-v1alpha1","clusterimagesflags-v1alpha1","clusterimagesbuildflags-v1alpha1","clusterflags-v1alpha1","clusterdestroyflags-v1alpha1","clusterapplyflags-v1alpha1","clusteramazon-v1alpha1","amazonesproxy-v1alpha1","-strong-field-definitions-strong-","-strong-old-api-versions-strong-","instance-v1alpha1","cluster-v1alpha1","flags-v1alpha1","image-v1alpha1","config-v1alpha1","-strong-tarmak-strong-"]};})(); \ No newline at end of file +(function(){navData = {"toc":[{"section":"-strong-field-definitions-strong-","subsections":[{"section":"volume-v1alpha1"},{"section":"values-v1alpha1"},{"section":"taint-v1alpha1"},{"section":"subnet-v1alpha1"},{"section":"ssh-v1alpha1"},{"section":"providergcp-v1alpha1"},{"section":"providerazure-v1alpha1"},{"section":"provideramazon-v1alpha1"},{"section":"provider-v1alpha1"},{"section":"network-v1alpha1"},{"section":"machinetemplatespec-v1alpha1"},{"section":"machinestatusmanifest-v1alpha1"},{"section":"machinespecmanifest-v1alpha1"},{"section":"machinerollingupdatedeployment-v1alpha1"},{"section":"loggingsinkelasticsearch-v1alpha1"},{"section":"loggingsink-v1alpha1"},{"section":"label-v1alpha1"},{"section":"kubernetesapi-v1alpha1"},{"section":"internetgw-v1alpha1"},{"section":"instancepoolkubernetes-v1alpha1"},{"section":"instancepoolamazon-v1alpha1"},{"section":"instancepool-v1alpha1"},{"section":"ingressrule-v1alpha1"},{"section":"httpbasicauth-v1alpha1"},{"section":"firewall-v1alpha1"},{"section":"environment-v1alpha1"},{"section":"egressrule-v1alpha1"},{"section":"clustervaulthelper-v1alpha1"},{"section":"clusterpodsecuritypolicy-v1alpha1"},{"section":"clusterplanflags-v1alpha1"},{"section":"clusterkubernetestiller-v1alpha1"},{"section":"clusterkubernetesscheduler-v1alpha1"},{"section":"clusterkubernetesproxy-v1alpha1"},{"section":"clusterkubernetesprometheus-v1alpha1"},{"section":"clusterkuberneteskubelet-v1alpha1"},{"section":"clusterkubernetesdashboard-v1alpha1"},{"section":"clusterkubernetescontrollermanager-v1alpha1"},{"section":"clusterkubernetesclusterautoscaleroverprovisioning-v1alpha1"},{"section":"clusterkubernetesclusterautoscaler-v1alpha1"},{"section":"clusterkubernetesapiserveroidc-v1alpha1"},{"section":"clusterkubernetesapiserveramazonaccesslogs-v1alpha1"},{"section":"clusterkubernetesapiserveramazon-v1alpha1"},{"section":"clusterkubernetesapiserver-v1alpha1"},{"section":"clusterkubernetes-v1alpha1"},{"section":"clusterkubeconfigflags-v1alpha1"},{"section":"clusterimagesflags-v1alpha1"},{"section":"clusterimagesbuildflags-v1alpha1"},{"section":"clusterflags-v1alpha1"},{"section":"clusterdestroyflags-v1alpha1"},{"section":"clusterapplyflags-v1alpha1"},{"section":"clusteramazon-v1alpha1"},{"section":"amazonesproxy-v1alpha1"}]},{"section":"-strong-old-api-versions-strong-","subsections":[]},{"section":"machinedeployment-v1alpha1","subsections":[]},{"section":"machineset-v1alpha1","subsections":[]},{"section":"machine-v1alpha1","subsections":[]},{"section":"cluster-v1alpha1","subsections":[]},{"section":"flags-v1alpha1","subsections":[]},{"section":"image-v1alpha1","subsections":[]},{"section":"config-v1alpha1","subsections":[]},{"section":"-strong-tarmak-strong-","subsections":[]}],"flatToc":["volume-v1alpha1","values-v1alpha1","taint-v1alpha1","subnet-v1alpha1","ssh-v1alpha1","providergcp-v1alpha1","providerazure-v1alpha1","provideramazon-v1alpha1","provider-v1alpha1","network-v1alpha1","machinetemplatespec-v1alpha1","machinestatusmanifest-v1alpha1","machinespecmanifest-v1alpha1","machinerollingupdatedeployment-v1alpha1","loggingsinkelasticsearch-v1alpha1","loggingsink-v1alpha1","label-v1alpha1","kubernetesapi-v1alpha1","internetgw-v1alpha1","instancepoolkubernetes-v1alpha1","instancepoolamazon-v1alpha1","instancepool-v1alpha1","ingressrule-v1alpha1","httpbasicauth-v1alpha1","firewall-v1alpha1","environment-v1alpha1","egressrule-v1alpha1","clustervaulthelper-v1alpha1","clusterpodsecuritypolicy-v1alpha1","clusterplanflags-v1alpha1","clusterkubernetestiller-v1alpha1","clusterkubernetesscheduler-v1alpha1","clusterkubernetesproxy-v1alpha1","clusterkubernetesprometheus-v1alpha1","clusterkuberneteskubelet-v1alpha1","clusterkubernetesdashboard-v1alpha1","clusterkubernetescontrollermanager-v1alpha1","clusterkubernetesclusterautoscaleroverprovisioning-v1alpha1","clusterkubernetesclusterautoscaler-v1alpha1","clusterkubernetesapiserveroidc-v1alpha1","clusterkubernetesapiserveramazonaccesslogs-v1alpha1","clusterkubernetesapiserveramazon-v1alpha1","clusterkubernetesapiserver-v1alpha1","clusterkubernetes-v1alpha1","clusterkubeconfigflags-v1alpha1","clusterimagesflags-v1alpha1","clusterimagesbuildflags-v1alpha1","clusterflags-v1alpha1","clusterdestroyflags-v1alpha1","clusterapplyflags-v1alpha1","clusteramazon-v1alpha1","amazonesproxy-v1alpha1","-strong-field-definitions-strong-","-strong-old-api-versions-strong-","machinedeployment-v1alpha1","machineset-v1alpha1","machine-v1alpha1","cluster-v1alpha1","flags-v1alpha1","image-v1alpha1","config-v1alpha1","-strong-tarmak-strong-"]};})(); \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/Gruntfile.js b/docs/generated/reference/output/node_modules/bootstrap/Gruntfile.js index 994a500871..c7bfac58f5 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/Gruntfile.js +++ b/docs/generated/reference/output/node_modules/bootstrap/Gruntfile.js @@ -1,7 +1,7 @@ /*! * Bootstrap's Gruntfile - * http://getbootstrap.com - * Copyright 2013-2016 Twitter, Inc. + * https://getbootstrap.com/ + * Copyright 2013-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -104,7 +104,7 @@ module.exports = function (grunt) { banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>', stripBanners: false }, - bootstrap: { + core: { src: [ 'js/transition.js', 'js/alert.js', @@ -125,78 +125,90 @@ module.exports = function (grunt) { uglify: { options: { - compress: { - warnings: false - }, + compress: true, mangle: true, - preserveComments: /^!|@preserve|@license|@cc_on/i + ie8: true, + output: { + comments: /^!|@preserve|@license|@cc_on/i + } }, core: { - src: '<%= concat.bootstrap.dest %>', + src: '<%= concat.core.dest %>', dest: 'dist/js/<%= pkg.name %>.min.js' }, customize: { src: configBridge.paths.customizerJs, dest: 'docs/assets/js/customize.min.js' }, - docsJs: { + docs: { src: configBridge.paths.docsJs, dest: 'docs/assets/js/docs.min.js' } }, - qunit: { + less: { options: { - inject: 'js/tests/unit/phantom.js' + ieCompat: true, + strictMath: true, + sourceMap: true, + outputSourceFiles: true }, - files: 'js/tests/index.html' - }, - - less: { - compileCore: { + core: { options: { - strictMath: true, - sourceMap: true, - outputSourceFiles: true, sourceMapURL: '<%= pkg.name %>.css.map', sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map' }, src: 'less/bootstrap.less', dest: 'dist/css/<%= pkg.name %>.css' }, - compileTheme: { + theme: { options: { - strictMath: true, - sourceMap: true, - outputSourceFiles: true, sourceMapURL: '<%= pkg.name %>-theme.css.map', sourceMapFilename: 'dist/css/<%= pkg.name %>-theme.css.map' }, src: 'less/theme.less', dest: 'dist/css/<%= pkg.name %>-theme.css' + }, + docs: { + options: { + sourceMapURL: 'docs.css.map', + sourceMapFilename: 'docs/assets/css/docs.css.map' + }, + src: 'docs/assets/less/docs.less', + dest: 'docs/assets/css/docs.css' + }, + docsIe: { + options: { + sourceMap: false + }, + src: 'docs/assets/less/ie10-viewport-bug-workaround.less', + dest: 'docs/assets/css/ie10-viewport-bug-workaround.css' } }, - autoprefixer: { + postcss: { options: { - browsers: configBridge.config.autoprefixerBrowsers + map: { + inline: false, + sourcesContent: true + }, + processors: [ + require('autoprefixer')(configBridge.config.autoprefixer) + ] }, core: { - options: { - map: true - }, src: 'dist/css/<%= pkg.name %>.css' }, theme: { - options: { - map: true - }, src: 'dist/css/<%= pkg.name %>-theme.css' }, docs: { - src: ['docs/assets/css/src/docs.css'] + src: 'docs/assets/css/docs.css' }, examples: { + options: { + map: false + }, expand: true, cwd: 'docs/examples/', src: ['**/*.css'], @@ -204,76 +216,47 @@ module.exports = function (grunt) { } }, - csslint: { + stylelint: { options: { - csslintrc: 'less/.csslintrc' + configFile: 'grunt/.stylelintrc', + reportNeedlessDisables: false }, dist: [ - 'dist/css/bootstrap.css', - 'dist/css/bootstrap-theme.css' + 'less/**/*.less' + ], + docs: [ + 'docs/assets/less/**/*.less' ], examples: [ 'docs/examples/**/*.css' - ], - docs: { - options: { - ids: false, - 'overqualified-elements': false - }, - src: 'docs/assets/css/src/docs.css' - } + ] }, cssmin: { options: { - // TODO: disable `zeroUnits` optimization once clean-css 3.2 is released - // and then simplify the fix for https://github.com/twbs/bootstrap/issues/14837 accordingly compatibility: 'ie8', - keepSpecialComments: '*', sourceMap: true, sourceMapInlineSources: true, - advanced: false + level: { + 1: { + specialComments: 'all' + } + } }, - minifyCore: { + core: { src: 'dist/css/<%= pkg.name %>.css', dest: 'dist/css/<%= pkg.name %>.min.css' }, - minifyTheme: { + theme: { src: 'dist/css/<%= pkg.name %>-theme.css', dest: 'dist/css/<%= pkg.name %>-theme.min.css' }, docs: { - src: [ - 'docs/assets/css/ie10-viewport-bug-workaround.css', - 'docs/assets/css/src/pygments-manni.css', - 'docs/assets/css/src/docs.css' - ], + src: 'docs/assets/css/docs.css', dest: 'docs/assets/css/docs.min.css' } }, - csscomb: { - options: { - config: 'less/.csscomb.json' - }, - dist: { - expand: true, - cwd: 'dist/css/', - src: ['*.css', '!*.min.css'], - dest: 'dist/css/' - }, - examples: { - expand: true, - cwd: 'docs/examples/', - src: '**/*.css', - dest: 'docs/examples/' - }, - docs: { - src: 'docs/assets/css/src/docs.css', - dest: 'docs/assets/css/src/docs.css' - } - }, - copy: { fonts: { expand: true, @@ -313,41 +296,6 @@ module.exports = function (grunt) { } }, - htmlmin: { - dist: { - options: { - collapseBooleanAttributes: true, - collapseWhitespace: true, - conservativeCollapse: true, - decodeEntities: false, - minifyCSS: { - compatibility: 'ie8', - keepSpecialComments: 0 - }, - minifyJS: true, - minifyURLs: false, - processConditionalComments: true, - removeAttributeQuotes: true, - removeComments: true, - removeOptionalAttributes: true, - removeOptionalTags: true, - removeRedundantAttributes: true, - removeScriptTypeAttributes: true, - removeStyleLinkTypeAttributes: true, - removeTagWhitespace: false, - sortAttributes: true, - sortClassName: true - }, - expand: true, - cwd: '_gh_pages', - dest: '_gh_pages', - src: [ - '**/*.html', - '!examples/**/*.html' - ] - } - }, - pug: { options: { pretty: true, @@ -366,67 +314,40 @@ module.exports = function (grunt) { htmllint: { options: { ignore: [ - 'Attribute "autocomplete" not allowed on element "button" at this point.', - 'Attribute "autocomplete" is only allowed when the input type is "color", "date", "datetime", "datetime-local", "email", "hidden", "month", "number", "password", "range", "search", "tel", "text", "time", "url", or "week".', 'Element "img" is missing required attribute "src".' - ] + ], + noLangDetect: true }, - src: '_gh_pages/**/*.html' + src: ['_gh_pages/**/*.html', 'js/tests/**/*.html'] }, watch: { src: { files: '<%= jshint.core.src %>', - tasks: ['jshint:core', 'qunit', 'concat'] + tasks: ['jshint:core', 'exec:karma', 'concat'] }, test: { files: '<%= jshint.test.src %>', - tasks: ['jshint:test', 'qunit'] + tasks: ['jshint:test', 'exec:karma'] }, less: { files: 'less/**/*.less', - tasks: 'less' - } - }, - - 'saucelabs-qunit': { - all: { - options: { - build: process.env.TRAVIS_JOB_ID, - throttled: 10, - maxRetries: 3, - maxPollRetries: 4, - urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'], - browsers: grunt.file.readYAML('grunt/sauce_browsers.yml') - } + tasks: ['less', 'copy'] + }, + docs: { + files: 'docs/assets/less/**/*.less', + tasks: ['less'] } }, exec: { - npmUpdate: { - command: 'npm update' - } - }, - - compress: { - main: { - options: { - archive: 'bootstrap-<%= pkg.version %>-dist.zip', - mode: 'zip', - level: 9, - pretty: true - }, - files: [ - { - expand: true, - cwd: 'dist/', - src: ['**'], - dest: 'bootstrap-<%= pkg.version %>-dist' - } - ] + browserstack: { + command: 'cross-env BROWSER=true karma start grunt/karma.conf.js' + }, + karma: { + command: 'karma start grunt/karma.conf.js' } } - }); @@ -441,16 +362,14 @@ module.exports = function (grunt) { return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset; }; var isUndefOrNonZero = function (val) { - return val === undefined || val !== '0'; + return typeof val === 'undefined' || val !== '0'; }; // Test task. var testSubtasks = []; // Skip core tests if running a different subset of the test suite - if (runSubset('core') && - // Skip core tests if this is a Savage build - process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { - testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']); + if (runSubset('core')) { + testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'stylelint:dist', 'test-js', 'docs']); } // Skip HTML validation if running a different subset of the test suite if (runSubset('validate-html') && @@ -458,24 +377,23 @@ module.exports = function (grunt) { isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) { testSubtasks.push('validate-html'); } - // Only run Sauce Labs tests if there's a Sauce access key - if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' && - // Skip Sauce if running a different subset of the test suite - runSubset('sauce-js-unit') && - // Skip Sauce on Travis when [skip sauce] is in the commit message - isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) { - testSubtasks.push('connect'); - testSubtasks.push('saucelabs-qunit'); + // Only run BrowserStack tests if there's a BrowserStack access key + if (typeof process.env.BROWSER_STACK_USERNAME !== 'undefined' && + // Skip BrowserStack if running a different subset of the test suite + runSubset('browserstack') && + // Skip BrowserStack on Travis when [skip browserstack] is in the commit message + isUndefOrNonZero(process.env.TWBS_DO_BROWSERSTACK)) { + testSubtasks.push('exec:browserstack'); } + grunt.registerTask('test', testSubtasks); - grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']); + grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'exec:karma']); // JS distribution task. grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']); // CSS distribution task. - grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']); - grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']); + grunt.registerTask('dist-css', ['less:core', 'less:theme', 'postcss:core', 'postcss:theme', 'cssmin:core', 'cssmin:theme']); // Full distribution task. grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']); @@ -483,7 +401,9 @@ module.exports = function (grunt) { // Default task. grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']); - grunt.registerTask('build-glyphicons-data', function () { generateGlyphiconsData.call(this, grunt); }); + grunt.registerTask('build-glyphicons-data', function () { + generateGlyphiconsData.call(this, grunt); + }); // task for building customizer grunt.registerTask('build-customizer', ['build-customizer-html', 'build-raw-files']); @@ -494,18 +414,17 @@ module.exports = function (grunt) { }); grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () { - var srcFiles = grunt.config.get('concat.bootstrap.src'); + var srcFiles = grunt.config.get('concat.core.src'); var destFilepath = 'dist/js/npm.js'; generateCommonJSModule(grunt, srcFiles, destFilepath); }); // Docs task. - grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']); - grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']); - grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']); + grunt.registerTask('docs-css', ['less:docs', 'less:docsIe', 'postcss:docs', 'postcss:examples', 'cssmin:docs']); + grunt.registerTask('lint-docs-css', ['stylelint:docs', 'stylelint:examples']); + grunt.registerTask('docs-js', ['uglify:docs', 'uglify:customize']); grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']); grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-glyphicons-data', 'build-customizer']); - grunt.registerTask('docs-github', ['jekyll:github', 'htmlmin']); - grunt.registerTask('prep-release', ['dist', 'docs', 'docs-github', 'compress']); + grunt.registerTask('prep-release', ['dist', 'docs', 'jekyll:github']); }; diff --git a/docs/generated/reference/output/node_modules/bootstrap/LICENSE b/docs/generated/reference/output/node_modules/bootstrap/LICENSE index 7a300022c3..420cde2e76 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/LICENSE +++ b/docs/generated/reference/output/node_modules/bootstrap/LICENSE @@ -1,21 +1,21 @@ -The MIT License (MIT) - -Copyright (c) 2011-2016 Twitter, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The MIT License (MIT) + +Copyright (c) 2011-2018 Twitter, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css index 31d8882661..7f66b3f6fa 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ .btn-default, @@ -9,9 +9,9 @@ .btn-info, .btn-warning, .btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); } .btn-default:active, .btn-primary:active, @@ -25,8 +25,8 @@ .btn-info.active, .btn-warning.active, .btn-danger.active { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-default.disabled, .btn-primary.disabled, @@ -47,7 +47,7 @@ fieldset[disabled] .btn-info, fieldset[disabled] .btn-warning, fieldset[disabled] .btn-danger { -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } .btn-default .badge, .btn-primary .badge, @@ -62,15 +62,15 @@ fieldset[disabled] .btn-danger { background-image: none; } .btn-default { - text-shadow: 0 1px 0 #fff; background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); - background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); + background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #dbdbdb; + text-shadow: 0 1px 0 #fff; border-color: #ccc; } .btn-default:hover, @@ -106,9 +106,9 @@ fieldset[disabled] .btn-default.active { } .btn-primary { background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); - background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; @@ -147,9 +147,9 @@ fieldset[disabled] .btn-primary.active { } .btn-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; @@ -188,9 +188,9 @@ fieldset[disabled] .btn-success.active { } .btn-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; @@ -229,9 +229,9 @@ fieldset[disabled] .btn-info.active { } .btn-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; @@ -270,9 +270,9 @@ fieldset[disabled] .btn-warning.active { } .btn-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; @@ -311,81 +311,81 @@ fieldset[disabled] .btn-danger.active { } .thumbnail, .img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { - background-color: #e8e8e8; background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; + background-color: #e8e8e8; } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { - background-color: #2e6da4; background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); background-repeat: repeat-x; + background-color: #2e6da4; } .navbar-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); - background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); + background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8)); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); } .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); - background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); + background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); } .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, .25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); } .navbar-inverse { background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); border-radius: 4px; } .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); - background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); + background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); } .navbar-inverse .navbar-brand, .navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .navbar-static-top, .navbar-fixed-top, @@ -398,120 +398,120 @@ fieldset[disabled] .btn-danger.active { .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { color: #fff; background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); background-repeat: repeat-x; } } .alert { - text-shadow: 0 1px 0 rgba(255, 255, 255, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); } .alert-success { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); background-repeat: repeat-x; border-color: #b2dba1; } .alert-info { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); background-repeat: repeat-x; border-color: #9acfea; } .alert-warning { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); background-repeat: repeat-x; border-color: #f5e79e; } .alert-danger { background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); background-repeat: repeat-x; border-color: #dca7a7; } .progress { background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; } .progress-bar { background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); - background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); background-repeat: repeat-x; } .progress-bar-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); background-repeat: repeat-x; } .progress-bar-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); background-repeat: repeat-x; } .progress-bar-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); background-repeat: repeat-x; } .progress-bar-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); background-repeat: repeat-x; } .progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .list-group { border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); } .list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { text-shadow: 0 -1px 0 #286090; background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); background-repeat: repeat-x; border-color: #2b669a; @@ -522,66 +522,66 @@ fieldset[disabled] .btn-danger.active { text-shadow: none; } .panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .panel-default > .panel-heading { background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; } .panel-primary > .panel-heading { background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); background-repeat: repeat-x; } .panel-success > .panel-heading { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); background-repeat: repeat-x; } .panel-info > .panel-heading { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); background-repeat: repeat-x; } .panel-warning > .panel-heading { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); background-repeat: repeat-x; } .panel-danger > .panel-heading { background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); background-repeat: repeat-x; } .well { background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; border-color: #dcdcdc; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); } -/*# sourceMappingURL=bootstrap-theme.css.map */ +/*# sourceMappingURL=bootstrap-theme.css.map */ \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css.map b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css.map index d876f60fb4..77252b0511 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css.map +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.css.map @@ -1 +1 @@ -{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file +{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// stylelint-disable selector-no-qualifying-type, selector-max-compound-selectors\n\n/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default {\n .btn-styles(@btn-default-bg);\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n .box-shadow(@shadow);\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// stylelint-disable value-no-vendor-prefix, selector-max-id\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css index 5e39401957..30c85f627f 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css @@ -1,6 +1,6 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x;background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x;background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} /*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css.map b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css.map index 94813e9006..82cd0c8763 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css.map +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap-theme.min.css.map @@ -1 +1 @@ -{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file +{"version":3,"sources":["bootstrap-theme.css","dist/css/bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// stylelint-disable selector-no-qualifying-type, selector-max-compound-selectors\n\n/*!\n * Bootstrap v3.4.0 (https://getbootstrap.com/)\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default {\n .btn-styles(@btn-default-bg);\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n .box-shadow(@shadow);\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// stylelint-disable value-no-vendor-prefix, selector-max-id\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css index 6167622cec..2321718e9e 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css @@ -1,13 +1,13 @@ /*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. + * Bootstrap v3.4.0 (https://getbootstrap.com/) + * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ html { font-family: sans-serif; + -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; } body { margin: 0; @@ -50,7 +50,11 @@ a:hover { outline: 0; } abbr[title] { - border-bottom: 1px dotted; + border-bottom: none; + text-decoration: underline; + -webkit-text-decoration: underline dotted; + -moz-text-decoration: underline dotted; + text-decoration: underline dotted; } b, strong { @@ -60,28 +64,28 @@ dfn { font-style: italic; } h1 { - margin: .67em 0; font-size: 2em; + margin: 0.67em 0; } mark { - color: #000; background: #ff0; + color: #000; } small { font-size: 80%; } sub, sup { - position: relative; font-size: 75%; line-height: 0; + position: relative; vertical-align: baseline; } sup { - top: -.5em; + top: -0.5em; } sub { - bottom: -.25em; + bottom: -0.25em; } img { border: 0; @@ -93,10 +97,10 @@ figure { margin: 1em 40px; } hr { - height: 0; -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } pre { overflow: auto; @@ -113,9 +117,9 @@ input, optgroup, select, textarea { - margin: 0; - font: inherit; color: inherit; + font: inherit; + margin: 0; } button { overflow: visible; @@ -137,8 +141,8 @@ html input[disabled] { } button::-moz-focus-inner, input::-moz-focus-inner { - padding: 0; border: 0; + padding: 0; } input { line-height: normal; @@ -146,8 +150,8 @@ input { input[type="checkbox"], input[type="radio"] { -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; padding: 0; } input[type="number"]::-webkit-inner-spin-button, @@ -155,23 +159,23 @@ input[type="number"]::-webkit-outer-spin-button { height: auto; } input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } fieldset { - padding: .35em .625em .75em; - margin: 0 2px; border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } legend { - padding: 0; border: 0; + padding: 0; } textarea { overflow: auto; @@ -180,8 +184,8 @@ optgroup { font-weight: bold; } table { - border-spacing: 0; border-collapse: collapse; + border-spacing: 0; } td, th { @@ -196,7 +200,7 @@ th { text-shadow: none !important; background: transparent !important; -webkit-box-shadow: none !important; - box-shadow: none !important; + box-shadow: none !important; } a, a:visited { @@ -215,7 +219,6 @@ th { pre, blockquote { border: 1px solid #999; - page-break-inside: avoid; } thead { @@ -261,20 +264,18 @@ th { } } @font-face { - font-family: 'Glyphicons Halflings'; - - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); + font-family: "Glyphicons Halflings"; + src: url("../fonts/glyphicons-halflings-regular.eot"); + src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"), url("../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); } .glyphicon { position: relative; top: 1px; display: inline-block; - font-family: 'Glyphicons Halflings'; + font-family: "Glyphicons Halflings"; font-style: normal; - font-weight: normal; + font-weight: 400; line-height: 1; - -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -1067,25 +1068,24 @@ th { } * { -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } *:before, *:after { -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } html { font-size: 10px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; - color: #333; + color: #333333; background-color: #fff; } input, @@ -1128,17 +1128,17 @@ img { border-radius: 6px; } .img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; padding: 4px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; } .img-circle { border-radius: 50%; @@ -1147,7 +1147,7 @@ hr { margin-top: 20px; margin-bottom: 20px; border: 0; - border-top: 1px solid #eee; + border-top: 1px solid #eeeeee; } .sr-only { position: absolute; @@ -1212,9 +1212,9 @@ h6 .small, .h4 .small, .h5 .small, .h6 .small { - font-weight: normal; + font-weight: 400; line-height: 1; - color: #777; + color: #777777; } h1, .h1, @@ -1306,7 +1306,7 @@ small, } mark, .mark { - padding: .2em; + padding: 0.2em; background-color: #fcf8e3; } .text-left { @@ -1334,7 +1334,7 @@ mark, text-transform: capitalize; } .text-muted { - color: #777; + color: #777777; } .text-primary { color: #337ab7; @@ -1410,7 +1410,7 @@ a.bg-danger:focus { .page-header { padding-bottom: 9px; margin: 40px 0 20px; - border-bottom: 1px solid #eee; + border-bottom: 1px solid #eeeeee; } ul, ol { @@ -1429,8 +1429,8 @@ ol ol { } .list-inline { padding-left: 0; - margin-left: -5px; list-style: none; + margin-left: -5px; } .list-inline > li { display: inline-block; @@ -1446,7 +1446,7 @@ dd { line-height: 1.42857143; } dt { - font-weight: bold; + font-weight: 700; } dd { margin-left: 0; @@ -1455,9 +1455,9 @@ dd { .dl-horizontal dt { float: left; width: 160px; - overflow: hidden; clear: left; text-align: right; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @@ -1468,7 +1468,6 @@ dd { abbr[title], abbr[data-original-title] { cursor: help; - border-bottom: 1px dotted #777; } .initialism { font-size: 90%; @@ -1478,7 +1477,7 @@ blockquote { padding: 10px 20px; margin: 0 0 20px; font-size: 17.5px; - border-left: 5px solid #eee; + border-left: 5px solid #eeeeee; } blockquote p:last-child, blockquote ul:last-child, @@ -1491,19 +1490,19 @@ blockquote .small { display: block; font-size: 80%; line-height: 1.42857143; - color: #777; + color: #777777; } blockquote footer:before, blockquote small:before, blockquote .small:before { - content: '\2014 \00A0'; + content: "\2014 \00A0"; } .blockquote-reverse, blockquote.pull-right { padding-right: 15px; padding-left: 0; text-align: right; - border-right: 5px solid #eee; + border-right: 5px solid #eeeeee; border-left: 0; } .blockquote-reverse footer:before, @@ -1512,7 +1511,7 @@ blockquote.pull-right footer:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { - content: ''; + content: ""; } .blockquote-reverse footer:after, blockquote.pull-right footer:after, @@ -1520,7 +1519,7 @@ blockquote.pull-right footer:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { - content: '\00A0 \2014'; + content: "\00A0 \2014"; } address { margin-bottom: 20px; @@ -1546,15 +1545,15 @@ kbd { color: #fff; background-color: #333; border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; - font-weight: bold; + font-weight: 700; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } pre { display: block; @@ -1562,7 +1561,7 @@ pre { margin: 0 0 10px; font-size: 13px; line-height: 1.42857143; - color: #333; + color: #333333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; @@ -1612,13 +1611,79 @@ pre code { margin-right: -15px; margin-left: -15px; } -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { +.row-no-gutters { + margin-right: 0; + margin-left: 0; +} +.row-no-gutters [class*="col-"] { + padding-right: 0; + padding-left: 0; +} +.col-xs-1, +.col-sm-1, +.col-md-1, +.col-lg-1, +.col-xs-2, +.col-sm-2, +.col-md-2, +.col-lg-2, +.col-xs-3, +.col-sm-3, +.col-md-3, +.col-lg-3, +.col-xs-4, +.col-sm-4, +.col-md-4, +.col-lg-4, +.col-xs-5, +.col-sm-5, +.col-md-5, +.col-lg-5, +.col-xs-6, +.col-sm-6, +.col-md-6, +.col-lg-6, +.col-xs-7, +.col-sm-7, +.col-md-7, +.col-lg-7, +.col-xs-8, +.col-sm-8, +.col-md-8, +.col-lg-8, +.col-xs-9, +.col-sm-9, +.col-md-9, +.col-lg-9, +.col-xs-10, +.col-sm-10, +.col-md-10, +.col-lg-10, +.col-xs-11, +.col-sm-11, +.col-md-11, +.col-lg-11, +.col-xs-12, +.col-sm-12, +.col-md-12, +.col-lg-12 { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; } -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11, +.col-xs-12 { float: left; } .col-xs-12 { @@ -1772,10 +1837,21 @@ pre code { margin-left: 8.33333333%; } .col-xs-offset-0 { - margin-left: 0; + margin-left: 0%; } @media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + .col-sm-1, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-10, + .col-sm-11, + .col-sm-12 { float: left; } .col-sm-12 { @@ -1929,11 +2005,22 @@ pre code { margin-left: 8.33333333%; } .col-sm-offset-0 { - margin-left: 0; + margin-left: 0%; } } @media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11, + .col-md-12 { float: left; } .col-md-12 { @@ -2087,11 +2174,22 @@ pre code { margin-left: 8.33333333%; } .col-md-offset-0 { - margin-left: 0; + margin-left: 0%; } } @media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + .col-lg-1, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-10, + .col-lg-11, + .col-lg-12 { float: left; } .col-lg-12 { @@ -2245,16 +2343,27 @@ pre code { margin-left: 8.33333333%; } .col-lg-offset-0 { - margin-left: 0; + margin-left: 0%; } } table { background-color: transparent; } +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} caption { padding-top: 8px; padding-bottom: 8px; - color: #777; + color: #777777; text-align: left; } th { @@ -2323,17 +2432,6 @@ th { .table-hover > tbody > tr:hover { background-color: #f5f5f5; } -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, @@ -2440,7 +2538,7 @@ table th[class*="col-"] { background-color: #ebcccc; } .table-responsive { - min-height: .01%; + min-height: 0.01%; overflow-x: auto; } @media screen and (max-width: 767px) { @@ -2501,7 +2599,7 @@ legend { margin-bottom: 20px; font-size: 21px; line-height: inherit; - color: #333; + color: #333333; border: 0; border-bottom: 1px solid #e5e5e5; } @@ -2509,12 +2607,15 @@ label { display: inline-block; max-width: 100%; margin-bottom: 5px; - font-weight: bold; + font-weight: 700; } input[type="search"] { -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } input[type="radio"], input[type="checkbox"] { @@ -2522,6 +2623,14 @@ input[type="checkbox"] { margin-top: 1px \9; line-height: normal; } +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} input[type="file"] { display: block; } @@ -2544,7 +2653,7 @@ output { padding-top: 7px; font-size: 14px; line-height: 1.42857143; - color: #555; + color: #555555; } .form-control { display: block; @@ -2553,22 +2662,25 @@ output { padding: 6px 12px; font-size: 14px; line-height: 1.42857143; - color: #555; + color: #555555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; } .form-control:focus { border-color: #66afe9; outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); } .form-control::-moz-placeholder { color: #999; @@ -2587,7 +2699,7 @@ output { .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - background-color: #eee; + background-color: #eeeeee; opacity: 1; } .form-control[disabled], @@ -2597,9 +2709,6 @@ fieldset[disabled] .form-control { textarea.form-control { height: auto; } -input[type="search"] { - -webkit-appearance: none; -} @media screen and (-webkit-min-device-pixel-ratio: 0) { input[type="date"].form-control, input[type="time"].form-control, @@ -2638,12 +2747,18 @@ input[type="search"] { margin-top: 10px; margin-bottom: 10px; } +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} .radio label, .checkbox label { min-height: 20px; padding-left: 20px; margin-bottom: 0; - font-weight: normal; + font-weight: 400; cursor: pointer; } .radio input[type="radio"], @@ -2664,34 +2779,20 @@ input[type="search"] { display: inline-block; padding-left: 20px; margin-bottom: 0; - font-weight: normal; + font-weight: 400; vertical-align: middle; cursor: pointer; } -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} .radio-inline.disabled, .checkbox-inline.disabled, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox-inline { cursor: not-allowed; } -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; } .form-control-static { min-height: 34px; @@ -2824,13 +2925,13 @@ select[multiple].input-lg { } .has-success .form-control { border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-success .form-control:focus { border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; } .has-success .input-group-addon { color: #3c763d; @@ -2854,13 +2955,13 @@ select[multiple].input-lg { } .has-warning .form-control { border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-warning .form-control:focus { border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; } .has-warning .input-group-addon { color: #8a6d3b; @@ -2884,13 +2985,13 @@ select[multiple].input-lg { } .has-error .form-control { border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-error .form-control:focus { border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; } .has-error .input-group-addon { color: #a94442; @@ -3002,24 +3103,24 @@ select[multiple].input-lg { } .btn { display: inline-block; - padding: 6px 12px; margin-bottom: 0; - font-size: 14px; font-weight: normal; - line-height: 1.42857143; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; - touch-action: manipulation; + touch-action: manipulation; cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; background-image: none; border: 1px solid transparent; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .btn:focus, .btn:active:focus, @@ -3040,17 +3141,17 @@ select[multiple].input-lg { .btn.active { background-image: none; outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn.disabled, .btn[disabled], fieldset[disabled] .btn { cursor: not-allowed; filter: alpha(opacity=65); + opacity: 0.65; -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; + box-shadow: none; } a.btn.disabled, fieldset[disabled] a.btn { @@ -3077,6 +3178,7 @@ fieldset[disabled] a.btn { .open > .dropdown-toggle.btn-default { color: #333; background-color: #e6e6e6; + background-image: none; border-color: #adadad; } .btn-default:active:hover, @@ -3092,11 +3194,6 @@ fieldset[disabled] a.btn { background-color: #d4d4d4; border-color: #8c8c8c; } -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, @@ -3134,6 +3231,7 @@ fieldset[disabled] .btn-default.focus { .open > .dropdown-toggle.btn-primary { color: #fff; background-color: #286090; + background-image: none; border-color: #204d74; } .btn-primary:active:hover, @@ -3149,11 +3247,6 @@ fieldset[disabled] .btn-default.focus { background-color: #204d74; border-color: #122b40; } -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, @@ -3191,6 +3284,7 @@ fieldset[disabled] .btn-primary.focus { .open > .dropdown-toggle.btn-success { color: #fff; background-color: #449d44; + background-image: none; border-color: #398439; } .btn-success:active:hover, @@ -3206,11 +3300,6 @@ fieldset[disabled] .btn-primary.focus { background-color: #398439; border-color: #255625; } -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, @@ -3248,6 +3337,7 @@ fieldset[disabled] .btn-success.focus { .open > .dropdown-toggle.btn-info { color: #fff; background-color: #31b0d5; + background-image: none; border-color: #269abc; } .btn-info:active:hover, @@ -3263,11 +3353,6 @@ fieldset[disabled] .btn-success.focus { background-color: #269abc; border-color: #1b6d85; } -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, @@ -3305,6 +3390,7 @@ fieldset[disabled] .btn-info.focus { .open > .dropdown-toggle.btn-warning { color: #fff; background-color: #ec971f; + background-image: none; border-color: #d58512; } .btn-warning:active:hover, @@ -3320,11 +3406,6 @@ fieldset[disabled] .btn-info.focus { background-color: #d58512; border-color: #985f0d; } -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, @@ -3362,6 +3443,7 @@ fieldset[disabled] .btn-warning.focus { .open > .dropdown-toggle.btn-danger { color: #fff; background-color: #c9302c; + background-image: none; border-color: #ac2925; } .btn-danger:active:hover, @@ -3377,11 +3459,6 @@ fieldset[disabled] .btn-warning.focus { background-color: #ac2925; border-color: #761c19; } -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, @@ -3399,7 +3476,7 @@ fieldset[disabled] .btn-danger.focus { background-color: #fff; } .btn-link { - font-weight: normal; + font-weight: 400; color: #337ab7; border-radius: 0; } @@ -3410,7 +3487,7 @@ fieldset[disabled] .btn-danger.focus { fieldset[disabled] .btn-link { background-color: transparent; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } .btn-link, .btn-link:hover, @@ -3428,7 +3505,7 @@ fieldset[disabled] .btn-link { fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { - color: #777; + color: #777777; text-decoration: none; } .btn-lg, @@ -3466,9 +3543,9 @@ input[type="button"].btn-block { } .fade { opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; } .fade.in { opacity: 1; @@ -3489,15 +3566,15 @@ tbody.collapse.in { position: relative; height: 0; overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; } .caret { display: inline-block; @@ -3531,13 +3608,12 @@ tbody.collapse.in { text-align: left; list-style: none; background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; + background-clip: padding-box; border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); + border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); } .dropdown-menu.pull-right { right: 0; @@ -3553,9 +3629,9 @@ tbody.collapse.in { display: block; padding: 3px 20px; clear: both; - font-weight: normal; + font-weight: 400; line-height: 1.42857143; - color: #333; + color: #333333; white-space: nowrap; } .dropdown-menu > li > a:hover, @@ -3575,7 +3651,7 @@ tbody.collapse.in { .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { - color: #777; + color: #777777; } .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { @@ -3604,7 +3680,7 @@ tbody.collapse.in { padding: 3px 20px; font-size: 12px; line-height: 1.42857143; - color: #777; + color: #777777; white-space: nowrap; } .dropdown-backdrop { @@ -3725,12 +3801,12 @@ tbody.collapse.in { padding-left: 12px; } .btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-group.open .dropdown-toggle.btn-link { -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } .btn .caret { margin-left: 0; @@ -3898,11 +3974,11 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .input-group-addon { padding: 6px 12px; font-size: 14px; - font-weight: normal; + font-weight: 400; line-height: 1; - color: #555; + color: #555555; text-align: center; - background-color: #eee; + background-color: #eeeeee; border: 1px solid #ccc; border-radius: 4px; } @@ -3988,14 +4064,14 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; - background-color: #eee; + background-color: #eeeeee; } .nav > li.disabled > a { - color: #777; + color: #777777; } .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { - color: #777; + color: #777777; text-decoration: none; cursor: not-allowed; background-color: transparent; @@ -4003,7 +4079,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { - background-color: #eee; + background-color: #eeeeee; border-color: #337ab7; } .nav .nav-divider { @@ -4029,12 +4105,12 @@ select[multiple].input-group-sm > .input-group-btn > .btn { border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; + border-color: #eeeeee #eeeeee #ddd; } .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { - color: #555; + color: #555555; cursor: default; background-color: #fff; border: 1px solid #ddd; @@ -4183,10 +4259,10 @@ select[multiple].input-group-sm > .input-group-btn > .btn { padding-right: 15px; padding-left: 15px; overflow-x: visible; - -webkit-overflow-scrolling: touch; border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; } .navbar-collapse.in { overflow-y: auto; @@ -4196,7 +4272,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { width: auto; border-top: 0; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } .navbar-collapse.collapse { display: block !important; @@ -4214,6 +4290,13 @@ select[multiple].input-group-sm > .input-group-btn > .btn { padding-left: 0; } } +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 340px; @@ -4224,6 +4307,21 @@ select[multiple].input-group-sm > .input-group-btn > .btn { max-height: 200px; } } +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, @@ -4249,28 +4347,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { border-radius: 0; } } -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} .navbar-brand { float: left; height: 50px; @@ -4295,8 +4371,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn { position: relative; float: right; padding: 9px 10px; - margin-top: 8px; margin-right: 15px; + margin-top: 8px; margin-bottom: 8px; background-color: transparent; background-image: none; @@ -4337,7 +4413,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { background-color: transparent; border: 0; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { @@ -4366,14 +4442,14 @@ select[multiple].input-group-sm > .input-group-btn > .btn { } .navbar-form { padding: 10px 15px; - margin-top: 8px; margin-right: -15px; - margin-bottom: 8px; margin-left: -15px; border-top: 1px solid transparent; border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; } @media (min-width: 768px) { .navbar-form .form-group { @@ -4442,7 +4518,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { margin-left: 0; border: 0; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } } .navbar-nav > li > .dropdown-menu { @@ -4527,20 +4603,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { color: #ccc; background-color: transparent; } -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { @@ -4569,6 +4631,20 @@ select[multiple].input-group-sm > .input-group-btn > .btn { background-color: transparent; } } +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} .navbar-default .navbar-link { color: #777; } @@ -4623,20 +4699,6 @@ fieldset[disabled] .navbar-default .btn-link:focus { color: #444; background-color: transparent; } -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { @@ -4671,6 +4733,20 @@ fieldset[disabled] .navbar-default .btn-link:focus { background-color: transparent; } } +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} .navbar-inverse .navbar-link { color: #9d9d9d; } @@ -4706,7 +4782,7 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { content: "/\00a0"; } .breadcrumb > .active { - color: #777; + color: #777777; } .pagination { display: inline-block; @@ -4729,6 +4805,15 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { background-color: #fff; border: 1px solid #ddd; } +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eeeeee; + border-color: #ddd; +} .pagination > li:first-child > a, .pagination > li:first-child > span { margin-left: 0; @@ -4740,15 +4825,6 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - background-color: #eee; - border-color: #ddd; -} .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, @@ -4767,7 +4843,7 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { - color: #777; + color: #777777; cursor: not-allowed; background-color: #fff; border-color: #ddd; @@ -4824,7 +4900,7 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { .pager li > a:hover, .pager li > a:focus { text-decoration: none; - background-color: #eee; + background-color: #eeeeee; } .pager .next > a, .pager .next > span { @@ -4838,21 +4914,21 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { - color: #777; + color: #777777; cursor: not-allowed; background-color: #fff; } .label { display: inline; - padding: .2em .6em .3em; + padding: 0.2em 0.6em 0.3em; font-size: 75%; - font-weight: bold; + font-weight: 700; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; - border-radius: .25em; + border-radius: 0.25em; } a.label:hover, a.label:focus { @@ -4868,7 +4944,7 @@ a.label:focus { top: -1px; } .label-default { - background-color: #777; + background-color: #777777; } .label-default[href]:hover, .label-default[href]:focus { @@ -4920,7 +4996,7 @@ a.label:focus { text-align: center; white-space: nowrap; vertical-align: middle; - background-color: #777; + background-color: #777777; border-radius: 10px; } .badge:empty { @@ -4960,7 +5036,7 @@ a.badge:focus { padding-bottom: 30px; margin-bottom: 30px; color: inherit; - background-color: #eee; + background-color: #eeeeee; } .jumbotron h1, .jumbotron .h1 { @@ -5006,9 +5082,9 @@ a.badge:focus { background-color: #fff; border: 1px solid #ddd; border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; } .thumbnail > img, .thumbnail a > img { @@ -5022,7 +5098,7 @@ a.thumbnail.active { } .thumbnail .caption { padding: 9px; - color: #333; + color: #333333; } .alert { padding: 15px; @@ -5129,69 +5205,69 @@ a.thumbnail.active { overflow: hidden; background-color: #f5f5f5; border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .progress-bar { float: left; - width: 0; + width: 0%; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; } .progress-striped .progress-bar, .progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; - background-size: 40px 40px; + background-size: 40px 40px; } .progress.active .progress-bar, .progress-bar.active { -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; } .progress-bar-success { background-color: #5cb85c; } .progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-info { background-color: #5bc0de; } .progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-warning { background-color: #f0ad4e; } .progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-danger { background-color: #d9534f; } .progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .media { margin-top: 15px; @@ -5262,32 +5338,12 @@ a.thumbnail.active { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} .list-group-item.disabled, .list-group-item.disabled:hover, .list-group-item.disabled:focus { - color: #777; + color: #777777; cursor: not-allowed; - background-color: #eee; + background-color: #eeeeee; } .list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading, @@ -5297,7 +5353,7 @@ button.list-group-item { .list-group-item.disabled .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text { - color: #777; + color: #777777; } .list-group-item.active, .list-group-item.active:hover, @@ -5323,6 +5379,26 @@ button.list-group-item { .list-group-item.active:focus .list-group-item-text { color: #c7ddef; } +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} .list-group-item-success { color: #3c763d; background-color: #dff0d8; @@ -5452,8 +5528,8 @@ button.list-group-item-danger.active:focus { background-color: #fff; border: 1px solid transparent; border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } .panel-body { padding: 15px; @@ -5686,7 +5762,7 @@ button.list-group-item-danger.active:focus { border-color: #ddd; } .panel-default > .panel-heading { - color: #333; + color: #333333; background-color: #f5f5f5; border-color: #ddd; } @@ -5695,7 +5771,7 @@ button.list-group-item-danger.active:focus { } .panel-default > .panel-heading .badge { color: #f5f5f5; - background-color: #333; + background-color: #333333; } .panel-default > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #ddd; @@ -5823,12 +5899,12 @@ button.list-group-item-danger.active:focus { background-color: #f5f5f5; border: 1px solid #e3e3e3; border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; - border-color: rgba(0, 0, 0, .15); + border-color: rgba(0, 0, 0, 0.15); } .well-lg { padding: 24px; @@ -5846,7 +5922,7 @@ button.list-group-item-danger.active:focus { color: #000; text-shadow: 0 1px 0 #fff; filter: alpha(opacity=20); - opacity: .2; + opacity: 0.2; } .close:hover, .close:focus { @@ -5854,14 +5930,16 @@ button.list-group-item-danger.active:focus { text-decoration: none; cursor: pointer; filter: alpha(opacity=50); - opacity: .5; + opacity: 0.5; } button.close { - -webkit-appearance: none; padding: 0; cursor: pointer; background: transparent; border: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } .modal-open { overflow: hidden; @@ -5879,19 +5957,21 @@ button.close { outline: 0; } .modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out; } .modal.in .modal-dialog { -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); } .modal-open .modal { overflow-x: hidden; @@ -5905,14 +5985,13 @@ button.close { .modal-content { position: relative; background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; + background-clip: padding-box; border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); + border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); } .modal-backdrop { position: fixed; @@ -5929,7 +6008,7 @@ button.close { } .modal-backdrop.in { filter: alpha(opacity=50); - opacity: .5; + opacity: 0.5; } .modal-header { padding: 15px; @@ -5974,8 +6053,8 @@ button.close { margin: 30px auto; } .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); } .modal-sm { width: 300px; @@ -5991,10 +6070,10 @@ button.close { z-index: 1070; display: block; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; font-style: normal; - font-weight: normal; + font-weight: 400; line-height: 1.42857143; + line-break: auto; text-align: left; text-align: start; text-decoration: none; @@ -6005,14 +6084,13 @@ button.close { word-spacing: normal; word-wrap: normal; white-space: normal; + font-size: 12px; filter: alpha(opacity=0); opacity: 0; - - line-break: auto; } .tooltip.in { filter: alpha(opacity=90); - opacity: .9; + opacity: 0.9; } .tooltip.top { padding: 5px 0; @@ -6030,21 +6108,6 @@ button.close { padding: 0 5px; margin-left: -3px; } -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; @@ -6101,6 +6164,21 @@ button.close { border-width: 0 5px 5px; border-bottom-color: #000; } +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} .popover { position: absolute; top: 0; @@ -6110,10 +6188,10 @@ button.close { max-width: 276px; padding: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; font-style: normal; - font-weight: normal; + font-weight: 400; line-height: 1.42857143; + line-break: auto; text-align: left; text-align: start; text-decoration: none; @@ -6124,16 +6202,14 @@ button.close { word-spacing: normal; word-wrap: normal; white-space: normal; + font-size: 14px; background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; + background-clip: padding-box; border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); + border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - - line-break: auto; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); } .popover.top { margin-top: -10px; @@ -6147,16 +6223,8 @@ button.close { .popover.left { margin-left: -10px; } -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; +.popover > .arrow { + border-width: 11px; } .popover > .arrow, .popover > .arrow:after { @@ -6167,9 +6235,6 @@ button.close { border-color: transparent; border-style: solid; } -.popover > .arrow { - border-width: 11px; -} .popover > .arrow:after { content: ""; border-width: 10px; @@ -6178,8 +6243,8 @@ button.close { bottom: -11px; left: 50%; margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); border-bottom-width: 0; } .popover.top > .arrow:after { @@ -6193,8 +6258,8 @@ button.close { top: 50%; left: -11px; margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); border-left-width: 0; } .popover.right > .arrow:after { @@ -6209,8 +6274,8 @@ button.close { left: 50%; margin-left: -11px; border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); } .popover.bottom > .arrow:after { top: 1px; @@ -6224,8 +6289,8 @@ button.close { right: -11px; margin-top: -11px; border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); } .popover.left > .arrow:after { right: 1px; @@ -6234,6 +6299,17 @@ button.close { border-right-width: 0; border-left-color: #fff; } +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} .carousel { position: relative; } @@ -6245,9 +6321,9 @@ button.close { .carousel-inner > .item { position: relative; display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; } .carousel-inner > .item > img, .carousel-inner > .item > a > img { @@ -6255,33 +6331,34 @@ button.close { } @media all and (transform-3d), (-webkit-transform-3d) { .carousel-inner > .item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out; -webkit-backface-visibility: hidden; - backface-visibility: hidden; + backface-visibility: hidden; -webkit-perspective: 1000px; - perspective: 1000px; + perspective: 1000px; } .carousel-inner > .item.next, .carousel-inner > .item.active.right { - left: 0; -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; } .carousel-inner > .item.prev, .carousel-inner > .item.active.left { - left: 0; -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; } .carousel-inner > .item.next.left, .carousel-inner > .item.prev.right, .carousel-inner > .item.active { - left: 0; -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; } } .carousel-inner > .active, @@ -6323,26 +6400,26 @@ button.close { font-size: 20px; color: #fff; text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); background-color: rgba(0, 0, 0, 0); filter: alpha(opacity=50); - opacity: .5; + opacity: 0.5; } .carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); background-repeat: repeat-x; } .carousel-control.right { right: 0; left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); background-repeat: repeat-x; } @@ -6350,9 +6427,9 @@ button.close { .carousel-control:focus { color: #fff; text-decoration: none; - filter: alpha(opacity=90); outline: 0; - opacity: .9; + filter: alpha(opacity=90); + opacity: 0.9; } .carousel-control .icon-prev, .carousel-control .icon-next, @@ -6382,10 +6459,10 @@ button.close { line-height: 1; } .carousel-control .icon-prev:before { - content: '\2039'; + content: "\2039"; } .carousel-control .icon-next:before { - content: '\203a'; + content: "\203a"; } .carousel-indicators { position: absolute; @@ -6426,7 +6503,7 @@ button.close { padding-bottom: 20px; color: #fff; text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); } .carousel-caption .btn { text-shadow: none; @@ -6754,4 +6831,4 @@ button.close { display: none !important; } } -/*# sourceMappingURL=bootstrap.css.map */ +/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file diff --git a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css.map b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css.map index f010c82d11..719175db33 100644 --- a/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css.map +++ b/docs/generated/reference/output/node_modules/bootstrap/dist/css/bootstrap.css.map @@ -1 +1 @@ -{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,iBAAA;CH8O9C;AG7OmC;EAAW,iBAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;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ukDH;AexkDC;EACE,oBAAA;Cf0kDH;Ae3kDC;EACE,WAAA;Cf6kDH;Ae9kDC;EACE,oBAAA;CfglDH;AejlDC;EACE,mBAAA;CfmlDH;Ae/kDC;EACE,YAAA;CfilDH;AejmDC;EACE,WAAA;CfmmDH;AepmDC;EACE,mBAAA;CfsmDH;AevmDC;EACE,mBAAA;CfymDH;Ae1mDC;EACE,UAAA;Cf4mDH;Ae7mDC;EACE,mBAAA;Cf+mDH;AehnDC;EACE,mBAAA;CfknDH;AennDC;EACE,UAAA;CfqnDH;AetnDC;EACE,mBAAA;CfwnDH;AeznDC;EACE,mBAAA;Cf2nDH;Ae5nDC;EACE,UAAA;Cf8nDH;Ae/nDC;EACE,mBAAA;CfioDH;AeloDC;EACE,kBAAA;CfooDH;AehoDC;EACE,WAAA;CfkoDH;AepnDC;EACE,kBAAA;CfsnDH;AevnDC;EACE,0BAAA;CfynDH;Ae1nDC;EACE,0BAAA;Cf4nDH;Ae7nDC;EACE,iBAAA;Cf+nDH;AehoDC;EACE,0BAAA;CfkoDH;AenoDC;EACE,0BAAA;CfqoDH;AetoDC;EACE,iBAAA;CfwoDH;AezoDC;EACE,0BAAA;Cf2oDH;Ae5oDC;EACE,0BAAA;Cf8oDH;Ae/oDC;EACE,iBAAA;CfipDH;AelpDC;EACE,0BAAA;CfopDH;AerpDC;EACE,yBAAA;CfupDH;AexpDC;EACE,gBAAA;Cf0pDH;Aa1pDD;EElCI;IACE,YAAA;Gf+rDH;EexrDD;IACE,YAAA;Gf0rDD;Ee3rDD;IACE,oBAAA;Gf6rDD;Ee9rDD;IACE,oBAAA;GfgsDD;EejsDD;IACE,WAAA;GfmsDD;EepsDD;IACE,oBAAA;GfssDD;EevsDD;IACE,oBAAA;GfysDD;Ee1sDD;IACE,WAAA;Gf4sDD;Ee7sDD;IACE,oBAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,WAAA;GfqtDD;EettDD;IACE,oBAAA;GfwtDD;EeztDD;IACE,mBAAA;Gf2tDD;Ee7sDD;IACE,YAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,oBAAA;GfqtDD;EettDD;IACE,WAAA;GfwtDD;EeztDD;IACE,oBAAA;Gf2tDD;Ee5tDD;IACE,oBAAA;Gf8tDD;Ee/tDD;IACE,WAAA;GfiuDD;EeluDD;IACE,oBAAA;GfouDD;EeruDD;IACE,oBAAA;GfuuDD;EexuDD;IACE,WAAA;Gf0uDD;Ee3uDD;IACE,oBAAA;Gf6uDD;Ee9uDD;IACE,mBAAA;GfgvDD;Ee5uDD;IACE,YAAA;Gf8uDD;Ee9vDD;IACE,WAAA;GfgwDD;EejwDD;IACE,mBAAA;GfmwDD;EepwDD;IACE,mBAAA;GfswDD;EevwDD;IACE,UAAA;GfywDD;Ee1wDD;IACE,mBAAA;Gf4wDD;Ee7wDD;IACE,mBAAA;Gf+wDD;EehxDD;IACE,UAAA;GfkxDD;EenxDD;IACE,mBAAA;GfqxDD;EetxDD;IACE,mBAAA;GfwxDD;EezxDD;IACE,UAAA;Gf2xDD;Ee5xDD;IACE,mBAAA;Gf8xDD;Ee/xDD;IACE,kBAAA;GfiyDD;Ee7xDD;IACE,WAAA;Gf+xDD;EejxDD;IACE,kBAAA;GfmxDD;EepxDD;IACE,0BAAA;GfsxDD;EevxDD;IACE,0BAAA;GfyxDD;Ee1xDD;IACE,iBAAA;Gf4xDD;Ee7xDD;IACE,0BAAA;Gf+xDD;EehyDD;IACE,0BAAA;GfkyDD;EenyDD;IACE,iBAAA;GfqyDD;EetyDD;IACE,0BAAA;GfwyDD;EezyDD;IACE,0BAAA;Gf2yDD;Ee5yDD;IACE,iBAAA;Gf8yDD;Ee/yDD;IACE,0BAAA;GfizDD;EelzDD;IACE,yBAAA;GfozDD;EerzDD;IACE,gBAAA;GfuzDD;CACF;Aa/yDD;EE3CI;IACE,YAAA;Gf61DH;Eet1DD;IACE,YAAA;Gfw1DD;Eez1DD;IACE,oBAAA;Gf21DD;Ee51DD;IACE,oBAAA;Gf81DD;Ee/1DD;IACE,WAAA;Gfi2DD;Eel2DD;IACE,oBAAA;Gfo2DD;Eer2DD;IACE,oBAAA;Gfu2DD;Eex2DD;IACE,WAAA;Gf02DD;Ee32DD;IACE,oBAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,WAAA;Gfm3DD;Eep3DD;IACE,oBAAA;Gfs3DD;Eev3DD;IACE,mBAAA;Gfy3DD;Ee32DD;IACE,YAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,oBAAA;Gfm3DD;Eep3DD;IACE,WAAA;Gfs3DD;Eev3DD;IACE,oBAAA;Gfy3DD;Ee13DD;IACE,oBAAA;Gf43DD;Ee73DD;IACE,WAAA;Gf+3DD;Eeh4DD;IACE,oBAAA;Gfk4DD;Een4DD;IACE,oBAAA;Gfq4DD;Eet4DD;IACE,WAAA;Gfw4DD;Eez4DD;IACE,oBAAA;Gf24DD;Ee54DD;IACE,mBAAA;Gf84DD;Ee14DD;IACE,YAAA;Gf44DD;Ee55DD;IACE,WAAA;Gf85DD;Ee/5DD;IACE,mBAAA;Gfi6DD;Eel6DD;IACE,mBAAA;Gfo6DD;Eer6DD;IACE,UAAA;Gfu6DD;Eex6DD;IACE,mBAAA;Gf06DD;Ee36DD;IACE,mBAAA;Gf66DD;Ee96DD;IACE,UAAA;Gfg7DD;Eej7DD;IACE,mBAAA;Gfm7DD;Eep7DD;IACE,mBAAA;Gfs7DD;Eev7DD;IACE,UAAA;Gfy7DD;Ee17DD;IACE,mBAAA;Gf47DD;Ee77DD;IACE,kBAAA;Gf+7DD;Ee37DD;IACE,WAAA;Gf67DD;Ee/6DD;IACE,kBAAA;Gfi7DD;Eel7DD;IACE,0BAAA;Gfo7DD;Eer7DD;IACE,0BAAA;Gfu7DD;Eex7DD;IACE,iBAAA;Gf07DD;Ee37DD;IACE,0BAAA;Gf67DD;Ee97DD;IACE,0BAAA;Gfg8DD;Eej8DD;IACE,iBAAA;Gfm8DD;Eep8DD;IACE,0BAAA;Gfs8DD;Eev8DD;IACE,0BAAA;Gfy8DD;Ee18DD;IACE,iBAAA;Gf48DD;Ee78DD;IACE,0BAAA;Gf+8DD;Eeh9DD;IACE,yBAAA;Gfk9DD;Een9DD;IACE,gBAAA;Gfq9DD;CACF;Aa18DD;EE9CI;IACE,YAAA;Gf2/DH;Eep/DD;IACE,YAAA;Gfs/DD;Eev/DD;IACE,oBAAA;Gfy/DD;Ee1/DD;IACE,oBAAA;Gf4/DD;Ee7/DD;IACE,WAAA;Gf+/DD;EehgED;IACE,oBAAA;GfkgED;EengED;IACE,oBAAA;GfqgED;EetgED;IACE,WAAA;GfwgED;EezgED;IACE,oBAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,WAAA;GfihED;EelhED;IACE,oBAAA;GfohED;EerhED;IACE,mBAAA;GfuhED;EezgED;IACE,YAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,oBAAA;GfihED;EelhED;IACE,WAAA;GfohED;EerhED;IACE,oBAAA;GfuhED;EexhED;IACE,oBAAA;Gf0hED;Ee3hED;IACE,WAAA;Gf6hED;Ee9hED;IACE,oBAAA;GfgiED;EejiED;IACE,oBAAA;GfmiED;EepiED;IACE,WAAA;GfsiED;EeviED;IACE,oBAAA;GfyiED;Ee1iED;IACE,mBAAA;Gf4iED;EexiED;IACE,YAAA;Gf0iED;Ee1jED;IACE,WAAA;Gf4jED;Ee7jED;IACE,mBAAA;Gf+jED;EehkED;IACE,mBAAA;GfkkED;EenkED;IACE,UAAA;GfqkED;EetkED;IACE,mBAAA;GfwkED;EezkED;IACE,mBAAA;Gf2kED;Ee5kED;IACE,UAAA;Gf8kED;Ee/kED;IACE,mBAAA;GfilED;EellED;IACE,mBAAA;GfolED;EerlED;IACE,UAAA;GfulED;EexlED;IACE,mBAAA;Gf0lED;Ee3lED;IACE,kBAAA;Gf6lED;EezlED;IACE,WAAA;Gf2lED;Ee7kED;IACE,kBAAA;Gf+kED;EehlED;IACE,0BAAA;GfklED;EenlED;IACE,0BAAA;GfqlED;EetlED;IACE,iBAAA;GfwlED;EezlED;IACE,0BAAA;Gf2lED;Ee5lED;IACE,0BAAA;Gf8lED;Ee/lED;IACE,iBAAA;GfimED;EelmED;IACE,0BAAA;GfomED;EermED;IACE,0BAAA;GfumED;EexmED;IACE,iBAAA;Gf0mED;Ee3mED;IACE,0BAAA;Gf6mED;Ee9mED;IACE,yBAAA;GfgnED;EejnED;IACE,gBAAA;GfmnED;CACF;AgBvrED;EACE,8BAAA;ChByrED;AgBvrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChByrED;AgBvrED;EACE,iBAAA;ChByrED;AgBnrED;EACE,YAAA;EACA,gBA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","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on