diff --git a/README.md b/README.md index 7daf405..e85d6b1 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,6 @@ A minimally functional source requires a `fetch` action that returns items. TTL, TTD, and TTS can be configured at the source level by setting the environment variables `INTAKE_TTL`, `INTAKE_TTS`, or `INTAKE_TTS` to an integer value. These values override any `ttl`, `ttd`, or `tts` value returned by a fetch or action. -Intake provides integration with `cron`. -To create a cron job for a source, set the `INTAKE_CRON` environment variable to a five-element crontab spec (e.g. `0 0 * * *`). -The `intake crontab` command will synchronize source cron jobs to your crontab. - Automatic fetching can be configured by setting the `INTAKE_FETCH` environment variable to a fetch schedule. A fetch schedule may be: - `every `, where `` is a Go duration string diff --git a/cmd/crontab.go b/cmd/crontab.go deleted file mode 100644 index ef6976e..0000000 --- a/cmd/crontab.go +++ /dev/null @@ -1,51 +0,0 @@ -package cmd - -import ( - "fmt" - "log" - "sort" - - "github.com/Jaculabilis/intake/core" - "github.com/spf13/cobra" -) - -var crontabCmd = &cobra.Command{ - Use: "crontab", - Short: "Update crontab entries", - Long: `Update crontab entries. - -A source's cron job is defined by its INTAKE_CRON environment variable. -`, - Run: func(cmd *cobra.Command, args []string) { - crontab(boolArg(cmd, "list")) - }, -} - -func init() { - rootCmd.AddCommand(crontabCmd) - - crontabCmd.Flags().BoolP("list", "l", false, "List crontab entries") -} - -func crontab(list bool) { - db := openAndMigrateDb() - - specs, err := core.GetCronSources(db) - if err != nil { - log.Fatalf("error: failed to get crontab sources: %v", err) - } - if list { - var sources []string - for source := range specs { - sources = append(sources, source) - } - sort.Strings(sources) - for _, source := range sources { - fmt.Println(specs[source]) - } - } else { - if err := core.UpdateCrontab(db, specs); err != nil { - log.Fatalf("error: failed to update crontab: %v", err) - } - } -} diff --git a/cmd/sourceEnv.go b/cmd/sourceEnv.go index c769b15..cddeca3 100644 --- a/cmd/sourceEnv.go +++ b/cmd/sourceEnv.go @@ -3,7 +3,6 @@ package cmd import ( "fmt" "log" - "strings" "github.com/Jaculabilis/intake/core" "github.com/spf13/cobra" @@ -51,16 +50,4 @@ func sourceEnv(source string, env []string) { if err := core.SetEnvs(db, source, env); err != nil { log.Fatalf("failed to set envs: %v", err) } - - for _, envval := range env { - if strings.HasPrefix(envval, "INTAKE_CRON=") { - specs, err := core.GetCronSources(db) - if err != nil { - log.Fatalf("failed to get cron specs: %v", err) - } - if err = core.UpdateCrontab(db, specs); err != nil { - log.Fatalf("failed to update crontab: %v", err) - } - } - } } diff --git a/core/crontab.go b/core/crontab.go deleted file mode 100644 index 01516bd..0000000 --- a/core/crontab.go +++ /dev/null @@ -1,121 +0,0 @@ -package core - -import ( - "fmt" - "io" - "log" - "os" - "os/exec" - "sort" - "strings" -) - -var IntakeCronBegin = "### begin intake-managed crontab entries" -var IntakeCronEnd = "### end intake-managed crontab entries" - -func makeCrontabEntry(source string, spec string) string { - // TODO the /etc/profile setup is NixOS-specific, maybe there's another way to do this - return fmt.Sprintf("%-20s . /etc/profile; intake source fetch -s %s", spec, source) -} - -func GetCronSources(db DB) (specs map[string]string, err error) { - res, err := db.Query(` - select source, value - from envs - where name = 'INTAKE_CRON' - `) - if err != nil { - return nil, fmt.Errorf("failed to get source crontabs: %v", err) - } - specs = make(map[string]string) - for res.Next() { - var source string - var value string - if err = res.Scan(&source, &value); err != nil { - return nil, fmt.Errorf("failed to scan source crontab: %v", err) - } - specs[source] = makeCrontabEntry(source, value) - } - return -} - -// Update the intake-managed section of the user's crontab. -func UpdateCrontab(db DB, specs map[string]string) (err error) { - // If there is no crontab command available, quit early. - crontabPath, err := exec.LookPath("crontab") - if err != nil { - return fmt.Errorf("no crontab found") - } - - // Get the current crontab without extra header lines via `EDITOR=cat crontab -e` - cmdLoad := exec.Command(crontabPath, "-e") - cmdLoad.Env = append(os.Environ(), "EDITOR=cat") - output, err := cmdLoad.Output() - if err != nil { - return fmt.Errorf("error: failed to get current crontab: %v", err) - } - lines := strings.Split(string(output), "\n") - - // Sort the new intake crons - var sources []string - for source := range specs { - sources = append(sources, source) - } - sort.Strings(sources) - - // Splice the intake crons into the crontab - var newCrontab []string - headerFound := false - inSection := false - for i := range lines { - switch { - case !headerFound && lines[i] == IntakeCronBegin: - headerFound = true - inSection = true - newCrontab = append(newCrontab, IntakeCronBegin) - for _, source := range sources { - newCrontab = append(newCrontab, specs[source]) - } - - case lines[i] == IntakeCronEnd: - newCrontab = append(newCrontab, IntakeCronEnd) - inSection = false - - case !inSection: - newCrontab = append(newCrontab, lines[i]) - } - } - - // If the splice mark was never found, append the whole section to the end - if !headerFound { - newCrontab = append(newCrontab, IntakeCronBegin) - for _, source := range sources { - newCrontab = append(newCrontab, specs[source]) - } - newCrontab = append(newCrontab, IntakeCronEnd) - } - - log.Printf("Updating %d crontab entries", len(specs)) - - // Save the updated crontab - cmdSave := exec.Command(crontabPath, "-") - stdin, err := cmdSave.StdinPipe() - if err != nil { - return fmt.Errorf("failed to open stdin: %v", err) - } - if _, err := io.WriteString(stdin, strings.Join(newCrontab, "\n")); err != nil { - return fmt.Errorf("failed to write to crontab: %v", err) - } - if err := stdin.Close(); err != nil { - return fmt.Errorf("failed to close stdin: %v", err) - } - output, err = cmdSave.CombinedOutput() - if err != nil { - log.Printf("failed to read crontab output: %v", err) - } - if len(output) > 0 { - log.Printf("crontab output: %s", string(output)) - } - - return nil -} diff --git a/demo/alice.sh b/demo/alice.sh index 23ba51f..227c742 100644 --- a/demo/alice.sh +++ b/demo/alice.sh @@ -5,9 +5,6 @@ if [ -f /home/alice/.intake-setup-done ]; then exit 0 fi -# intake service gets a crontab wrapper, cheat here -export PATH="/run/wrappers/bin:$PATH" - mkdir -p $INTAKE_DATA_DIR intake source add -s echo @@ -18,7 +15,7 @@ intake channel add -s echo -c home intake source add -s currenttime intake action add -s currenttime -a fetch -- sh -c "date +%Y-%m-%d-%H-%M | jq -cR '{id: .}'" -intake source env -s currenttime --set "INTAKE_CRON=* * * * *" +intake source env -s currenttime --set "INTAKE_FETCH=every 1m" intake channel add -s currenttime -c home touch /home/alice/.intake-setup-done diff --git a/demo/bob.sh b/demo/bob.sh index dab1c98..44994b6 100644 --- a/demo/bob.sh +++ b/demo/bob.sh @@ -5,9 +5,6 @@ if [ -f /home/bob/.intake-setup-done ]; then exit 0 fi -# intake service gets a crontab wrapper, cheat here -export PATH="/run/wrappers/bin:$PATH" - mkdir -p $INTAKE_DATA_DIR intake source add -s echo diff --git a/module.nix b/module.nix index 41105be..a309515 100644 --- a/module.nix +++ b/module.nix @@ -75,9 +75,6 @@ in enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users; enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers; userPackages = userName: [ intakeCfg.package ] ++ intakeCfg.extraPackages ++ intakeCfg.users.${userName}.extraPackages; - crontabWrapper = pkgs.writeShellScriptBin "crontab" '' - exec ${config.security.wrapperDir}/crontab "$@" - ''; in { # Apply the overlay so intake is included in pkgs. @@ -92,9 +89,6 @@ in in mkMerge (map addPackagesToUser enabledUserNames); - # Enable cron - services.cron.enable = true; - # Define a user service for each configured user systemd.services = let @@ -102,8 +96,6 @@ in userName: pkgs.writeShellScript "intake-run.sh" '' mkdir -p $INTAKE_DATA_DIR - # Add the setuid wrapper directory so `crontab` is accessible - export PATH="${config.security.wrapperDir}:$PATH" ${intakeCfg.package}/bin/intake serve --addr ${enabledUsers.${userName}.listen.addr} --port ${toString enabledUsers.${userName}.listen.port} ''; # systemd service definition for a single user, given `services.intake.users.userName` = `userCfg` @@ -111,7 +103,7 @@ in "intake-${userName}" = { description = "Intake service for user ${userName}"; script = "${runScript userName}"; - path = [ crontabWrapper ] ++ intakeCfg.extraPackages ++ userCfg.extraPackages; + path = intakeCfg.extraPackages ++ userCfg.extraPackages; environment = { INTAKE_DATA_DIR = "/home/${userName}/.local/share/intake"; }; diff --git a/web/source.go b/web/source.go index 9744ede..66dba38 100644 --- a/web/source.go +++ b/web/source.go @@ -135,17 +135,6 @@ func (env *Env) editSource(writer http.ResponseWriter, req *http.Request) { http.Error(writer, err.Error(), 500) return } - if envName == "INTAKE_CRON" { - specs, err := core.GetCronSources(env.db) - if err != nil { - log.Printf("error: failed to get cron specs: %v", err) - } else { - err = core.UpdateCrontab(env.db, specs) - if err != nil { - log.Printf("error: failed to update crontab: %v", err) - } - } - } } actionName := req.PostForm.Get("actionName")