How can I change a production setting programmatically?
Hi folks!
How can I change the production setting programmatically?
I have a production that is a solution that uses some api-keys, which are the parameters of Business Operations but of course cannot be hard-coded into the source code.
E.g. here is the example of such a production that runs a connection of Telegram and ChatGPT.
And it can be installed as:
zpm "install telegram-gpt"
But now one needs to setup the key manually before using the production, having the following setting:
I'd like to set up it programmatically so one could install it as:
zpm "install telegram-gpt -D Token=sometoken"
How can I make it work?
Override the AssignOneSetting method in the adapter your operation is using to get the setting value from somehere of your choosing.
Hello Eugene.
Look into the code
there seems to be clear how to change properties programmatically
Thank you, @Sergey Mikhailenko !
This is exactly the thing I was looking for.
Implemented in a new version of ChatGPT Telegram bot
The only caveat that this approach works only for the "pre-initialised" settings - those that are presented in the production class xdata block. So, if you plan to make changes programmatically, init these settings with any placeholders and this method will be able to change it programmatically later.
Thanks @Evgeny Shvarov for the challenge.
I was digging through the ZPM code this afternoon. What I discovered is the need to implement AbstractInstaller and include in your module resources.
Here is a class that implements loading System Default Settings via ZPM command (when configuration phase is included by a ZPM activity)
Next in my ZPM module definition I added the tag at same level as Resource tags:
In the zpm install command I could use:
If you change your mind about the setting or want to add a second setting you can use for example:
For the arguments the only mandatory ones are:
When the others are not specified they simply go in as wildcard "*" against the System Default Settings.
BTW: Need to delete the "settable" values from the Production XData configuration in distribution, so that the default is applied.
ie: If looking at Production Configuration in Management Portal and a production Item setting is displaying with the Black font label, it means this value is masking the System Default Setting.
If you don't want to pass so many D parameters then some of the values could be hardcoded for project as Parameters in the InstallerClass.
Then would would be closer to original requirement:
Hope this helps.
Kind regards,
Alex
Thanks @Alexander.Woodhead!
Already implemented in this manner. Now the module can be installed as is:
USER>zpm "install telegram-gpt -D TgToken=your_telegram_token -D GPTKey=your_ChatGPT_key"
Introduced a module that does the thing what @Sergey Mikhailenko suggested.
So install it:
and call:
do ##class(shvarov.i14y.Settings).SetValue("ProductionName","ServiceOrOperationName","Setting",Value)
For info to also share about Class: Ens.Production has ClassMethod ApplySettings.
set pSettings(<itemName>,<target>,<settingName>)=<settingValue>
do ##class(Ens.Production).ApplySettings(<productionName>, .pSettings)
Wow. This is much easier. It’s a pity this is not in documentation. Thank you!
Hi,
Do you know that every component in a production has a OnInit() method that is called when the component starts?
You can use this method to set the value of the parameter.
For example:
Method OnInit() As %Status { Set ..#Token = $System.Util.GetEnviron("Token") Quit $$$OK }
May be it's more elegant to do so than update the parameter in the Production file.
FYI, that what i do in IOP (Interoperability On Python) to set the value of the parameter of any component in a production.
def on_init(self): self.my_param = os.environ.get("MY_PARAM", "default_value")
Thank you, @Guillaume Rongier! I like it!
But sometimes we can just have a production with "standard" services and operations, so there is no option to override OnInit().
Why not use "System default settings"?
You can add the value of the property in this table and it is used in your production item.
Have a look iris-deploy-tools
How can I use it as a parameter to IPM installation?
Hi,
In iris.script add the following line:
zpm "install iris-deploy-tools -v"
In TgGptProduction.cls remove the settings of Token and ApiKey
<Item Name="Telegram.InboundService" Category="" ClassName="Telegram.LongPollingService" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule=""> <Setting Target="Adapter" Name="SSLConfig">tg</Setting> <Setting Target="Host" Name="Target">GPTRouter</Setting> </Item> .... <Item Name="St.OpenAi.BO.Api.Connect" Category="" ClassName="St.OpenAi.BO.Api.Connect" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule=""> <Setting Target="Host" Name="Organization"></Setting> <Setting Target="Adapter" Name="SSLConfig">tg</Setting> </Item>
In Setup.cls, extends the class to St.Tools.Deploy and modify the loop to add the default configuration.
Class shvarov.telegramgpt.Setup Extends St.Tools.Deploy { ClassMethod Init(TgToken As %String, GPTKey As %String) As %Status { set st=$$$OK set production="shvarov.telegramgpt.i14y.TgGptProduction" for item="Telegram.InboundService","Telegram.OutboundOperation" { set st = ..AddDefaultSetting("*",item,,"Token",TgToken) quit:$$$ISERR(st) } set item="St.OpenAi.BO.Api.Connect" set st = ..AddDefaultSetting("*",item,,"ApiKey",GPTKey) return st } .... }
I hope you find it useful
Thank you, @Kurro Lopez ! I'll take a look!
@Kurro Lopez !
I overlooked your package and introduced my own "one-class" package to handle this.
So the Setup.Init() method is not a loop anymore :)
ClassMethod Init(TgToken As %String, GPTKey As %String) As %Status { set st=$$$OK set production="shvarov.telegramgpt.i14y.TgGptProduction" for item="Telegram.InboundService","Telegram.OutboundOperation" { set st=##class(shvarov.i14y.Settings).SetValue(production,item,"Token",TgToken) quit:$$$ISERR(st) } set item="St.OpenAi.BO.Api.Connect" set st=##class(shvarov.i14y.Settings).SetValue(production,item,"ApiKey",GPTKey) return st }
Sorry, I realized that your problem is how to pass the parameters when you install the component via ZPM, not how to add the value into the item.
💡 This question is considered a Key Question. More details here.