-
Notifications
You must be signed in to change notification settings - Fork 243
/
watch.go
178 lines (147 loc) · 5.65 KB
/
watch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package component
import (
"fmt"
"os"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/occlient"
appCmd "github.com/openshift/odo/pkg/odo/cli/application"
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/pkg/errors"
ktemplates "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
"github.com/golang/glog"
"github.com/openshift/odo/pkg/odo/genericclioptions"
"github.com/openshift/odo/pkg/component"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/util"
"github.com/spf13/cobra"
)
// WatchRecommendedCommandName is the recommended watch command name
const WatchRecommendedCommandName = "watch"
var watchLongDesc = ktemplates.LongDesc(`Watch for changes, update component on change.`)
var watchExample = ktemplates.Examples(` # Watch for changes in directory for current component
%[1]s
# Watch for changes in directory for component called frontend
%[1]s frontend
`)
// WatchOptions contains attributes of the watch command
type WatchOptions struct {
ignores []string
delay int
show bool
sourceType config.SrcType
sourcePath string
componentContext string
client *occlient.Client
localConfig *config.LocalConfigInfo
*genericclioptions.Context
}
// NewWatchOptions returns new instance of WatchOptions
func NewWatchOptions() *WatchOptions {
return &WatchOptions{}
}
// Complete completes watch args
func (wo *WatchOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
wo.client = genericclioptions.Client(cmd)
// Retrieve configuration
conf, err := config.NewLocalConfigInfo(wo.componentContext)
if err != nil {
return errors.Wrap(err, "unable to retrieve configuration information")
}
// Set the necessary values within WatchOptions
wo.localConfig = conf
wo.sourceType = conf.LocalConfig.GetSourceType()
// Get SourceLocation here...
wo.sourcePath, err = conf.GetOSSourcePath()
if err != nil {
return errors.Wrap(err, "unable to retrieve absolute path to source location")
}
// Apply ignore information
err = genericclioptions.ApplyIgnore(&wo.ignores, wo.sourcePath)
if err != nil {
return errors.Wrap(err, "unable to apply ignore information")
}
// Set the correct context
wo.Context = genericclioptions.NewContextCreatingAppIfNeeded(cmd)
return
}
// Validate validates the watch parameters
func (wo *WatchOptions) Validate() (err error) {
// Validate source of component is either local source or binary path until git watch is supported
if wo.sourceType != "binary" && wo.sourceType != "local" {
return fmt.Errorf("Watch is supported by binary and local components only and source type of component %s is %s",
wo.localConfig.GetName(),
wo.sourceType)
}
// Validate component path existence and accessibility permissions for odo
if _, err := os.Stat(wo.sourcePath); err != nil {
return errors.Wrapf(err, "Cannot watch %s", wo.sourcePath)
}
// Delay interval cannot be -ve
if wo.delay < 0 {
return fmt.Errorf("Delay cannot be lesser than 0 and delay=0 means changes will be pushed as soon as they are detected which can cause performance issues")
}
// Print a debug message warning user if delay is set to 0
if wo.delay == 0 {
glog.V(4).Infof("delay=0 means changes will be pushed as soon as they are detected which can cause performance issues")
}
cmpName := wo.localConfig.GetName()
appName := wo.localConfig.GetApplication()
exists, err := component.Exists(wo.Client, cmpName, appName)
if err != nil {
return
}
if !exists {
return fmt.Errorf("component does not exist. Please use `odo push` to create you component")
}
return
}
// Run has the logic to perform the required actions as part of command
func (wo *WatchOptions) Run() (err error) {
err = component.WatchAndPush(
wo.Context.Client,
os.Stdout,
component.WatchParameters{
ComponentName: wo.localConfig.GetName(),
ApplicationName: wo.Context.Application,
Path: wo.sourcePath,
FileIgnores: util.GetAbsGlobExps(wo.sourcePath, wo.ignores),
PushDiffDelay: wo.delay,
StartChan: nil,
ExtChan: make(chan bool),
WatchHandler: component.PushLocal,
Show: wo.show,
},
)
if err != nil {
return errors.Wrapf(err, "Error while trying to watch %s", wo.sourcePath)
}
return
}
// NewCmdWatch implements the watch odo command
func NewCmdWatch(name, fullName string) *cobra.Command {
wo := NewWatchOptions()
var watchCmd = &cobra.Command{
Use: fmt.Sprintf("%s [component name]", name),
Short: "Watch for changes, update component on change",
Long: watchLongDesc,
Example: fmt.Sprintf(watchExample, fullName),
Args: cobra.MaximumNArgs(1),
Annotations: map[string]string{"command": "component"},
Run: func(cmd *cobra.Command, args []string) {
genericclioptions.GenericRun(wo, cmd, args)
},
}
watchCmd.Flags().BoolVar(&wo.show, "show-log", false, "If enabled, logs will be shown when built")
watchCmd.Flags().StringSliceVar(&wo.ignores, "ignore", []string{}, "Files or folders to be ignored via glob expressions.")
watchCmd.Flags().IntVar(&wo.delay, "delay", 1, "Time in seconds between a detection of code change and push.delay=0 means changes will be pushed as soon as they are detected which can cause performance issues")
watchCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
// Adding context flag
genericclioptions.AddContextFlag(watchCmd, &wo.componentContext)
//Adding `--application` flag
appCmd.AddApplicationFlag(watchCmd)
//Adding `--project` flag
projectCmd.AddProjectFlag(watchCmd)
completion.RegisterCommandHandler(watchCmd, completion.ComponentNameCompletionHandler)
return watchCmd
}