I've dipped my toe in chef and am having a few difficulties with what should be simple concepts.
I'm obtains data from a node by running a search; my plan is to iterate over the results and create an object of type X setting its variables as I go.
I'd like to store these objects in a collection so that I can access them later in the recipe to carry out other tasks and so on.
My GoogleFu has so far come up short and I'm worried that I'm tackling this in the wrong way. My search is fine and returning the values, my separate class is also fine but the storing of these objects into a collection and then persisting that is proving more difficult. Many posts frown against using arrays for my purpose(if it's possible) and I've not found anything similar to an ArrayList or Map. Additionally, if I use a ruby collection, does it need to be maintained inside a ruby block?
Thanks for any help / advice.
With Chef, you have several ways of storing persistent data:
1) set node attributes
2) chef data bags
3) chef vault
4) environments
5) environment recipes
6) roles
IMHO, you should decide where this data should reside by determining which of the items I listed it belongs to.
What does it apply to? What does it describe?
You got to be more specific in where you are actually facing the issue but as far as I have understood why not
just define a ruby class and initialize all the variables you are supposed to get. In the recipe instantiate the object and keep settings its properties from the result. There should be no issue in this approach.
But more importantly what is your use-case here, because you could just define an array attribute and then keep syncing the result in that attribute . As in ruby Objects are referenced , thus any change you make to resource attributes which takes that object, changes are persistent to in that object.
Related
I have developed a system where various classes have attributes consisting of a custom formula. The formula can contain special tokens which refer to different types of object. For example an object of class FruitSalad may have the following attribute;
$contents = "[A12] + [B76]";
In somewhat abstract terms, this means "add apple 12 to banana 76". It can also get significantly more complex than that with as many as 15 or 20 references to other objects involved in one formula.
I have a trait which passes formulae such as this and each time it finds a reference to a model (i.e. "[A12]") it gets it from the database with A::find(12) and adds it to an array of component objects which can be used for other processes later on in the request.
So, in essence, it's a relationship. But instead of a pivot table to describe the relationship, there is a formula on the parent model which can include references to child models.
This is all working. Yay! But it's really inefficient because there are so many tiny queries to get single models as formulae are parsed. One request may quite easily result in hundreds of queries. Oops.
I see two potential options;
1. Get all my apples and bananas from the database at the start of the request and get them from an in-memory store instead of from the database when parsing a formula (is this the repository pattern??).
2. Create a custom relation type (something like hasManyFromFormula) which makes eager loading work so that the parsing becomes much simpler because the relevant apples and bananas would already be loaded into the parent model.
Is there a precedent for this? As for why I am doing it like this, it would a bit tough to explain in brief but suffice to say it is to support a highly configurable data retrieval system which supports as-yet unknown input data configurations.
Help!
Thanks,
Geoff
Am not completely sure if it is the best solution, but in the end I created a new directory class for basic components and then set it up in the app service provider as a singleton. The constructor for the directory class loaded all models of several relevant classes and made them available as collections throughout the app.
I am using GATE in one of my applications and I have few queries related to Multi-tenancy. My requirements are as given below.
I have the keywords set, specific for each user and depending on
which user is signed in, I need to initialise gazetteer with the
applicable set of keywords.
At a given time there could be multiple users logging into my
application and I want to make sure that the multi-tenancy
approach will not be inefficient.
I don't want to store the keywords for each user in the .lst
file(s) but store it on a DB (mongo) and inject only at the
runtime.
I searched the web for few samples and though I found some thoughts on working with Processing Resource, I have no idea how the performance will be affected.
Your help is much appreciated.
Thanks in advance,
Sajith
That's an interesting use-case for a GATE gazetteer.
One thing I believe you should definitely do is add the user ID as a feature when you're creating the document. This way you'll be able to make your MongoDB query in a processing resource later on.
When you're processing the document, you have several options:
Create a custom PR which calls MongoDB and replicates the DefaultGazetteer code but with overwritten "init" method (or inherit or wrap it, haven't looked into much detail if that's possible). Instead of the default init method you should provide your list of keywords, then set the needed fields and call execute().
If you don't have too many keywords, create a custom PR (or groovy scripting PR) which calls MongoDB and does some simple regex search like the one in this thread.
They also suggest the stringsearch library in the comments. Then just use start and end indices to create Lookup annotations on your own.
You said you don't want that but still, several million words can be handled by both the default and the Hash gazetteer. Although, you should be careful as gate documents could be very memory-intensive if you have too many annotations - in your case Lookups for all user keywords.
Hope this helps.
I have a puppet environment where I need to add a variable number of very similar objects to a single server. The objects vary only by attributes such as name and path, all of which can be extrapolated from a single name parameter.
This seems like the perfect use for puppet resource definitions since multiple definitions can be added to a single server and their specific attributes can be taken from the definition name declaration.
This setup works well for me and I have had no issues getting it up and running on several servers. I have a requirement now however to hand this over to an ops department with almost no scripting experience, so they aren't really comfortable managing from the file system.
They requested a dashboard, so I setup puppet dashboard for them. After I set the dashboard up however, I found out that it only supports adding classes to servers, not definitions. This seems pretty shortsighted on the part of the folks at PuppetLabs, so I can only think that I am approaching this problem the wrong way and that there must be a solution using classes whereby multiple almost identical entities can be added to a single node.
I realize I could create a class for each entity, but there are hundreds, even thousands of potential variations so that's not really practical.
I have also considered a wrapper class that declares each definition on a per node basis, but this seems like more work to manage than it's worth.
Any thoughts on alternate approaches that would be compatible with the dashboard would be appreciated.
To make ENCs such as dashboard work this way, you have to pass in node data in the form of node variables. Note that Hiera is often preferable to plain node variables.
Generally, the value you want to hand in is an array of your resource titles
$resources = [ "name1", "name2", ... ]
Then classify your node with (at least) one class that instanciates your defined type using this data, e.g.
class my_resources {
my_defined_type { $resources: }
}
I have an dropdown attribute that I am creating during my module setup.
I want to pre-populate this attribute with some values while my module is installing. I can do this no problem, currently by simply storing the values in an array and then creating adding the options to the attribute in the install script.
Where would be the correct place to store these values - in a model? If so would it be a source model utilizing the toOptionArray method? This is technically used for forms so it doesnt seem right. But neither does just storing the values in the setup script.
Any ideas?
Yes, the toOptionArray method would be in line with standard Magento practices.
Typically the toOptionArray() is found in Helpers, if that is what you are asking. Helpers extend far fewer classes, and therefore inherit far fewer methods than models. This makes them much lighter weight for simple tasks like setting up an array of options, provided that they are static.
If the values are stored in a new DB table, and can be expanded upon by the user, it may make more sense to put this in a Model that has direct access to your DB table.
OK, Ruby gurus, this is a hard one to describe in the title, so bear with me for this explanation:
I'm looking to pass a string that represents a variable: not an instance, not the collection of properties that make up an object, but the actual variable: the handle to the object.
The reason for this is that I am dealing with resources that can be located on the filesystem, on the network, or in-memory. I want to create URI handler that can handle each of these in a consistent manner, so I can have schemes like eg.
file://
http://
ftp://
inmemory://
you get the idea. It's the last one that I'm trying to figure out: is there some way to get a string representation of a reference to an object in Ruby, and then use that string to create a new reference? I'm truly interested in marshalling the reference, not the object. Ideally there would be something like taking Object#object_id, which is easy enough to get, and using it to create a new variable elsewhere that refers to the same object. I'm aware that this could be really fragile and so is an unusual use case: it only works within one Ruby process for as long as there is an existing variable to keep the object from being garbage collected, but those are both true for the inmemory scheme I'm developing.
The only alternatives I can think of are:
marshal the whole object and cram it into the URI, but that won't work because the data in the object is an image buffer - very large
Create a global or singleton purgatory area to store a variable for retrieval later using e.g. a hash of object_id:variable pairs. This is a bit smelly, but would work.
Any other thoughts, StackOverflowers?
There's ObjectSpace._id2ref :
f = Foo.new #=> #<Foo:0x10036c9b8>
f.object_id #=> 2149278940
ObjectSpace._id2ref(2149278940) #=> #<Foo:0x10036c9b8>
In addition to the caveats about garbage collection ObjectSpace carries a large performance penalty in jruby (so much so that it's disabled by default)
Variables aren't objects in Ruby. You not only cannot marshal/unmarshal them, you can't do anything with them. You can only do something with objects, which variables aren't.
(It would be really nice if they were objects, though!)
You could look into MagLev which is an alternative Ruby implementation built on top of VMware's Gemstone. It has a distributes object model wiht might suit your use-case.
Objects are saved in the central Gemstne instance (with some nifty caching) and can be accessed by any number of remote worker instances. That way, any of the workers act on the same object space and can access the very same objects simultaneously. That way, you can even do things like having the global Garbage Collector running on a single Ruby instance or seamlessly moving execution at any point to different nodes (while preserving all the stack frames) using Continuations.