github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/bddtests/steps/docgen.py (about)

     1  
     2  from StringIO import StringIO
     3  from itertools import chain
     4  from google.protobuf.message import Message
     5  
     6  from b3j0f.aop import weave, unweave, is_intercepted, weave_on
     7  
     8  from jinja2 import Environment, PackageLoader, select_autoescape, FileSystemLoader, Template
     9  env = Environment(
    10      loader=FileSystemLoader(searchpath="templates"),
    11      autoescape=select_autoescape(['html', 'xml']),
    12      trim_blocks=True,
    13      lstrip_blocks=True
    14  )
    15  
    16  from bootstrap_util import getDirectory
    17  from compose import Composition
    18  
    19  class DocumentGenerator:
    20  
    21  
    22      def __init__(self, contextHelper, scenario):
    23          self.contextHelper = contextHelper
    24          self.directory = getDirectory(contextHelper.context)
    25          self.output = StringIO()
    26          self.currentStep = 0
    27          self.composition = None
    28  
    29          #Weave advices into contextHelper
    30          weave(target=self.contextHelper.before_step, advices=self.stepAdvice)
    31          weave(target=self.contextHelper.after_scenario, advices=self.afterScenarioAdvice)
    32          weave(target=self.contextHelper.getBootrapHelper, advices=self.getBootstrapHelperAdvice)
    33  
    34  
    35          weave(target=Composition.__init__, advices=self.registerCompositionAdvice)
    36  
    37          # Weave advices into Directory
    38          weave(target=self.directory._registerOrg, advices=self.registerOrgAdvice)
    39          weave(target=self.directory._registerUser, advices=self.registerUserAdvice)
    40          weave(target=self.directory.registerOrdererAdminTuple, advices=self.registerNamedNodeAdminTupleAdvice)
    41  
    42      def stepAdvice(self, joinpoint):
    43          self.currentStep += 1
    44          step = joinpoint.kwargs['step']
    45          # Now the jinja template
    46          self.output.write(env.get_template("html/step.html").render(step_id="Step {0}".format(self.currentStep), step=step))
    47          return joinpoint.proceed()
    48  
    49      def compositionCallCLIAdvice(self, joinpoint):
    50          'This advice is called around the compositions usage of the cli'
    51          result = joinpoint.proceed()
    52          # Create table for environment
    53          composition = joinpoint.kwargs['self']
    54          envAdditions = composition.getEnvAdditions()
    55          keys = envAdditions.keys()
    56          keys.sort()
    57          envPreamble = " ".join(["{0}={1}".format(key,envAdditions[key]) for key in keys])
    58          args= " ".join(joinpoint.kwargs['argList'])
    59          self.output.write(env.get_template("html/cli.html").render(command="{0} {1}".format(envPreamble, args)))
    60          return result
    61  
    62      def _getNetworkGroup(self, serviceName):
    63          groups = {"peer" : 1, "orderer" : 2}
    64          groupId = 0
    65          for group, id in groups.iteritems():
    66              if serviceName.lower().startswith(group):
    67                  groupId = id
    68          return groupId
    69  
    70      def _getNetworkForConfig(self, configAsYaml):
    71          import yaml
    72          config = yaml.load(configAsYaml)
    73          assert "services" in config, "Expected config from docker-compose config to have services key at top level:  \n{0}".format(config)
    74          network = {"nodes": [], "links" : []}
    75          for serviceName in config['services'].keys():
    76              network['nodes'].append({"id" : serviceName, "group" : self._getNetworkGroup(serviceName), "type" : "node"})
    77              # Now get links
    78              if "depends_on" in config['services'][serviceName]:
    79                  for dependedOnServiceName in config['services'][serviceName]['depends_on']:
    80                      network['links'].append({"source": serviceName, "target": dependedOnServiceName, "value" : 1})
    81          return network
    82  
    83      def _getNetworkForDirectory(self):
    84          network = {"nodes":[], "links": []}
    85          for orgName, org in self.directory.getOrganizations().iteritems():
    86              network['nodes'].append({"id" : orgName, "group" : 3, "type" : "org"})
    87          for userName, user in self.directory.getUsers().iteritems():
    88              network['nodes'].append({"id" : userName, "group" : 4, "type" : "user"})
    89          # Now get links
    90          for nct, cert in self.directory.getNamedCtxTuples().iteritems():
    91              nctId = "{0}-{1}-{2}".format(nct.user, nct.nodeName, nct.organization)
    92              network['nodes'].append({"id" : nctId, "group" : 5, "type" : "cert"})
    93              network['links'].append({"source": nctId, "target": nct.organization, "value" : 1})
    94              network['links'].append({"source": nctId, "target": nct.user, "value" : 1})
    95              # Only add the context link if it is a compose service, else the target may not exist.
    96              if nct.nodeName in self.composition.getServiceNames():
    97                  network['links'].append({"source": nctId, "target": nct.nodeName, "value" : 1})
    98          return network
    99  
   100      def _writeNetworkJson(self):
   101          if self.composition:
   102              import json
   103              configNetwork = self._getNetworkForConfig(configAsYaml=self.composition.getConfig())
   104              directoryNetwork = self._getNetworkForDirectory()
   105              # Join the network info together
   106              fullNetwork = dict(chain([(key, configNetwork[key] + directoryNetwork[key]) for key in configNetwork.keys()]))
   107              (fileName, fileExists) = self.contextHelper.getTmpPathForName("network", extension="json")
   108              with open(fileName, "w") as f:
   109                  f.write(json.dumps(fullNetwork))
   110  
   111  
   112      def registerCompositionAdvice(self, joinpoint):
   113          composition = None
   114          if joinpoint.kwargs['context'] == self.contextHelper.context:
   115              # This is our context, weave into issue_command
   116              composition = joinpoint.kwargs['self']
   117              weave(target=composition._callCLI, advices=self.compositionCallCLIAdvice)
   118          result = joinpoint.proceed()
   119          if composition:
   120              #Now get the config for the composition and dump out.
   121              self.composition = composition
   122              configAsYaml = composition.getConfig()
   123              self.output.write(env.get_template("html/header.html").render(text="Configuration", level=4))
   124              self.output.write(env.get_template("html/cli.html").render(command=configAsYaml))
   125              #Inject the graph
   126              self.output.write(env.get_template("html/header.html").render(text="Network Graph", level=4))
   127              self.output.write(env.get_template("html/graph.html").render())
   128          return result
   129  
   130      def _addLinkToFile(self, fileName ,linkText):
   131          import ntpath
   132          baseName = ntpath.basename(fileName)
   133          # self.markdownWriter.addLink(linkUrl="./{0}".format(baseName), linkText=linkText, linkTitle=baseName)
   134  
   135      def _getLinkInfoForFile(self, fileName):
   136          import ntpath
   137          return "./{0}".format(ntpath.basename(fileName))
   138  
   139      def registerOrgAdvice(self, joinpoint):
   140          orgName = joinpoint.kwargs['orgName']
   141          newlyRegisteredOrg = joinpoint.proceed()
   142          orgCert = newlyRegisteredOrg.getCertAsPEM()
   143          #Write out key material
   144          (fileName, fileExists) = self.contextHelper.getTmpPathForName(name="dir-org-{0}-cert".format(orgName), extension="pem")
   145          with open(fileName, 'w') as f:
   146              f.write(orgCert)
   147          self._addLinkToFile(fileName=fileName, linkText="Public cert for Organization")
   148          #Now the jinja output
   149          self.output.write(env.get_template("html/org.html").render(org=newlyRegisteredOrg, cert_href=self._getLinkInfoForFile(fileName)))
   150          return newlyRegisteredOrg
   151  
   152      def registerUserAdvice(self, joinpoint):
   153          userName = joinpoint.kwargs['userName']
   154          newlyRegisteredUser = joinpoint.proceed()
   155          #Write out key material
   156          privateKeyAsPem = newlyRegisteredUser.getPrivateKeyAsPEM()
   157          (fileName, fileExists) = self.contextHelper.getTmpPathForName(name="dir-user-{0}-privatekey".format(userName), extension="pem")
   158          with open(fileName, 'w') as f:
   159              f.write(privateKeyAsPem)
   160          #Weave into user tags setting
   161          weave(target=newlyRegisteredUser.setTagValue, advices=self.userSetTagValueAdvice)
   162          #Now the jinja output
   163          self.output.write(env.get_template("html/user.html").render(user=newlyRegisteredUser, private_key_href=self._getLinkInfoForFile(fileName)))
   164          return newlyRegisteredUser
   165  
   166      def afterScenarioAdvice(self, joinpoint):
   167          scenario = joinpoint.kwargs['scenario']
   168          #Render with jinja
   169          header = env.get_template("html/scenario.html").render(scenario=scenario, steps=scenario.steps)
   170          main = env.get_template("html/main.html").render(header=header, body=self.output.getvalue())
   171          (fileName, fileExists) = self.contextHelper.getTmpPathForName("scenario", extension="html")
   172          with open(fileName, 'w') as f:
   173              f.write(main)
   174          self._writeNetworkJson()
   175          return joinpoint.proceed()
   176  
   177      def registerNamedNodeAdminTupleAdvice(self, joinpoint):
   178          namedNodeAdminTuple = joinpoint.proceed()
   179          directory = joinpoint.kwargs['self']
   180          #jinja
   181          newCertAsPEM = directory.getCertAsPEM(namedNodeAdminTuple)
   182          self.output.write(env.get_template("html/header.html").render(text="Created new named node admin tuple: {0}".format(namedNodeAdminTuple), level=4))
   183          self.output.write(env.get_template("html/cli.html").render(command=newCertAsPEM))
   184          #Write cert out
   185          fileNameTocheck = "dir-user-{0}-cert-{1}-{2}".format(namedNodeAdminTuple.user, namedNodeAdminTuple.nodeName, namedNodeAdminTuple.organization)
   186          (fileName, fileExists) = self.contextHelper.getTmpPathForName(fileNameTocheck, extension="pem")
   187          with open(fileName, 'w') as f:
   188              f.write(newCertAsPEM)
   189          return namedNodeAdminTuple
   190  
   191      def bootstrapHelperSignConfigItemAdvice(self, joinpoint):
   192          configItem = joinpoint.kwargs['configItem']
   193          #jinja
   194          self.output.write(env.get_template("html/header.html").render(text="Dumping signed config item...", level=4))
   195          self.output.write(env.get_template("html/protobuf.html").render(msg=configItem, msgLength=len(str(configItem))))
   196  
   197          signedConfigItem = joinpoint.proceed()
   198          return signedConfigItem
   199  
   200      def getBootstrapHelperAdvice(self, joinpoint):
   201          bootstrapHelper = joinpoint.proceed()
   202          weave(target=bootstrapHelper.signConfigItem, advices=self.bootstrapHelperSignConfigItemAdvice)
   203          return bootstrapHelper
   204  
   205      def _isProtobufMessage(self, target):
   206          return isinstance(target, Message)
   207  
   208      def _isListOfProtobufMessages(self, target):
   209          result = False
   210          if isinstance(target, list):
   211              messageList = [item for item in target if self._isProtobufMessage(item)]
   212              result = len(messageList) == len(target)
   213          return result
   214  
   215      def _writeProtobuf(self, fileName, msg):
   216          import ntpath
   217          baseName = ntpath.basename(fileName)
   218          dataToWrite = msg.SerializeToString()
   219          with open("{0}".format(fileName), 'wb') as f:
   220              f.write(dataToWrite)
   221          self.output.write(env.get_template("html/protobuf.html").render(id=baseName, msg=msg, path_to_protobuf=fileName, msgLength=len(dataToWrite),linkUrl="./{0}".format(baseName), linkText="Protobuf message in binary form", linkTitle=baseName))
   222  
   223  
   224      def userSetTagValueAdvice(self, joinpoint):
   225          result = joinpoint.proceed()
   226          user = joinpoint.kwargs['self']
   227          tagKey = joinpoint.kwargs['tagKey']
   228          tagValue = joinpoint.kwargs['tagValue']
   229  
   230          #jinja invoke
   231          self.output.write(env.get_template("html/tag.html").render(user=user, tag_key=tagKey))
   232  
   233          # If protobuf message, write out in binary form
   234          if self._isProtobufMessage(tagValue):
   235              import ntpath
   236              (fileName, fileExists) = self.contextHelper.getTmpPathForName("{0}-{1}".format(user.getUserName(), tagKey), extension="protobuf")
   237              self._writeProtobuf(fileName=fileName, msg=tagValue)
   238          # If protobuf message, write out in binary form
   239          elif self._isListOfProtobufMessages(tagValue):
   240              import ntpath
   241              index = 0
   242              for msg in tagValue:
   243                  (fileName, fileExists) = self.contextHelper.getTmpPathForName("{0}-{1}-{2:0>4}".format(user.getUserName(), tagKey, index), extension="protobuf")
   244                  self._writeProtobuf(fileName=fileName, msg=msg)
   245                  index += 1
   246          else:
   247              self.output.write(env.get_template("html/cli.html").render(command=str(tagValue)))
   248          return result