Commit Graph

102 Commits

Author SHA1 Message Date
James Shubin
ab5957f1e9 make: Clean up the Makefiles so the output is more elegant
This avoids printing erroneous messages when nothing is actually
happening.
2019-02-24 12:28:59 -05:00
James Shubin
253ed78cc6 engine: Rewrite the core algorithm
The engine core had some unfortunate bugs that were the result of some
early design errors when I wasn't as familiar with channels. I've
finally rewritten most of the bad parts, and I think it's much more
logical and stable now.

This also simplifies the resource API, since more of the work is done
completely in the engine, and hidden from view.

Lastly, this adds a few new metaparameters and associated code.

There are still some open problems left to solve, but hopefully this
brings us one step closer.
2019-02-24 12:28:59 -05:00
Toshaan Bharvani
88fcda2c99 lang: funcs: Added an uptime function
Signed-off-by: Toshaan Bharvani <toshaan@vantosh.com>
2019-02-24 12:20:58 -05:00
James Shubin
00db953c9f lang: funcs: funcgen: Clean up some small details
Some small changes were needed, here they are. Unfortunately this only
supports the `string` type at the moment.
2019-02-21 13:06:29 -05:00
Julien Pivotto
a0df4829a8 lang: Add more string functions, autogenerated
Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
2019-02-21 17:50:06 +01:00
James Shubin
1247c789aa lang: Remove unnecessary log package 2019-02-08 10:23:44 -05:00
Johan Bloemberg
749038c76d misc: Make build on macOS work 2019-02-08 00:14:17 +01:00
James Shubin
90fa83a5cf lang: funcs: core: Move world API functions
Some of the core functions interact with the remote "world" API. Move
them all into the same package.
2019-02-07 12:32:32 -05:00
James Shubin
4eaff892c1 lang: funcs: core: Rename core module files
More cleanup...
2019-02-07 12:19:59 -05:00
James Shubin
f368f75209 lang: funcs: core: Drop unnecessary core prefix from imports
This unbreaks the mcl bindata code. Of course we could change the parser
to allow this prefix, but this is cleaner. The packages still have a
core prefix, which it seems we could also remove, but this isn't
particularly important for anything.
2019-02-07 09:33:20 -05:00
Lander Van den Bulcke
04048b13ed lang: funcs: Add strings.split function
Signed-off-by: Lander Van den Bulcke <landervdb@inuits.eu>
2019-02-07 10:55:39 +01:00
Lander Van den Bulcke
5acc33c751 lang: funcs: Add tests for sqrt function
Signed-off-by: Lander Van den Bulcke <landervdb@inuits.eu>
2019-02-06 17:11:42 +01:00
Lander Van den Bulcke
dac019290d lang: funcs: Add sqrt function
Signed-off-by: Lander Van den Bulcke <landervdb@inuits.eu>
2019-02-06 14:32:13 +01:00
Julien Pivotto
bdc424e39d lang: Add to_lower and to_upper functions
Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
2019-02-06 14:24:15 +01:00
James Shubin
b5e29771ab lang: funcs: Add a trim space function to the new strings module 2019-02-01 07:00:05 -05:00
James Shubin
f5f09d3640 lang: funcs: Add str2int example function
We might want to move this into a real module eventually.
2019-02-01 06:59:07 -05:00
James Shubin
5a531b7948 lang: funcs: Add a new readfile function
This adds a new function that reads files from the local host.
2019-02-01 05:20:22 -05:00
James Shubin
f716a3a73b lang: funcs: Rename template functions to remove periods
Due to a limitation in the template library, we need to rename some
functions. It's probably worth looking into modifying this library or
finding an alternate version.
2019-02-01 03:58:02 -05:00
Kevin Kuehler
5d0efce278 engine: lang: util: Kill race in socketset
After some investigation, it appears that SocketSet.Shutdown() and
SocketSet.Close() are not synchronous operations. The sendto system call
called in SocketSet.Shutdown() is not a blocking send. That means there
is a race in which SocketSet.Shutdown() sends a message to a file
descriptor to unblock select, while SocketSet.Close() will close the
file descriptor that the message is being sent to. If SocketSet.Close()
wins the race, select is listening on a dead file descriptor and will
hang indefinitely.

This is fixed in the current master by putting SocketSet.Close() inside
of the goroutine in which data from the socket is being received. It
relies on SocketSet.Shutdown() being called to terminate the goroutine.
While this works most of the time, there is a race here. All the
goroutines can also be terminated by a closeChan. If the goroutine
receives an event (thus unblocking select) and then closeChan is
triggered, both SocketSet.Shutdown() and SocketSet.Close() race, leading
to undefined behavior.

This patch ensures the ordering of the two function calls by pulling
them both out of the goroutine and separating them with a WaitGroup.

