Yes, it is, but in this case, it exceeded connections limit for one license unit and it is even just only 4 in comparing with 25 for ordinary versions.

And I think this message in the log should be changed to be more clear. 

Another issue, here

USER> Write $SYSTEM.License.MaxConnections()
25

25 connections for ordinary version, but Community Edition, has only 4 connections and fails to start more.

And another problem is that reaching connections limit for just one user, changes state of the instance as with warn

root@d5eaa844235c:/# iris list

Configuration 'IRIS'   (default)
        directory:    /usr/irissys
        versionid:    2019.2.0.107.0com
        datadir:      /dur/config
        conf file:    iris.cpf  (SuperServer port = 51773, WebServer = 52773)
        status:       running, since Tue Jun 25 13:00:11 2019
        state:        warn
        product:      InterSystems IRIS

And this state used for HEALTHCHECK of the container, so, this container became as Unhealthy, which means in production such container should be killed, even it is actually in good condition.

$ docker-compose ps
        Name                   Command               State     
---------------------------------------------------------------
jdbc-jpa-rest_iris_1   /iris-main             Up (unhealthy)
ClassMethod GetSSLConfiguration(host) As %String
{
  NEW $NAMESPACE
  SET $NAMESPACE = "%SYS"
  
  IF '##class(Security.SSLConfigs).Exists(host) {
    DO ##class(Security.SSLConfigs).Create(host)
  }
  QUIT host
}

Set tRequest = ##class(%Net.HttpRequest).%New()
Set tRequest.Server = "community.intersystems.com"
Set tRequest.Https = 1
Set tRequest.SSLConfiguration = ..GetSSLConfiguration(tRequest.Server)
....

It actually, does not matter, where to install drivers.

My Caché works in docker, so, I downloaded ODBC drivers from the ftp.

extracted it, just in Downloads, and run there ODBCInstall from a terminal.

with ODBCInstall I got file mgr/cacheodbc.ini, which I copied to ~/Library/ODBC/odbc.ini, there will be as User DSN. /Library/ODBC/odbc.ini for System DSN.

DYLD_LIBRARY_PATH should follow to bin folder in extracted ODBC Drivers folder

in my case 

export DYLD_LIBRARY_PATH=/Users/daimor/Downloads/ODBC-2018.1.2.309.0-macx64/bin

you can check connection with iODBC Manager, running right from terminal

DYLD_LIBRARY_PATH=/Users/daimor/Downloads/ODBC-2018.1.2.309.0-macx64/bin open /Applications/iODBC/iODBC\ Administrator64.app

and open excel same way

DYLD_LIBRARY_PATH=/Users/daimor/Downloads/ODBC-2018.1.2.309.0-macx64/bin open /Applications/Microsoft\ Excel.app

So, you'll be able to test settings without relogin

It's not so much important to have key before install, much more important to have it when server is running.

But how you sure that your key is suitable for this platform. You can check it on running container, where you can enter inside, and go the csession. You can find some intersting methods for $SYSTEM.License in the documentation which can help you to check license file inside the container.

Most of the reasons for getting such error is just missed license file or exceeded license limit.

Just check it, you can mount it during docker run or copy it inside the image during docker build.

I see that you use quite an old version, I would recommend considering usage latest version based on IRIS. Due to many limitations of using such an old version in Docker.

There is also ClassMethod GetGlobalSize in the class %Library.GlobalEdit , where you can select a fast way to count or not, and you will get a different result.

 ClassMethod GetGlobalSize(Directory As %String, GlobalName As %String, ByRef Allocated As %Integer, ByRef Used As %Integer, fast As %Boolean = 0) as %Status

Get size of this global
'Allocated' - total size, in MB, of blocks allocated for the global.
'Used' - total used data, in MB, for the global.
'fast' - TRUE : faster return, it won't return the value of 'Used'.
FALSE - slower return,, it returns values for both 'Allocated' and 'Used'.

So, when fast, it just counts blocks and don't care how those blocks fill by data and multiply the number of blocks on Size of the block.

Used, counts only when you pass fast=0, and it calculates exact size, and to be more accurate reads all blocks, so it could be slower.

Visual Studio and Visual Studio Code are two very different products but just with similar names.

