Code Review

I advise that “first viewers” of this technical blog series begin with the initial posting at url:  Portal Automation Introduction

As initially stated:  …..each new post will describe configuring a subsequent step(s) in the (initially stated)agenda. I expect to be adding new posts for this series semi-weekly.
This entry will illustrate examples of the interoperation between Model-View-Controller within the virtual lab that I configured. Uninterrupted code can be referred to as addendum in later (and final) blog entries.  This entry will only include code excerpts and their relationship for the purpose of explaining the application’s MVC operation.
This entry is broken into chapters so as to assist illustrating MVC process flow.

The Model

Launching the View Begins at the Model app5.py
Preparation and Imports
import os:  not necessary for this application, but needed for some file management
import sys: necessary for this application, as stdout is imperative for ExaBGP to operate
from flask import Flask, render_template: necessary for relating Python code to url references
from flask_bower import Bower:  Bower is our package CSS/js management utility
from flask import request: HTTP requests sent from Python, unused here
import json : necessary. Python can parse JSON dict into Python lists
from flask import jsonify: necessary. Python can parse lists into json format
from pymongo import MongoClient, DESCENDING : necessary for doc mongo insertion
from sys import stdout: ExaBGP receives  stdout from child process as prefix input
from sys import stdin: not used here
from time import sleep: used as variable rest between ExaBGP announcements
client = MongoClient()
db = client.portalDB: set up the mongo db to use
.
.
app = Flask(__name__)  sets up object of Flask class assigned to variableapp”.  Necessary when app is a single module
@app.route(“/”)  Python decorator for function main. This is Flask at work
def main():
    return render_template(‘sandbox5.html’)  now make the view available at Flask port 5000 . This  module launches View service at the Flask port

The View

Content Style Sheets and js scripts should have placement in sandbox5.html
The Content Style Sheet references are placed in head section, as is most conventional.
<head>
 <link href=”static/js/bootstrap.css” rel=”stylesheet”>
    <link href=”http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css” rel=”stylesheet”>
    <link rel=”stylesheet” href=”https://www.w3schools.com/w3css/4/w3.css”>
</head>
javascript files are placed at the bottom of the body section, as this improved display speed (display not waiting on compilation). Minimized versions of scripts should be used for space efficiency:
<body>
.
.
  <script type=”text/javascript” src=”static/js/angular.min.js”></script>
    <script type=”text/javascript” src=”static/js/jquery.min.js”></script>
    <script type=”text/javascript” src=”static/js/bootstrap.min.js”></script>
    <script type=”text/javascript” src=”static/js/bootstrap-theme.css”></script>
    <script type=”text/javascript” src=”static/js/ngIpAddress.min.js”></script>
    <script type=”text/javascript” src=”static/js/app-ip.js”></script>
    <script type=”text/javascript” src=”static/js/announce_prefix3.js”></script>
</body>

Initial View Directives

The first user selection options are available in the initial view portal:
<div ng-app=”myApp” ng-controller=”HomeCtrl”>
        <form name=”SearchForm”>
            <div ng-if=“PhaseOne”> following div segment presented in view only if condition is true (i.e. view has just been refreshed)
                <div class=”container”>
                    <div class=”header”>
                        <nav>
                            <ul class=”nav nav-pills pull-right”>
                            </ul>
                        </nav>
                        <h3 align=”center”>Route Black-Hole Portal</h3>
                    </div>
                    <div class=”jumbotron”>
                        <h3 align=”left”>Re-push all B-H prefixes? Or search for a B-H prefix in the Data Base?</h3>
                        <button class=”w3-btn w3-large w3-blue” ng-click=”Repush()”>Repush ?</button>  angularjs directive, re-announce all prefixes in DB?
                        <button class=”w3-btn w3-large w3-blue” ng-click=”DBaseSearch()“>Database Search ?</button>  angularjs directive, search  for a prefix in DB?
                    </div>
                </div>
            </div>
From the above, the user is presented with the initial portal view as below:
 

The Controller

