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

package tests_test

import (
	"time"

	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	k8sv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
	"kubevirt.io/kubevirt/tests"
	cd "kubevirt.io/kubevirt/tests/containerdisk"
)

var _ = Describe("[rfe_id:127][posneg:negative][crit:medium][vendor:cnv-qe@redhat.com][level:component]Console", func() {

	var virtClient kubecli.KubevirtClient

	BeforeEach(func() {
		var err error

		virtClient, err = kubecli.GetKubevirtClient()
		tests.PanicOnError(err)

		tests.BeforeTestCleanup()
	})

	RunVMIAndWaitForStart := func(vmi *v1.VirtualMachineInstance) {
		By("Creating a new VirtualMachineInstance")
		Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

		By("Waiting until it starts")
		tests.WaitForSuccessfulVMIStart(vmi)
	}

	ExpectConsoleOutput := func(vmi *v1.VirtualMachineInstance, expected string) {
		By("Expecting the VirtualMachineInstance console")
		expecter, _, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
		Expect(err).ToNot(HaveOccurred())
		defer func() {
			By("Closing the opened expecter")
			expecter.Close()
		}()

		By("Checking that the console output equals to expected one")
		_, err = expecter.ExpectBatch([]expect.Batcher{
			&expect.BSnd{S: "\n"},
			&expect.BExp{R: expected},
		}, 120*time.Second)
		Expect(err).ToNot(HaveOccurred())
	}

	OpenConsole := func(vmi *v1.VirtualMachineInstance) (expect.Expecter, <-chan error) {
		By("Expecting the VirtualMachineInstance console")
		expecter, errChan, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
		Expect(err).ToNot(HaveOccurred())
		return expecter, errChan
	}

	deleteDataVolume := func(dv *cdiv1.DataVolume) {
		if dv != nil {
			By("Deleting the DataVolume")
			ExpectWithOffset(1, virtClient.CdiClient().CdiV1alpha1().DataVolumes(dv.Namespace).Delete(dv.Name, &metav1.DeleteOptions{})).To(Succeed())
		}
	}

	Describe("[rfe_id:127][posneg:negative][crit:medium][vendor:cnv-qe@redhat.com][level:component]A new VirtualMachineInstance", func() {
		Context("with a serial console", func() {
			Context("with a cirros image", func() {

				It("[test_id:1588]should return that we are running cirros", func() {
					vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(
						vmi,
						"login as 'cirros' user",
					)
				})
			})

			Context("with a fedora image", func() {
				It("[test_id:1589]should return that we are running fedora", func() {
					vmi := tests.NewRandomVMIWithEphemeralDiskHighMemory(cd.ContainerDiskFor(cd.ContainerDiskFedora))
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(
						vmi,
						"Welcome to",
					)
				})
			})

			Context("with an alpine image", func() {
				type vmiBuilder func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume)

				newVirtualMachineInstanceWithAlpineContainerDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine)), nil
				}

				newVirtualMachineInstanceWithAlpineOCSFileDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVirtualMachineInstanceWithOCSDisk(tests.GetUrl(tests.AlpineHttpUrl), tests.NamespaceTestDefault, k8sv1.ReadWriteOnce, k8sv1.PersistentVolumeFilesystem)
				}

				newVirtualMachineInstanceWithAlpineOCSBlockDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVirtualMachineInstanceWithOCSDisk(tests.GetUrl(tests.AlpineHttpUrl), tests.NamespaceTestDefault, k8sv1.ReadWriteOnce, k8sv1.PersistentVolumeBlock)
				}

				table.DescribeTable("[test_id:2706] should return that we are running alpine", func(createVMI vmiBuilder) {
					vmi, dv := createVMI()
					defer deleteDataVolume(dv)
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(vmi, "login")
				},
					table.Entry("with ContainerDisk", newVirtualMachineInstanceWithAlpineContainerDisk),
					table.Entry("with OCS Filesystem Disk", newVirtualMachineInstanceWithAlpineOCSFileDisk),
					table.Entry("with OCS Block Disk", newVirtualMachineInstanceWithAlpineOCSBlockDisk),
				)
			})

			It("[test_id:1590]should be able to reconnect to console multiple times", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))

				RunVMIAndWaitForStart(vmi)

				for i := 0; i < 5; i++ {
					ExpectConsoleOutput(vmi, "login")
				}
			})

			It("[test_id:1591]should close console connection when new console connection is opened", func(done Done) {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))

				RunVMIAndWaitForStart(vmi)

				By("opening 1st console connection")
				expecter, errChan := OpenConsole(vmi)
				defer expecter.Close()

				By("expecting error on 1st console connection")
				go func() {
					defer GinkgoRecover()
					select {
					case receivedErr := <-errChan:
						Expect(receivedErr.Error()).To(ContainSubstring("close"))
						close(done)
					case <-time.After(60 * time.Second):
						Fail("timed out waiting for closed 1st connection")
					}
				}()

				By("opening 2nd console connection")
				ExpectConsoleOutput(vmi, "login")
			}, 220)

			It("[test_id:1592]should wait until the virtual machine is in running state and return a stream interface", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				By("Creating a new VirtualMachineInstance")
				_, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
				Expect(err).ToNot(HaveOccurred())

				_, err = virtClient.VirtualMachineInstance(vmi.Namespace).SerialConsole(vmi.Name, &kubecli.SerialConsoleOptions{ConnectionTimeout: 30 * time.Second})
				Expect(err).ToNot(HaveOccurred())
			})

			It("[test_id:1593]should fail waiting for the virtual machine instance to be running", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				vmi.Spec.Affinity = &k8sv1.Affinity{
					NodeAffinity: &k8sv1.NodeAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: &k8sv1.NodeSelector{
							NodeSelectorTerms: []k8sv1.NodeSelectorTerm{
								{
									MatchExpressions: []k8sv1.NodeSelectorRequirement{
										{Key: "kubernetes.io/hostname", Operator: k8sv1.NodeSelectorOpIn, Values: []string{"notexist"}},
									},
								},
							},
						},
					},
				}

				By("Creating a new VirtualMachineInstance")
				Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

				_, err := virtClient.VirtualMachineInstance(vmi.Namespace).SerialConsole(vmi.Name, &kubecli.SerialConsoleOptions{ConnectionTimeout: 30 * time.Second})
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("Timeout trying to connect to the virtual machine instance"))
			})

			It("[test_id:1594]should fail waiting for the expecter", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				vmi.Spec.Affinity = &k8sv1.Affinity{
					NodeAffinity: &k8sv1.NodeAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: &k8sv1.NodeSelector{
							NodeSelectorTerms: []k8sv1.NodeSelectorTerm{
								{
									MatchExpressions: []k8sv1.NodeSelectorRequirement{
										{Key: "kubernetes.io/hostname", Operator: k8sv1.NodeSelectorOpIn, Values: []string{"notexist"}},
									},
								},
							},
						},
					},
				}

				By("Creating a new VirtualMachineInstance")
				Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

				By("Expecting the VirtualMachineInstance console")
				_, _, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("Timeout trying to connect to the virtual machine instance"))
			})
		})

		Context("without a serial console", func() {
			var vmi *v1.VirtualMachineInstance

			BeforeEach(func() {
				vmi = tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				f := false
				vmi.Spec.Domain.Devices.AutoattachSerialConsole = &f
			})

			It("[test_id:4116]should create the vmi without any issue", func() {
				tests.RunVMIAndExpectLaunch(vmi, 30)
			})

			It("[test_id:4117]should not have the  serial console in xml", func() {
				tests.RunVMIAndExpectLaunch(vmi, 30)

				runningVMISpec, err := tests.GetRunningVMIDomainSpec(vmi)
				Expect(err).ToNot(HaveOccurred(), "should get vmi spec without problem")

				Expect(len(runningVMISpec.Devices.Serials)).To(Equal(0), "should not have any serial consoles present")
				Expect(len(runningVMISpec.Devices.Consoles)).To(Equal(0), "should not have any virtio console for serial consoles")
			})

			It("[test_id:4118]should not connect to the serial console", func() {
				vmi = tests.RunVMIAndExpectLaunch(vmi, 30)

				_, err := virtClient.VirtualMachineInstance(vmi.ObjectMeta.Namespace).SerialConsole(vmi.ObjectMeta.Name, &kubecli.SerialConsoleOptions{})

				Expect(err.Error()).To(Equal("No serial consoles are present."), "serial console should not connect if there are no serial consoles present")
			})
		})
	})
})
<commit_msg>tests, console_test: use safe expect batcher<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package tests_test