To configure Visual Studio Code, you can use this settings

{
    "objectscript.conn": {
        "active": true,
        "host": "localhost",
        "port": 57772,
        "ns": "SAMPLES",
        "username": "admin",
        "password": "SYS"
    }
}

Where,

  • active, should be true, if you going to be connected
  • port should point to Web server port, and not super port
  • username/password, the user should have enough permissions with role %Development

If you would like to do it with %Installer Manifiest, it is not going to be easy, unfortunately. CSPApplication there quite limited.

I can't just do it this way.

<CSPApplication Url="${CSPApp}" Directory="${CSPAppDir}" iKnowEnabled="yes"/>

You should first create simple csp application

<CSPApplication Url="${CSPApp}" Directory="${CSPAppDir}"/>

Add something like this method

ClassMethod EnableiKnow(pCSPName As %String = "") As %Status
{
  new $namespace
  znspace "%SYS"
  set props("iKnowEnabled")=1
  d ##class(Security.Applications).Modify(pCSPName,.props)
  quit $$$OK
}

But unfortunately, I also can't just call it from an installer, Invoke tag should be placed in Namespace tag. which is actually current namespace, but you should compute it first. This may help to declare a couple more default variables. Just place two first lines before your Installer generator

  do %code.WriteLine($c(9)_"set pVars(""CURRENTCLASS"")="""_%classname_"""")
  do %code.WriteLine($c(9)_"set pVars(""CURRENTNS"")=$namespace")
  quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")

And finally, you can add this to your installer. Place it after CSPApplication creation, but outside of Namespace tag.

<Namespace Name="${CURRENTNS}">
    <Invoke Class="${CURRENTCLASS}" Method="EnableiKnow" CheckStatus="true">
      <Arg Value="${CSPAPP}"/>
    </Invoke>
  </Namespace>

To activate OS authentication in your docker image, you can run this code, in %SYS namespace

Do ##class(Security.System).Get(,.p) Set p("AutheEnabled")=p("AutheEnabled")+16 Do ##class(Security.System).Modify(,.p)

If you work with community edition, you can use my image, where you can easily define also user and password for external use.

Running server

$ docker run -d --rm --name iris \
 -p 52773:52773 \
 -e IRIS_USER=test \
 -e IRIS_PASSWORD=test \
 daimor/intersystems-iris:2019.1.0S.111.0-community

Terminal connect

$ docker exec -it iris iris session iris

Node: 413a4da758e7, Instance: IRIS

USER>write $username
root
USER>write $roles
%All

Or with docker-compose, something like this

  iris:
    image: daimor/intersystems-iris:2019.1.0S.111.0-community
    ports:
      - 52773:52773
    environment:
      IRIS_USER: ${IRIS_PASSWORD:-test}
      IRIS_PASSWORD: ${IRIS_PASSWORD:-test}

You can extend UrlMap only by splitting routes

While in one class you have this

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/class/:namespace/:classname" Method="GET" Call="GetClass" Cors="true"/>
<Map Prefix="/something" Forward="Some.Your.Class"/>
</Routes>
}

You can add one more class, whic will work only with routes started with /something with

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/more" Method="GET" Call="More" Cors="true"/>
</Routes>
}

Where real route will be /something/more


  Set ht = ##class(%Net.HttpRequest).%New()
  Set ht.Server = "server"
  Do ht.SetParam("param1", "true")
  Do ht.SetHeader("myheader", "headervalue")
  Set tSC = ht.Get("/api/get", 1)

Look at the second parameter in the call of Get method, it is a test flag, helps to understand how your request will actually go

GET /api/get?param1=true HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; InterSystems IRIS;)
Host: server
Accept-Encoding: gzip
myheader: headervalue

Look at this code, it will do the same


  Set ht = ##class(%Net.HttpRequest).%New()
  Set ht.Server = "server"
  Do ht.SetParam("param1", "true")
  Do ht.SetHeader("myheader", "headervalue")
  Set ht.Location = "/api/get"
  Set tSC = ht.Get(, 1)

Or even this code


  Set ht = ##class(%Net.HttpRequest).%New()
  Do ht.SetHeader("myheader", "headervalue")
  Set tSC = ht.Get("http://server/api/get?param1=true", 1)