Skip to content

Commit

Permalink
abstract to dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
mostlikelee committed Nov 11, 2024
1 parent 4cc127f commit 61e1516
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 58 deletions.
55 changes: 55 additions & 0 deletions orbit/pkg/dialog/dialog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package dialog

// Dialog represents a UI dialog that can be displayed to the end user
// on a host

import (
"context"
"errors"
"time"
)

var (
// ErrCanceled is returned when the dialog is canceled by the cancel button.
ErrCanceled = errors.New("dialog canceled")
// ErrTimeout is returned when the dialog is automatically closed due to a timeout.
ErrTimeout = errors.New("dialog timed out")
// ErrUnknown is returned when an unknown error occurs.
ErrUnknown = errors.New("unknown error")
)

type Dialog interface {
// ShowEntry displays a dialog that accepts end user input. It returns the entered
// text or errors ErrCanceled, ErrTimeout, or ErrUnknown.
ShowEntry(ctx context.Context, opts EntryOptions) ([]byte, error)
// ShowInfo displays a dialog that displays information. It returns an error if the dialog
// could not be displayed.
ShowInfo(ctx context.Context, opts InfoOptions) error
}

// EntryOptions represents options for a dialog that accepts end user input.
type EntryOptions struct {
// Title sets the title of the dialog.
Title string

// Text sets the text of the dialog.
Text string

// HideText hides the text entered by the user.
HideText bool

// TimeOut sets the time in seconds before the dialog is automatically closed.
TimeOut time.Duration
}

// InfoOptions represents options for a dialog that displays information.
type InfoOptions struct {
// Title sets the title of the dialog.
Title string

// Text sets the text of the dialog.
Text string

// Timeout sets the time in seconds before the dialog is automatically closed.
TimeOut time.Duration
}
51 changes: 9 additions & 42 deletions orbit/pkg/zenity/zenity.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package zenity

import (
"context"
"errors"
"fmt"
"time"

"github.com/fleetdm/fleet/v4/orbit/pkg/dialog"
"github.com/fleetdm/fleet/v4/orbit/pkg/execuser"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
)
Expand All @@ -15,40 +14,8 @@ type Zenity struct {
execCmdFn func(ctx context.Context, args ...string) ([]byte, int, error)
}

var (
ErrCanceled = errors.New("dialog canceled")
ErrTimeout = errors.New("dialog timed out")
ErrUnknown = errors.New("unknown error")
)

// EntryOptions represents options for the Entry dialog.
type EntryOptions struct {
// Title sets the title of the dialog.
Title string

// Text sets the text of the dialog.
Text string

// HideText hides the text entered by the user.
HideText bool

// TimeOut sets the time in seconds before the dialog is automatically closed.
TimeOut time.Duration
}

// InfoOptions represents options for the Info dialog.
type InfoOptions struct {
// Title sets the title of the dialog.
Title string

// Text sets the text of the dialog.
Text string

// Timeout sets the time in seconds before the dialog is automatically closed.
TimeOut time.Duration
}

