summaryrefslogtreecommitdiffstats
path: root/roles/openshift_logging/library/openshift_logging_facts.py
diff options
context:
space:
mode:
Diffstat (limited to 'roles/openshift_logging/library/openshift_logging_facts.py')
-rw-r--r--roles/openshift_logging/library/openshift_logging_facts.py303
1 files changed, 303 insertions, 0 deletions
diff --git a/roles/openshift_logging/library/openshift_logging_facts.py b/roles/openshift_logging/library/openshift_logging_facts.py
new file mode 100644
index 000000000..1f0c25a84
--- /dev/null
+++ b/roles/openshift_logging/library/openshift_logging_facts.py
@@ -0,0 +1,303 @@
+
+DOCUMENTATION = """
+---
+module: openshift_logging_facts
+version_added: ""
+short_description: Gather facts about the OpenShift logging stack
+description:
+ - Determine the current facts about the OpenShift logging stack (e.g. cluster size)
+options:
+author: Red Hat, Inc
+"""
+
+EXAMPLES = """
+- action: opneshift_logging_facts
+"""
+
+RETURN = """
+"""
+
+import copy
+import json
+import exceptions
+import yaml
+from subprocess import *
+
+default_oc_options = ["-o","json"]
+
+#constants used for various labels and selectors
+COMPONENT_KEY="component"
+LOGGING_INFRA_KEY="logging-infra"
+
+#selectors for filtering resources
+DS_FLUENTD_SELECTOR=LOGGING_INFRA_KEY + "=" + "fluentd"
+LOGGING_SELECTOR=LOGGING_INFRA_KEY + "=" + "support"
+ROUTE_SELECTOR = "component=support,logging-infra=support,provider=openshift"
+COMPONENTS = ["kibana","curator","elasticsearch","fluentd", "kibana_ops", "curator_ops", "elasticsearch_ops"]
+
+class OCBaseCommand(object):
+ def __init__(self, binary, kubeconfig, namespace):
+ self.binary = binary
+ self.kubeconfig = kubeconfig
+ self.user = self.getSystemAdmin(self.kubeconfig)
+ self.namespace = namespace
+
+ def getSystemAdmin(self,kubeconfig):
+ with open(kubeconfig,'r') as f:
+ config = yaml.load(f)
+ for user in config["users"]:
+ if user["name"].startswith("system:admin"):
+ return user["name"]
+ raise Exception("Unable to find system:admin in: " + kubeconfig)
+
+ def oc(self, sub, kind, namespace=None, name=None,addOptions=[]):
+ cmd = [self.binary, sub, kind]
+ if name != None:
+ cmd = cmd + [name]
+ if namespace != None:
+ cmd = cmd + ["-n", namespace]
+ cmd = cmd + ["--user="+self.user,"--config="+self.kubeconfig] + default_oc_options + addOptions
+ try:
+ process = Popen(cmd, stdout=PIPE, stderr=PIPE)
+ out, err = process.communicate(cmd)
+ if len(err) > 0:
+ if 'not found' in err:
+ return {'items':[]}
+ if 'No resources found' in err:
+ return {'items':[]}
+ raise Exception(err)
+ except Exception as e:
+ err = "There was an exception trying to run the command '"+ " ".join(cmd) +"' " + str(e)
+ raise Exception(err)
+
+ return json.loads(out)
+
+class OpenshiftLoggingFacts(OCBaseCommand):
+
+ name = "facts"
+
+ def __init__(self, logger, binary, kubeconfig, namespace):
+ super(OpenshiftLoggingFacts, self).__init__(binary, kubeconfig, namespace)
+ self.logger = logger
+ self.facts = dict()
+
+ def defaultKeysFor(self, kind):
+ for comp in COMPONENTS:
+ self.addFactsFor(comp, kind)
+
+ def addFactsFor(self, comp, kind, name=None, facts=None):
+ if self.facts.has_key(comp) == False:
+ self.facts[comp] = dict()
+ if self.facts[comp].has_key(kind) == False:
+ self.facts[comp][kind] = dict()
+ if name:
+ self.facts[comp][kind][name] = facts
+
+ def factsForRoutes(self, namespace):
+ self.defaultKeysFor("routes")
+ routeList = self.oc("get","routes", namespace=namespace, addOptions=["-l",ROUTE_SELECTOR])
+ if len(routeList["items"]) == 0:
+ return None
+ for route in routeList["items"]:
+ name = route["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None:
+ self.addFactsFor(comp, "routes", name, dict(host=route["spec"]["host"]))
+ self.facts["agl_namespace"] = namespace
+
+
+ def factsForDaemonsets(self, namespace):
+ self.defaultKeysFor("daemonsets")
+ dsList = self.oc("get", "daemonsets", namespace=namespace, addOptions=["-l",LOGGING_INFRA_KEY+"=fluentd"])
+ if len(dsList["items"]) == 0:
+ return
+ for ds in dsList["items"]:
+ name = ds["metadata"]["name"]
+ comp = self.comp(name)
+ spec = ds["spec"]["template"]["spec"]
+ container = spec["containers"][0]
+ result = dict(
+ selector = ds["spec"]["selector"],
+ image = container["image"],
+ resources = container["resources"],
+ nodeSelector = spec["nodeSelector"],
+ serviceAccount = spec["serviceAccount"],
+ terminationGracePeriodSeconds = spec["terminationGracePeriodSeconds"]
+ )
+ self.addFactsFor(comp, "daemonsets", name, result)
+
+ def factsForPvcs(self, namespace):
+ self.defaultKeysFor("pvcs")
+ pvclist = self.oc("get", "pvc", namespace=namespace, addOptions=["-l",LOGGING_INFRA_KEY])
+ if len(pvclist["items"]) == 0:
+ return
+ pvcs = []
+ for pvc in pvclist["items"]:
+ name = pvc["metadata"]["name"]
+ comp = self.comp(name)
+ self.addFactsFor(comp,"pvcs",name,dict())
+
+ def factsForDeploymentConfigs(self, namespace):
+ self.defaultKeysFor("deploymentconfigs")
+ dclist = self.oc("get", "deploymentconfigs", namespace=namespace, addOptions=["-l",LOGGING_INFRA_KEY])
+ if len(dclist["items"]) == 0:
+ return
+ dcs = dclist["items"]
+ for dc in dcs:
+ name = dc["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None:
+ spec = dc["spec"]["template"]["spec"]
+ facts = dict(
+ selector = dc["spec"]["selector"],
+ replicas = dc["spec"]["replicas"],
+ serviceAccount = spec["serviceAccount"],
+ containers = dict(),
+ volumes = dict()
+ )
+ if spec.has_key("volumes"):
+ for vol in spec["volumes"]:
+ clone = copy.deepcopy(vol)
+ clone.pop("name", None)
+ facts["volumes"][vol["name"]] = clone
+ for container in spec["containers"]:
+ facts["containers"][container["name"]] = dict(
+ image = container["image"],
+ resources = container["resources"],
+ )
+ self.addFactsFor(comp,"deploymentconfigs",name,facts)
+
+ def factsForServices(self, namespace):
+ self.defaultKeysFor("services")
+ servicelist = self.oc("get", "services", namespace=namespace, addOptions=["-l",LOGGING_SELECTOR])
+ if len(servicelist["items"]) == 0:
+ return
+ for service in servicelist["items"]:
+ name = service["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None:
+ self.addFactsFor(comp, "services", name, dict())
+
+ def factsForConfigMaps(self, namespace):
+ self.defaultKeysFor("configmaps")
+ aList = self.oc("get", "configmaps", namespace=namespace, addOptions=["-l",LOGGING_SELECTOR])
+ if len(aList["items"]) == 0:
+ return
+ for item in aList["items"]:
+ name = item["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None:
+ self.addFactsFor(comp, "configmaps", name, item["data"])
+
+ def factsForOAuthClients(self, namespace):
+ self.defaultKeysFor("oauthclients")
+ aList = self.oc("get", "oauthclients", namespace=namespace, addOptions=["-l",LOGGING_SELECTOR])
+ if len(aList["items"]) == 0:
+ return
+ for item in aList["items"]:
+ name = item["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None:
+ result = dict(
+ redirectURIs = item["redirectURIs"]
+ )
+ self.addFactsFor(comp, "oauthclients", name, result)
+
+ def factsForSecrets(self, namespace):
+ self.defaultKeysFor("secrets")
+ aList = self.oc("get", "secrets", namespace=namespace)
+ if len(aList["items"]) == 0:
+ return
+ for item in aList["items"]:
+ name = item["metadata"]["name"]
+ comp = self.comp(name)
+ if comp != None and item["type"] == "Opaque":
+ result = dict(
+ keys = item["data"].keys()
+ )
+ self.addFactsFor(comp, "secrets", name, result)
+
+ def factsForSCCs(self, namespace):
+ self.defaultKeysFor("sccs")
+ scc = self.oc("get", "scc", name="privileged")
+ if len(scc["users"]) == 0:
+ return
+ for item in scc["users"]:
+ comp = self.comp(item)
+ if comp != None:
+ self.addFactsFor(comp, "sccs", "privileged", dict())
+
+ def factsForClusterRoleBindings(self, namespace):
+ self.defaultKeysFor("clusterrolebindings")
+ role = self.oc("get", "clusterrolebindings", name="cluster-readers")
+ if "subjects" not in role or len(role["subjects"]) == 0:
+ return
+ for item in role["subjects"]:
+ comp = self.comp(item["name"])
+ if comp != None and namespace == item["namespace"]:
+ self.addFactsFor(comp, "clusterrolebindings", "cluster-readers", dict())
+
+# this needs to end up nested under the service account...
+ def factsForRoleBindings(self, namespace):
+ self.defaultKeysFor("rolebindings")
+ role = self.oc("get", "rolebindings", namespace=namespace, name="logging-elasticsearch-view-role")
+ if "subjects" not in role or len(role["subjects"]) == 0:
+ return
+ for item in role["subjects"]:
+ comp = self.comp(item["name"])
+ if comp != None and namespace == item["namespace"]:
+ self.addFactsFor(comp, "rolebindings", "logging-elasticsearch-view-role", dict())
+
+ def comp(self, name):
+ if name.startswith("logging-curator-ops"):
+ return "curator_ops"
+ elif name.startswith("logging-kibana-ops") or name.startswith("kibana-ops"):
+ return "kibana_ops"
+ elif name.startswith("logging-es-ops") or name.startswith("logging-elasticsearch-ops"):
+ return "elasticsearch_ops"
+ elif name.startswith("logging-curator"):
+ return "curator"
+ elif name.startswith("logging-kibana") or name.startswith("kibana"):
+ return "kibana"
+ elif name.startswith("logging-es") or name.startswith("logging-elasticsearch"):
+ return "elasticsearch"
+ elif name.startswith("logging-fluentd") or name.endswith("aggregated-logging-fluentd"):
+ return "fluentd"
+ else:
+ return None
+
+ def do(self):
+ self.factsForRoutes(self.namespace)
+ self.factsForDaemonsets(self.namespace)
+ self.factsForDeploymentConfigs(self.namespace)
+ self.factsForServices(self.namespace)
+ self.factsForConfigMaps(self.namespace)
+ self.factsForSCCs(self.namespace)
+ self.factsForOAuthClients(self.namespace)
+ self.factsForClusterRoleBindings(self.namespace)
+ self.factsForRoleBindings(self.namespace)
+ self.factsForSecrets(self.namespace)
+ self.factsForPvcs(self.namespace)
+
+ return self.facts
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ admin_kubeconfig = {"required": True, "type": "str"},
+ oc_bin = {"required": True, "type": "str"},
+ openshift_logging_namespace = {"required": True, "type": "str"}
+ ),
+ supports_check_mode = False
+ )
+ try:
+ cmd = OpenshiftLoggingFacts(module, module.params['oc_bin'], module.params['admin_kubeconfig'],module.params['openshift_logging_namespace'])
+ module.exit_json(
+ ansible_facts = {"openshift_logging_facts": cmd.do() }
+ )
+ except Exception as e:
+ module.fail_json(msg=str(e))
+
+from ansible.module_utils.basic import *
+if __name__ == '__main__':
+ main()