Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Merge pull request #201 from ngtuna/ingress-https
Browse files Browse the repository at this point in the history
Enable ingress (annotation ready for HTTPS with kube-lego)
  • Loading branch information
ngtuna authored Jul 31, 2017
2 parents 77cb32c + 46193ff commit 0c62caf
Show file tree
Hide file tree
Showing 13 changed files with 777 additions and 2 deletions.
41 changes: 41 additions & 0 deletions cmd/kubeless/ingress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2016 Skippbox, Ltd.
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 main

import (
"github.com/spf13/cobra"
"k8s.io/client-go/pkg/api"
)

var ingressCmd = &cobra.Command{
Use: "ingress SUBCOMMAND",
Short: "manage route to function on Kubeless",
Long: `ingress command allows user to list, create, delete ingress rule for function on Kubeless`,
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

func init() {
cmds := []*cobra.Command{ingressCreateCmd, ingressListCmd, ingressDeleteCmd}

for _, cmd := range cmds {
ingressCmd.AddCommand(cmd)
cmd.Flags().StringP("namespace", "n", api.NamespaceDefault, "Specify namespace for the ingress")

}
}
85 changes: 85 additions & 0 deletions cmd/kubeless/ingressCreate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
Copyright 2016 Skippbox, Ltd.
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 main

import (
"github.com/Sirupsen/logrus"
"github.com/kubeless/kubeless/pkg/spec"
"github.com/kubeless/kubeless/pkg/utils"
"github.com/spf13/cobra"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
)

var ingressCreateCmd = &cobra.Command{
Use: "create <name> FLAG",
Short: "create a route to function",
Long: `create a route to function`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
logrus.Fatal("Need exactly one argument - ingress name")
}
ingressName := args[0]
ns, err := cmd.Flags().GetString("namespace")
if err != nil {
logrus.Fatal(err)
}
domain, err := cmd.Flags().GetString("domain")
if err != nil {
logrus.Fatal(err)
}

function, err := cmd.Flags().GetString("function")
if err != nil {
logrus.Fatal(err)
}

validateInput(function, ns)

client := utils.GetClientOutOfCluster()

err = utils.CreateIngress(client, ingressName, function, domain, ns)
if err != nil {
logrus.Fatal(err)
}
},
}

func validateInput(function, ns string) {
tprClient, err := utils.GetTPRClientOutOfCluster()
if err != nil {
logrus.Fatalf("error validate input %v", err)
}
f := spec.Function{}
err = tprClient.Get().
Resource("functions").
Namespace(ns).
Name(function).
Do().
Into(&f)
if err != nil {
if k8sErrors.IsNotFound(err) {
logrus.Fatalf("function %s doesn't exist in namespace %s", function, ns)
} else {
logrus.Fatalf("error validate input %v", err)
}
}
}

func init() {
ingressCreateCmd.Flags().StringP("domain", "", "", "Specify a valid domain for the function")
ingressCreateCmd.Flags().StringP("function", "", "", "Name of the function")
}
47 changes: 47 additions & 0 deletions cmd/kubeless/ingressDelete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Copyright 2016 Skippbox, Ltd.
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 main

import (
"github.com/Sirupsen/logrus"
"github.com/kubeless/kubeless/pkg/utils"
"github.com/spf13/cobra"
)

var ingressDeleteCmd = &cobra.Command{
Use: "delete <name>",
Short: "delete a route from Kubeless",
Long: `delete a route from Kubeless`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
logrus.Fatal("Need exactly one argument - route name")
}
ingName := args[0]

ns, err := cmd.Flags().GetString("namespace")
if err != nil {
logrus.Fatal(err)
}

client := utils.GetClientOutOfCluster()

err = utils.DeleteIngress(client, ingName, ns)
if err != nil {
logrus.Fatal(err)
}
},
}
100 changes: 100 additions & 0 deletions cmd/kubeless/ingressList.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
Copyright 2016 Skippbox, Ltd.
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 main