import (
	"time"

	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	k8sv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
	"kubevirt.io/kubevirt/tests"
	cd "kubevirt.io/kubevirt/tests/containerdisk"
)

var _ = Describe("[rfe_id:127][posneg:negative][crit:medium][vendor:cnv-qe@redhat.com][level:component]Console", func() {

	var virtClient kubecli.KubevirtClient

	BeforeEach(func() {
		var err error

		virtClient, err = kubecli.GetKubevirtClient()
		tests.PanicOnError(err)

		tests.BeforeTestCleanup()
	})

	RunVMIAndWaitForStart := func(vmi *v1.VirtualMachineInstance) {
		By("Creating a new VirtualMachineInstance")
		Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

		By("Waiting until it starts")
		tests.WaitForSuccessfulVMIStart(vmi)
	}

	ExpectConsoleOutput := func(vmi *v1.VirtualMachineInstance, expected string) {
		By("Expecting the VirtualMachineInstance console")
		expecter, _, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
		Expect(err).ToNot(HaveOccurred())
		defer func() {
			By("Closing the opened expecter")
			expecter.Close()
		}()

		By("Checking that the console output equals to expected one")
		_, err = tests.ExpectBatchWithValidatedSend(expecter, []expect.Batcher{
			&expect.BSnd{S: "\n"},
			&expect.BExp{R: expected},
		}, 120*time.Second)
		Expect(err).ToNot(HaveOccurred())
	}

	OpenConsole := func(vmi *v1.VirtualMachineInstance) (expect.Expecter, <-chan error) {
		By("Expecting the VirtualMachineInstance console")
		expecter, errChan, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
		Expect(err).ToNot(HaveOccurred())
		return expecter, errChan
	}

	deleteDataVolume := func(dv *cdiv1.DataVolume) {
		if dv != nil {
			By("Deleting the DataVolume")
			ExpectWithOffset(1, virtClient.CdiClient().CdiV1alpha1().DataVolumes(dv.Namespace).Delete(dv.Name, &metav1.DeleteOptions{})).To(Succeed())
		}
	}

	Describe("[rfe_id:127][posneg:negative][crit:medium][vendor:cnv-qe@redhat.com][level:component]A new VirtualMachineInstance", func() {
		Context("with a serial console", func() {
			Context("with a cirros image", func() {

				It("[test_id:1588]should return that we are running cirros", func() {
					vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(
						vmi,
						"login as 'cirros' user",
					)
				})
			})

			Context("with a fedora image", func() {
				It("[test_id:1589]should return that we are running fedora", func() {
					vmi := tests.NewRandomVMIWithEphemeralDiskHighMemory(cd.ContainerDiskFor(cd.ContainerDiskFedora))
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(
						vmi,
						"Welcome to",
					)
				})
			})

			Context("with an alpine image", func() {
				type vmiBuilder func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume)

				newVirtualMachineInstanceWithAlpineContainerDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine)), nil
				}

				newVirtualMachineInstanceWithAlpineOCSFileDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVirtualMachineInstanceWithOCSDisk(tests.GetUrl(tests.AlpineHttpUrl), tests.NamespaceTestDefault, k8sv1.ReadWriteOnce, k8sv1.PersistentVolumeFilesystem)
				}

				newVirtualMachineInstanceWithAlpineOCSBlockDisk := func() (*v1.VirtualMachineInstance, *cdiv1.DataVolume) {
					return tests.NewRandomVirtualMachineInstanceWithOCSDisk(tests.GetUrl(tests.AlpineHttpUrl), tests.NamespaceTestDefault, k8sv1.ReadWriteOnce, k8sv1.PersistentVolumeBlock)
				}

				table.DescribeTable("[test_id:2706] should return that we are running alpine", func(createVMI vmiBuilder) {
					vmi, dv := createVMI()
					defer deleteDataVolume(dv)
					RunVMIAndWaitForStart(vmi)
					ExpectConsoleOutput(vmi, "login")
				},
					table.Entry("with ContainerDisk", newVirtualMachineInstanceWithAlpineContainerDisk),
					table.Entry("with OCS Filesystem Disk", newVirtualMachineInstanceWithAlpineOCSFileDisk),
					table.Entry("with OCS Block Disk", newVirtualMachineInstanceWithAlpineOCSBlockDisk),
				)
			})

			It("[test_id:1590]should be able to reconnect to console multiple times", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))

				RunVMIAndWaitForStart(vmi)

				for i := 0; i < 5; i++ {
					ExpectConsoleOutput(vmi, "login")
				}
			})

			It("[test_id:1591]should close console connection when new console connection is opened", func(done Done) {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))

				RunVMIAndWaitForStart(vmi)

				By("opening 1st console connection")
				expecter, errChan := OpenConsole(vmi)
				defer expecter.Close()

				By("expecting error on 1st console connection")
				go func() {
					defer GinkgoRecover()
					select {
					case receivedErr := <-errChan:
						Expect(receivedErr.Error()).To(ContainSubstring("close"))
						close(done)
					case <-time.After(60 * time.Second):
						Fail("timed out waiting for closed 1st connection")
					}
				}()

				By("opening 2nd console connection")
				ExpectConsoleOutput(vmi, "login")
			}, 220)

			It("[test_id:1592]should wait until the virtual machine is in running state and return a stream interface", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				By("Creating a new VirtualMachineInstance")
				_, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
				Expect(err).ToNot(HaveOccurred())

				_, err = virtClient.VirtualMachineInstance(vmi.Namespace).SerialConsole(vmi.Name, &kubecli.SerialConsoleOptions{ConnectionTimeout: 30 * time.Second})
				Expect(err).ToNot(HaveOccurred())
			})

			It("[test_id:1593]should fail waiting for the virtual machine instance to be running", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				vmi.Spec.Affinity = &k8sv1.Affinity{
					NodeAffinity: &k8sv1.NodeAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: &k8sv1.NodeSelector{
							NodeSelectorTerms: []k8sv1.NodeSelectorTerm{
								{
									MatchExpressions: []k8sv1.NodeSelectorRequirement{
										{Key: "kubernetes.io/hostname", Operator: k8sv1.NodeSelectorOpIn, Values: []string{"notexist"}},
									},
								},
							},
						},
					},
				}

				By("Creating a new VirtualMachineInstance")
				Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

				_, err := virtClient.VirtualMachineInstance(vmi.Namespace).SerialConsole(vmi.Name, &kubecli.SerialConsoleOptions{ConnectionTimeout: 30 * time.Second})
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("Timeout trying to connect to the virtual machine instance"))
			})

			It("[test_id:1594]should fail waiting for the expecter", func() {
				vmi := tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				vmi.Spec.Affinity = &k8sv1.Affinity{
					NodeAffinity: &k8sv1.NodeAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: &k8sv1.NodeSelector{
							NodeSelectorTerms: []k8sv1.NodeSelectorTerm{
								{
									MatchExpressions: []k8sv1.NodeSelectorRequirement{
										{Key: "kubernetes.io/hostname", Operator: k8sv1.NodeSelectorOpIn, Values: []string{"notexist"}},
									},
								},
							},
						},
					},
				}

				By("Creating a new VirtualMachineInstance")
				Expect(virtClient.RestClient().Post().Resource("virtualmachineinstances").Namespace(tests.NamespaceTestDefault).Body(vmi).Do().Error()).To(Succeed())

				By("Expecting the VirtualMachineInstance console")
				_, _, err := tests.NewConsoleExpecter(virtClient, vmi, 30*time.Second)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("Timeout trying to connect to the virtual machine instance"))
			})
		})

		Context("without a serial console", func() {
			var vmi *v1.VirtualMachineInstance

			BeforeEach(func() {
				vmi = tests.NewRandomVMIWithEphemeralDisk(cd.ContainerDiskFor(cd.ContainerDiskAlpine))
				f := false
				vmi.Spec.Domain.Devices.AutoattachSerialConsole = &f
			})

			It("[test_id:4116]should create the vmi without any issue", func() {
				tests.RunVMIAndExpectLaunch(vmi, 30)
			})

			It("[test_id:4117]should not have the  serial console in xml", func() {
				tests.RunVMIAndExpectLaunch(vmi, 30)

				runningVMISpec, err := tests.GetRunningVMIDomainSpec(vmi)
				Expect(err).ToNot(HaveOccurred(), "should get vmi spec without problem")

				Expect(len(runningVMISpec.Devices.Serials)).To(Equal(0), "should not have any serial consoles present")
				Expect(len(runningVMISpec.Devices.Consoles)).To(Equal(0), "should not have any virtio console for serial consoles")
			})

			It("[test_id:4118]should not connect to the serial console", func() {
				vmi = tests.RunVMIAndExpectLaunch(vmi, 30)

				_, err := virtClient.VirtualMachineInstance(vmi.ObjectMeta.Namespace).SerialConsole(vmi.ObjectMeta.Name, &kubecli.SerialConsoleOptions{})

				Expect(err.Error()).To(Equal("No serial consoles are present."), "serial console should not connect if there are no serial consoles present")
			})
		})
	})
})
<|endoftext|>