Co-authored-by: James Shubin <james@shubin.ca>
2019-01-22 20:59:17 -08:00
Kevin Kuehler
3f396a7c52 lang: funcs: Add cpucount fact
Adds a CPU count fact, that can be used to determine how many CPUs are
presently on the machine and ready for use (online). We get this by
reading from a netlink socket to the kernel, and the kernel sends us
uevents when CPUs are added, removed, and brought online or offline.
Whenever one of these events are received, we look in sysfs to update
the fact's Stream with the number of online CPUs.
2019-01-22 20:59:16 -08:00
James Shubin
db1dbe7a27 lang: Edges should allow lists of strings
This continues the earlier patch that allowed resource names to be lists
of strings so that edges can now allow the same. This also includes a
new fancy test!
2019-01-20 17:27:40 -05:00
James Shubin
d6bbb94be5 lang: test: Add a new giant test infra for matching static output
This greatly expands our test infra to allow us to drop in mcl tests and
look at their resource graph output. The only downside is that this only
runs the function engine once, so if the function graph would be
constantly changing over time, then this is not a good fit here.
2019-01-20 17:27:40 -05:00
James Shubin
e3b4c0aee3 test: Fix a small copy pasta typo 2019-01-20 17:27:40 -05:00
James Shubin
a1fbe152bb lang: unification: Fix up small typos in example code 2019-01-20 04:22:05 -05:00
James Shubin
9d28ff9b23 lang: unification: Catch unification error on typed var expr
This was similar to the typed if expr error.
2019-01-20 04:19:39 -05:00
James Shubin
43f0ddd25d lang: unification: Catch unification error on typed if expr
I found a case where we had two missing unification rules. Now fixed in
the previous commits, and including this test to show I'm responsible.
I've added the same test in two locations for redundancy and as an
example.
2019-01-20 04:19:39 -05:00
James Shubin
7a28b00d75 lang: If expression was missing two invariants
I forgot to ensure that the type of the final expression matched the
type of each of the branches. It's rare, but possible for this to occur.
Luckily, this never would have caused a panic, because the func engine
would have caught the issue anyways, but it's still better we catch it
here first!
2019-01-20 04:02:54 -05:00
James Shubin
32e29862f2 lang: Check that set type matches actual expression
I forgot to include these two invariants which are occasionally
necessary, although in most cases they're necessary to prevent incorrect
code from getting past unification. In any case, they would have been
caught by the engine.
2019-01-20 04:02:54 -05:00
James Shubin
6c5c38f5a7 lang: unification: Allow err string comparisons in tests
Let's improve our test infra to make it more capable. It's important to
catch we failed for the _right_ reason so as to not mask the wrong
errors.
2019-01-20 03:39:02 -05:00
James Shubin
2da7854b24 lang: unification: Add logging to make capturing errors easier
This makes building new tests easier.
2019-01-20 03:39:02 -05:00
James Shubin
6d0c5ab2d5 lang: unification: Add missing return to exit early
This exits the test early, since we don't need to continue.
2019-01-20 03:39:02 -05:00
Kevin Kuehler
34550246f4 lang: Add debug flag and Logf to fact init struct 2019-01-17 18:12:45 -05:00
James Shubin
b1ffb1d4a4 lang: Add autoedge and autogroup meta params to mcl
These weren't yet exposed in mcl. They're now available under the same
Meta namespace as the normal meta param structs. Even though they live
as a separate trait, they should be exposed together for a consistent
interface in mcl. If autoedge or autogroup ever grow additional params,
we can always add: `Meta:autoedge:something` to break it down further.
2019-01-12 13:16:39 -05:00
James Shubin
451e1122a7 lang: Refactor the res metaparams helper
We can do all the actions without returning anything but an error.
2019-01-12 12:34:07 -05:00
James Shubin
10dcf32f3c lang: Allow a list of strings in the resource name
This adds a core looping construct by allowing a list of names to build
a resource. They'll all have the same parameters, but they'll
intelligently add the correct list of edges that they'd individually
create.

Constructs like these are one reason we do NOT have actual looping
functionality in the language, and it should stay that way.
2019-01-12 11:54:02 -05:00
James Shubin
7f1477b26d lang: Add a placeholder "ExprAny" expression for unification hacks
Instead of adding complexity to the unification engine, we can add a
fake placeholder expression that is unreachable by the AST, but used for
unification so that we can ensure a "wrap" invariant has some contents.

Ideally we'd improve the unification engine, but we'll leave that for
the future, and it's easy to revert this one commit in the future.
2019-01-12 11:45:53 -05:00
James Shubin
33b68c09d3 lang: Refactor edges helper method 2019-01-12 11:45:53 -05:00
James Shubin
7ec48ca845 lang: Refactor resource creation into a helper method 2019-01-12 11:45:53 -05:00
James Shubin
ad30737119 lang: Add meta parameter parsing to resources
Now we can actually specify metaparameters in the resources!
2019-01-11 04:13:13 -05:00
James Shubin
8e0bde3071 lang: Move capitalized res identifier into parser
This gives us more specificity when trying to match exactly.
2019-01-11 02:57:39 -05:00
James Shubin
e3eefeb3fe engine: resources: pkg: Implement the CompatibleRes interface
This signals to an interested consumer that two or more compatible
resources can be merged safely. This is so that we can avoid the
"duplicate resource" design problem that puppet had.