import (
"encoding/json"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/kubeless/kubeless/pkg/utils"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"io"

"github.com/olekukonko/tablewriter"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

var ingressListCmd = &cobra.Command{
Use: "list FLAG",
Aliases: []string{"ls"},
Short: "list all routes in Kubeless",
Long: `list all routes in Kubeless`,
Run: func(cmd *cobra.Command, args []string) {
output, err := cmd.Flags().GetString("out")
if err != nil {
logrus.Fatal(err.Error())
}
ns, err := cmd.Flags().GetString("namespace")
if err != nil {
logrus.Fatal(err.Error())
}

client := utils.GetClientOutOfCluster()

if err := doIngressList(cmd.OutOrStdout(), client, ns, output); err != nil {
logrus.Fatal(err.Error())
}
},
}

func init() {
ingressListCmd.Flags().StringP("out", "o", "", "Output format. One of: json|yaml")
}

func doIngressList(w io.Writer, client kubernetes.Interface, ns, output string) error {
ingList, err := client.ExtensionsV1beta1().Ingresses(ns).List(v1.ListOptions{})
if err != nil {
return err
}

return printIngress(w, ingList.Items, output)
}

// printIngress formats the output of ingress list
func printIngress(w io.Writer, ings []v1beta1.Ingress, output string) error {
if output == "" {
table := tablewriter.NewWriter(w)
table.SetHeader([]string{"Name", "namespace", "host", "path", "service name", "service port"})
for _, i := range ings {
n := i.Name
h := i.Spec.Rules[0].Host
p := i.Spec.Rules[0].HTTP.Paths[0].Path
ns := i.Namespace
sN := i.Spec.Rules[0].HTTP.Paths[0].Backend.ServiceName
sP := i.Spec.Rules[0].HTTP.Paths[0].Backend.ServicePort
table.Append([]string{n, ns, h, p, sN, sP.String()})
}
table.Render()
} else {
for _, i := range ings {
switch output {
case "json":
b, _ := json.MarshalIndent(i.Spec, "", " ")
fmt.Fprintln(w, string(b))
case "yaml":
b, _ := yaml.Marshal(i.Spec)
fmt.Fprintln(w, string(b))
default:
return fmt.Errorf("Wrong output format. Please use only json|yaml")
}
}
}
return nil
}
96 changes: 96 additions & 0 deletions cmd/kubeless/ingressList_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"bytes"
"strings"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
xv1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

func listIngressOutput(t *testing.T, client kubernetes.Interface, ns, output string) string {
var buf bytes.Buffer

if err := doIngressList(&buf, client, ns, output); err != nil {
t.Fatalf("doList returned error: %v", err)
}

return buf.String()
}

func TestIngressList(t *testing.T) {
ing1 := xv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "myns",
},
Spec: xv1beta1.IngressSpec{
Rules: []xv1beta1.IngressRule{
{
Host: "foobar.192.168.99.100.nip.io",
IngressRuleValue: xv1beta1.IngressRuleValue{
HTTP: &xv1beta1.HTTPIngressRuleValue{
Paths: []xv1beta1.HTTPIngressPath{
{
Path: "/",
Backend: xv1beta1.IngressBackend{
ServiceName: "foobar",
ServicePort: intstr.FromInt(8080),
},
},
},
},
},
},
},
},
}

ing2 := xv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "myns",
},
Spec: xv1beta1.IngressSpec{
Rules: []xv1beta1.IngressRule{
{
Host: "example.com",
IngressRuleValue: xv1beta1.IngressRuleValue{
HTTP: &xv1beta1.HTTPIngressRuleValue{
Paths: []xv1beta1.HTTPIngressPath{
{
Path: "/",
Backend: xv1beta1.IngressBackend{
ServiceName: "barfoo",
ServicePort: intstr.FromInt(8080),
},
},
},
},
},
},
},
},
}

client := fake.NewSimpleClientset(&ing1, &ing2)

output := listIngressOutput(t, client, "myns", "")
t.Log("output is", output)

if !strings.Contains(output, "foo") || !strings.Contains(output, "bar") {
t.Errorf("table output didn't mention both functions")
}

// json output
output = listIngressOutput(t, client, "myns", "json")
t.Log("output is", output)

// yaml output
output = listIngressOutput(t, client, "myns", "yaml")
t.Log("output is", output)
}
2 changes: 1 addition & 1 deletion cmd/kubeless/kubeless.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func newRootCmd() *cobra.Command {
Long: globalUsage,
}

cmd.AddCommand(functionCmd, topicCmd, versionCmd)
cmd.AddCommand(functionCmd, topicCmd, versionCmd, ingressCmd)
return cmd
}

Expand Down
Loading

0 comments on commit 0c62caf

Please sign in to comment.