<commit_before>package formatters

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

const (
	BYTE     = 1.0
	KILOBYTE = 1024 * BYTE
	MEGABYTE = 1024 * KILOBYTE
	GIGABYTE = 1024 * MEGABYTE
	TERABYTE = 1024 * GIGABYTE
)

func ByteSize(bytes uint64) string {
	unit := ""
	value := float32(bytes)

	switch {
	case bytes >= TERABYTE:
		unit = "T"
		value = value / TERABYTE
	case bytes >= GIGABYTE:
		unit = "G"
		value = value / GIGABYTE
	case bytes >= MEGABYTE:
		unit = "M"
		value = value / MEGABYTE
	case bytes >= KILOBYTE:
		unit = "K"
		value = value / KILOBYTE
	case bytes == 0:
		return "0"
	}

	stringValue := fmt.Sprintf("%.1f", value)
	stringValue = strings.TrimSuffix(stringValue, ".0")
	return fmt.Sprintf("%s%s", stringValue, unit)
}

func BytesFromString(s string) (bytes uint64, err error) {
	unit := string(s[len(s)-1])
	stringValue := s[0 : len(s)-1]

	value, err := strconv.ParseUint(stringValue, 10, 0)
	if err != nil {
		return
	}

	switch unit {
	case "T":
		bytes = value * TERABYTE
	case "G":
		bytes = value * GIGABYTE
	case "M":
		bytes = value * MEGABYTE
	case "K":
		bytes = value * KILOBYTE
	}

	if bytes == 0 {
		err = errors.New("Could not parse byte string")
	}

	return
}
<commit_msg>Megabytes from string formatter<commit_after>package formatters

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