Based upon user selections in the above view, the Angularjs directives in the view will initiate actions in the Controller announce_prefix3.js:
For example: The user selected “Repush in the View
From the Angularjs controller announce_prefix3.js
$scope.Repush = function () {  Directive from the View
            $scope.PhaseOne = false  this is no longer the first pass thru the view
            $scope.repush = true  and this IS a repush
            $http({    employ the  Angularjs http post service back to the Model
                method: ‘POST’,
                url: ‘/repush’, this controller refers back to the Model (app5.py), at Flask base url/repush
            }).
The Model
Model’s (app5.py) data I/O for user’s repush selection in the View
@app.route(“/repush”,methods=[‘POST’]) Python decorator pointed by (above) controller reference
def repush():
      try:
         prefix_adv = 0
         message = ” “
         cursorPos= db.prefixinfo2.find() point at the initial DB record position
         for record in cursorPos: in the loop, retrieve all prefixes in the DB
             next_entry = “announce route ” + ” ” + record[‘prefix’] + ” next-hop” + ” ” + record[‘nexthop’]
             stdout.write( next_entry + ‘\n’) end result of the view’s repush  selection. ExaBGP listens to stdout for prefixes to announce
             prefix_adv  = prefix_adv+1
             stdout.flush()
             sleep(.1)
         return
 ng-if, ng-show actions
After the above examples of MVC interoperation, I want to illustrate differences in View management.
Managing what is seen in the portal is often accomplished by way of ng-if, ng-show and ng-hide directives.
ng-if: this directive removes code in the same html block from the Document of Modules (DOM) entirely as long as its conditional test is true.
ng-show/hide:  these directives will show or hide code in a HTML block if the conditional test is true. BUT the code following these directives will remain in the DOM.
To understand the relevance of the above differences, consider the HTML code and the explanation below:
           <div ng-if=”DBSearched && buttonpressed == false”>
                <div class=”container”>
                    <div class=”header”>
                        <nav>
                            <ul class=”nav nav-pills pull-right”>
                            </ul>
                        </nav>
                        <h3 align=”center”>Route Black-Hole Portal</h3>
                    </div>
                    <div class=”jumbotron”>
                        <h3 align=”center”>Data base Search </h3>
                        <div>
                            <fieldset>
                                <legend>Enter Address for Search</legend>
                                <label>IP Address</label>
                                <input type=”text” name=”SearchInput1″ ng-model=”$parent.ipAddress1″ ng-ip-address />
                                <span ng-if=”SearchForm.SearchInput1.$invalid”>Invalid</span>
                                <div>
                                    <span ng-if=”SearchForm.SearchInput1.$dirty && SearchForm.SearchInput1.$valid”>
                                    Valid
                                    <button ng-click=”selectentry()”>Select</button></span>
                                </div>
                            </fieldset>
                        </div>
                    </div>
                </div>
            </div>
There are both view actions and Angularjs directives included in the code block above.  The directive ng-if is employed so as to either include or exclude the above code entirely from the DOM.  If ng-show were used instead, it could prevent the inclusion of the above code in the view, but some code would still be executed and cause unexpected results, because with ng-show the code remains in the DOM.
The Scope
The topic of scope deserves attention. By definition, the scope is the two-way binding ensuring properties available between the HTML (view) and the Angularjs (controller).
Scope is generally subdivided so that there is a parent scope plus child scopes. Child scopes are established within Angularjs functions and within HTML Angularjs directives (such as ng-if, ng-repeat, ng-switch, and ng-include).
With the above in mind care must be taken to ensure of the proper availability of properties created under ng-if directives.  Take in consideration the HTML code from my application below:
<legend>Enter Address for Search</legend>
                                <label>IP Address</label>
                                <input type=”text” name=”SearchInput1″ ng-model=”$parent.ipAddress1″ ng-ip-address />
In order for the text to be available within the parent scope (and not limited to the ng-if directive’s child scope), the scope parent is  specified. Otherwise, the text may not be available to the Angularjs functions that will process it.
“…..As for the nuances, scope inheritance is normally straightfoward… until you need 2-way data binding (i.e., form elements, ng-model) in the child scope. Ng-repeat, ng-switch, and ng-include can trip you up if you try to bind to a primitive (e.g., number, string, boolean) in the parent scope from inside the child scope. It doesn’t work the way most people expect it should work. The child scope gets its own property that hides/shadows the parent property of the same name. Your workarounds are
1) define objects in the parent for your model, then reference a property of that object in the child: parentObj.someProp
2) use $parent.parentScopeProperty (not always possible, but easier than 1. where possible)
3) define a function on the parent scope, and call it from the child (not always possible …..    “
Understanding the relationship of data properties and their related scopes becomes essential for effective trouble-shooting such as with developer tools, as shall be illustrated in much more detail in a later entry.
Managing Controller size
Controller size may be managed by way of injecting dependencies as adjunct functions instead of repeating function code that has (or could have been) built elsewhere.  An example can be seen in the Angular Module statement at the top of my controller code:
angular.module(‘myApp’, [‘app-ip’])
“app-ip”  is an imported js function that assists in the user’s ipv4 prefix text qualification. The code is imported as a dependency, rather than recoded in the controller.
This method is described in   https://docs.angularjs.org/guide/controller
“….In general, a Controller shouldn’t try to do too much. It should contain only the business logic needed for a single view.
The most common way to keep Controllers slim is by encapsulating work that doesn’t belong to controllers into services and then using these services in Controllers via dependency injection. This is discussed in the Dependency Injection and Services sections of this guide. 
 In Conclusion
​Obviously this cannot be a conclusion. There’s much more that can be described about the operation of this application, but the operational flow between the Model, View and Controller has been thoroughly introduced.
​The next blog entry will introduce the use and advantage of developer tools as applied during the development process of this (or any) application.