Browse Source

Merge pull request #14085 from afishbeck/wsecl-list

HPCC-24598 Improve helm service definitions and add to configMaps

Reviewed-By: Gavin Halliday <gavin.halliday@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 4 years ago
parent
commit
f314b3731e

+ 100 - 47
esp/services/ws_ecl/ws_ecl_service.cpp

@@ -196,57 +196,36 @@ static void appendServerAddress(StringBuffer &s, IPropertyTree &env, IPropertyTr
     s.append(netAddress).append(':').append(port ? port : "9876");
 }
 
-bool CWsEclService::init(const char * name, const char * type, IPropertyTree * cfg, const char * process)
+void initContainerRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap)
 {
-    StringBuffer xpath;
-    xpath.appendf("Software/EspProcess[@name='%s']", process);
-    IPropertyTree *prc = cfg->queryPropTree(xpath.str());
-    if (!prc)
-        throw MakeStringException(-1, "ESP Process %s not configured", process);
+    Owned<IPropertyTreeIterator> services = queryComponentConfig().getElements("services[@type='roxie']");
+    ForEach(*services)
+    {
+        IPropertyTree &service = services->query();
+        const char *name = service.queryProp("@name");
+        const char *target = service.queryProp("@target");
+        const char *port = service.queryProp("@port");
 
-    auth_method.set(prc->queryProp("Authentication/@method"));
-    portal_URL.set(prc->queryProp("@portalurl"));
+        if (isEmptyString(target) || isEmptyString(name)) //bad config?
+            continue;
 
-    StringBuffer daliAddress;
-    const char *daliServers = prc->queryProp("@daliServers");
-    if (daliServers)
-    {
-        while (*daliServers && !strchr(":;,", *daliServers))
-            daliAddress.append(*daliServers++);
+        StringBuffer s;
+        s.append(name).append(':').append(port ? port : "9876");
+        Owned<ISmartSocketFactory> sf = new RoxieSocketFactory(s.str(), false, true, nullptr, (unsigned) -1);
+        connMap.setValue(target, sf.get());
     }
+}
+
+void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap, IPropertyTree *serviceTree, const char *daliAddress)
+{
+    IPropertyTree *vips = serviceTree->queryPropTree("VIPS");
+    Owned<IStringIterator> roxieTargets = getTargetClusters("RoxieCluster", NULL);
 
     Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
     Owned<IConstEnvironment> environment = factory->openEnvironment();
     Owned<IPropertyTree> pRoot = &environment->getPTree();
 
-    xpath.clear().appendf("EspService[@name='%s']", name);
-    IPropertyTree *serviceTree = prc->queryPropTree(xpath);
-    if (!serviceTree)
-        throw MakeStringException(-1, "ESP Service %s not configured", name);
-
-    roxieTimeout = serviceTree->getPropInt("RoxieTimeout", 10 * 60);
-    if (!roxieTimeout)
-        roxieTimeout = WAIT_FOREVER;
-    workunitTimeout = serviceTree->getPropInt("WorkunitTimeout", 10 * 60);
-    if (workunitTimeout)
-        workunitTimeout *= 1000;
-    else
-        workunitTimeout = WAIT_FOREVER;
-
-    const char *headerName = serviceTree->queryProp("HttpGlobalIdHeader");
-    if (headerName && *headerName && !streq(headerName, "Global-Id") && !streq(headerName, "HPCC-Global-Id")) //defaults will be checked anyway
-        globalIdHttpHeader.set(headerName);
-    headerName = serviceTree->queryProp("HttpCallerIdHeader");
-    if (headerName && *headerName && !streq(headerName, "Caller-Id") && !streq(headerName, "HPCC-Caller-Id")) //defaults will be checked anyway
-        callerIdHttpHeader.set(headerName);
-
-    Owned<IPropertyTreeIterator> cfgTargets = serviceTree->getElements("Targets/Target");
-    ForEach(*cfgTargets)
-        targets.append(cfgTargets->query().queryProp(NULL));
-
-    IPropertyTree *vips = serviceTree->queryPropTree("VIPS");
-    Owned<IStringIterator> roxieTargets = getTargetClusters("RoxieCluster", NULL);
-
+    StringBuffer xpath;
     ForEach(*roxieTargets)
     {
         SCMStringBuffer target;
@@ -289,7 +268,7 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
             {
                 Owned<IPropertyTreeIterator> servers = it->query().getElements("RoxieServerProcess");
                 ForEach(*servers)
-                    appendServerAddress(list, *pRoot, servers->query(), daliAddress.str());
+                    appendServerAddress(list, *pRoot, servers->query(), daliAddress);
             }
         }
         if (list.length())
@@ -301,7 +280,56 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
                 connMap.setValue(alias.str(), sf.get());
         }
     }