const (
	BYTE     = 1.0
	KILOBYTE = 1024 * BYTE
	MEGABYTE = 1024 * KILOBYTE
	GIGABYTE = 1024 * MEGABYTE
	TERABYTE = 1024 * GIGABYTE
)

func ByteSize(bytes uint64) string {
	unit := ""
	value := float32(bytes)

	switch {
	case bytes >= TERABYTE:
		unit = "T"
		value = value / TERABYTE
	case bytes >= GIGABYTE:
		unit = "G"
		value = value / GIGABYTE
	case bytes >= MEGABYTE:
		unit = "M"
		value = value / MEGABYTE
	case bytes >= KILOBYTE:
		unit = "K"
		value = value / KILOBYTE
	case bytes == 0:
		return "0"
	}

	stringValue := fmt.Sprintf("%.1f", value)
	stringValue = strings.TrimSuffix(stringValue, ".0")
	return fmt.Sprintf("%s%s", stringValue, unit)
}

func BytesFromString(s string) (bytes uint64, err error) {
	unit := string(s[len(s)-1])
	stringValue := s[0 : len(s)-1]

	value, err := strconv.ParseUint(stringValue, 10, 0)
	if err != nil {
		return
	}

	switch unit {
	case "T":
		bytes = value * TERABYTE
	case "G":
		bytes = value * GIGABYTE
	case "M":
		bytes = value * MEGABYTE
	case "K":
		bytes = value * KILOBYTE
	}

	if bytes == 0 {
		err = errors.New("Could not parse byte string")
	}

	return
}

func MegabytesFromString(s string) (megabytes uint64, err error) {
	if s == "" {
		return 0, nil
	}

	if  strings.ContainsAny(string(s[len(s)-1]),"0123456789"){
		return strconv.ParseUint(s, 10, 0)
	}

	var bytes uint64

	bytes, err = BytesFromString(s)
	if err != nil {
		return
	}

	megabytes = bytes / MEGABYTE

	return
}
<|endoftext|>


<commit_before>package version

import (
	"fmt"

	"github.com/spf13/cobra"
)

// Command config
var Command = &cobra.Command{
	Use:   "version",
	Short: "Print version of Eclectica",
	Run:   run,
}

// Version number
const Version = "0.0.6"

// Runner
func run(c *cobra.Command, args []string) {
	fmt.Println(Version)
}
<commit_msg>Bump version to 0.0.7<commit_after>package version

import (
	"fmt"

	"github.com/spf13/cobra"
)

// Command config
var Command = &cobra.Command{
	Use:   "version",
	Short: "Print version of Eclectica",
	Run:   run,
}

// Version number
const Version = "0.0.7"

// Runner
func run(c *cobra.Command, args []string) {
	fmt.Println(Version)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc. All rights reserved.

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

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

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

package parser

import (
	"fmt"

	"github.com/google/go-jsonnet/ast"
)

var topLevelContext = "$"

const anonymous = "anonymous"

// TODO(sbarzowski) polish children functions and consider moving to AST
// and exporting

// directChildren are children of AST node that are executed in the same context
// and environment as their parent
//
// They must satisfy the following rules:
// * (no-delayed-evaluation) They are evaluated when their parent is evaluated or never.
// * (no-indirect-evaluation) They cannot be evaluated during evaluation of any non-direct children
// * (same-environment) They must be evaluated in the same environment as their parent
func directChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		return []ast.Node{node.Target}
		// TODO(sbarzowski) tailstrict call arguments (once we have tailstrict)
	case *ast.ApplyBrace:
		return []ast.Node{node.Left, node.Right}
	case *ast.Array:
		return nil
	case *ast.Assert:
		return []ast.Node{node.Cond, node.Message, node.Rest}
	case *ast.Binary:
		return []ast.Node{node.Left, node.Right}
	case *ast.Conditional:
		return []ast.Node{node.Cond, node.BranchTrue, node.BranchFalse}
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return []ast.Node{node.Expr}
	case *ast.Function:
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return []ast.Node{node.Target, node.Index}
	case *ast.Slice:
		return []ast.Node{node.Target, node.BeginIndex, node.EndIndex, node.Step}
	case *ast.Local:
		return []ast.Node{node.Body}
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return objectFieldsDirectChildren(node.Fields)
	case *ast.ArrayComp:
		result := []ast.Node{}
		spec := &node.Spec
		for spec != nil {
			result = append(result, spec.Expr)
			for _, ifspec := range spec.Conditions {
				result = append(result, ifspec.Expr)
			}
			spec = spec.Outer
		}
		return result
	case *ast.ObjectComp:
		result := objectFieldsDirectChildren(node.Fields)
		spec := &node.Spec
		for spec != nil {
			result = append(result, spec.Expr)
			for _, ifspec := range spec.Conditions {
				result = append(result, ifspec.Expr)
			}
			spec = spec.Outer
		}
		return result
	case *ast.Parens:
		return []ast.Node{node.Inner}
	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return []ast.Node{node.Index}
	case *ast.InSuper:
		return []ast.Node{node.Index}
	case *ast.Unary:
		return []ast.Node{node.Expr}
	case *ast.Var:
		return nil
	}
	panic(fmt.Sprintf("directChildren: Unknown node %#v", node))
}

// thunkChildren are children of AST node that are executed in a new context
// and capture environment from parent (thunked)
// TODO(sbarzowski) Make sure it works well with boundary cases like tailstrict arguments,
//					make it more precise.
// Rules:
// * (same-environment) They must be evaluated in the same environment as their parent
// * (not-direct) If they can be direct children, they should (and cannot be thunked).
func thunkChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		var nodes []ast.Node
		for _, arg := range node.Arguments.Positional {
			nodes = append(nodes, arg)
		}
		for _, arg := range node.Arguments.Named {
			nodes = append(nodes, arg.Arg)
		}
		return nodes
	case *ast.ApplyBrace:
		return nil
	case *ast.Array:
		return node.Elements
	case *ast.Assert:
		return nil
	case *ast.Binary:
		return nil
	case *ast.Conditional:
		return nil
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return nil
	case *ast.Function:
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return nil
	case *ast.Slice:
		return nil
	case *ast.Local:
		// TODO(sbarzowski) complicated
		return nil
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return nil
	case *ast.ArrayComp:
		return []ast.Node{node.Body}
	case *ast.ObjectComp:
		return nil
	case *ast.Parens:
		return nil
	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return nil
	case *ast.InSuper:
		return nil
	case *ast.Unary:
		return nil
	case *ast.Var:
		return nil
	}
	panic(fmt.Sprintf("thunkChildren: Unknown node %#v", node))
}