To test this, you can run:

./mgmt run --tmp-prefix lang --lang 'pkg "cowsay" { state => "installed", } pkg "cowsay" { state => "newest", }'

which should work.
2018-12-29 02:54:55 -05:00
James Shubin
f10dddadd6 lang: Handle merging of compatible resources properly
The duplicate resource problem that puppet had should now be correctly
solved in mgmt.
2018-12-29 02:51:09 -05:00
James Shubin
bdc33cd421 lang: Validate the edge field names in our resources
Validate these early instead of waiting for this to be caught during
output generation.
2018-12-29 00:18:10 -05:00
James Shubin
889dae2955 lang: Improve sub testing
This makes individual sub tests from the table easier to run.
2018-12-29 00:16:35 -05:00
James Shubin
22105af720 lang: test: Add a test of duplicate resource generation
These two cases should be allowed in our language. This is something
that puppet got wrong, and hopefully this makes writing modules more
sane in mcl, since two modules both depending on a "cowsay" package
won't cause compile errors.

This only checks the language. The de-duplication is done there. We
don't currently have a check for this in the engine. (We should!)
2018-12-28 18:44:07 -05:00
James Shubin
880c4d2f48 lang, util: Tests that depend on the fs should be sorted
This ensures they're deterministic on any file system.
2018-12-28 18:00:08 -05:00
James Shubin
96dccca475 lang: Add module imports and more
This enables imports in mcl code, and is one of last remaining blockers
to using mgmt. Now we can start writing standalone modules, and adding
standard library functions as needed. There's still lots to do, but this
was a big missing piece. It was much harder to get right than I had
expected, but I think it's solid!

This unfortunately large commit is the result of some wild hacking I've
been doing for the past little while. It's the result of a rebase that
broke many "wip" commits that tracked my private progress, into
something that's not gratuitously messy for our git logs. Since this was
a learning and discovery process for me, I've "erased" the confusing git
history that wouldn't have helped. I'm happy to discuss the dead-ends,
and a small portion of that code was even left in for possible future
use.

This patch includes:

* A change to the cli interface:
You now specify the front-end explicitly, instead of leaving it up to
the front-end to decide when to "activate". For example, instead of:

mgmt run --lang code.mcl

we now do:

mgmt run lang --lang code.mcl

We might rename the --lang flag in the future to avoid the awkward word
repetition. Suggestions welcome, but I'm considering "input". One
side-effect of this change, is that flags which are "engine" specific
now must be specified with "run" before the front-end name. Eg:

mgmt run --tmp-prefix lang --lang code.mcl

instead of putting --tmp-prefix at the end. We also changed the GAPI
slightly, but I've patched all code that used it. This also makes things
consistent with the "deploy" command.

* The deploys are more robust and let you deploy after a run
This has been vastly improved and let's mgmt really run as a smart
engine that can handle different workloads. If you don't want to deploy
when you've started with `run` or if one comes in, you can use the
--no-watch-deploy option to block new deploys.

* The import statement exists and works!
We now have a working `import` statement. Read the docs, and try it out.
I think it's quite elegant how it fits in with `SetScope`. Have a look.
As a result, we now have some built-in functions available in modules.
This also adds the metadata.yaml entry-point for all modules. Have a
look at the examples or the tests. The bulk of the patch is to support
this.

* Improved lang input parsing code:
I re-wrote the parsing that determined what ran when we passed different
things to --lang. Deciding between running an mcl file or raw code is
now handled in a more intelligent, and re-usable way. See the inputs.go
file if you want to have a look. One casualty is that you can't stream
code from stdin *directly* to the front-end, it's encapsulated into a
deploy first. You can still use stdin though! I doubt anyone will notice
this change.

* The scope was extended to include functions and classes:
Go forth and import lovely code. All these exist in scopes now, and can
be re-used!

* Function calls actually use the scope now. Glad I got this sorted out.

* There is import cycle detection for modules!
Yes, this is another dag. I think that's #4. I guess they're useful.

* A ton of tests and new test infra was added!
This should make it much easier to add new tests that run mcl code. Have
a look at TestAstFunc1 to see how to add more of these.

As usual, I'll try to keep these commits smaller in the future!
2018-12-21 06:22:12 -05:00
James Shubin
aae714db6b lang: Add a top-level stmt safety method
This adds a new method to the *StmtProg that lets us determine if the
prog contains only what is necessary for a scope and nothing more. This
is useful because that is exactly what is produced when doing an import.
With this detection method, we can know if a module contains dead code
that might mislead the user into thinking it will get run when it won't.
2018-12-20 21:21:30 -05:00
James Shubin
a7c9673bcf lang: Improve empty scope and output
For some reason these were unnecessary methods on the structs, even when
those structs contained nothing useful to offer.
2018-12-20 21:21:30 -05:00
James Shubin
3d06775ddc lang: Add some lambda function parsing and tests
Part of this isn't fully implemented, but might as well get the tests
running.
2018-12-20 21:21:30 -05:00