+}
+bool CWsEclService::init(const char * name, const char * type, IPropertyTree * cfg, const char * process)
+{
+    StringBuffer xpath;
+    xpath.appendf("Software/EspProcess[@name='%s']", process);
+    IPropertyTree *prc = cfg->queryPropTree(xpath.str());
+    if (!prc)
+        throw MakeStringException(-1, "ESP Process %s not configured", process);
+
+    auth_method.set(prc->queryProp("Authentication/@method"));
+    portal_URL.set(prc->queryProp("@portalurl"));
 
+    StringBuffer daliAddress;
+    const char *daliServers = prc->queryProp("@daliServers");
+    if (daliServers)
+    {
+        while (*daliServers && !strchr(":;,", *daliServers))
+            daliAddress.append(*daliServers++);
+    }
+
+    xpath.clear().appendf("EspService[@name='%s']", name);
+    IPropertyTree *serviceTree = prc->queryPropTree(xpath);
+    if (!serviceTree)
+        throw MakeStringException(-1, "ESP Service %s not configured", name);
+
+    roxieTimeout = serviceTree->getPropInt("RoxieTimeout", 10 * 60);
+    if (!roxieTimeout)
+        roxieTimeout = WAIT_FOREVER;
+    workunitTimeout = serviceTree->getPropInt("WorkunitTimeout", 10 * 60);
+    if (workunitTimeout)
+        workunitTimeout *= 1000;
+    else
+        workunitTimeout = WAIT_FOREVER;
+
+    const char *headerName = serviceTree->queryProp("HttpGlobalIdHeader");
+    if (headerName && *headerName && !streq(headerName, "Global-Id") && !streq(headerName, "HPCC-Global-Id")) //defaults will be checked anyway
+        globalIdHttpHeader.set(headerName);
+    headerName = serviceTree->queryProp("HttpCallerIdHeader");
+    if (headerName && *headerName && !streq(headerName, "Caller-Id") && !streq(headerName, "HPCC-Caller-Id")) //defaults will be checked anyway
+        callerIdHttpHeader.set(headerName);
+
+    Owned<IPropertyTreeIterator> cfgTargets = serviceTree->getElements("Targets/Target");
+    ForEach(*cfgTargets)
+        targets.append(cfgTargets->query().queryProp(NULL));
+
+#ifdef _CONTAINERIZED
+    initContainerRoxieTargets(connMap);
+#else
+    initBareMetalRoxieTargets(connMap, serviceTree, daliAddress.str());
+#endif
     translator = new wsEclTypeTranslator();
 
     Owned<IPropertyTreeIterator> xsltProps = serviceTree->getElements("xslt*");
@@ -332,6 +360,28 @@ void CWsEclBinding::getNavigationData(IEspContext &context, IPropertyTree & data
     ensureNavDynFolder(data, "Targets", "Targets", "root=true", NULL);
 }
 
+static IStringIterator *getContainerTargetClusters()
+{
+    Owned<CStringArrayIterator> ret = new CStringArrayIterator;
+    Owned<IPropertyTreeIterator> queues = queryComponentConfig().getElements("queues");
+    ForEach(*queues)
+    {
+        IPropertyTree &queue = queues->query();
+        const char *qName = queue.queryProp("@name");
+        if (!isEmptyString(qName))
+            ret->append_unique(qName);
+    }
+    Owned<IPropertyTreeIterator> services = queryComponentConfig().getElements("services[@type='roxie']");
+    ForEach(*services)
+    {
+        IPropertyTree &service = services->query();
+        const char *targetName = service.queryProp("@target");
+        if (!isEmptyString(targetName))
+            ret->append_unique(targetName);
+    }
+    return ret.getClear();
+}
+
 void CWsEclBinding::getRootNavigationFolders(IEspContext &context, IPropertyTree & data)
 {
     DBGLOG("CScrubbedXmlBinding::getNavigationData");
@@ -343,7 +393,11 @@ void CWsEclBinding::getRootNavigationFolders(IEspContext &context, IPropertyTree
     data.addProp("@action", "NavMenuEvent");
     data.addProp("@appName", "WsECL 3.0");
 
+#ifdef _CONTAINERIZED
+    Owned<IStringIterator> envTargets = getContainerTargetClusters();
+#else
     Owned<IStringIterator> envTargets = getTargetClusters(NULL, NULL);
+#endif
 
     SCMStringBuffer target;
     ForEach(*envTargets)
@@ -2142,13 +2196,12 @@ int CWsEclBinding::onSubmitQueryOutputView(IEspContext &context, CHttpRequest* r
     StringBuffer status;
     StringBuffer html;
 
-    SCMStringBuffer clustertype;
-    wu->getDebugValue("targetclustertype", clustertype);
-
     StringBuffer xsltfile(getCFD());
     xsltfile.append("xslt/wsecl3_result.xslt");
     const char *view = context.queryRequestParameters()->queryProp("view");
-    if (!forceCreateWorkunit && strieq(clustertype.str(), "roxie"))
+
+    bool callRoxieQuery = !forceCreateWorkunit && nullptr!=wsecl->connMap.getValue(wsinfo.qsetname.get());
+    if (callRoxieQuery)
     {
         sendRoxieRequest(wsinfo.qsetname.get(), soapmsg, output, status, wsinfo.queryname, false, "text/xml", request);
         Owned<IWuWebView> web = createWuWebView(*wu, wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());

+ 4 - 4
esp/xslt/wsecl3_jsontest.xsl

@@ -38,12 +38,12 @@
     <html>
       <head>
         <title>JSON Test Page</title>
-        <link rel="shortcut icon" href="files_/img/affinity_favicon_1.ico" />
-        <link rel="stylesheet" type="text/css" href="files_/yui/build/fonts/fonts-min.css" />
-        <link rel="stylesheet" type="text/css" href="files_/css/espdefault.css" />
+        <link rel="shortcut icon" href="/esp/files/img/affinity_favicon_1.ico" />
+        <link rel="stylesheet" type="text/css" href="/esp/files/yui/build/fonts/fonts-min.css" />
+        <link rel="stylesheet" type="text/css" href="/esp/files/css/espdefault.css" />
 
         <script>dojoConfig = {async:true, parseOnLoad:false}</script>
-        <script src="files_/dist/dojoLib.eclwatch.js"></script>
+        <script src="/esp/files/dist/dojoLib.eclwatch.js"></script>
     </head>
     <body class="yui-skin-sam" id="body">
       <h3>

+ 25 - 0
helm/hpcc/templates/_helpers.tpl

@@ -531,3 +531,28 @@ Generate instance queue names
  {{- end }}
 {{- end -}}
 {{- end -}}
+
+{{/*
+Generate list of available services
+*/}}
+{{- define "hpcc.generateConfigMapServices" -}}
+{{- range $roxie := $.Values.roxie -}}
+ {{- if not $roxie.disabled -}}
+  {{- range $service := $roxie.services -}}
+   {{- if ne (int $service.port) 0 -}}
+- name: {{ $service.name }}
+  type: roxie
+  port: {{ $service.port }}
+  target: {{ $roxie.name }}
+   {{- end -}}
+  {{- end }}
+{{ end -}}
+{{- end -}}
+{{- range $esp := $.Values.esp -}}
+- name: {{ $esp.name }}
+  type: {{ $esp.application }}
+  port: {{ $esp.servicePort }}
+  tls: {{ $esp.tls }}
+  public: {{ $esp.public }}
+{{ end -}}
+{{- end -}}

+ 2 - 0
helm/hpcc/templates/esp.yaml

@@ -51,6 +51,8 @@ data:
 {{- include "hpcc.generateLoggingConfig" (dict "root" $ "me" .) | indent 6 }}
       queues:
 {{ include "hpcc.generateConfigMapQueues" $ | indent 6 }}
+      services:
+{{ include "hpcc.generateConfigMapServices" $ | indent 6 }}
     global:
 {{ include "hpcc.generateGlobalConfigMap" $ | indent 6 }}
 ---

+ 2 - 0
helm/hpcc/templates/localroxie.yaml

@@ -65,6 +65,8 @@ apiVersion: v1
 kind: Service
 metadata:
   name: {{ $name | quote }}
+  labels:
+    type: roxie-service
 spec:
   ports:
   - port: {{ $service.port }}

+ 3 - 2
helm/hpcc/templates/roxie.yaml

@@ -40,11 +40,12 @@ spec:
 
 {{- range $service := $roxie.services }}
 {{- if ne (int $service.port)  0 }}
-{{- $name := printf "%s-%s" $roxie.name $service.name }}
 apiVersion: v1
 kind: Service
 metadata:
-  name: {{ $name | quote }}
+  name: {{ $service.name | quote }}
+  labels:
+    type: roxie-service
 spec:
   ports:
   - port: {{ $service.port }}

+ 5 - 7
helm/hpcc/values.yaml

@@ -107,9 +107,9 @@ eclagent:
   ## type may be 'hthor' (the default) or 'roxie', to specify that the roxie engine rather than the hthor engine should be used for eclagent workunit processing
   type: hthor
 
-- name: roxie
+- name: roxie-workunit
   replicas: 1
-  prefix: roxie
+  prefix: roxie_workunit
   maxActive: 20
   useChildProcesses: true
   type: roxie
@@ -163,17 +163,15 @@ esp:
   servicePort: 8510
 
 roxie:
-- name: roxie-cluster
+- name: roxie
   disabled: false
-  prefix: roxiecluster
+  prefix: roxie
   services:
-  - name: query
+  - name: roxie
     port: 9876
     listenQueue: 200
     numThreads: 0
     external: true
-  - name: on-demand
-    port: 0
   numChannels: 2
   ## Set serverReplicas to indicate a separate replicaSet of roxie servers, with agent nodes not acting as servers
   serverReplicas: 0

+ 1 - 0
system/jlib/jutil.hpp

@@ -268,6 +268,7 @@ class jlib_decl CStringArrayIterator : implements CInterfaceOf<IStringIterator>
     StringArray strings;
 public:
     void append(const char *str) { strings.append(str); }
+    void append_unique(const char *str) { strings.appendUniq(str); }
     virtual bool first() { idx = 0; return strings.isItem(idx); }
     virtual bool next() { idx ++; return strings.isItem(idx); }
     virtual bool isValid() { return strings.isItem(idx); }