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: }
}
Related
So as a project matures it will almost certainly be necessary to modify attributes of the resource definitions to cope with additional requirements.
Let's use two trivial examples - to add a country code to a client address, or to remove a middle initial and swap in a middle name field instead.
Currently if the resource definition changes, composer won't read whatever values are extant in the repository. I didn't exhaustively try all combos, but have had to reconstitute my blockchain at least twice because of this problem.
Is there a way to mark fields either as "new" or "deprecated" to get past this that I overlooked? It will be hard to make a case to move a system that can't be changed forward to production.
In the same vein it doesn't seem to like empty or null strings much (at least for participant attributes). Having an "optional" override somewhere would save a lot of extra bounds checking in my application. Is there one of those I missed too?
So you can use the APIs or REST to expose the legacy data? You may be referring to Playground above (its not really a tool for looking at production data, its for model prototyping/sandbox/testing type stuff).
On optional question - can just add that the field is optional in the model - example here -> https://github.com/hyperledger/composer-sample-networks/blob/master/packages/pii-network/models/pii.cto#L20
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.
I've been using Ruby Selenium-Webdriver for one of the automation scripts I'm developing and I'm being asked to use Page Objects, we use page objects a lot however for this application I am using CSV file instead, I have defined all the xpaths that I'm using in my application in a CSV file and I'm parsing that CSV file in my script to refer to those objects, I would like to know is there much of a difference in using a class for defining Page Objects or using a CSV file instead apart from performance concern? I believe using a CSV file will be an addon for us from configuration standpoint and will make it much easier to maintain, any suggestions on this?
Edit - In our use case, we're actually automating applications built on a cloud based tool, so basically all the applications share same design structure from HTML standpoint so we define xpath patterns in CSV and then we pass certain parameters to some custom methods that we've developed to generate xpath's automatically using the CSV instead of finding those manually as its overhead for us because we already know that all the applications will share similar xpath pattern for all elements.
Thanks
I think, POM is better than CSV approach. In POM, you put elements for a page in a separate class file. So, if any change is to make then it's easier to find where to change/maintain. Moreover, it won't get too messy as CSV file and you don't need to use extra utility function to parse those.
There is also a pageobjects gem that provides a set of libraries over and above webdriver/watir, simplifying the code.
Plus, why xpaths? Its one of the last recommended ways to identify an element.
As for the frameork aspect, csv should be more of a maintenance problem than PageObjects. Its the basic difference between text and code. You enforce Object oriented approach on your elements in PageObjects but that is not possible with csv.
In the best case scenario, you have created a column/separate sheets defining which page that element xpath belongs to. That sounds like an overhead. As your application / suite grows there can be thousands of elements. Imagine parsing/ manually updating a csv with that kind of data.
Instead in PageObjects, your elements will be restricted to the Page. Any changes to the app will also specify which elements may get impacted. Now, when define your element as an object in PageObject, rather than css, you also dont need to explicitly create your elements by reading the csv.
It completely depends on the application and the type of test you might perform.
Since it is an automated test script, you do not have to really worry about the performance of the script (it might take few more milli seconds to parse, which should be OK).
Maintaining all the elements identification properties & corresponding actions in a CSV file will make the maintenance easier and make the framework application independent which are nice. But maintaining your framework is bit difficult to make it more robust. Both approaches have its own pros and cons.
Refer to below posts [examples are in java - but you will get the idea]:
Keyword driven framework
Advanced Page Objects
Update:
If you like both, you can comeup with your implementation to easily integrate these too.
#ObjectRepository(src="/login.csv")
public class LoginPage{
private Map<String, WebElement> elements;
public void login(){
elements.get("username").sendKeys('');
elements.get("password").sendKeys('');
elements.get("signin").click();
}
}
Ie, define all the elements in a config file like csv/json etc. Let the page object refer to the class for the page elements. All the methods will be part of the page class.
I'd like to access attributes that are inside instances of defined types from other classes/instances.
This is very similar to a question asked on SO before - In Puppet, how can I access a variable/attribute inside a defined type?, however from what I understood the answer was specifically related to accessing parameters as opposed to arbitrary variables.
For example, given the following defined type:
define server (
$server_name = 'my_server'
){
$server_history = 'A long story'
}
I can successfully use getparam(...) to fetch server_name but I cannot do the same for server_history.
Also, if server was a class as opposed to to a defined type, accessing this variable is straightforward using something like server::serverhistory
Does anyone have any ideas on how to expose these variables? Or am I approaching this completely the wrong way?
Edit: For some higher level context on what I'm trying to do my server type gets instantiated by 3 other classes. A variable in the server type builds out some directory paths based on parameters provided to it by these classes (which naturally, are specific to those classes). There are some other classes that would like to use the directory path variable to place files there.
You ask
I'd like to access attributes that are inside instances of defined types from other classes/instances.
and you go on to clarify that you're after
arbitrary variables.
In fact, ordinary variables in the body of a defined type are not attributes of that type, nor of any instance thereof. They are not part of the accessible persistent state of instances of such types at all.
More generally, Puppet treats defined types just like native types in almost every observable way, but by the same token, it does not provide any features that serve to distinguish defined types as a special case. You are looking for such a feature, and it does not exist.
Since your design idea will not work, you'll need to think of an alternative. You say
my server type gets instantiated by 3 other classes. A variable in the server type builds out some directory paths based on parameters provided to it by these classes (which naturally, are specific to those classes). There are some other classes that would like to use the directory path variable to place files there.
Since the paths you're after are characteristic of specific classes, it makes sense for them to be accessible directly via those classes. It seems odd to me that you would even want to access them indirectly via resources declared by those classes.
I think this should be an easy one, but haven't found any clear answer, on what would the best practice be.
In an application, we keep current status of an order (open, canceled, shipped, closed ...).
This variables cannot change without code change, but application should meet the following criteria:
status names should be easily displayed in different languages,
application can search via freetext status names (like googling for "open")
status_id should be available to developer via enum
zero headache when adding new statuses
Possible ways we have tackled this so far:
having DB table status with PK(id, language_id) and a separate enum which represents this statuses in an application.
PROS: 1.,2.,3. work out of the box, CONS: 4. needs to run update script on every client installation, SQL selects can become large and cumbersome, when dealing with a lot of code tables
having just enum:
PROS: 3.,4. CONS: 1.,2. is a total nightmare
having enums, which populate database tables on each start of an application:
PROS: 1.,2.,3.,4. work CONS: some overhead on application start, SQL select can become large and cumbersome, when dealing a lot code tables.
What is the most common way of tackling this problem?
Sounds like you summarized it pretty good yourself, and comparing the pros/cons points towards #3. Just one comment when you implement #3 though:
Use a caching mechanism (even a simple HashMap!) plus adding the option to refresh the cache - will ease your work when you'll want to change values (without the need to restart every time!).
I would, and do, use method 3 because it is the best of the lot. You can use resource files to store the translations in and map the enum values to keys in the resource files. Your database can contain the id of the enum for the status.
1.status names should be easily displayed in different languages,
2.application can search via freetext status names (like googling for "open")
These are interfaces layer's concern, you'd better not mix them in you domain model.
I would setup a mapping between status enum and i18n codes. the mapping could be stored in a file (cached in memory) or hardcoded.
for example: if you use dto or view adatper to render your ui.
public class OrderDetailViewAdapter {
private Order order;
public String getStatus() {
return i18nMapper.to(order.getStatus());//use hardcoded switch case or file impl
}
}
Or you could done this before you populating you dtos.
You could use a similar solution for goal2. When user types text, find corresponding enum from mapping and use enum for search.
Anyway, use db tables the less the better.
Personally, I always use dedicated enum class inside domain. Only responsibility of this class is holding status name (OPEN, CANCELED, SHIPPED, ...). Status name is not visible outside codebase. Also, status could be also stored inside database field as string (varchar or similar).
For the purpose of rendering, depending of number of use cases, sometimes I implement formatting inside formatter (e.g. OrderFormatter::formatStatusName(), OrderFormatter::formatAbbreviatedStatusName(), ...). If formatting is needed often I create dedicated class with all formatting styles needed (OrderStatusFormatter::short(), OrderStatusFormatter::abbriviated()...). Of course, internal mapping is needed to map status name to status title, and this is tricky part. But if you want layering you can't avoid mapping.
Translation is not dealt so far. I translate strings inside templates so formatters are clean of that responsibility. To summarize:
enum inside domain model
formatter inside presentation layer
translation inside template
There is no need to create special table for order status translations. Better choice would be to implement generic translation mechanism, seperated from your business code.