Let's say I have my NixOS configuration.nix set up as follows:
{config, pkgs, ...}:
{
services.openssh.enable = true;
}
I now want to have a second file called networking.nix which sets my hostname based on an argument.
{config, pkgs, hostname, ...}:
{
networking.hostName = hostname
}
Is this possible? How can I include the file. I already tried doing it by using imports = [ ./networking.nix { hostname = "helloworld"; } ]; but that didn't work.
Thanks.
A 'NixOS configuration file' is simply a module that doesn't define options, so there is really no distinction. A configuration.nix file is just a module, and typically it does not define any options, so it can be written in the abbreviated form.
Defining options is the normal way for NixOS modules to pass information around, so that's the most idiomatic way to go about.
However, if you really must, for some very special reason, because you're doing very unusual things with NixOS, you can put arbitrary functions in imports. But you shouldn't, because it doesn't work well with the module system's custom error messages and potentially other aspects that rely on knowing where a module is defined. If you do so, do make sure it is an actual function. In your case, that would imply modifying the first line of networking.nix to make it a curried function:
hostname: {config, pkgs, ...}:
Not very pretty in my opinion. Although it is very explicit about what is going on, it deviates from what is to be expected of a NixOS module.
I encountered this problem today and came up with a fairly simple solution recommended in the manual.
foobar.nix
{ lib, withFoo ? "bar", ... }:
# simple error checking to ensure garbage isn't passed in
assert lib.asserts.assertOneOf "withFoo" withFoo [
"bar"
"baz"
# other valid choices ...
];
{
# ...
}
configuration.nix
args#{ ... }:
{
imports = [
# ...
(
import ./foobar.nix (
args
// { withFoo = "baz"; }
)
)
# ...
];
}
This is ideal for 'one off' options in your configurations.
You should be able to use the _module.argsoption [1] to do that. So your configuration.nix would be like:
{config, pkgs, ...}:
{
_module.args.hostname = "ahostname";
services.openssh.enable = true;
}
However where the values are very simple it will probably be much easier to just set them directly, e.g. just define networking.hostname in configuration.nix. This section of the manual re. merging and priorities may be helpful also [2].
Further discussion:
The value of _module.args is indeed applied to all imported configurations (though the value will only be used in modules that directly refer to it, such as the pkgs value, the ... represents all the values that aren't referenced).
For passing arguments to modules it seems a good approach to me, but from your comments perhaps a different approach might be more suitable.
Another solution could be to flip the relationship in the imports: rather than a single common config that passes multiple different arguments instead multiple different configs import the common configuration. E.g.
$cat ./common.nix
{ services.openssh.enable = true; }
$cat ./ahostname.nix
{ imports = [ ./common.nix ]; networking.hostname = "ahostname"; }
The NixOS config in this Reddit comment looks like it uses this approach. There are quite a few other NixOS configurations that people have shared publicly online so you might find some useful ideas there. The points in the answer from Robert Hensing are very useful to bear in mind as well.
However it's hard to say what might be a better solution in your case without knowing a bit more about the context in which you want to use it. You could create a new SO question with some more information on that which might make it easier to see a more appropriate solution.
Related
I have some files, like,
test/test1,
test/test2,
test/test3
and i want to rename there path to
newtest/test1,
newtest/test2,
newtest/test3
so that if we try to require the above file, then it will point to new path.
In require, one to one mapping is present, but not sure, if something like this is achievable,
require.map = {
"test/*": "newtest/*",
}
Any help :)
The map configuration option supports mapping module prefixes. Here's an example:
require.config({
map: {
"*": {
"foo": "bar"
}
}
});
define("bar/x", function () {
return "bar/x";
})
require(["foo/x"], console.log);
The last require call that tries to load foo/x will load bar/x.
This is as good as it gets for pattern matching with map. RequireJS does not support putting arbitrary patterns in there. Using "test/*": "newtest/*" would not work. The "*" I used in map is not a pattern. It is a hardcoded value that means "in all modules", and happens to look like a glob pattern. So the map above means "in all modules, when foo is required, load bar instead".
I wonder if you really need map. You can probably just use paths. Quoting from map documentation
This sort of capability is really important for larger projects which
may have two sets of modules that need to use two different versions
of 'foo', but they still need to cooperate with each other.
Also see paths documentation
Using the above sample config, "some/module"'s script tag will be
src="/another/path/some/v1.0/module.js".
Here is how paths can be used to map the directory from test to newtest for your example
paths: {
"test": "newtest"
}
Or, the goal: How can I take a single package from Nix unstable in a declarative manner?
I'm new to NixOS and currently trying to install a newer version of Consul than the default 0.5.2 of my NixOS version (latest stable). I'm attempting this by overriding the derivative in my /etc/nix/configuration.nix.
I'd like to keep running stable, but I found unstable had the version of Consul that I wanted (0.7.0) already, and so I decided to use this package's attributes as a starting point to override https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/consul/default.nix
I copied it for most part into my configuration.nix, here are the relevant sections:
nixpkgs.config.packageOverrides = pkgs: rec {
consul = pkgs.lib.overrideDerivation pkgs.consul (attrs: rec {
version = "0.7.0";
name = "consul-${version}";
rev = "v${version}";
goPackagePath = "github.com/hashicorp/consul";
src = pkgs.fetchFromGitHub {
owner = "hashicorp";
repo = "consul";
inherit rev;
sha256 = "04h5y5vixjh9np9lsrk02ypbqwcq855h7l1jlnl1vmfq3sfqjds7";
};
# Keep consul.ui for backward compatability
passthru.ui = pkgs.consul-ui;
});
};
environment.systemPackages = with pkgs; [
vim
which
telnet
consul-ui
consul-alerts
consul-template
consul
];
I'm running nix-build (Nix) 1.11.2 which throws:
$ nixos-rebuild switch
building Nix...
building the system configuration...
error: cannot coerce a set to a string, at /etc/nixos/configuration.nix:19:7
(use ‘--show-trace’ to show detailed location information)
When I look at line 19 it's where name is set to "consul-${version}".
Why there is type-coercion going on here? Any tips will be greatly appreciated!
I'm also wondering if there is a better way to run just a single package in unstable, yet doing so declaratively from configuration.nix, rather than imperatively?
To add to what Rok said:
Which should point you that an error actually happens at passthru, line. If you comment it out it will probably build. I'm assuming some recursive calls are at play here and error occurs when it tries to evaluate consul/consul-ui packages.
If you're just starting out, you can safely ignore what follows and perhaps come back to it if/when you're curious about the nitty-gritty.
The problem here is that overrideDerivation is a kind of low-level approach to overriding things. Behind stdenv.mkDerivation, we have a much smaller primitive function called derivation. The derivation function takes some attributes and (more or less -- see the docs for the finer details) just passes those attributes as environment variables during the build. The stdenv.mkDerivation function, on the other hand, has a whole bunch of smarts layered on top that massages the attributes given to it before passing them onto derivation -- and in some cases, as is the case with passthru, it doesn't pass the attribute to derivation at all.
Back to overrideDerivation: it takes the final, tweaked attributes that stdenv.mkDerivation would pass to derivation, and just before that happens it allows you to override those attributes with the function you give it (e.g. that implies that, at that point, passthru has already been removed). When your function adds a passthru, that makes its way into derivation, which then wants to coerce the value of passthru into a string so it can make passthru an environment variable during the build; however, because passthru now points at a attribute-set, and such coercion isn't supported, Nix then complains.
So this sort of puts us in an odd situation. To illustrate, I'll copy the source for the consul package here:
{ stdenv, lib, buildGoPackage, consul-ui, fetchFromGitHub }:
buildGoPackage rec {
name = "consul-${version}";
version = "0.6.4";
rev = "v${version}";
goPackagePath = "github.com/hashicorp/consul";
src = fetchFromGitHub {
owner = "hashicorp";
repo = "consul";
inherit rev;
sha256 = "0p6m2rl0d30w418n4fzc4vymqs3vzfa468czmy4znkjmxdl5vp5a";
};
# Keep consul.ui for backward compatability
passthru.ui = consul-ui;
}
(Note that buildGoPackage is a wrapper around stdenv.mkDerivation.)
You might be familiar with e.g. consul.override, which allows you to supply different inputs (e.g. maybe a different version of consul-ui, or buildGoPackage), but it doesn't allow you to override things that aren't inputs (e.g. src, passthru, etc). Meanwhile, overrideDerivation allows you to modify the attrs given to derivation, but not the ones given to stdenv.mkDerivation. Ideally there would be something in-between, that would allow for manipulating the attrs given to stdenv.mkDerivation, and it so happens that there's a PR open to address this:
https://github.com/NixOS/nixpkgs/pull/18660
Welcome to Nix/NixOS :)
Whenever you need to know more about the error you can use --show-trace and that would give you more verbose error. In your case you would see something like
error: while evaluating the attribute ‘passthru’ of the derivation ‘consul-0.7.0’ at /home/rok/tmp/consul.nix:6:3:
cannot coerce a set to a string, at /home/rok/tmp/consul.nix:6:3
Which should point you that an error actually happens at passthru, line. If you comment it out it will probably build. I'm assuming some recursive calls are at play here and error occurs when it tries to evaluate consul/consul-ui packages.
As for overriding only one package from unstable channel something like this is needed
let
unstable_pkgs = import ./path/to/unstabe/nixpkgs {};
# or
# unstable_pkgs = import (pkgs.fetchFromGitHub {...}) {};
in {
...
nixpkgs.config.packageOverrides = pkgs: rec {
consul = unstable_pkgs.consul;
};
...
}
I haven't try the above, but I'm assuming it will work.
I currently have a project in a loose ES6 module format and my database connection is hard coded. I am wanting to turn this into an npm module and am now facing the issue of how to best allow the end user to configure the code. My first attempt was to rewrite it as classes to be instantiated but it is making the use of the code more convoluted than before so am looking at alternatives. I am exploring my configuration options. It looks like writing to the process env would be the way but I am pondering potential issues, no-nos and other options I have not considered.
Is having the user write config to process env an acceptable method of configuring an npm module? It's a bit like a global write so am dealing with namespace considerations for one. I have also considered using package.json but that's not going to work for things like credentials. Likewise using an rc file is cumbersome. I have not found any docs on the proper methodology if any.
process.env['MY_COOL_MODULE_DB'] = ...
There are basically 5ish options as I see it:
hardcode - not an option
create a configured scope such as classes - what I have now and bleh
use a config such as node-config - not really a user friendly option for npm
store as globals/env. As suggested in comment I can wrap that process in an exported function and thereby ensure that I have a complex non collisive namespace while abstracting that from end user
Ask user to create some .rc file - I would if I was big time like AWS but not in this case.
I mention this npm use case but this really applies to the general challenge of configuring code that is exported as functions. I have use cases for classes but when the only need is creating a configured scope at the expense (in my case) of more complex code I am not sure its worth it.
Update I realize this is a bit of a discussion question but it's helped me wrap my brain around options. I think something like this:
// options.js
let options = {}
export function setOptions(o) { options = o }
export function getOptions(o) { return options }
Then have the user call setOptions() and call this getOptions internally. I realize that since Node requires the module just once that my options object will be kept configured as I pass it around.
NPM modules should IMO be agnostic as to where configuration is stored. That should be left up to the developer, and they may pick their favorite method (env vars, rc files, JSON files, whatever).
The configuration can be passed to your module in various ways. A common way is to export a function that takes an options object:
export default options => {
let db = database.connect(options.database);
...
}
From there, it really depends on what exactly your module provides. If it's just a bunch of loosely coupled functions, you can just return an object:
export default options => {
let db = database.connect(options.database);
return {
getUsers() { return db.getUsers() }
}
}
If you want to allow multiple versions of that object to exist simultaneously, you can use classes:
class MyClass {
constructor(options) {
...
}
...
}
export default options => {
return new MyClass(options)
}
Or export the entire class itself.
If the number of configuration options is limited (say 3 or less), you can also allow them to be passed as separate arguments, instead of passing an object.
I decided to start a new project to get into hacklang, and after fixing some if the problems I initially ran into transitioning from php habits, I ran into the following errors:
Unbound name: str_replace
Unbound name: empty
Doing some research I found that this is due to using 'legacy' php which isn't typechecked, and will error with //strict.
That's fine and all, empty() was easy enough to replace, however str_replace() is a bit more difficult.
Is there an equivalent function that will work with //strict? Or at least something similar.
I'm aware that I could use //decl but I feel like that defeats the purpose in my case.
Is there at least any way to tell which functions are implemented in hack and which are not in the documentation as I couldn't find one?
For reference (though it isn't too relevant to the question itself), here is the code:
<?hh //strict
class HackMarkdown {
public function parse(string $content) : string {
if($content===null){
throw new RuntimeException('Empty Content');
}
$prepared = $this->prepare($content);
}
private function prepare(string $contentpre) : Vector<string>{
$contentpre = str_replace(array("\r\n","\r"),"\n",$contentpre);
//probably need more in here
$prepared = Vector::fromArray(explode($contentpre,"\n"));
//and here
return $prepared;
}
}
You don't need to change your code at all. You just need to tell the Hack tools about all the inbuilt PHP functions.
The easiest way to do this is to download this folder and put it somewhere in your project. I put it in a hhi folder in the base of my project. The files in there tell Hack about all the inbuilt PHP functions.
Most of them don't have type hints, which can lead to Hack thinking the return type of everything is mixed instead of the actual return, that is actually correct in most cases as, for example, str_replace can return either a string or a bool. However, it does stop the "unbound name" errors, which is the main reason for adding them.
I would like to iterate over an array that is stored as a Facter fact, and for each element of the array create a new system user and a directory, and finally make API calls to AWS.
Example of the fact: my_env => [shared1,shared2,shared3]
How can I iterate over an array in Puppet?
This might work, depending on what you are doing
# Assuming fact my_env => [ shared1, shared2, shared3 ]
define my_resource {
file { "/var/tmp/$name":
ensure => directory,
mode => '0600',
}
user { $name:
ensure => present,
}
}
my_resource { $my_env: }
It will work if your requirements are simple, if not, Puppet makes this very hard to do. The Puppet developers have irrational prejudices against iteration based on a misunderstanding about how declarative languages work.
If this kind of resource doesn't work for you, perhaps you could give a better idea of which resource properties you are trying to set from your array?
EDIT:
With Puppet 4, this lamentable flaw was finally fixed. Current state of affairs documented here. As the documentation says, you'll find examples of the above solution in a lot of old code.
As of puppet 3.2 this is possible using the "future" parser like so:
$my_env = [ 'shared1', 'shared2', 'shared3', ]
each($my_env) |$value| {
file { "/var/tmp/$value":
ensure => directory,
mode => 0600,
}
user { $value:
ensure -> present,
}
}
See also: http://docs.puppetlabs.com/puppet/3/reference/lang_experimental_3_2.html#background-the-puppet-future-parser
Puppet 3.7 released earlier this month have the new DSL, which one feature is the iteration, check the following URL https://docs.puppetlabs.com/puppet/latest/reference/experiments_lambdas.html#enabling-lambdas-and-iteration
these new features can be enabled with the :
Setting parser = future in your puppet.conf file
or adding the command line switch --parser=future
hope that helps
As of latest Puppet (6.4.2), and since Puppet 4, iteration over arrays is supported in a few ways:
$my_arr = ['foo', 'bar', 'baz']
Each function:
$my_arr.each |$v| {
notice($v)
}
Each function alternative syntax:
each($my_arr) |$v| {
notice($v)
}
To get the index:
Pass a second argument to each:
$my_arr.each |$i, $v| {
notice("Index: $i, value: $v")
}
Comparison with Ruby:
Note that this grammar is inspired by Ruby but slightly different, and it's useful to show the two side by side to avoid confusion. Ruby would allow:
my_arr.each do |v|
notice(v)
end
Or:
my_arr.each { |v|
notice(v)
}
Other iteration functions:
Note that Puppet provides a number of other iteration functions:
each - Repeats a block of code a number of times, using a collection of values to provide different parameters each time.
slice - Repeats a block of code a number of times, using groups of values from a collection as parameters.
filter - Uses a block of code to transform a data structure by removing non-matching elements.
map - Uses a block of code to transform every value in a data structure.
reduce - Uses a block of code to create a new value, or data structure, by combining values from a provided data structure.
with - Evaluates a block of code once, isolating it in its own local scope. It doesn’t iterate, but has a family resemblance to the iteration functions.
Puppet 3 and earlier:
If you have inherited old code still using Puppet 3, the accepted answer is still correct:
define my_type {
notice($name)
}
my_type { $my_arr: }
Note however that this is usually considered bad style in modern Puppet.
itsbruce's answer is probably the best for now, but there is an iteration proposal going through puppetlabs' armatures process for possible implementation in future.
There is a "create_resources()" function in puppet. that will be very helpful while iterating over the list of itmes