func objectFieldsDirectChildren(fields ast.ObjectFields) ast.Nodes {
	result := ast.Nodes{}
	for _, field := range fields {
		if field.Expr1 != nil {
			result = append(result, field.Expr1)
		}
	}
	return result
}

func inObjectFieldsChildren(fields ast.ObjectFields) ast.Nodes {
	result := ast.Nodes{}
	for _, field := range fields {
		if field.MethodSugar {
			result = append(result, field.Method)
		} else {
			if field.Expr2 != nil {
				result = append(result, field.Expr2)
			}
			if field.Expr3 != nil {
				result = append(result, field.Expr3)
			}
		}
	}
	return result
}

// children that are neither direct nor thunked, e.g. object field body
// They are evaluated in a different environment from their parent.
func specialChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		return nil
	case *ast.ApplyBrace:
		return nil
	case *ast.Array:
		return nil
	case *ast.Assert:
		return nil
	case *ast.Binary:
		return nil
	case *ast.Conditional:
		return nil
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return nil
	case *ast.Function:
		// TODO(sbarzowski) this
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return nil
	case *ast.Slice:
		return nil
	case *ast.Local:
		return nil
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return inObjectFieldsChildren(node.Fields)
	case *ast.ArrayComp:
		return []ast.Node{node.Body}
	case *ast.ObjectComp:

	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return nil
	case *ast.InSuper:
		return nil
	case *ast.Unary:
		return nil
	case *ast.Var:
		return nil
	}
	panic(fmt.Sprintf("specialChildren: Unknown node %#v", node))
}

// Children returns all children of a node.
func Children(node ast.Node) []ast.Node {
	var result []ast.Node
	result = append(result, directChildren(node)...)
	result = append(result, thunkChildren(node)...)
	result = append(result, specialChildren(node)...)
	return result
}

func functionContext(funcName string) *string {
	r := "function <" + funcName + ">"
	return &r
}

func objectContext(objName string) *string {
	r := "object <" + objName + ">"
	return &r
}