// NewZenity creates a new Zenity dialog instance for zenity v4 on Linux.
// Zenity implements the Dialog interface.
func New() *Zenity {
return &Zenity{
execCmdFn: execCmd,
Expand All @@ -57,7 +24,7 @@ func New() *Zenity {

// ShowEntry displays an dialog that accepts end user input. It returns the entered
// text or errors ErrCanceled, ErrTimeout, or ErrUnknown.
func (z *Zenity) ShowEntry(ctx context.Context, opts EntryOptions) ([]byte, error) {
func (z *Zenity) ShowEntry(ctx context.Context, opts dialog.EntryOptions) ([]byte, error) {
args := []string{"--entry"}
if opts.Title != "" {
args = append(args, fmt.Sprintf("--title=%s", opts.Title))
Expand All @@ -76,19 +43,19 @@ func (z *Zenity) ShowEntry(ctx context.Context, opts EntryOptions) ([]byte, erro
if err != nil {
switch statusCode {
case 1:
return nil, ctxerr.Wrap(ctx, ErrCanceled)
return nil, ctxerr.Wrap(ctx, dialog.ErrCanceled)
case 5:
return nil, ctxerr.Wrap(ctx, ErrTimeout)
return nil, ctxerr.Wrap(ctx, dialog.ErrTimeout)
default:
return nil, ctxerr.Wrap(ctx, ErrUnknown, err.Error())
return nil, ctxerr.Wrap(ctx, dialog.ErrUnknown, err.Error())
}
}

return output, nil
}

// ShowInfo displays an information dialog. It returns errors ErrTimeout or ErrUnknown.
func (z *Zenity) ShowInfo(ctx context.Context, opts InfoOptions) error {
func (z *Zenity) ShowInfo(ctx context.Context, opts dialog.InfoOptions) error {
args := []string{"--info"}
if opts.Title != "" {
args = append(args, fmt.Sprintf("--title=%s", opts.Title))
Expand All @@ -104,9 +71,9 @@ func (z *Zenity) ShowInfo(ctx context.Context, opts InfoOptions) error {
if err != nil {
switch statusCode {
case 5:
return ctxerr.Wrap(ctx, ErrTimeout)
return ctxerr.Wrap(ctx, dialog.ErrTimeout)
default:
return ctxerr.Wrap(ctx, ErrUnknown, err.Error())
return ctxerr.Wrap(ctx, dialog.ErrUnknown, err.Error())
}
}

Expand Down
29 changes: 15 additions & 14 deletions orbit/pkg/zenity/zenity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"
"time"

"github.com/fleetdm/fleet/v4/orbit/pkg/dialog"
"github.com/stretchr/testify/require"
"github.com/tj/assert"
)
Expand All @@ -32,20 +33,20 @@ func TestShowEntryArgs(t *testing.T) {

testCases := []struct {
name string
opts EntryOptions
opts dialog.EntryOptions
expectedArgs []string
}{
{
name: "Basic Entry",
opts: EntryOptions{
opts: dialog.EntryOptions{
Title: "A Title",
Text: "Some text",
},
expectedArgs: []string{"--entry", "--title=A Title", "--text=Some text"},
},
{
name: "All Options",
opts: EntryOptions{
opts: dialog.EntryOptions{
Title: "Another Title",
Text: "Some more text",
HideText: true,
Expand Down Expand Up @@ -82,17 +83,17 @@ func TestShowEntryError(t *testing.T) {
{
name: "Dialog Cancelled",
exitCode: 1,
expectedErr: ErrCanceled,
expectedErr: dialog.ErrCanceled,
},
{
name: "Dialog Timed Out",
exitCode: 5,
expectedErr: ErrTimeout,
expectedErr: dialog.ErrTimeout,
},
{
name: "Unknown Error",
exitCode: 99,
expectedErr: ErrUnknown,
expectedErr: dialog.ErrUnknown,
},
}

Expand All @@ -104,7 +105,7 @@ func TestShowEntryError(t *testing.T) {
z := &Zenity{
execCmdFn: mock.run,
}
output, err := z.ShowEntry(ctx, EntryOptions{})
output, err := z.ShowEntry(ctx, dialog.EntryOptions{})
require.ErrorIs(t, err, tt.expectedErr)
assert.Nil(t, output)
})
Expand All @@ -120,7 +121,7 @@ func TestShowEntrySuccess(t *testing.T) {
z := &Zenity{
execCmdFn: mock.run,
}
output, err := z.ShowEntry(ctx, EntryOptions{})
output, err := z.ShowEntry(ctx, dialog.EntryOptions{})
assert.NoError(t, err)
assert.Equal(t, []byte("some output"), output)
}
Expand All @@ -130,17 +131,17 @@ func TestShowInfoArgs(t *testing.T) {

testCases := []struct {
name string
opts InfoOptions
opts dialog.InfoOptions
expectedArgs []string
}{
{
name: "Basic Entry",
opts: InfoOptions{},
opts: dialog.InfoOptions{},
expectedArgs: []string{"--info"},
},
{
name: "All Options",
opts: InfoOptions{
opts: dialog.InfoOptions{
Title: "Another Title",
Text: "Some more text",
TimeOut: 1 * time.Minute,
Expand Down Expand Up @@ -173,12 +174,12 @@ func TestShowInfoError(t *testing.T) {
{
name: "Dialog Timed Out",
exitCode: 5,
expectedErr: ErrTimeout,
expectedErr: dialog.ErrTimeout,
},
{
name: "Unknown Error",
exitCode: 99,
expectedErr: ErrUnknown,
expectedErr: dialog.ErrUnknown,
},
}

Expand All @@ -190,7 +191,7 @@ func TestShowInfoError(t *testing.T) {
z := &Zenity{
execCmdFn: mock.run,
}
err := z.ShowInfo(ctx, InfoOptions{})
err := z.ShowInfo(ctx, dialog.InfoOptions{})
require.ErrorIs(t, err, tt.expectedErr)
})
}
Expand Down
5 changes: 3 additions & 2 deletions tools/zenity/main.go → tools/dialog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"fmt"
"time"

"github.com/fleetdm/fleet/v4/orbit/pkg/dialog"
"github.com/fleetdm/fleet/v4/orbit/pkg/zenity"
)

func main() {
prompt := zenity.New()
ctx := context.Background()

output, err := prompt.ShowEntry(ctx, zenity.EntryOptions{
output, err := prompt.ShowEntry(ctx, dialog.EntryOptions{
Title: "Zenity Test Entry Title",
Text: "Zenity Test Entry Text",
HideText: true,
Expand All @@ -23,7 +24,7 @@ func main() {
panic(err)
}

err = prompt.ShowInfo(ctx, zenity.InfoOptions{
err = prompt.ShowInfo(ctx, dialog.InfoOptions{
Title: "Zenity Test Info Title",
Text: "Result: " + string(output),
TimeOut: 10 * time.Second,
Expand Down

0 comments on commit 61e1516

Please sign in to comment.