Antonio, sure I will review the patch. But please make sure that API backwards compatibly is intact, otherwise the fix won¹t be accepted.
-Alena. On 3/2/14, 4:31 PM, "Antonio Fornié Casarrubios" <antonio.for...@gmail.com> wrote: >Hi Alena, > >The reasons for this strange format? I don't know. There doesn't seem to >be >one. After asking on my team and in the dev list I thought perhaps you >could know. It seems we all see it strange and nobody knows why. But of >course, if it is for reasons I will stop the change. > > > >And about the DB, you are right, in the DB is not like I said. But you can >have this in a table row field: >{0={value=Toronto,key=City}} >for some tables. I think there are two cases: > >1- params in wich the get method fixes the params on the fly. In these of >course the strange format is not propagated anymore. But this is still >wrong: the format itself before the get is invoked, the time spent on >fixing something that should be a normal Map from the begining (each time >the get method is invoked) and mainly the fact that these get methods that >fix the map on the fly are copies of each other: instead of fixing the >structure in one method, the are plenty of methods almost identical >copying >and pasting the same lines. Some times the same method twice in the same >cmd class for two Map params (look CreateNetworkOfferingCmd >#getServiceCapabilities and #getServiceProviders). > >2- params in which the get method returns the map as it is. With the >strange format. For example, >Cloudmonkey command >create networkoffering ... tags[0].key="City" tags[0].value="Toronto" > >You store in the table network_offeringstags, field tags, the String: >{0={value=Toronto,key=City}} >(including brackets and all) > >So knowing all this I guess you agree this should be refactored... unless >at some point the strange format is needed. But after looking for it >everywhere I didn't find any place where it was. I already did the change >and tested most of the cases and it all seems to work. > > >It would be great if once I upload the patch somebody could help me double >check that it doesn't brake anything, not only reviewing to code. I did >plenty of tests of many kinds, but I cannot be sure that I am covering >enough. Further, there seem to be several places where the code expects >the >strange format. >->ConfigurationManagerImpl line 1545 > > >Thanks. Cheers >Antonio > > >2014-02-28 18:44 GMT+01:00 Alena Prokharchyk ><alena.prokharc...@citrix.com>: > >> >> >> From: Antonio Fornié Casarrubios <antonio.for...@gmail.com> >> Date: Friday, February 28, 2014 at 2:09 AM >> To: Rohit Yadav <rohityada...@gmail.com>, cloudstack < >> dev@cloudstack.apache.org>, Alena Prokharchyk < >> alena.prokharc...@citrix.com> >> Subject: Re: [PROPOSAL][QUESTION] Map parameters in API Commands >> >> Hi Alena, >> >> I would like to know your opinion on this change. Mainly consists on: >> 1- Change the way we store the Map params after unpackParams in order to >> have, for each Map param, a Map<String, String> instead of Map<String, >> Map<String, Object>>. >> >> >> -Antonio, what was the reason for storing the parameter in the old >> format to begin with? Where there any case where we actually needed a >>map >> of map parameters? >> >> > >> >> 2- There are many commands that fix this strange format on demand on >> their getters, so they do the conversion there. Since I already have the >> final format I replace these getters with just >> getTags(){ return this.tags;} >> >> 3- Persistence of these Map params. This last change is more tricky and >> error-prone but the previous two would brake the functionality without >>it. >> Actually it doesn't seem that I should change this for all the cases, >>given >> that for some commands the current behavior is storing in the DB the >>Map as >> it comes, so after the change it will just do the same and thus >>retrieve it >> with the right format. So, although in the tables we move from >> ------ >> key | City >> ------ >> value | The Hague >> ------ >> >> to >> ------ >> City | The Hague >> ------ >> >> then in memory, after DB read, we will just have the proper format >>again >> (Map<String, String>). Is that right? >> >> >> >> - in what table do you see key name being a field name? I've looked >>at >> various *_details tables, as well as resource_tag table, everywhere >>we have >> key/value fields where we store key and the value respectfully: >> >> mysql> desc user_Vm_details; >> >>+---------+---------------------+------+-----+---------+----------------+ >> | Field | Type | Null | Key | Default | Extra >>| >> >>+---------+---------------------+------+-----+---------+----------------+ >> | id | bigint(20) unsigned | NO | PRI | NULL | auto_increment >>| >> | vm_id | bigint(20) unsigned | NO | MUL | NULL | >>| >> | name | varchar(255) | NO | | NULL | >>| >> | value | varchar(1024) | NO | | NULL | >>| >> | display | tinyint(1) | NO | | 1 | >>| >> >>+---------+---------------------+------+-----+---------+----------------+ >> 5 rows in set (0.01 sec) >> >> mysql> desc resource_tags; >> >> >>+---------------+---------------------+------+-----+---------+----------- >>-----+ >> | Field | Type | Null | Key | Default | Extra >> | >> >> >>+---------------+---------------------+------+-----+---------+----------- >>-----+ >> | id | bigint(20) unsigned | NO | PRI | NULL | >> auto_increment | >> | uuid | varchar(40) | YES | UNI | NULL | >> | >> | key | varchar(255) | YES | | NULL | >> | >> | value | varchar(255) | YES | | NULL | >> | >> | resource_id | bigint(20) unsigned | NO | MUL | NULL | >> | >> | resource_uuid | varchar(40) | YES | | NULL | >> | >> | resource_type | varchar(255) | YES | | NULL | >> | >> | customer | varchar(255) | YES | | NULL | >> | >> | domain_id | bigint(20) unsigned | NO | MUL | NULL | >> | >> | account_id | bigint(20) unsigned | NO | MUL | NULL | >> | >> >> >>+---------------+---------------------+------+-----+---------+----------- >>-----+ >> >> >> 4- The last change should be related to any code expecting the old >> format, that will fail with the new one. I guess UI will be an example >>of >> that, but I didn't check yet. If the JS code receives the new Map >> serialized, then chances are this will break it, right? Can you tell >>your >> thoughts on this? Can you tell me places I should check first to confirm >> this guess? >> >> >> - Its not just about the uI> You should never break the API backwards >> compatibility. Remember that lots of third party vendors use our APIs, >>not >> the UI. As long as we support the old format, introducing the new one >> shouldn't be a problem. >> >> >> >> Considering it all, do you think this change is worth it? For me this >> seems to be something that was wrong from the beginning and it should >>have >> been changed before the mess got spread. But know, although I want to >>fix >> it, I'm afraid this involves touching too many things in order to fix >> something that looks horrible but seems to be actually working and I >>don't >> want to break. >> >> Thanks. Cheers >> Antonio >> >> >> >> 2014-02-12 23:32 GMT+01:00 Rohit Yadav <rohityada...@gmail.com>: >> >>> On Wed, Feb 12, 2014 at 9:52 PM, Antonio Fornié Casarrubios >>> <antonio.for...@gmail.com> wrote: >>> > Hi Rohit, >>> > >>> > I didn't mean changing the format of the HTTP request, but only >>> changing the >>> > intermediate format in which we keep it in the property of the >>>Command >>> > class. I mentioned the format in the request just to explain what I >>> meant. >>> > >>> > My proposal is to leave the request format as it is, but then when >>>the >>> > method "apiDispatcher#setFieldValue" parses the map and assign it to >>>the >>> > property, do it in a normal way: which is a Map<String, String> >>>instead >>> of a >>> > Map<String, Map<String, Object>> as it is now. And then, our getter >>> methods >>> > (like CreateTagsCommand#GetTag) will be just a normal getter that >>> doesn't >>> > need to transform the structure on the fly. >>> >>> Cool, let's request the present API layer maintainer(s) and other >>> folks in the community to comment. >>> >>> Regards. >>> >>> > >>> > Thanks, cheers >>> > antonio >>> > >>> > >>> > 2014-02-11 17:38 GMT+01:00 Rohit Yadav <rohityada...@gmail.com>: >>> > >>> >> Hi Antonio, >>> >> >>> >> On Tue, Feb 11, 2014 at 9:57 PM, Antonio Fornié Casarrubios >>> >> <antonio.for...@gmail.com> wrote: >>> >> > Hi all, >>> >> > >>> >> > When invoking a CS API command that has parameters of type Map, >>>the >>> >> > request >>> >> > will be something like this: >>> >> > >>> >> > >>> >>>URL/api?command=createTags&tags[0].key=region&tags[0].value=canada&tags[ >>>1].key=name&tags[1].value=bob >>> >> > >>> >> > in order to send a Map with the pairs: >>> >> > >>> >> > tags{ >>> >> > region : "canada", >>> >> > name : "bob" >>> >> > } >>> >> > >>> >> > Then in the server side the parameters go through several stages >>> (IMHO >>> >> > too >>> >> > many), and have different formats. At some point >>> >> > >>> >> > apiDispatcher#setFieldValue >>> >> > >>> >> > will assign the value to the command property (CreateTagsCmd#tag >>>in >>> the >>> >> > example) in a VERY strange way: >>> >> > >>> >> > CreateTagsCmd#tag = { >>> >> > 0 : { >>> >> > "key" : "region", >>> >> > "value" : "canada" >>> >> > }, >>> >> > 1 : { >>> >> > "key" : "name", >>> >> > "value" : "bob" >>> >> > } >>> >> > } >>> >> > >>> >> > This is true for several Cmd classes. And the funny thing is they >>> >> > usually >>> >> > provide a public getter method to get the Map in an already >>> "normalized" >>> >> > structure. The problem is we have this method again a again in >>>each >>> of >>> >> > these commands, only with different name depending on what >>>property >>> the >>> >> > get, and the body is almost copy and pasted. so my next >>>refactoring >>> >> > would >>> >> > be to have a generic method only once in BaseCmd so that all >>> subclasses >>> >> > can >>> >> > reuse it for their Map getters. Pretty obvious, but... >>> >> >>> >> This is a well know issue and is such a pain, both for the users of >>> >> the API to create this API and the programmer who have to put hack >>>at >>> >> the backend to extract the map. >>> >> >>> >> > Is it really necessary to have this strange format? Wouldn't it be >>> much >>> >> > better to just store it in a more normal way from the beginning, >>>and >>> >> > have >>> >> > the getters just standard getters? Does it have any use to have >>>those >>> >> > Maps >>> >> > of Maps? >>> >> >>> >> Changing the API will break many client so no one attempted it for >>> >> keeping backward-compatibility I think. >>> >> >>> >> The HTTP RFC states that if same keys are sent in param they must be >>> >> received as an array. For example, /api?q=1&q=2&q=3 should received >>>q >>> >> = [1,2,3] which is what we're not doing. >>> >> >>> >> We should do that and this way we can capture maps using keys and >>> >> values in order, so for example, >>> >> /api?q.key1=value1&q.key2=value2&q.key1=value3&q.key2=value4 should >>>be >>> >> received as as array of maps: [{key1: value1, key2: value2}, >>> >> {key3:value3, key4: value4}] etc. >>> >> >>> >> I think it does not have to be maps of maps, but since our API is >>> >> query based these ugly hacks were invented. We should definitely get >>> >> rid of them, and perhaps work on the RESTful API layer, cloud-engine >>> >> and other good stuff we were talking about more than a year ago and >>> >> deprecate the present query API over next few years. Thoughts, >>>flames? >>> >> >>> >> Regards. >>> >> >>> >> > >>> >> > Thanks. Cheers >>> >> > Antonio Fornie >>> >> > Schuberg Philis - MCE >>> > >>> > >>> >> >>