Forum OpenACS Q&A: How to get an instance url from a package key?
map? The only function I can find to address this is
site_node_closest_ancestor_package_url, but it only works for a
package key that's in the same site map branch as the page that's
calling the function. If I try to retrieve a url for a package in
another branch, I get a blank.
I can get the package_id from the package_key, so that's no problem. But I can't find any function in site_node that will return a url. When I use site_node_closest_ancestor_package_url, it only looks in the current branch.
root/ | -------foo/ | | -------bar/
As far as I can tell, if package foo is mounted at /foo, and package bar is mounted at /bar, and I run this code:
[site_node_closest_ancestor_package_url -package_key foo]from the page /bar/testpage.tcl, I get back a null result. If I run the same code from /foo/testpage.tcl, I get back "/foo/".
What I'm trying to do is write code for a package which will be run by the aa-test package, from the context of aa-test. So, given a package_key, I just want to know if it's installed, if it's mounted, and what its url is. If it's mounted more than once, I don't really care which one I get (though maybe I should, so that a test can be directed at a specific mount - but aren't all the mounts pointing to the same thing?).
This is obviously not ideal, as its going to slow down the execution time of all the tests that need to so it. Particularly in the current situation where a testcase should clear all its own data up. One can imagine a set of say, 20 testcases for a package, each testcase having to do its own mount/unmount. Nasty.....
My suggestion would be that a testcase could belong to a "init_class", where an init_class indicates that a chunk of code should be run before and after a complete set of testcases is run. This essentially allows testcases to share initialisation/cleardown code. This slightly breaks the notion of a testcase clearing up its own data, but should enforce that everything does get cleared up by the aa-test package after running a set of testcases.
You might get duplicates:
SQL> select package_id, package_key, instance_name from apm_packages order by package_key; PACKAGE_ID PACKAGE_KEY INSTANCE_NAME ---------- ------------------------------ ------------------------------ 209 acs-admin ACS Administration 241 acs-api-browser ACS API Browser 251 acs-content ACS Content 1113 acs-content-repository ACS Content Repository 741 acs-core-docs ACS Core Documents 765 acs-datetime ACS DateTime 1512 acs-developer-support Developer Support 96 acs-kernel ACS Kernel 780 acs-mail ACS Mail 1133 acs-messaging ACS Messaging 789 acs-notification ACS Notification 1479 acs-subsite Main Site 13050 acs-subsite Bar 13003 acs-subsite Foo Site 333 acs-tcl ACS Tcl 633 acs-templating ACS Templating 644 acs-util ACS Utilities 1020 acs-workflow ACS Workflow 2050 simple-survey Survey 1478 skin Skin 20 rows selected.
I can't find any function in site_node that will return a url.
SQL> select node_id, object_id, name from site_nodes; NODE_ID OBJECT_ID NAME ---------- ---------- ------------------------------ 1504 1479 1505 209 acs-admin 1506 741 doc 1507 241 api-doc 1510 1512 ds 13001 13003 foo 2048 2050 survey 13034 241 api 13048 13050 bar 13086 empty-folder 10 rows selected. SQL> select site_node.url(node_id) from site_nodes; SITE_NODE.URL(NODE_ID) ---------------------- / /acs-admin/ /doc/ /api-doc/ /ds/ /survey/ /foo/ /foo/api/ /bar/ /foo/empty-folder/ 10 rows selected.
The object_id in site_nodes is a package_id. You can join against apm_packages to get the URLs of the packages you're interested in, given a package key:
SQL> select p.package_id, site_node.url(n.node_id) from site_nodes n, apm_packages p where n.object_id = p.package_id and p.package_key = 'acs-subsite'; 2 3 4 PACKAGE_ID site_node.url(n.node_id) ---------- ------------------------------ 1479 / 13003 /foo/ 13050 /bar/
Aren't all the mounts pointing to the same thing?
For your purposes (I'm guessing) no. The testing you want to do will be agianst the database, and you'll need some data, and you'll need to distinguish it from other data. For that you need the package_id. Think of the package_id as an instance_id, it is unique for each mounted instance of a package, and distinguishes one mouonted packages data from another's.
Thanks for the db examples; I was hoping to use a function instead of writing new code to dig out basic information, but ah well. I guess there isn't much perceived need to do this sort of thing?
So. To address both of the previous posts at once: IMHO, it should be possible to aim the test suite at any application - at any instance of a package. Reasons:
1) The test suite, or at least a subset (maybe the 'smoke-test' portion, maybe a 'data-safe' category, should be reasonably safe to run on a live package, so that it can be used for diagnosis of problems.
2) The full test suite should be run on new applications to make sure that they work.
3) There might also be a version of the test suite that runs against functions, not pages. It would be used for other types of testing, such as before the UI is built, or if a custom UI breaks the automated test.
Whenever possible, tests should go through the UI and use the full http_request/parse the results approach, because this is the most comprehensive testing and can catch the most errors.
Ah I see, makes sense now. I thought you were building some kind of utPLSQL package for Postgres, but you're planning to exercise the UI as well. Nice...
At that time, what I pointed out was that the package system and procedural API is oriented towards mounted independent packages, but offered little support for packages that have a dependency on other packages, or might want to change their behavior if another package has been mounted.
As you said, you could have a package key, but couldn't precisely determine the url (or the proper instance) of the package without diving into the SQL. How then, can one package create redirects to another package or more precisely, to the right instance of the right package?
I felt then, that the SQL solution was overly complex, introduced unneccessary complexity and maintainance constraints into the code, and while it would work, it missed the point: to interoperate reliably, and easily, packages need a richer runtime exploration API.
I ask the current architects to look at this anew.
Ok, to make sure I understand: When I install a package on my site, it's identified by a package key. When I choose "new application" in the site map, I'm creating an instance of that package (with its own, unique package_id) and, simultaneously, mounting it. A "package-aware" application should partition its data by package_id. I can mount the application in several places, and all will point back to the same code and the same data slice. If I create a new application with the same package, the applications will share code but not data.Joel, you understand very well! Something similar to this wording ought to go on the main site map page or linked as "help" or something. I think a lot of misunderstanding would be avoided if it were.
Jerry ... service contracts are meant to provide a means for a package to announce itself available to fulfill the needs of another package. "package glue". We need more work and thought in this area to think about what it really means to glue packages together under subsites and all that but I think the basic concept's very promising.
As you said, you could have a package key, but couldn't precisely determine the url (or the proper instance) of the package without diving into the SQL.If the package you're interested in is not a singleton or service, or cannot be found with
site_node_closest_ancestor_package*then the proper instance of a package is a tricky thing to define, or at least package specific, I think...
I agree. What I thought then that I would like to see was some method in which packages and package instances can publish/make known certain attributes about themselves: the names of services they provide, perhaps just a unique id, perhaps the ids of their administrators, or their organizations, or ...? Structured in a property list, but perhaps unstructured beyond that: the name and value of the property might be left up to the package instance, and might be settable both in the package init as well as from the site map. That would enable packages to examine their where-abouts and enable administrators to bundle/config together various package instances. (Sigh, how many tenses are in this paragraph?)
...enable administrators to bundle/config together various package instances.The way I seem to be building sites is to create meta-packages that implement the new functionality, and which mount other packages within their URL branch for re-use.
In this case I know exactly where a bboard is and what it's package_id is, as my meta-package mounts it itself and stores away the details.
The only problem I was having was getting dependant packages mounted when my meta-package is mounted from the site map. I think I see the correct solution in
apm_post_instantiation_tcl_proc_from_key, but I haven't tried that yet.
As for administrators bundling together packages, that sounds like the problem "How do i transfer my site map and parameter values from dev to production?". I thought someone was looking at that a while ago, Henry..? How about storing the site map in the file system with Apache style .htaccess files which describe which package should be mounted there, and any parameter values..?
My own view is that the package manager doesn't suit our needs. It is not important to package up individual applications into standalone distribution files (*.apm) so that they can be installed willy-nilly. In fact I think it's detremental to the goal of producing an *integrated* tool kit (you don't have to look far to see the wheel re-invention...)
The problems discussed in "How do you separate project customisations from improvements?" are faced by each of us, but we have no tools to help us manage the complexity. A FreeBSD style system using CVS rather than the RedHat style package system we have would be more appropriate.
Anyway... If I wait long enough maybe Don will do it all for me.
So your package wants to include redirects to adserver or clickthrough or all sorts of things that may not be mounted relative to your package. If the target is not a singleton, and if the context isn't specified by user_id or something similar, how can anything determine the proper URL.
I don't know if this has been solved or not. I solved it in the limited case of the adserver as the adserver was a singleton. But I can certainly imagine cases when the adserver is not a singleton, you want different ads (and maybe different adserver instances) depending on the subsite, or gender, or zip code, or time of day, referrer_url, shopping cart contents, .... What sort of things can be done by the implementor to address this?