// addContext adds context to a node and its whole subtree.
//
// context is the surrounding context of a node (e.g. a function it's in)
//
// bind is a name that the node is bound to, i.e. if node is a local bind body
// then bind is its name. For nodes that are not bound to variables `anonymous`
// should be passed. For example:
// local x = 2 + 2; x
// In such case bind for binary node 2 + 2 is "x" and for every other node,
// including its children, its anonymous.
func addContext(node ast.Node, context *string, bind string) {
	if node == nil {
		return
	}

	node.SetContext(context)

	switch node := node.(type) {
	case *ast.Function:
		funContext := functionContext(bind)
		addContext(node.Body, funContext, anonymous)
		for i := range node.Parameters.Optional {
			// Default arguments have the same context as the function body.
			addContext(node.Parameters.Optional[i].DefaultArg, funContext, anonymous)
		}
	case *ast.Object:
		// TODO(sbarzowski) include fieldname, maybe even chains

		outOfObject := directChildren(node)
		for _, f := range outOfObject {
			// This actually is evaluated outside of object
			addContext(f, context, anonymous)
		}

		objContext := objectContext(bind)
		inObject := inObjectFieldsChildren(node.Fields)
		for _, f := range inObject {
			// This actually is evaluated outside of object
			addContext(f, objContext, anonymous)
		}

	case *ast.ObjectComp:
		outOfObject := directChildren(node)
		for _, f := range outOfObject {
			// This actually is evaluated outside of object
			addContext(f, context, anonymous)
		}

		objContext := objectContext(bind)
		inObject := inObjectFieldsChildren(node.Fields)
		for _, f := range inObject {
			// This actually is evaluated outside of object
			addContext(f, objContext, anonymous)
		}

	case *ast.Local:
		for _, bind := range node.Binds {
			namedThunkContext := "thunk <" + string(bind.Variable) + "> from <" + *context + ">"
			if bind.Fun != nil {
				addContext(bind.Fun, &namedThunkContext, string(bind.Variable))
			} else {
				addContext(bind.Body, &namedThunkContext, string(bind.Variable))
			}
		}
		addContext(node.Body, context, bind)
	default:
		for _, child := range directChildren(node) {
			addContext(child, context, anonymous)
		}

		// TODO(sbarzowski) avoid "thunk from <thunk from..."
		thunkContext := "thunk from <" + *context + ">"
		for _, child := range thunkChildren(node) {
			addContext(child, &thunkContext, anonymous)
		}
	}
}
<commit_msg>support for traversing AST tree with parens and objectcomps<commit_after>/*
Copyright 2017 Google Inc. All rights reserved.

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

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

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

package parser

import (
	"fmt"

	"github.com/google/go-jsonnet/ast"
)

var topLevelContext = "$"

const anonymous = "anonymous"

// TODO(sbarzowski) polish children functions and consider moving to AST
// and exporting

// directChildren are children of AST node that are executed in the same context
// and environment as their parent
//
// They must satisfy the following rules:
// * (no-delayed-evaluation) They are evaluated when their parent is evaluated or never.
// * (no-indirect-evaluation) They cannot be evaluated during evaluation of any non-direct children
// * (same-environment) They must be evaluated in the same environment as their parent
func directChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		return []ast.Node{node.Target}
		// TODO(sbarzowski) tailstrict call arguments (once we have tailstrict)
	case *ast.ApplyBrace:
		return []ast.Node{node.Left, node.Right}
	case *ast.Array:
		return nil
	case *ast.Assert:
		return []ast.Node{node.Cond, node.Message, node.Rest}
	case *ast.Binary:
		return []ast.Node{node.Left, node.Right}
	case *ast.Conditional:
		return []ast.Node{node.Cond, node.BranchTrue, node.BranchFalse}
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return []ast.Node{node.Expr}
	case *ast.Function:
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return []ast.Node{node.Target, node.Index}
	case *ast.Slice:
		return []ast.Node{node.Target, node.BeginIndex, node.EndIndex, node.Step}
	case *ast.Local:
		return []ast.Node{node.Body}
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return objectFieldsDirectChildren(node.Fields)
	case *ast.ArrayComp:
		result := []ast.Node{}
		spec := &node.Spec
		for spec != nil {
			result = append(result, spec.Expr)
			for _, ifspec := range spec.Conditions {
				result = append(result, ifspec.Expr)
			}
			spec = spec.Outer
		}
		return result
	case *ast.ObjectComp:
		result := objectFieldsDirectChildren(node.Fields)
		spec := &node.Spec
		for spec != nil {
			result = append(result, spec.Expr)
			for _, ifspec := range spec.Conditions {
				result = append(result, ifspec.Expr)
			}
			spec = spec.Outer
		}
		return result
	case *ast.Parens:
		return []ast.Node{node.Inner}
	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return []ast.Node{node.Index}
	case *ast.InSuper:
		return []ast.Node{node.Index}
	case *ast.Unary:
		return []ast.Node{node.Expr}
	case *ast.Var:
		return nil
	}
	panic(fmt.Sprintf("directChildren: Unknown node %#v", node))
}

// thunkChildren are children of AST node that are executed in a new context
// and capture environment from parent (thunked)
// TODO(sbarzowski) Make sure it works well with boundary cases like tailstrict arguments,
//					make it more precise.
// Rules:
// * (same-environment) They must be evaluated in the same environment as their parent
// * (not-direct) If they can be direct children, they should (and cannot be thunked).
func thunkChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		var nodes []ast.Node
		for _, arg := range node.Arguments.Positional {
			nodes = append(nodes, arg)
		}
		for _, arg := range node.Arguments.Named {
			nodes = append(nodes, arg.Arg)
		}
		return nodes
	case *ast.ApplyBrace:
		return nil
	case *ast.Array:
		return node.Elements
	case *ast.Assert:
		return nil
	case *ast.Binary:
		return nil
	case *ast.Conditional:
		return nil
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return nil
	case *ast.Function:
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return nil
	case *ast.Slice:
		return nil
	case *ast.Local:
		// TODO(sbarzowski) complicated
		return nil
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return nil
	case *ast.ArrayComp:
		return []ast.Node{node.Body}
	case *ast.ObjectComp:
		return nil
	case *ast.Parens:
		return nil
	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return nil
	case *ast.InSuper:
		return nil
	case *ast.Unary:
		return nil
	case *ast.Var:
		return nil
	}
	panic(fmt.Sprintf("thunkChildren: Unknown node %#v", node))
}

func objectFieldsDirectChildren(fields ast.ObjectFields) ast.Nodes {
	result := ast.Nodes{}
	for _, field := range fields {
		if field.Expr1 != nil {
			result = append(result, field.Expr1)
		}
	}
	return result
}

func inObjectFieldsChildren(fields ast.ObjectFields) ast.Nodes {
	result := ast.Nodes{}
	for _, field := range fields {
		if field.MethodSugar {
			result = append(result, field.Method)
		} else {
			if field.Expr2 != nil {
				result = append(result, field.Expr2)
			}
			if field.Expr3 != nil {
				result = append(result, field.Expr3)
			}
		}
	}
	return result
}

// children that are neither direct nor thunked, e.g. object field body
// They are evaluated in a different environment from their parent.
func specialChildren(node ast.Node) []ast.Node {
	switch node := node.(type) {
	case *ast.Apply:
		return nil
	case *ast.ApplyBrace:
		return nil
	case *ast.Array:
		return nil
	case *ast.Assert:
		return nil
	case *ast.Binary:
		return nil
	case *ast.Conditional:
		return nil
	case *ast.Dollar:
		return nil
	case *ast.Error:
		return nil
	case *ast.Function:
		// TODO(sbarzowski) this
		return nil
	case *ast.Import:
		return nil
	case *ast.ImportStr:
		return nil
	case *ast.Index:
		return nil
	case *ast.Slice:
		return nil
	case *ast.Local:
		return nil
	case *ast.LiteralBoolean:
		return nil
	case *ast.LiteralNull:
		return nil
	case *ast.LiteralNumber:
		return nil
	case *ast.LiteralString:
		return nil
	case *ast.Object:
		return inObjectFieldsChildren(node.Fields)
	case *ast.ArrayComp:
		return []ast.Node{node.Body}
	case *ast.ObjectComp:
		return inObjectFieldsChildren(node.Fields)
	case *ast.Self:
		return nil
	case *ast.SuperIndex:
		return nil
	case *ast.InSuper:
		return nil
	case *ast.Unary:
		return nil
	case *ast.Var:
		return nil
	case *ast.Parens:
		return nil
	}
	panic(fmt.Sprintf("specialChildren: Unknown node %#v", node))
}

// Children returns all children of a node.
func Children(node ast.Node) []ast.Node {
	var result []ast.Node
	result = append(result, directChildren(node)...)
	result = append(result, thunkChildren(node)...)
	result = append(result, specialChildren(node)...)
	return result
}

func functionContext(funcName string) *string {
	r := "function <" + funcName + ">"
	return &r
}

func objectContext(objName string) *string {
	r := "object <" + objName + ">"
	return &r
}

// addContext adds context to a node and its whole subtree.
//
// context is the surrounding context of a node (e.g. a function it's in)
//
// bind is a name that the node is bound to, i.e. if node is a local bind body
// then bind is its name. For nodes that are not bound to variables `anonymous`
// should be passed. For example:
// local x = 2 + 2; x
// In such case bind for binary node 2 + 2 is "x" and for every other node,
// including its children, its anonymous.
func addContext(node ast.Node, context *string, bind string) {
	if node == nil {
		return
	}

	node.SetContext(context)

	switch node := node.(type) {
	case *ast.Function:
		funContext := functionContext(bind)
		addContext(node.Body, funContext, anonymous)
		for i := range node.Parameters.Optional {
			// Default arguments have the same context as the function body.
			addContext(node.Parameters.Optional[i].DefaultArg, funContext, anonymous)
		}
	case *ast.Object:
		// TODO(sbarzowski) include fieldname, maybe even chains

		outOfObject := directChildren(node)
		for _, f := range outOfObject {
			// This actually is evaluated outside of object
			addContext(f, context, anonymous)
		}

		objContext := objectContext(bind)
		inObject := inObjectFieldsChildren(node.Fields)
		for _, f := range inObject {
			// This actually is evaluated outside of object
			addContext(f, objContext, anonymous)
		}

	case *ast.ObjectComp:
		outOfObject := directChildren(node)
		for _, f := range outOfObject {
			// This actually is evaluated outside of object
			addContext(f, context, anonymous)
		}

		objContext := objectContext(bind)
		inObject := inObjectFieldsChildren(node.Fields)
		for _, f := range inObject {
			// This actually is evaluated outside of object
			addContext(f, objContext, anonymous)
		}

	case *ast.Local:
		for _, bind := range node.Binds {
			namedThunkContext := "thunk <" + string(bind.Variable) + "> from <" + *context + ">"
			if bind.Fun != nil {
				addContext(bind.Fun, &namedThunkContext, string(bind.Variable))
			} else {
				addContext(bind.Body, &namedThunkContext, string(bind.Variable))
			}
		}
		addContext(node.Body, context, bind)
	default:
		for _, child := range directChildren(node) {
			addContext(child, context, anonymous)
		}

		// TODO(sbarzowski) avoid "thunk from <thunk from..."
		thunkContext := "thunk from <" + *context + ">"
		for _, child := range thunkChildren(node) {
			addContext(child, &thunkContext, anonymous)
		}
	}
}
<|endoftext|>


<commit_before>package parser

import "github.com/hansrodtang/semver"

type comparatorFunc func(*semver.Version, *semver.Version) bool
type satisfactionMap map[*semver.Version]comparatorFunc

func gt(main, other *semver.Version) bool {
	return main.Compare(other) > 0
}

func gte(main, other *semver.Version) bool {
	return main.Compare(other) >= 0
}

func lt(main, other *semver.Version) bool {
	return main.Compare(other) < 0
}

func lte(main, other *semver.Version) bool {
	return main.Compare(other) <= 0
}

func eq(main, other *semver.Version) bool {
	return main.Compare(other) == 0
}

func rng2cmp(main, other *semver.Version) satisfactionMap {
	return satisfactionMap{main: gt, other: lt}
}

func cr2cmp(*semver.Version) satisfactionMap {
	return nil
}

func tld2cmp(*semver.Version) satisfactionMap {
	return nil
}
<commit_msg>Removed unfinished converters.<commit_after>package parser

import "github.com/hansrodtang/semver"

type comparatorFunc func(*semver.Version, *semver.Version) bool
type satisfactionMap map[*semver.Version]comparatorFunc

func gt(main, other *semver.Version) bool {
	return main.Compare(other) > 0
}

func gte(main, other *semver.Version) bool {
	return main.Compare(other) >= 0
}

func lt(main, other *semver.Version) bool {
	return main.Compare(other) < 0
}

func lte(main, other *semver.Version) bool {
	return main.Compare(other) <= 0
}

func eq(main, other *semver.Version) bool {
	return main.Compare(other) == 0
}
<|endoftext|>


<commit_before>package tests_test

import (
	"strings"

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

	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("[rfe_id:3423][vendor:cnv-qe@redhat.com][level:component]oc/kubectl get vm/vmi tests", func() {
	tests.FlagParse()

	var k8sClient string

	virtCli, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		k8sClient = tests.GetK8sCmdClient()
		tests.SkipIfNoCmd(k8sClient)
		tests.BeforeTestCleanup()
	})

	table.DescribeTable("should verify set of columns for", func(verb, resource string, expectedHeader []string) {
		vm := tests.NewRandomVirtualMachine(tests.NewRandomVMI(), false)
		vm, err := virtCli.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
		Expect(err).NotTo(HaveOccurred())

		tests.StartVirtualMachine(vm)

		result, _, _ := tests.RunCommand(k8sClient, verb, resource)
		Expect(result).ToNot(BeNil())
		resultFields := strings.Fields(result)
		columnHeaders := resultFields[:len(expectedHeader)]
		// Verify the generated header is same as expected
		Expect(columnHeaders).To(Equal(expectedHeader))
		// Name will be there in all the cases, so verify name
		Expect(resultFields[len(expectedHeader)]).To(Equal(vm.Name))
	},
		table.Entry("virtualmachine", "get", "vm", []string{"NAME", "AGE", "RUNNING", "VOLUME"}),
		table.Entry("virtualmachineinstance", "get", "vmi", []string{"NAME", "AGE", "PHASE", "IP", "NODENAME"}),
	)

	table.DescribeTable("should verify set of wide columns for", func(verb, resource, option string, expectedHeader []string, verifyPos int, expectedData string) {
		vm := tests.NewRandomVirtualMachine(tests.NewRandomVMI(), false)
		vm, err := virtCli.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
		Expect(err).NotTo(HaveOccurred())

		tests.StartVirtualMachine(vm)

		result, _, _ := tests.RunCommand(k8sClient, verb, resource, "-o", option)

		Expect(result).ToNot(BeNil())
		resultFields := strings.Fields(result)
		columnHeaders := resultFields[:len(expectedHeader)]
		// Verify the generated header is same as expected
		Expect(columnHeaders).To(Equal(expectedHeader))
		// Name will be there in all the cases, so verify name
		Expect(resultFields[len(expectedHeader)]).To(Equal(vm.Name))
		// Verify one of the wide column output field
		Expect(resultFields[len(resultFields)-verifyPos]).To(Equal(expectedData))
	},
		table.Entry("[test_id:3421]virtualmachine", "get", "vm", "wide", []string{"NAME", "AGE", "RUNNING", "VOLUME", "CREATED"}, 1, "true"),
		table.Entry("[test_id:3422]virtualmachineinstance", "get", "vmi", "wide", []string{"NAME", "AGE", "PHASE", "IP", "NODENAME", "LIVE-MIGRATABLE"}, 1, "True"),
	)
})
<commit_msg>Added test ids<commit_after>package tests_test

import (
	"strings"

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

	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("[rfe_id:3423][vendor:cnv-qe@redhat.com][level:component]oc/kubectl get vm/vmi tests", func() {
	tests.FlagParse()

	var k8sClient string

	virtCli, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		k8sClient = tests.GetK8sCmdClient()
		tests.SkipIfNoCmd(k8sClient)
		tests.BeforeTestCleanup()
	})

	table.DescribeTable("should verify set of columns for", func(verb, resource string, expectedHeader []string) {
		vm := tests.NewRandomVirtualMachine(tests.NewRandomVMI(), false)
		vm, err := virtCli.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
		Expect(err).NotTo(HaveOccurred())

		tests.StartVirtualMachine(vm)

		result, _, _ := tests.RunCommand(k8sClient, verb, resource)
		Expect(result).ToNot(BeNil())
		resultFields := strings.Fields(result)
		columnHeaders := resultFields[:len(expectedHeader)]
		// Verify the generated header is same as expected
		Expect(columnHeaders).To(Equal(expectedHeader))
		// Name will be there in all the cases, so verify name
		Expect(resultFields[len(expectedHeader)]).To(Equal(vm.Name))
	},
		table.Entry("[test_id:3464]virtualmachine", "get", "vm", []string{"NAME", "AGE", "RUNNING", "VOLUME"}),
		table.Entry("[test_id:3465]virtualmachineinstance", "get", "vmi", []string{"NAME", "AGE", "PHASE", "IP", "NODENAME"}),
	)

	table.DescribeTable("should verify set of wide columns for", func(verb, resource, option string, expectedHeader []string, verifyPos int, expectedData string) {
		vm := tests.NewRandomVirtualMachine(tests.NewRandomVMI(), false)
		vm, err := virtCli.VirtualMachine(tests.NamespaceTestDefault).Create(vm)
		Expect(err).NotTo(HaveOccurred())

		tests.StartVirtualMachine(vm)

		result, _, _ := tests.RunCommand(k8sClient, verb, resource, "-o", option)

		Expect(result).ToNot(BeNil())
		resultFields := strings.Fields(result)
		columnHeaders := resultFields[:len(expectedHeader)]
		// Verify the generated header is same as expected
		Expect(columnHeaders).To(Equal(expectedHeader))
		// Name will be there in all the cases, so verify name
		Expect(resultFields[len(expectedHeader)]).To(Equal(vm.Name))
		// Verify one of the wide column output field
		Expect(resultFields[len(resultFields)-verifyPos]).To(Equal(expectedData))
	},
		table.Entry("[test_id:3421]virtualmachine", "get", "vm", "wide", []string{"NAME", "AGE", "RUNNING", "VOLUME", "CREATED"}, 1, "true"),
		table.Entry("[test_id:3422]virtualmachineinstance", "get", "vmi", "wide", []string{"NAME", "AGE", "PHASE", "IP", "NODENAME", "LIVE-MIGRATABLE"}, 1, "True"),
	)
})
<|endoftext|>


<commit_before>package main

import (
	runner "github.com/alanctgardner/ampl-go/runner"
	"fmt"
)

/* Test commands to submit to the AMPL CLI - in this case
   use the diet model from the AMPL book and write an MPS file */
