Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
caddy
Commits
b7167803
Commit
b7167803
authored
Oct 02, 2017
by
elcore
Committed by
Matt Holt
Oct 01, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
startupshutdown: is an alias for 'on' (#1880)
parent
97710ced
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
84 additions
and
87 deletions
+84
-87
startupshutdown/startupshutdown.go
startupshutdown/startupshutdown.go
+47
-39
startupshutdown/startupshutdown_test.go
startupshutdown/startupshutdown_test.go
+37
-48
No files found.
startupshutdown/startupshutdown.go
View file @
b7167803
...
...
@@ -15,12 +15,12 @@
package
startupshutdown
import
(
"log"
"os"
"os/exec"
"fmt"
"strings"
"github.com/google/uuid"
"github.com/mholt/caddy"
"github.com/mholt/caddy/onevent/hook"
)
func
init
()
{
...
...
@@ -28,60 +28,68 @@ func init() {
caddy
.
RegisterPlugin
(
"shutdown"
,
caddy
.
Plugin
{
Action
:
Shutdown
})
}
// Startup registers a startup callback to execute during server start.
// Startup
(an alias for 'on startup')
registers a startup callback to execute during server start.
func
Startup
(
c
*
caddy
.
Controller
)
error
{
return
registerCallback
(
c
,
c
.
OnFirstStartup
)
config
,
err
:=
onParse
(
c
,
caddy
.
InstanceStartupEvent
)
if
err
!=
nil
{
return
c
.
ArgErr
()
}
// Register Event Hooks.
for
_
,
cfg
:=
range
config
{
caddy
.
RegisterEventHook
(
"on-"
+
cfg
.
ID
,
cfg
.
Hook
)
}
fmt
.
Println
(
"NOTICE: Startup directive will be removed in a later version. Please migrate to 'on startup'"
)
return
nil
}
// Shutdown
registers a shutdown callback to execute during server stop
.
// Shutdown
(an alias for 'on shutdown') registers a shutdown callback to execute during server start
.
func
Shutdown
(
c
*
caddy
.
Controller
)
error
{
return
registerCallback
(
c
,
c
.
OnFinalShutdown
)
config
,
err
:=
onParse
(
c
,
caddy
.
ShutdownEvent
)
if
err
!=
nil
{
return
c
.
ArgErr
()
}
// Register Event Hooks.
for
_
,
cfg
:=
range
config
{
caddy
.
RegisterEventHook
(
"on-"
+
cfg
.
ID
,
cfg
.
Hook
)
}
fmt
.
Println
(
"NOTICE: Shutdown directive will be removed in a later version. Please migrate to 'on shutdown'"
)
return
nil
}
// registerCallback registers a callback function to execute by
// using c to parse the directive. It registers the callback
// to be executed using registerFunc.
func
registerCallback
(
c
*
caddy
.
Controller
,
registerFunc
func
(
func
()
error
))
error
{
var
funcs
[]
func
()
error
func
onParse
(
c
*
caddy
.
Controller
,
event
caddy
.
EventName
)
([]
*
hook
.
Config
,
error
)
{
var
config
[]
*
hook
.
Config
for
c
.
Next
()
{
cfg
:=
new
(
hook
.
Config
)
args
:=
c
.
RemainingArgs
()
if
len
(
args
)
==
0
{
return
c
.
ArgErr
()
return
c
onfig
,
c
.
ArgErr
()
}
nonblock
:=
false
if
len
(
args
)
>
1
&&
args
[
len
(
args
)
-
1
]
==
"&"
{
// Run command in background; non-blocking
nonblock
=
true
args
=
args
[
:
len
(
args
)
-
1
]
}
// Configure Event.
cfg
.
Event
=
event
// Assign an unique ID.
cfg
.
ID
=
uuid
.
New
()
.
String
()
// Extract command and arguments.
command
,
args
,
err
:=
caddy
.
SplitCommandAndArgs
(
strings
.
Join
(
args
,
" "
))
if
err
!=
nil
{
return
c
.
Err
(
err
.
Error
())
return
c
onfig
,
c
.
Err
(
err
.
Error
())
}
fn
:=
func
()
error
{
cmd
:=
exec
.
Command
(
command
,
args
...
)
cmd
.
Stdin
=
os
.
Stdin
cmd
.
Stdout
=
os
.
Stdout
cmd
.
Stderr
=
os
.
Stderr
if
nonblock
{
log
.
Printf
(
"[INFO] Nonblocking Command:
\"
%s %s
\"
"
,
command
,
strings
.
Join
(
args
,
" "
))
return
cmd
.
Start
()
}
log
.
Printf
(
"[INFO] Blocking Command:
\"
%s %s
\"
"
,
command
,
strings
.
Join
(
args
,
" "
))
return
cmd
.
Run
()
}
cfg
.
Command
=
command
cfg
.
Args
=
args
funcs
=
append
(
funcs
,
fn
)
config
=
append
(
config
,
cfg
)
}
return
c
.
OncePerServerBlock
(
func
()
error
{
for
_
,
fn
:=
range
funcs
{
registerFunc
(
fn
)
}
return
nil
})
return
config
,
nil
}
startupshutdown/startupshutdown_test.go
View file @
b7167803
...
...
@@ -15,66 +15,55 @@
package
startupshutdown
import
(
"os"
"path/filepath"
"strconv"
"testing"
"time"
"github.com/mholt/caddy"
)
// The Startup function's tests are symmetrical to Shutdown tests,
// because the Startup and Shutdown functions share virtually the
// same functionality
func
TestStartup
(
t
*
testing
.
T
)
{
tempDirPath
:=
os
.
TempDir
()
tests
:=
[]
struct
{
name
string
input
string
shouldErr
bool
}{
{
name
:
"noInput"
,
input
:
"startup"
,
shouldErr
:
true
},
{
name
:
"startup"
,
input
:
"startup cmd arg"
,
shouldErr
:
false
},
}
testDir
:=
filepath
.
Join
(
tempDirPath
,
"temp_dir_for_testing_startupshutdown"
)
defer
func
()
{
// clean up after non-blocking startup function quits
time
.
Sleep
(
500
*
time
.
Millisecond
)
os
.
RemoveAll
(
testDir
)
}()
osSenitiveTestDir
:=
filepath
.
FromSlash
(
testDir
)
os
.
RemoveAll
(
osSenitiveTestDir
)
// start with a clean slate
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
c
:=
caddy
.
NewTestController
(
""
,
test
.
input
)
var
registeredFunction
func
()
error
fakeRegister
:=
func
(
fn
func
()
error
)
{
registeredFunction
=
fn
err
:=
Startup
(
c
)
if
err
==
nil
&&
test
.
shouldErr
{
t
.
Error
(
"Test didn't error, but it should have"
)
}
else
if
err
!=
nil
&&
!
test
.
shouldErr
{
t
.
Errorf
(
"Test errored, but it shouldn't have; got '%v'"
,
err
)
}
})
}
}
func
TestShutdown
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
input
string
shouldExecutionErr
bool
should
RemoveErr
bool
name
string
input
string
should
Err
bool
}{
// test case #0 tests proper functionality blocking commands
{
"startup mkdir "
+
osSenitiveTestDir
,
false
,
false
},
// test case #1 tests proper functionality of non-blocking commands
{
"startup mkdir "
+
osSenitiveTestDir
+
" &"
,
false
,
true
},
// test case #2 tests handling of non-existent commands
{
"startup "
+
strconv
.
Itoa
(
int
(
time
.
Now
()
.
UnixNano
())),
true
,
true
},
{
name
:
"noInput"
,
input
:
"shutdown"
,
shouldErr
:
true
},
{
name
:
"shutdown"
,
input
:
"shutdown cmd arg"
,
shouldErr
:
false
},
}
for
i
,
test
:=
range
tests
{
c
:=
caddy
.
NewTestController
(
""
,
test
.
input
)
err
:=
registerCallback
(
c
,
fakeRegister
)
if
err
!=
nil
{
t
.
Errorf
(
"Expected no errors, got: %v"
,
err
)
}
if
registeredFunction
==
nil
{
t
.
Fatalf
(
"Expected function to be registered, but it wasn't"
)
}
err
=
registeredFunction
()
if
err
!=
nil
&&
!
test
.
shouldExecutionErr
{
t
.
Errorf
(
"Test %d received an error of:
\n
%v"
,
i
,
err
)
}
err
=
os
.
Remove
(
osSenitiveTestDir
)
if
err
!=
nil
&&
!
test
.
shouldRemoveErr
{
t
.
Errorf
(
"Test %d received an error of:
\n
%v"
,
i
,
err
)
}
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
c
:=
caddy
.
NewTestController
(
""
,
test
.
input
)
err
:=
Shutdown
(
c
)
if
err
==
nil
&&
test
.
shouldErr
{
t
.
Error
(
"Test didn't error, but it should have"
)
}
else
if
err
!=
nil
&&
!
test
.
shouldErr
{
t
.
Errorf
(
"Test errored, but it shouldn't have; got '%v'"
,
err
)
}
})
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment