Skip to content

Commit

Permalink
add egctl edit, egctl logs, update egctl create cmd (#1067)
Browse files Browse the repository at this point in the history
* add egctl edit command

* add verbose flag for egctl describe

* fix bug for edit custom data

* update egctl cheat sheet

* finish egctl create httpproxy command, add some test

* add more test for egctl create cmd

* add more test, add integration test

* finish egctl logs command

* optim egctl logs command

* add integration test for egctl logs

* udpate doc, add examples

* update based on github action

* close watcher

* udpate based on comments

* update egctl edit example
  • Loading branch information
suchen-sci committed Aug 31, 2023
1 parent ac7d43d commit 8f2dc59
Show file tree
Hide file tree
Showing 27 changed files with 2,170 additions and 260 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,13 @@ filters:
The pipeline means it will forward traffic to 3 backend endpoints, using the
`roundRobin` load balance policy.

You can also create them using `egctl create httpproxy` command.
```bash
egctl create httpproxy demo --port 10080 \
--rule="/pipeline=http:https://127.0.0.1:9095,http:https://127.0.0.1:9096,http:https://127.0.0.1:9097"
```
this command will create `HTTPServer` `demo` and `Pipeline` `demo-0` which work exactly same to `server-demo` and `pipeline-demo`. See more about [`egctl create httpproxy`](./doc/egctl-cheat-sheet.md#create-httpproxy).

Additionally, we provide a [dashboard](https://cloud.megaease.com) that
streamlines the aforementioned steps, this intuitive tool can help you create,
manage HTTPServers, Pipelines and other Easegress configuration.
Expand Down
102 changes: 102 additions & 0 deletions build/test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package test

import (
"bytes"
"context"
"fmt"
"io"
Expand Down Expand Up @@ -535,3 +536,104 @@ list:
err = deleteResource("cdk", "custom-data-kind1")
assert.NoError(err)
}

func TestCreateHTTPProxy(t *testing.T) {
assert := assert.New(t)

for i, port := range []int{9096, 9097, 9098} {
currentPort := port
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello from backend %d", currentPort)
})

server := startServer(currentPort, mux)
defer server.Shutdown(context.Background())
started := checkServerStart(t, func() *http.Request {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http:https://127.0.0.1:%d", currentPort), nil)
require.Nil(t, err)
return req
})
require.True(t, started, i)
}

cmd := egctlCmd(
"create",
"httpproxy",
"http-proxy-test",
"--port", "10080",
"--rule",
"/pipeline=http:https://127.0.0.1:9096",
"--rule",
"/barz=http:https://127.0.0.1:9097",
"--rule",
"/bar*=http:https://127.0.0.1:9098",
)
_, stderr, err := runCmd(cmd)
assert.NoError(err)
assert.Empty(stderr)

output, err := getResource("httpserver")
assert.NoError(err)
assert.True(strings.Contains(output, "http-proxy-test"))

output, err = getResource("pipeline")
assert.NoError(err)
assert.True(strings.Contains(output, "http-proxy-test-0"))

testFn := func(p string, expected string) {
req, err := http.NewRequest(http.MethodGet, "http:https://127.0.0.1:10080"+p, nil)
assert.Nil(err, p)
resp, err := http.DefaultClient.Do(req)
assert.Nil(err, p)
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
assert.Nil(err, p)
assert.Equal(expected, string(data), p)
}

testFn("/pipeline", "hello from backend 9096")
testFn("/barz", "hello from backend 9097")
testFn("/bar-prefix", "hello from backend 9098")
}

func TestLogs(t *testing.T) {
assert := assert.New(t)

{
// test egctl logs --tail n
cmd := egctlCmd("logs", "--tail", "5")
output, stderr, err := runCmd(cmd)
assert.NoError(err)
assert.Empty(stderr)
assert.True(strings.Contains(output, "INFO"))
assert.True(strings.Contains(output, ".go"), "should contain go file in log")
lines := strings.Split(strings.TrimSpace(output), "\n")
assert.Len(lines, 5)
}
{
// test egctl logs -f
cmd := egctlCmd("logs", "-f", "--tail", "0")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Start()
assert.NoError(err)

// check if new logs are printed
yamlStr := `
kind: HTTPServer
name: test-egctl-logs
port: 12345
rules:
- paths:
- pathPrefix: /pipeline
backend: pipeline-demo
`
err = applyResource(yamlStr)
assert.NoError(err)
time.Sleep(1 * time.Second)
cmd.Process.Kill()
assert.True(strings.Contains(stdout.String(), "test-egctl-logs"))
}
}
48 changes: 3 additions & 45 deletions cmd/client/commandv2/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,13 @@
package commandv2

import (
"errors"

"github.com/megaease/easegress/v2/cmd/client/general"
"github.com/megaease/easegress/v2/cmd/client/resources"
"github.com/megaease/easegress/v2/cmd/client/commandv2/create"
"github.com/spf13/cobra"
)

// CreateCmd returns create command.
func CreateCmd() *cobra.Command {
examples := []general.Example{
{Desc: "Create a resource from a file", Command: "egctl create -f <filename>.yaml"},
{Desc: "Create a resource from stdin", Command: "cat <filename>.yaml | egctl create -f -"},
}

var specFile string
cmd := &cobra.Command{
Use: "create",
Short: "Create a resource from a file or from stdin.",
Example: createMultiExample(examples),
Args: func(cmd *cobra.Command, args []string) error {
if specFile == "" {
return errors.New("yaml file is required")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
visitor := general.BuildSpecVisitor(specFile, cmd)
visitor.Visit(func(s *general.Spec) error {
var err error
defer func() {
if err != nil {
general.ExitWithError(err)
}
}()

switch s.Kind {
case resources.CustomDataKind().Kind:
err = resources.CreateCustomDataKind(cmd, s)
case resources.CustomData().Kind:
err = resources.CreateCustomData(cmd, s)
default:
err = resources.CreateObject(cmd, s)
}
return err
})
visitor.Close()
},
}

cmd.Flags().StringVarP(&specFile, "file", "f", "", "A yaml file specifying the object.")
cmd := create.Cmd()
cmd.AddCommand(create.HTTPProxyCmd())
return cmd
}
73 changes: 73 additions & 0 deletions cmd/client/commandv2/create/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, MegaEase
* 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:https://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 create provides create commands.
package create

import (
"errors"

"github.com/megaease/easegress/v2/cmd/client/general"
"github.com/megaease/easegress/v2/cmd/client/resources"
"github.com/spf13/cobra"
)

// Cmd returns create command.
func Cmd() *cobra.Command {
examples := []general.Example{
{Desc: "Create a resource from a file", Command: "egctl create -f <filename>.yaml"},
{Desc: "Create a resource from stdin", Command: "cat <filename>.yaml | egctl create -f -"},
}

var specFile string
cmd := &cobra.Command{
Use: "create",
Short: "Create a resource from a file or from stdin.",
Example: general.CreateMultiExample(examples),
Args: func(cmd *cobra.Command, args []string) error {
if specFile == "" {
return errors.New("yaml file is required")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
visitor := general.BuildSpecVisitor(specFile, cmd)
visitor.Visit(func(s *general.Spec) error {
var err error
defer func() {
if err != nil {
general.ExitWithError(err)
}
}()

switch s.Kind {
case resources.CustomDataKind().Kind:
err = resources.CreateCustomDataKind(cmd, s)
case resources.CustomData().Kind:
err = resources.CreateCustomData(cmd, s)
default:
err = resources.CreateObject(cmd, s)
}
return err
})
visitor.Close()
},
}

cmd.Flags().StringVarP(&specFile, "file", "f", "", "A yaml file specifying the object.")
return cmd
}
30 changes: 30 additions & 0 deletions cmd/client/commandv2/create/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2017, MegaEase
* 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:https://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 create provides create commands.
package create

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCmd(t *testing.T) {
cmd := Cmd()
assert.NotNil(t, cmd)
}
Loading

0 comments on commit 8f2dc59

Please sign in to comment.