summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/35-networks.at28
-rw-r--r--test/e2e/generate_systemd_test.go12
-rw-r--r--test/e2e/logs_test.go8
-rw-r--r--test/e2e/ps_test.go15
-rw-r--r--test/e2e/run_networking_test.go66
-rw-r--r--test/e2e/run_test.go50
-rw-r--r--test/e2e/run_working_dir.go69
-rw-r--r--test/system/001-basic.bats31
-rw-r--r--test/system/070-build.bats17
-rw-r--r--test/system/075-exec.bats2
-rw-r--r--test/system/110-history.bats2
-rw-r--r--test/system/120-load.bats14
-rw-r--r--test/utils/utils.go14
13 files changed, 313 insertions, 15 deletions
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index fff3f3b1f..4c032c072 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -3,6 +3,32 @@
# network-related tests
#
-t GET /networks/non-existing-network 404
+t GET networks/non-existing-network 404 \
+ .cause='network not found'
+
+if root; then
+ t POST libpod/networks/create?name=network1 '' 200 \
+ .Filename~.*/network1\\.conflist
+
+ # --data '{"Subnet":{"IP":"10.10.254.0","Mask":[255,255,255,0]}}'
+ t POST libpod/networks/create?name=network2 '"Subnet":{"IP":"10.10.254.0","Mask":[255,255,255,0]}' 200 \
+ .Filename~.*/network2\\.conflist
+
+ # test for empty mask
+ t POST libpod/networks/create '"Subnet":{"IP":"10.10.1.0","Mask":[]}' 500 \
+ .cause~'.*cannot be empty'
+ # test for invalid mask
+ t POST libpod/networks/create '"Subnet":{"IP":"10.10.1.0","Mask":[0,255,255,0]}' 500 \
+ .cause~'.*mask is invalid'
+
+ # clean the network
+ t DELETE libpod/networks/network1 200 \
+ .[0].Name~network1 \
+ .[0].Err=null
+ t DELETE libpod/networks/network2 200 \
+ .[0].Name~network2 \
+ .[0].Err=null
+
+fi
# vim: filetype=sh
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index d114744c4..60d9162d1 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -53,6 +53,18 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session).To(ExitWithError())
})
+ It("podman generate systemd bad restart-policy value", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--restart-policy", "bogus", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).To(ExitWithError())
+ found, _ := session.ErrorGrepString("Error: bogus is not a valid restart policy")
+ Expect(found).Should(BeTrue())
+ })
+
It("podman generate systemd good timeout value", func() {
session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 381336b8b..e63bce3fe 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -72,16 +72,16 @@ var _ = Describe("Podman logs", func() {
Expect(len(results.OutputToStringArray())).To(Equal(0))
})
- It("tail 99 lines", func() {
- logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
+ It("tail 800 lines", func() {
+ logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "i=1; while [ \"$i\" -ne 1000 ]; do echo \"line $i\"; i=$((i + 1)); done"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
cid := logc.OutputToString()
- results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
+ results := podmanTest.Podman([]string{"logs", "--tail", "800", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(len(results.OutputToStringArray())).To(Equal(800))
})
It("tail 2 lines with timestamps", func() {
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index f10ef5c99..a734d399d 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -188,6 +188,21 @@ var _ = Describe("Podman ps", func() {
Expect(result.IsJSONOutputValid()).To(BeTrue())
})
+ It("podman ps print a human-readable `Status` with json format", func() {
+ _, ec, _ := podmanTest.RunLsContainer("test1")
+ Expect(ec).To(Equal(0))
+
+ result := podmanTest.Podman([]string{"ps", "-a", "--format", "json"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.IsJSONOutputValid()).To(BeTrue())
+ // must contain "Status"
+ match, StatusLine := result.GrepString(`Status`)
+ Expect(match).To(BeTrue())
+ // container is running or exit, so it must contain `ago`
+ Expect(StatusLine[0]).To(ContainSubstring("ago"))
+ })
+
It("podman ps namespace flag with go template format", func() {
Skip(v2fail)
_, ec, _ := podmanTest.RunLsContainer("test1")
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 0353db9a6..83befe730 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -1,11 +1,14 @@
package integration
import (
+ "fmt"
"os"
+ "strings"
. "github.com/containers/podman/v2/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "github.com/uber/jaeger-client-go/utils"
)
var _ = Describe("Podman run networking", func() {
@@ -290,6 +293,69 @@ var _ = Describe("Podman run networking", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman run slirp4netns network with different cidr", func() {
+ slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
+ Expect(slirp4netnsHelp.ExitCode()).To(Equal(0))
+
+ networkConfiguration := "slirp4netns:cidr=192.168.0.0/24,allow_host_loopback=true"
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, ALPINE, "ping", "-c1", "192.168.0.2"})
+ session.Wait(30)
+
+ if strings.Contains(slirp4netnsHelp.OutputToString(), "cidr") {
+ Expect(session.ExitCode()).To(Equal(0))
+ } else {
+ Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session.ErrorToString()).To(ContainSubstring("cidr not supported"))
+ }
+ })
+
+ It("podman run network bind to 127.0.0.1", func() {
+ slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
+ Expect(slirp4netnsHelp.ExitCode()).To(Equal(0))
+ networkConfiguration := "slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true"
+
+ if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
+ ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8083"})
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
+ session.Wait(30)
+ ncListener.Wait(30)
+
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(ncListener.ExitCode()).To(Equal(0))
+ Expect(ncListener.ErrorToString()).To(ContainSubstring("127.0.0.1"))
+ } else {
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
+ session.Wait(30)
+ Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
+ }
+ })
+
+ It("podman run network bind to HostIP", func() {
+ ip, err := utils.HostIP()
+ Expect(err).To(BeNil())
+
+ slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
+ Expect(slirp4netnsHelp.ExitCode()).To(Equal(0))
+ networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip.String())
+
+ if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
+ ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8084"})
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
+ session.Wait(30)
+ ncListener.Wait(30)
+
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(ncListener.ExitCode()).To(Equal(0))
+ Expect(ncListener.ErrorToString()).To(ContainSubstring(ip.String()))
+ } else {
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
+ session.Wait(30)
+ Expect(session.ExitCode()).ToNot(Equal(0))
+ Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
+ }
+ })
+
It("podman run network expose ports in image metadata", func() {
session := podmanTest.Podman([]string{"create", "--name", "test", "-dt", "-P", nginx})
session.Wait(90)
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 9cb76d1f6..6c65a23e8 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -193,22 +193,46 @@ var _ = Describe("Podman run", func() {
Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("FALSE"))
})
- It("podman run seccomp test", func() {
-
+ forbidGetCWDSeccompProfile := func() string {
in := []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`)
jsonFile, err := podmanTest.CreateSeccompJson(in)
if err != nil {
fmt.Println(err)
Skip("Failed to prepare seccomp.json for test.")
}
+ return jsonFile
+ }
- session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", jsonFile}, ""), ALPINE, "pwd"})
+ It("podman run seccomp test", func() {
+ session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
match, _ := session.GrepString("Operation not permitted")
Expect(match).Should(BeTrue())
})
+ It("podman run seccomp test --privileged", func() {
+ session := podmanTest.Podman([]string{"run", "-it", "--privileged", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).To(ExitWithError())
+ match, _ := session.GrepString("Operation not permitted")
+ Expect(match).Should(BeTrue())
+ })
+
+ It("podman run seccomp test --privileged no profile should be unconfined", func() {
+ session := podmanTest.Podman([]string{"run", "-it", "--privileged", ALPINE, "grep", "Seccomp", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(ContainSubstring("0"))
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
+ It("podman run seccomp test no profile should be default", func() {
+ session := podmanTest.Podman([]string{"run", "-it", ALPINE, "grep", "Seccomp", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(ContainSubstring("2"))
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman run capabilities test", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--cap-add", "all", ALPINE, "cat", "/proc/self/status"})
session.WaitWithDefaultTimeout()
@@ -803,6 +827,15 @@ USER mail`
Expect(isSharedOnly).Should(BeTrue())
})
+ It("podman run --security-opts proc-opts=", func() {
+ session := podmanTest.Podman([]string{"run", "--security-opt", "proc-opts=nosuid,exec", fedoraMinimal, "findmnt", "-noOPTIONS", "/proc"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ output := session.OutputToString()
+ Expect(output).To(ContainSubstring("nosuid"))
+ Expect(output).To(Not(ContainSubstring("exec")))
+ })
+
It("podman run --mount type=bind,bind-nonrecursive", func() {
SkipIfRootless()
session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"})
@@ -1143,7 +1176,7 @@ USER mail`
Expect(session.ErrorToString()).To(ContainSubstring("Invalid umask"))
})
- It("podman run makes entrypoint from image", func() {
+ It("podman run makes workdir from image", func() {
// BuildImage does not seem to work remote
SkipIfRemote()
dockerfile := `FROM busybox
@@ -1154,4 +1187,13 @@ WORKDIR /madethis`
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("/madethis"))
})
+
+ It("podman run --entrypoint does not use image command", func() {
+ session := podmanTest.Podman([]string{"run", "--entrypoint", "/bin/echo", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ // We can't guarantee the output is completely empty, some
+ // nonprintables seem to work their way in.
+ Expect(session.OutputToString()).To(Not(ContainSubstring("/bin/sh")))
+ })
})
diff --git a/test/e2e/run_working_dir.go b/test/e2e/run_working_dir.go
new file mode 100644
index 000000000..93330deba
--- /dev/null
+++ b/test/e2e/run_working_dir.go
@@ -0,0 +1,69 @@
+package integration
+
+import (
+ "os"
+ "strings"
+
+ . "github.com/containers/podman/v2/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman run", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman run a container without workdir", func() {
+ session := podmanTest.Podman([]string{"run", ALPINE, "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal("/"))
+ })
+
+ It("podman run a container using non existing --workdir", func() {
+ if !strings.Contains(podmanTest.OCIRuntime, "crun") {
+ Skip("Test only works on crun")
+ }
+ session := podmanTest.Podman([]string{"run", "--workdir", "/home/foobar", ALPINE, "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(127))
+ })
+
+ It("podman run a container on an image with a workdir", func() {
+ SkipIfRemote()
+ dockerfile := `FROM alpine
+RUN mkdir -p /home/foobar
+WORKDIR /etc/foobar`
+ podmanTest.BuildImage(dockerfile, "test", "false")
+
+ session := podmanTest.Podman([]string{"run", "test", "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal("/etc/foobar"))
+
+ session = podmanTest.Podman([]string{"run", "--workdir", "/home/foobar", "test", "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal("/home/foobar"))
+ })
+})
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 71595f419..b23107e79 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -31,6 +31,37 @@ function setup() {
run_podman pull $IMAGE
}
+# PR #7212: allow --remote anywhere before subcommand, not just as 1st flag
+@test "podman-remote : really is remote, works as --remote option" {
+ if ! is_remote; then
+ skip "only applicable on podman-remote"
+ fi
+
+ # First things first: make sure our podman-remote actually is remote!
+ run_podman version
+ is "$output" ".*Server:" "the given podman path really contacts a server"
+
+ # $PODMAN may be a space-separated string, e.g. if we include a --url.
+ # Split it into its components; remove "-remote" from the command path;
+ # and preserve any other args if present.
+ local -a podman_as_array=($PODMAN)
+ local podman_path=${podman_as_array[0]}
+ local podman_non_remote=${podman_path%%-remote}
+ local -a podman_args=("${podman_as_array[@]:1}")
+
+ # This always worked: running "podman --remote ..."
+ PODMAN="${podman_non_remote} --remote ${podman_args[@]}" run_podman version
+ is "$output" ".*Server:" "podman --remote: contacts server"
+
+ # This was failing: "podman --foo --bar --remote".
+ PODMAN="${podman_non_remote} --tmpdir /var/tmp --log-level=error ${podman_args[@]} --remote" run_podman version
+ is "$output" ".*Server:" "podman [flags] --remote: contacts server"
+
+ # ...but no matter what, --remote is never allowed after subcommand
+ PODMAN="${podman_non_remote} ${podman_args[@]}" run_podman 125 version --remote
+ is "$output" "Error: unknown flag: --remote" "podman version --remote"
+}
+
# This is for development only; it's intended to make sure our timeout
# in run_podman continues to work. This test should never run in production
# because it will, by definition, fail.
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index d2ef9f0f9..0e6e97d40 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -165,6 +165,7 @@ EOF
# cd to the dir, so we test relative paths (important for podman-remote)
cd $PODMAN_TMPDIR
run_podman build -t build_test -f build-test/Containerfile build-test
+ local iid="${lines[-1]}"
# Run without args - should run the above script. Verify its output.
export MYENV2="$s_env2"
@@ -232,6 +233,22 @@ Labels.$label_name | $label_value
run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/myfile
is "$output" "4:5:/a/b/c/myfile" "file in volume is chowned"
+ # Hey, as long as we have an image with lots of layers, let's
+ # confirm that 'image tree' works as expected
+ run_podman image tree build_test
+ is "${lines[0]}" "Image ID: ${iid:0:12}" \
+ "image tree: first line"
+ is "${lines[1]}" "Tags: \[localhost/build_test:latest]" \
+ "image tree: second line"
+ is "${lines[2]}" "Size: [0-9.]\+[kM]B" \
+ "image tree: third line"
+ is "${lines[3]}" "Image Layers" \
+ "image tree: fourth line"
+ is "${lines[4]}" "... ID: [0-9a-f]\{12\} Size: .* Top Layer of: \[$IMAGE]" \
+ "image tree: first layer line"
+ is "${lines[-1]}" "... ID: [0-9a-f]\{12\} Size: .* Top Layer of: \[localhost/build_test:latest]" \
+ "image tree: last layer line"
+
# Clean up
run_podman rmi -f build_test
}
diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index aa6e2bd28..38c6c2312 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -6,6 +6,8 @@
load helpers
@test "podman exec - basic test" {
+ skip_if_remote "FIXME: pending #7241"
+
rand_filename=$(random_string 20)
rand_content=$(random_string 50)
diff --git a/test/system/110-history.bats b/test/system/110-history.bats
index b83e90fe4..5dc221d61 100644
--- a/test/system/110-history.bats
+++ b/test/system/110-history.bats
@@ -3,8 +3,6 @@
load helpers
@test "podman history - basic tests" {
- skip_if_remote "FIXME: pending #7122"
-
tests="
| .*[0-9a-f]\\\{12\\\} .* CMD .* LABEL
--format '{{.ID}} {{.Created}}' | .*[0-9a-f]\\\{12\\\} .* ago
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index ccfbc51ca..14dae4c8a 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -26,10 +26,18 @@ verify_iid_and_name() {
is "$new_img_name" "$1" "Name & tag of restored image"
}
+@test "podman save to pipe and load" {
+ # We can't use run_podman because that uses the BATS 'run' function
+ # which redirects stdout and stderr. Here we need to guarantee
+ # that podman's stdout is a pipe, not any other form of redirection
+ $PODMAN save --format oci-archive $IMAGE | cat >$PODMAN_TMPDIR/test.tar
+ [ $status -eq 0 ]
+
+ run_podman load -i $PODMAN_TMPDIR/test.tar
+}
-@test "podman load - by image ID" {
- skip_if_remote "FIXME: pending #7123"
+@test "podman load - by image ID" {
# FIXME: how to build a simple archive instead?
get_iid_and_name
@@ -77,8 +85,6 @@ verify_iid_and_name() {
}
@test "podman load - NAME and NAME:TAG arguments work" {
- skip_if_remote "FIXME: pending #7124"
-
get_iid_and_name
run_podman save $iid -o $archive
run_podman rmi $iid
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 2c454f532..a45ce7b36 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -207,6 +207,10 @@ func WaitContainerReady(p PodmanTestCommon, id string, expStr string, timeout in
// OutputToString formats session output to string
func (s *PodmanSession) OutputToString() string {
+ if s == nil || s.Out == nil || s.Out.Contents() == nil {
+ return ""
+ }
+
fields := strings.Fields(string(s.Out.Contents()))
return strings.Join(fields, " ")
}
@@ -341,6 +345,16 @@ func SystemExec(command string, args []string) *PodmanSession {
return &PodmanSession{session}
}
+// StartSystemExec is used to start exec a system command
+func StartSystemExec(command string, args []string) *PodmanSession {
+ c := exec.Command(command, args...)
+ session, err := gexec.Start(c, GinkgoWriter, GinkgoWriter)
+ if err != nil {
+ Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
+ }
+ return &PodmanSession{session}
+}
+
// StringInSlice determines if a string is in a string slice, returns bool
func StringInSlice(s string, sl []string) bool {
for _, i := range sl {