Skip to content

Commit

Permalink
Add probe cobra command (istio#97)
Browse files Browse the repository at this point in the history
* Add probe cobra command

mixer, galley and security(istio_ca) have `probe` sub-command and
their codes are duplicated.

This patch adds probe cobra command to be commonly used.

* Fix review comments:

* Add the func Validate() to produce proper error.
* Add the Example.
* Add the LongDesc to understand the option more easily.
* Add the comment for CobraCommand for probe.
* Add copyright banner

* Fix typo
  • Loading branch information
nak3 authored Feb 11, 2020
1 parent 50ca236 commit 045db3e
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 1 deletion.
62 changes: 62 additions & 0 deletions probe/cobra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2020 Istio Authors
//
// 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 probe

import (
"fmt"

"github.com/spf13/cobra"
)

var (
probeLongDesc = `Check the liveness or readiness of a locally-running server
Check if the target file is older than the interval. The locally-running server updates the last modified time
(you need to enable it on server side), so probe command compares it with current time.`

probeExample = `
# Check if the target file '/health' is older than interval of 4 seconds
probe --probe-path=/health --interval=4s`
)

// CobraCommand returns a command used to probe liveness or readiness of a locally-running server
// by checking the last modified time of target file.
func CobraCommand() *cobra.Command {
var probeOptions Options

prb := &cobra.Command{
Use: "probe",
Short: "Check the liveness or readiness of a locally-running server",
Long: probeLongDesc,
Args: cobra.ExactArgs(0),
Example: probeExample,
RunE: func(cmd *cobra.Command, _ []string) error {
if err := probeOptions.Validate(); err != nil {
return err
}
if err := NewFileClient(&probeOptions).GetStatus(); err != nil {
return fmt.Errorf("fail on inspecting path %s: %v", probeOptions.Path, err)
}
fmt.Fprintf(cmd.OutOrStdout(), "OK")
return nil
},
}
prb.PersistentFlags().StringVar(&probeOptions.Path, "probe-path", "",
"Path of the file for checking the last modified time.")
prb.PersistentFlags().DurationVar(&probeOptions.UpdateInterval, "interval", 0,
"Duration used for checking the target file's last modified time.")

return prb
}
66 changes: 66 additions & 0 deletions probe/cobra_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2020 Istio Authors

// 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 probe

import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
)

func TestOpts(t *testing.T) {
fp, err := ioutil.TempFile(os.TempDir(), t.Name())
if err != nil {
t.Fatalf("failed to create temp file")
}
cases := []struct {
args string
expectFail bool
}{
{
"probe",
true,
},
{
"extra-args",
true,
},
{
fmt.Sprintf("--probe-path=%s.invalid --interval=1s", fp.Name()),
true,
},
{
fmt.Sprintf("--probe-path=%s --interval=1s", fp.Name()),
false,
},
}

for _, v := range cases {
t.Run(v.args, func(t *testing.T) {
cmd := CobraCommand()
cmd.SetArgs(strings.Split(v.args, " "))
err := cmd.Execute()

if !v.expectFail && err != nil {
t.Errorf("Got %v, expecting success", err)
}
if v.expectFail && err == nil {
t.Errorf("Expected failure, got success")
}
})
}
}
19 changes: 18 additions & 1 deletion probe/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

package probe

import "time"
import (
"fmt"
"time"
)

// Options customizes the parameters of a probe.
type Options struct {
Expand All @@ -30,3 +33,17 @@ type Options struct {
func (o *Options) IsValid() bool {
return o != nil && o.Path != "" && o.UpdateInterval > 0*time.Second
}

// Validate returns true if some values are filled into the options.
func (o *Options) Validate() error {
if o == nil {
return fmt.Errorf("option is empty")
}
if o.Path == "" {
return fmt.Errorf("probe-path must be specified")
}
if o.UpdateInterval <= 0*time.Second {
return fmt.Errorf("interval must be greater than zero")
}
return nil
}
15 changes: 15 additions & 0 deletions probe/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,35 @@ func TestOption(t *testing.T) {
if o.IsValid() {
t.Error("nil should not be valid")
}
if err := o.Validate(); err == nil {
t.Errorf("nil should produce an error")
}
o = &Options{}
if o.IsValid() {
t.Errorf("Empty option %+v should not be valid", o)
}
if err := o.Validate(); err == nil {
t.Errorf("Empty option %+v should produce an error", o)
}
o.Path = "foo"
if o.IsValid() {
t.Errorf("%+v should not be valid since interval is missing", o)
}
if err := o.Validate(); err == nil {
t.Errorf("%+v should produce an error since interval is missing", o)
}
o.UpdateInterval = time.Second
if !o.IsValid() {
t.Errorf("%+v should be valid", o)
}
if err := o.Validate(); err != nil {
t.Errorf("%+v should be no error but got %v", o, err)
}
o.Path = ""
if o.IsValid() {
t.Errorf("%+v should not be valid since path is missing", o)
}
if err := o.Validate(); err == nil {
t.Errorf("%+v should produce an error since path is missing", o)
}
}

0 comments on commit 045db3e

Please sign in to comment.