Skip to content

Commit

Permalink
refactoring wind scheduler, still need to do osx
Browse files Browse the repository at this point in the history
  • Loading branch information
creativeprojects committed Jul 10, 2020
1 parent f6081c7 commit e837a2e
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 57 deletions.
21 changes: 12 additions & 9 deletions examples/windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@ default:
self:
inherit: default
initialize: true
schedule:
- "Mon..Fri *:00,30" # every 15 minutes
- "Mon..Fri *:15,45" # both combined together
- "Sat,Sun 0,12:*"
schedule-permission: user
backup:
source: "."
schedule:
- "Mon..Fri *:00,30" # every 15 minutes
- "Mon..Fri *:15,45" # both combined together
- "Sat,Sun 0,12:*"
schedule-permission: user

test:
inherit: default
initialize: true
schedule:
- "2020-07-31"
- "*:0,15,30,45"
schedule-permission: user
backup:
source: "."
schedule:
- "2020-07-31"
- "*:0,15,30,45"
schedule-permission: user
check:
schedule: "*-*-1"
schedule-permission: user
3 changes: 0 additions & 3 deletions schedule/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ type Config interface {
// Job scheduler
type Job struct {
config Config
// configFile string
// profile *config.Profile
// schedules map[config.ScheduledCommand][]*calendar.Event
}

// NewJob instantiates a Job object to schedule jobs
Expand Down
36 changes: 11 additions & 25 deletions schedule/schedule_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,25 @@
package schedule

import (
"fmt"
"os"

"github.com/creativeprojects/resticprofile/calendar"
"github.com/creativeprojects/resticprofile/constants"
"github.com/creativeprojects/resticprofile/win"
)

// createJob is creating the task scheduler job.
func (j *Job) createJob(command string, schedules []*calendar.Event) error {
binary, err := os.Executable()
if err != nil {
return err
}
wd, err := os.Getwd()
if err != nil {
return err
}
args := fmt.Sprintf("--no-ansi --config %s --name %s backup", j.configFile, j.profile.Name)
description := fmt.Sprintf("restic backup using profile '%s' from '%s'", j.profile.Name, j.configFile)
// checkSystem does nothing on windows as the task scheduler is always available
func checkSystem() error {
return nil
}

// createJob is creating the task scheduler job.
func (j *Job) createJob(schedules []*calendar.Event) error {
// default permission will be system
permission := win.SystemAccount
if j.profile.Backup.SchedulePermission == constants.SchedulePermissionUser {
if j.config.Permission() == constants.SchedulePermissionUser {
permission = win.UserAccount
}
taskScheduler := win.NewTaskScheduler(j.profile)
err = taskScheduler.Create(binary, args, wd, description, schedules, permission)
taskScheduler := win.NewTaskScheduler(j.config)
err := taskScheduler.Create(schedules, permission)
if err != nil {
return err
}
Expand All @@ -39,22 +30,17 @@ func (j *Job) createJob(command string, schedules []*calendar.Event) error {

// removeJob is deleting the task scheduler job
func (j *Job) removeJob() error {
taskScheduler := win.NewTaskScheduler(j.profile)
taskScheduler := win.NewTaskScheduler(j.config)
err := taskScheduler.Delete()
if err != nil {
return err
}
return nil
}

// checkSystem does nothing on windows as the task scheduler is always available
func checkSystem() error {
return nil
}

// displayStatus display some information about the task scheduler job
func (j *Job) displayStatus(command string) error {
taskScheduler := win.NewTaskScheduler(j.profile)
taskScheduler := win.NewTaskScheduler(j.config)
err := taskScheduler.Status()
if err != nil {
return err
Expand Down
65 changes: 46 additions & 19 deletions win/taskscheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"fmt"
"os"
"os/user"
"strings"
"text/tabwriter"
"time"

"github.com/capnspacehook/taskmaster"
"github.com/creativeprojects/resticprofile/calendar"
"github.com/creativeprojects/resticprofile/config"
"github.com/creativeprojects/resticprofile/term"
"github.com/rickb777/date/period"
)
Expand Down Expand Up @@ -45,27 +45,40 @@ const (
SystemAccount
)

// Config contains all the information needed to schedule a Job
type Config interface {
Title() string
SubTitle() string
JobDescription() string
TimerDescription() string
Schedules() []string
Permission() string
WorkingDirectory() string
Command() string
Arguments() []string
}

// TaskScheduler wraps up a task scheduler service
type TaskScheduler struct {
profile *config.Profile
config Config
}

// NewTaskScheduler creates a new service to talk to windows task scheduler
func NewTaskScheduler(profile *config.Profile) *TaskScheduler {
func NewTaskScheduler(config Config) *TaskScheduler {
return &TaskScheduler{
profile: profile,
config: config,
}
}

// Create a task
func (s *TaskScheduler) Create(binary, args, workingDir, description string, schedules []*calendar.Event, permission Permission) error {
func (s *TaskScheduler) Create(schedules []*calendar.Event, permission Permission) error {
if permission == SystemAccount {
return s.createSystemTask(binary, args, workingDir, description, schedules)
return s.createSystemTask(schedules)
}
return s.createUserTask(binary, args, workingDir, description, schedules)
return s.createUserTask(schedules)
}

func (s *TaskScheduler) createUserTask(binary, args, workingDir, description string, schedules []*calendar.Event) error {
func (s *TaskScheduler) createUserTask(schedules []*calendar.Event) error {
currentUser, err := user.Current()
if err != nil {
return err
Expand All @@ -84,40 +97,54 @@ func (s *TaskScheduler) createUserTask(binary, args, workingDir, description str
defer taskService.Disconnect()

task := taskService.NewTaskDefinition()
task.AddExecAction(binary, args, workingDir, "")
task.AddExecAction(
s.config.Command(),
strings.Join(s.config.Arguments(), " "),
s.config.WorkingDirectory(),
"")
task.Principal.LogonType = taskmaster.TASK_LOGON_PASSWORD
task.Principal.RunLevel = taskmaster.TASK_RUNLEVEL_LUA
task.Principal.UserID = currentUser.Username
task.RegistrationInfo.Author = "resticprofile"
task.RegistrationInfo.Description = description
task.RegistrationInfo.Description = s.config.JobDescription()

s.createSchedules(&task, schedules)

_, _, err = taskService.CreateTaskEx(getTaskPath(s.profile.Name), task, currentUser.Username, password, taskmaster.TASK_LOGON_PASSWORD, true)
_, _, err = taskService.CreateTaskEx(
getTaskPath(s.config.Title(), s.config.SubTitle()),
task,
currentUser.Username,
password,
taskmaster.TASK_LOGON_PASSWORD,
true)
if err != nil {
return err
}
return nil
}

func (s *TaskScheduler) createSystemTask(binary, args, workingDir, description string, schedules []*calendar.Event) error {
func (s *TaskScheduler) createSystemTask(schedules []*calendar.Event) error {
taskService, err := s.connect()
if err != nil {
return err
}
defer taskService.Disconnect()

task := taskService.NewTaskDefinition()
task.AddExecAction(binary, args, workingDir, "")
task.AddExecAction(
s.config.Command(),
strings.Join(s.config.Arguments(), " "),
s.config.WorkingDirectory(),
"")
task.Principal.LogonType = taskmaster.TASK_LOGON_SERVICE_ACCOUNT
task.Principal.RunLevel = taskmaster.TASK_RUNLEVEL_HIGHEST
task.Principal.UserID = "SYSTEM"
task.RegistrationInfo.Author = "resticprofile"
task.RegistrationInfo.Description = description
task.RegistrationInfo.Description = s.config.JobDescription()

s.createSchedules(&task, schedules)

_, _, err = taskService.CreateTask(getTaskPath(s.profile.Name), task, true)
_, _, err = taskService.CreateTask(getTaskPath(s.config.Title(), s.config.SubTitle()), task, true)
if err != nil {
return err
}
Expand Down Expand Up @@ -184,7 +211,7 @@ func (s *TaskScheduler) Delete() error {
}
defer taskService.Disconnect()

err = taskService.DeleteTask(getTaskPath(s.profile.Name))
err = taskService.DeleteTask(getTaskPath(s.config.Title(), s.config.SubTitle()))
if err != nil {
return err
}
Expand All @@ -199,7 +226,7 @@ func (s *TaskScheduler) Status() error {
}
defer taskService.Disconnect()

taskName := getTaskPath(s.profile.Name)
taskName := getTaskPath(s.config.Title(), s.config.SubTitle())
registeredTask, err := taskService.GetRegisteredTask(taskName)
if err != nil {
return err
Expand Down Expand Up @@ -230,6 +257,6 @@ func (s *TaskScheduler) connect() (*taskmaster.TaskService, error) {
return taskmaster.Connect("", "", "", "")
}

func getTaskPath(profileName string) string {
return tasksPath + profileName
func getTaskPath(profileName, commandName string) string {
return fmt.Sprintf("%s%s %s", tasksPath, profileName, commandName)
}
2 changes: 1 addition & 1 deletion win/taskscheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestTaskSchedulerConversion(t *testing.T) {
schedules[index] = event
}
task := taskmaster.Definition{}
taskScheduler := NewTaskScheduler(&config.Profile{})
taskScheduler := NewTaskScheduler(&config.ScheduleConfig{})
taskScheduler.createSchedules(&task, schedules)
// first task should be a single event
singleEvent, ok := task.Triggers[0].(taskmaster.TimeTrigger)
Expand Down

0 comments on commit e837a2e

Please sign in to comment.