var amplCommands = []string {
	"model src/github.com/alanctgardner/ampl-go/demo/diet1.mod;",
	"data src/github.com/alanctgardner/ampl-go/demo/diet1.dat",
	"write gdiet1;",
}

func main() {
	/* Try to get the cached location of the AMPL binary from a file on disk */
	amplLoc, err := runner.GetAMPLLoc()
	if err != nil {
		fmt.Printf("Error getting cached AMPL executable location: %v\n", err)
		return
	}

	/* If there was no cached location, prompt the user and cache what they enter - NB: if the user's entry is wrong, delete the cached file to be prompted again. */
	if amplLoc == "" {
		amplLoc, err = runner.PromptAMPLLoc()
		if err != nil {
			fmt.Printf("Error getting AMPL executable location on stdin: %v\n", err)
			return
		}
	}

	/* Run the AMPL binary */
	amplRunner, err := runner.NewRunner(amplLoc)
	if err != nil {
		fmt.Printf("Error starting AMPL executable %q: %v\n", amplLoc, err)
		return
	}

	/* Run each of the commands in order. If there's an error, print it out and quit. Continuing after an error will not work. */
	for _, cmd := range amplCommands {
		fmt.Printf("Running command: %q\n", cmd)
		err := amplRunner.RunCommand(cmd)
		if err != nil {
			fmt.Printf("%v\n", err)
			return
		}
	}
}
<commit_msg>Runner demo clears the cached AMPL path if the binary fails to run<commit_after>package main

