tests
This commit is contained in:
parent
e037b0b102
commit
474f0f1a04
7 changed files with 67 additions and 27 deletions
2
Makefile
2
Makefile
|
@ -7,4 +7,4 @@ build:
|
|||
run:
|
||||
cd entrypoint && dotnet run -- --user ${USER} --password ${PASSWORD} -H ${HOST}
|
||||
test:
|
||||
dotnet test
|
||||
cd tests && dotnet test
|
||||
|
|
20
src/Cron.fs
20
src/Cron.fs
|
@ -8,7 +8,6 @@ open Pentole
|
|||
open Datatypes
|
||||
|
||||
open Pentole.String
|
||||
open Pentole.Path
|
||||
open Pentole.Map
|
||||
|
||||
type User = string
|
||||
|
@ -23,13 +22,13 @@ let private parse_expr (now: Instant) text =
|
|||
| true -> Ok c
|
||||
| false -> Error $"Can't parse cron expression: {text}"
|
||||
|
||||
let to_pattern text =
|
||||
match Pentole.String.split " " text |> List.head with
|
||||
let to_pattern (text: string) =
|
||||
match text with
|
||||
| Prefix "@after" job -> After job |> Ok
|
||||
| _ -> Error $"Can't parse as pattern: {text}"
|
||||
|
||||
match to_cron text, to_pattern text with
|
||||
| Error e, Error _ -> Error e
|
||||
| Error e, Error p -> Error $"Can't parse {text} neither as pattern or cron expression"
|
||||
| _, Ok p -> Ok (Pattern p)
|
||||
| Ok cron_expr, _ ->
|
||||
(now.ToDateTimeOffset(), local_tz_net)
|
||||
|
@ -40,7 +39,7 @@ let private parse_expr (now: Instant) text =
|
|||
else Instant.FromDateTimeOffset i.Value |> Cron |> Ok)
|
||||
|
||||
|
||||
let private parse now (db: Database.Requirements) =
|
||||
let private parse now (db: Requirements) =
|
||||
let when_ = parse_expr now db.``when``
|
||||
let env =
|
||||
db.environment
|
||||
|
@ -52,7 +51,7 @@ let private parse now (db: Database.Requirements) =
|
|||
else
|
||||
Ok (splitted.[0], splitted.[1]))
|
||||
|
||||
let executable = Path.of_string db.executable |> Result.bind FileSystem.resolve
|
||||
let executable = Which.which db.executable
|
||||
let workdir = Path.of_string db.workdir |> Result.bind FileSystem.resolve
|
||||
|
||||
let last_completed =
|
||||
|
@ -76,8 +75,7 @@ let private parse now (db: Database.Requirements) =
|
|||
type JobKey = {
|
||||
j: string; h: string
|
||||
}
|
||||
let sort_cron_jobs (now: Instant) (db_crons: Database.Requirements seq) =
|
||||
|
||||
let sort_cron_jobs (now: Instant) (db_crons: Requirements seq) =
|
||||
|
||||
let build_deps (lst: CronJob list) =
|
||||
let standalone, deps =
|
||||
|
@ -90,7 +88,7 @@ let sort_cron_jobs (now: Instant) (db_crons: Database.Requirements seq) =
|
|||
in index, deps
|
||||
in
|
||||
let rec build_job_table acc (index: Map<JobKey, CronJob>) = function
|
||||
| [] -> Ok acc
|
||||
| [] -> Map.values acc |> Ok
|
||||
| {when_=Cron _}::_ -> invalidOp "The jobs should have been partitioned"
|
||||
| {when_=Pattern (After jb)} as x::xs ->
|
||||
let father = {j=jb; h=x.hostname}
|
||||
|
@ -100,7 +98,7 @@ let sort_cron_jobs (now: Instant) (db_crons: Database.Requirements seq) =
|
|||
Map.find father index |> Result.map List.singleton
|
||||
| Some p -> Ok p
|
||||
if previous |> Result.isError then
|
||||
Error "Invalid job definition. No such job_name {jb} in host {x.hostname}"
|
||||
Error $"Invalid job definition. No such job_name {jb} in host {x.hostname}"
|
||||
else
|
||||
let p = Result.get previous
|
||||
let acc' = Map.add father (x::p) acc
|
||||
|
@ -109,4 +107,4 @@ let sort_cron_jobs (now: Instant) (db_crons: Database.Requirements seq) =
|
|||
db_crons
|
||||
|> ResultList.collect (parse now)
|
||||
|> Result.map build_deps
|
||||
|> Result.map (fun (standalone, deps) -> build_job_table Map.empty standalone deps)
|
||||
|> Result.bind (fun (standalone, deps) -> build_job_table Map.empty standalone deps)
|
||||
|
|
|
@ -9,6 +9,8 @@ open Serilog
|
|||
open Npgsql
|
||||
open Dapper
|
||||
|
||||
open Datatypes
|
||||
|
||||
let private connstring =
|
||||
let c = Environment.Environment()
|
||||
$"Server={c.pg_host};Database={c.pg_dbname};" +
|
||||
|
@ -58,19 +60,6 @@ let make (logger: ILogger) =
|
|||
let wait_notification (ct: CancellationToken) (db: t) =
|
||||
db.connection.WaitAsync ct
|
||||
|
||||
[<CLIMutable>]
|
||||
type Requirements = {
|
||||
job_name: string
|
||||
``when``: string
|
||||
executable: string
|
||||
user: string
|
||||
workdir: string
|
||||
hostname: string
|
||||
args: string array
|
||||
environment: string
|
||||
done_at: System.DateTime option
|
||||
}
|
||||
|
||||
let gather_requirements (hostname: string) (ct: CancellationToken) (db: t) =
|
||||
let query = """select
|
||||
c.job_name, c."when", c.executable, c.user, c.workdir, c.args, h.hostname,
|
||||
|
|
|
@ -27,3 +27,16 @@ type CronJob = {
|
|||
hostname: string
|
||||
last_completed_at: Instant
|
||||
}
|
||||
|
||||
[<CLIMutable>]
|
||||
type Requirements = {
|
||||
job_name: string
|
||||
``when``: string
|
||||
executable: string
|
||||
user: string
|
||||
workdir: string
|
||||
hostname: string
|
||||
args: string array
|
||||
environment: string
|
||||
done_at: System.DateTime option
|
||||
}
|
||||
|
|
|
@ -5,3 +5,6 @@ module Map =
|
|||
match Map.tryFind key map with
|
||||
| Some v -> Ok v
|
||||
| None -> Error $"Can't find key {key}"
|
||||
|
||||
let values (map: Map<'k, 'v>): 'v seq =
|
||||
Map.values map
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<Compile Include="Map.fs" />
|
||||
<Compile Include="Result.fs" />
|
||||
<Compile Include="String.fs" />
|
||||
<Compile Include="Which.fs" />
|
||||
<Compile Include="Datatypes.fs" />
|
||||
<Compile Include="Grains.fs" />
|
||||
<Compile Include="DatabaseMigrations.fs" />
|
||||
|
@ -38,6 +39,7 @@
|
|||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="Sheller" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -2,7 +2,42 @@ module tests
|
|||
|
||||
open NUnit.Framework
|
||||
open Pentole.TestsExtensions
|
||||
open Bidello.Datatypes
|
||||
open Bidello
|
||||
|
||||
open Pentole.String
|
||||
|
||||
[<Test>]
|
||||
let Test1 () =
|
||||
Assert.Pass()
|
||||
let string_prefix_active_pattern () =
|
||||
match "@after job" with
|
||||
| Prefix "@after" j -> Assert.Pass ()
|
||||
| _ -> Assert.Pass ()
|
||||
|
||||
match "@after job " with
|
||||
| Prefix "@after" j -> Assert.Pass ()
|
||||
| _ -> Assert.Pass ()
|
||||
|
||||
let bj =
|
||||
{ job_name = "j1"
|
||||
hostname = "h1"
|
||||
``when`` = "* * * * *"
|
||||
executable = "echo"
|
||||
workdir = "/"; user = "nobody"
|
||||
args = [||]; environment = "";
|
||||
done_at = None }
|
||||
|
||||
[<Test>]
|
||||
let job_deps () =
|
||||
|
||||
let requirements = [
|
||||
bj
|
||||
{bj with job_name = "j2"}
|
||||
{bj with hostname = "h2"}
|
||||
{bj with job_name = "j1_after"; ``when``="@after j1"}
|
||||
// TODO: another test with this at h2
|
||||
]
|
||||
|
||||
let now = NodaTime.SystemClock.Instance.GetCurrentInstant ()
|
||||
let cjs = Cron.sort_cron_jobs now requirements
|
||||
|
||||
Assert.ok_is_equal Seq.empty cjs
|
||||
|
|
Loading…
Reference in a new issue