import (
	runner "github.com/alanctgardner/ampl-go/runner"
	"fmt"
)

/* Test commands to submit to the AMPL CLI - in this case
   use the diet model from the AMPL book and write an MPS file */
var amplCommands = []string {
	"model src/github.com/alanctgardner/ampl-go/demo/diet1.mod;",
	"data src/github.com/alanctgardner/ampl-go/demo/diet1.dat",
	"write gdiet1;",
}

func main() {
	/* Try to get the cached location of the AMPL binary from a file on disk */
	amplLoc, err := runner.GetAMPLLoc()
	if err != nil {
		fmt.Printf("Error getting cached AMPL executable location: %v\n", err)
		return
	}

	/* If there was no cached location, prompt the user and cache what they enter */
	if amplLoc == "" {
		amplLoc, err = runner.PromptAMPLLoc()
		if err != nil {
			fmt.Printf("Error getting AMPL executable location on stdin: %v\n", err)
			return
		}
	}

	/* Run the AMPL binary */
	amplRunner, err := runner.NewRunner(amplLoc)
	if err != nil {
		fmt.Printf("Error starting AMPL executable %q: %v\n", amplLoc, err)
		runner.ClearAMPLLoc()
		return
	}

	/* Run each of the commands in order. If there's an error, print it out and quit. Continuing after an error will not work. */
	for _, cmd := range amplCommands {
		fmt.Printf("Running command: %q\n", cmd)
		err := amplRunner.RunCommand(cmd)
		if err != nil {
			fmt.Printf("%v\n", err)
			return
		}
	}
}
<|endoftext|>


<commit_before>// Package notifier contains types and methods for sending notifications
// that a job has completed.
package notifier

import (
	"io"
	"net/http"
)

// To create notifications, an object has to have a destination in mind
// and be able to serialize itself into a JSON message.
type Notifiable interface {
	Recipient() string
	Content() io.Reader
}

func SendNotification(n Notifiable) (response *http.Response, err error) {
	destination := n.Recipient()
	body := n.Content()
	response, err = http.Post(destination, "application/json", body)
	return
}
<commit_msg>Use auth and check response<commit_after>// Package notifier contains types and methods for sending notifications
// that a job has completed.
package notifier

import (
	"io"
	"fmt"
	"net/http"
)

// To create notifications, an object has to have a destination in mind
// and be able to serialize itself into a JSON message.
type Notifiable interface {
	Recipient() string
	Content() io.Reader
}

func SendNotification(n Notifiable) (response *http.Response, err error) {
	destination := n.Recipient()
	body := n.Content()
	client := &http.Client{}
	req, _ := http.NewRequest("POST", destination, body)
	req.SetBasicAuth("admin","admin")
	req.Header.Set("Content-Type","application/json")
	response, err = client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	return
}
<|endoftext|>